@mathwiz/ui-components 0.1.25 → 0.1.26

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../node_modules/react/cjs/react-jsx-runtime.production.js","../node_modules/react/cjs/react-jsx-runtime.development.js","../node_modules/react/jsx-runtime.js","../src/components/Button/Button.tsx","../src/components/ContentAccordion/types.ts","../src/components/ContentAccordion/ContentAccordion.tsx","../src/components/Sidebar/types.ts","../src/components/Sidebar/Sidebar.tsx","../src/components/Submenu/Submenu.tsx","../node_modules/axios/lib/helpers/bind.js","../node_modules/axios/lib/utils.js","../node_modules/axios/lib/core/AxiosError.js","../node_modules/axios/lib/helpers/null.js","../node_modules/axios/lib/helpers/toFormData.js","../node_modules/axios/lib/helpers/AxiosURLSearchParams.js","../node_modules/axios/lib/helpers/buildURL.js","../node_modules/axios/lib/core/InterceptorManager.js","../node_modules/axios/lib/defaults/transitional.js","../node_modules/axios/lib/platform/browser/classes/URLSearchParams.js","../node_modules/axios/lib/platform/browser/classes/FormData.js","../node_modules/axios/lib/platform/browser/classes/Blob.js","../node_modules/axios/lib/platform/browser/index.js","../node_modules/axios/lib/platform/common/utils.js","../node_modules/axios/lib/platform/index.js","../node_modules/axios/lib/helpers/toURLEncodedForm.js","../node_modules/axios/lib/helpers/formDataToJSON.js","../node_modules/axios/lib/defaults/index.js","../node_modules/axios/lib/helpers/parseHeaders.js","../node_modules/axios/lib/core/AxiosHeaders.js","../node_modules/axios/lib/core/transformData.js","../node_modules/axios/lib/cancel/isCancel.js","../node_modules/axios/lib/cancel/CanceledError.js","../node_modules/axios/lib/core/settle.js","../node_modules/axios/lib/helpers/parseProtocol.js","../node_modules/axios/lib/helpers/speedometer.js","../node_modules/axios/lib/helpers/throttle.js","../node_modules/axios/lib/helpers/progressEventReducer.js","../node_modules/axios/lib/helpers/isURLSameOrigin.js","../node_modules/axios/lib/helpers/cookies.js","../node_modules/axios/lib/helpers/isAbsoluteURL.js","../node_modules/axios/lib/helpers/combineURLs.js","../node_modules/axios/lib/core/buildFullPath.js","../node_modules/axios/lib/core/mergeConfig.js","../node_modules/axios/lib/helpers/resolveConfig.js","../node_modules/axios/lib/adapters/xhr.js","../node_modules/axios/lib/helpers/composeSignals.js","../node_modules/axios/lib/helpers/trackStream.js","../node_modules/axios/lib/adapters/fetch.js","../node_modules/axios/lib/adapters/adapters.js","../node_modules/axios/lib/core/dispatchRequest.js","../node_modules/axios/lib/env/data.js","../node_modules/axios/lib/helpers/validator.js","../node_modules/axios/lib/core/Axios.js","../node_modules/axios/lib/cancel/CancelToken.js","../node_modules/axios/lib/helpers/spread.js","../node_modules/axios/lib/helpers/isAxiosError.js","../node_modules/axios/lib/helpers/HttpStatusCode.js","../node_modules/axios/lib/axios.js","../node_modules/axios/index.js","../src/components/UserProfile/UserProfile.tsx","../src/components/MathWizHeader/MathWizHeader.tsx","../src/components/EquationRender/EquationRender.tsx","../src/components/GeometryTransform/types/transform.ts","../src/components/GeometryTransform/utils/geometryCalculations.ts","../src/components/GeometryTransform/utils/validation.ts","../src/components/GeometryTransform/executors/TransformExecutor.ts","../src/components/GeometryTransform/utils/transformAlgorithms.ts","../src/components/GeometryTransform/executors/TranslationExecutor.ts","../src/components/GeometryTransform/executors/RotationExecutor.ts","../src/components/GeometryTransform/executors/ScaleExecutor.ts","../src/components/GeometryTransform/utils/colorUtils.ts","../src/components/GeometryTransform/executors/FillColorSetExecutor.ts","../src/components/GeometryTransform/executors/TransformExecutorRegistry.ts","../src/components/GeometryTransform/utils/GroupMatcher.ts","../src/components/GeometryTransform/types/composition.ts","../src/components/GeometryTransform/composition/TransformCompositor.ts","../src/components/GeometryTransform/composition/TransformPipeline.ts","../src/components/GeometryTransform/hooks/useTransformProgress.ts","../src/components/GeometryTransform/hooks/useKeyboardNavigation.ts","../src/components/GeometryTransform/GeometryTransform.tsx","../src/components/HundredChart/HundredChart.store.ts","../src/components/HundredChart/HundredChart.utils.ts","../src/components/HundredChart/HundredChart.tsx","../src/components/MathCardV2/context.ts","../src/components/MathCardV2/hooks/useDataAdapter.ts","../src/components/MathCardV2/components/layouts/CardLayout.tsx","../src/components/MathCardV2/components/layouts/GridLayout.tsx","../src/components/MathCardV2/components/layouts/FlowLayout.tsx","../src/components/MathCardV2/components/content/TextContent.tsx","../src/components/MathCardV2/components/content/FormulaContent.tsx","../src/components/MathGraph/MathGraphErrorBoundary.tsx","../src/components/MathGraph/utils/transformUtils.ts","../src/components/MathGraph/GraphContainer.tsx","../src/components/MathGraph/utils/boundingBoxCalculator.ts","../src/components/MathGraph/utils/debugBoundingBox.ts","../src/components/MathGraph/MathGraph.tsx","../src/components/MathCardV2/components/content/GraphContent.tsx","../src/components/MathCardV2/components/content/GeometryTransformContent.tsx","../src/components/MathCardV2/components/content/PlaceValueChart.tsx","../src/components/MathCardV2/components/renderers/ContentRenderer.tsx","../src/components/MathCardV2/MathCardV2.tsx","../src/components/IXLStyleCard/hooks/useIXLStyle.ts","../src/components/IXLStyleCard/hooks/useResponsive.ts","../src/components/IXLStyleCard/IXLStyleCard.tsx","../src/components/IXLStyleCard/IXLStyleCard.types.ts","../src/components/GradeNavigation.tsx","../src/components/radarAbility/RadarChart/RadarChart.tsx","../src/services/radarAbilityService.ts","../src/store/radarAbilityStore.ts","../src/components/radarAbility/AbilityProgressBar/AbilityProgressBar.tsx","../src/components/radarAbility/PersonalizedAdvicePanel/PersonalizedAdvicePanel.tsx","../src/components/radarAbility/RecommendationCard/RecommendationCard.tsx","../src/components/radarAbility/AbilityAssessmentDashboard/AbilityAssessmentDashboard.tsx","../src/types/index.ts","../src/data/mockData.ts","../src/data/courseData.ts","../src/services/courseService.ts","../src/data-sources/types.ts","../src/data-sources/api-data-source.ts","../src/data-sources/mock-data-source.ts","../src/data-sources/factory.ts","../src/config/utils.ts","../src/pages/GradeUnitBrowserPage/GradeUnitBrowserContext.tsx","../src/pages/GradeUnitBrowserPage/GradeUnitBrowserPage.tsx","../src/components/MathCardV2/MathPracticeSessionStore.ts","../src/components/MathCardV2/MathPracticeStoreContext.tsx","../src/components/MathCardV2/MathPracticeStoreHooks.ts","../src/components/MathCardV2/scenes/QuestionScene/QuestionScene.tsx","../src/components/MathCardV2/modules/RememberModule/RememberModule.tsx","../src/components/MathCardV2/modules/ReviewModule/ReviewModule.tsx","../src/components/MathCardV2/ExplanationStep.tsx","../src/components/MathCardV2/MathPracticeSessionTypes.ts","../src/components/MathCardV2/modules/SolveModule/SolveModule.tsx","../src/components/MathCardV2/scenes/ExplanationScene/ExplanationScene.tsx","../src/components/MathCardV2/scenes/SuccessScene/SuccessScene.tsx","../src/data/GeometryProblemAdapterV4/geometry-types.ts","../src/data/GeometryProblemAdapterV4/types.ts","../src/data/TriangleAdapterV3/types.ts","../src/data/TriangleAdapterV3/constants.ts","../src/data/TriangleAdapterV3/config/embeddedConfigs.ts","../src/data/TriangleAdapterV3/config/index.ts","../src/data/TriangleAdapterV3/resolvers/designTokenResolver.ts","../src/data/TriangleAdapterV3/resolvers/geometryRefResolver.ts","../src/data/TriangleAdapterV3/resolvers/transformRefResolver.ts","../src/data/TriangleAdapterV3/resolvers/styleRefResolver.ts","../src/data/TriangleAdapterV3/resolvers/layoutRefResolver.ts","../src/data/TriangleAdapterV3/resolvers/animationRefResolver.ts","../src/data/TriangleAdapterV3/resolvers/sliderRefResolver.ts","../src/data/TriangleAdapterV3/resolvers/geometryTransformRefResolver.ts","../src/data/TriangleAdapterV3/resolvers/referenceExtractor.ts","../src/data/TriangleAdapterV3/resolvers/index.ts","../src/data/TriangleAdapterV3/transformers/graphTransformer.ts","../src/data/TriangleAdapterV3/transformers/geometryTransformTransformer.ts","../src/data/TriangleAdapterV3/transformers/textTransformer.ts","../src/data/TriangleAdapterV3/transformers/index.ts","../src/data/TriangleAdapterV3/validators/inputValidator.ts","../src/data/TriangleAdapterV3/validators/outputValidator.ts","../src/data/TriangleAdapterV3/validators/index.ts","../src/data/TriangleAdapterV3/utils/referenceUtils.ts","../src/data/TriangleAdapterV3/utils/performanceUtils.ts","../src/data/TriangleAdapterV3/utils/index.ts","../src/data/TriangleAdapterV3/core/syncAdapter.ts","../src/data/GeometryProblemAdapterV4/GeometryAdapterCore.ts","../src/data/GeometryProblemAdapterV4/index.ts","../src/pages/AreaGeometrySessionPage/data/config/types.ts","../src/pages/AreaGeometrySessionPage/data/config/configValidation.ts","../src/pages/AreaGeometrySessionPage/data/config/parallelogramConfigGenerator.ts","../src/pages/AreaGeometrySessionPage/data/adapters/adapterUtils.ts","../src/pages/AreaGeometrySessionPage/data/adapters/parallelogramDefaults.ts","../src/pages/AreaGeometrySessionPage/data/adapters/parallelogramDataAdapter.ts","../src/pages/AreaGeometrySessionPage/data/index.ts","../src/pages/AreaCalculationSessionPage/ParallelogramAreaCalculationSessionPage.tsx","../src/pages/AreaCalculationSessionPage/TriangleAreaCalculationSessionPage/TriangleAreaCalculationSessionPage.tsx","../src/components/MathCard/context.ts","../src/components/MathCard/utils/templateParser.ts","../src/components/MathCard/utils/contentRenderer.ts","../src/components/MathCard/MathCard.tsx","../node_modules/@emotion/sheet/dist/emotion-sheet.esm.js","../node_modules/stylis/src/Enum.js","../node_modules/stylis/src/Utility.js","../node_modules/stylis/src/Tokenizer.js","../node_modules/stylis/src/Parser.js","../node_modules/stylis/src/Serializer.js","../node_modules/stylis/src/Middleware.js","../node_modules/@emotion/memoize/dist/emotion-memoize.esm.js","../node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js","../node_modules/react-is/cjs/react-is.production.min.js","../node_modules/react-is/cjs/react-is.development.js","../node_modules/react-is/index.js","../node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js","../node_modules/@emotion/utils/dist/emotion-utils.browser.esm.js","../node_modules/@emotion/hash/dist/emotion-hash.esm.js","../node_modules/@emotion/unitless/dist/emotion-unitless.esm.js","../node_modules/@emotion/serialize/dist/emotion-serialize.esm.js","../node_modules/@emotion/use-insertion-effect-with-fallbacks/dist/emotion-use-insertion-effect-with-fallbacks.browser.esm.js","../node_modules/@emotion/react/dist/emotion-element-f0de968e.browser.esm.js","../node_modules/@emotion/react/dist/emotion-react.browser.esm.js","../src/components/MathCard/styles.ts","../src/stores/mathSessionStore.ts","../src/components/MathSessionContainer/hooks/useSessionCalculations.ts","../src/components/MathSessionContainer/hooks/useGeometryManagement.ts","../src/components/MathSessionContainer/hooks/useSessionEventHandlers.ts","../src/components/MathSessionContainer/MathSessionContainer.tsx","../src/pages/MathSessionPage/MathSessionPage.tsx","../src/components/MathCardV2/scenes/DecimalNumberExplanationScene/DecimalNumberExplanationScene.tsx","../src/components/MathCardV2/MathPracticeSessionPage.tsx","../src/components/MathCardV2/DecimalNumberRecognitionSessionStore.ts","../src/components/MathCardV2/data/decimalNumberRecognitionData.ts","../src/components/MathCardV2/DecimalNumberRecognitionSessionPage.tsx","../src/utils/geometryCore.js","../src/data/userCourseProgress.ts","../src/data/usergradeuintsnav.ts","../src/data/usergradeunitsProgressData.ts","../src/pages/AreaGeometrySessionPage/AreaGeometrySessionPage.tsx","../src/index.ts"],"sourcesContent":["/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\"production\" !== process.env.NODE_ENV &&\n (function () {\n function getComponentNameFromType(type) {\n if (null == type) return null;\n if (\"function\" === typeof type)\n return type.$$typeof === REACT_CLIENT_REFERENCE\n ? null\n : type.displayName || type.name || null;\n if (\"string\" === typeof type) return type;\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return \"Fragment\";\n case REACT_PROFILER_TYPE:\n return \"Profiler\";\n case REACT_STRICT_MODE_TYPE:\n return \"StrictMode\";\n case REACT_SUSPENSE_TYPE:\n return \"Suspense\";\n case REACT_SUSPENSE_LIST_TYPE:\n return \"SuspenseList\";\n case REACT_ACTIVITY_TYPE:\n return \"Activity\";\n }\n if (\"object\" === typeof type)\n switch (\n (\"number\" === typeof type.tag &&\n console.error(\n \"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.\"\n ),\n type.$$typeof)\n ) {\n case REACT_PORTAL_TYPE:\n return \"Portal\";\n case REACT_CONTEXT_TYPE:\n return type.displayName || \"Context\";\n case REACT_CONSUMER_TYPE:\n return (type._context.displayName || \"Context\") + \".Consumer\";\n case REACT_FORWARD_REF_TYPE:\n var innerType = type.render;\n type = type.displayName;\n type ||\n ((type = innerType.displayName || innerType.name || \"\"),\n (type = \"\" !== type ? \"ForwardRef(\" + type + \")\" : \"ForwardRef\"));\n return type;\n case REACT_MEMO_TYPE:\n return (\n (innerType = type.displayName || null),\n null !== innerType\n ? innerType\n : getComponentNameFromType(type.type) || \"Memo\"\n );\n case REACT_LAZY_TYPE:\n innerType = type._payload;\n type = type._init;\n try {\n return getComponentNameFromType(type(innerType));\n } catch (x) {}\n }\n return null;\n }\n function testStringCoercion(value) {\n return \"\" + value;\n }\n function checkKeyStringCoercion(value) {\n try {\n testStringCoercion(value);\n var JSCompiler_inline_result = !1;\n } catch (e) {\n JSCompiler_inline_result = !0;\n }\n if (JSCompiler_inline_result) {\n JSCompiler_inline_result = console;\n var JSCompiler_temp_const = JSCompiler_inline_result.error;\n var JSCompiler_inline_result$jscomp$0 =\n (\"function\" === typeof Symbol &&\n Symbol.toStringTag &&\n value[Symbol.toStringTag]) ||\n value.constructor.name ||\n \"Object\";\n JSCompiler_temp_const.call(\n JSCompiler_inline_result,\n \"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.\",\n JSCompiler_inline_result$jscomp$0\n );\n return testStringCoercion(value);\n }\n }\n function getTaskName(type) {\n if (type === REACT_FRAGMENT_TYPE) return \"<>\";\n if (\n \"object\" === typeof type &&\n null !== type &&\n type.$$typeof === REACT_LAZY_TYPE\n )\n return \"<...>\";\n try {\n var name = getComponentNameFromType(type);\n return name ? \"<\" + name + \">\" : \"<...>\";\n } catch (x) {\n return \"<...>\";\n }\n }\n function getOwner() {\n var dispatcher = ReactSharedInternals.A;\n return null === dispatcher ? null : dispatcher.getOwner();\n }\n function UnknownOwner() {\n return Error(\"react-stack-top-frame\");\n }\n function hasValidKey(config) {\n if (hasOwnProperty.call(config, \"key\")) {\n var getter = Object.getOwnPropertyDescriptor(config, \"key\").get;\n if (getter && getter.isReactWarning) return !1;\n }\n return void 0 !== config.key;\n }\n function defineKeyPropWarningGetter(props, displayName) {\n function warnAboutAccessingKey() {\n specialPropKeyWarningShown ||\n ((specialPropKeyWarningShown = !0),\n console.error(\n \"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)\",\n displayName\n ));\n }\n warnAboutAccessingKey.isReactWarning = !0;\n Object.defineProperty(props, \"key\", {\n get: warnAboutAccessingKey,\n configurable: !0\n });\n }\n function elementRefGetterWithDeprecationWarning() {\n var componentName = getComponentNameFromType(this.type);\n didWarnAboutElementRef[componentName] ||\n ((didWarnAboutElementRef[componentName] = !0),\n console.error(\n \"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.\"\n ));\n componentName = this.props.ref;\n return void 0 !== componentName ? componentName : null;\n }\n function ReactElement(type, key, props, owner, debugStack, debugTask) {\n var refProp = props.ref;\n type = {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n props: props,\n _owner: owner\n };\n null !== (void 0 !== refProp ? refProp : null)\n ? Object.defineProperty(type, \"ref\", {\n enumerable: !1,\n get: elementRefGetterWithDeprecationWarning\n })\n : Object.defineProperty(type, \"ref\", { enumerable: !1, value: null });\n type._store = {};\n Object.defineProperty(type._store, \"validated\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: 0\n });\n Object.defineProperty(type, \"_debugInfo\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: null\n });\n Object.defineProperty(type, \"_debugStack\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugStack\n });\n Object.defineProperty(type, \"_debugTask\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugTask\n });\n Object.freeze && (Object.freeze(type.props), Object.freeze(type));\n return type;\n }\n function jsxDEVImpl(\n type,\n config,\n maybeKey,\n isStaticChildren,\n debugStack,\n debugTask\n ) {\n var children = config.children;\n if (void 0 !== children)\n if (isStaticChildren)\n if (isArrayImpl(children)) {\n for (\n isStaticChildren = 0;\n isStaticChildren < children.length;\n isStaticChildren++\n )\n validateChildKeys(children[isStaticChildren]);\n Object.freeze && Object.freeze(children);\n } else\n console.error(\n \"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.\"\n );\n else validateChildKeys(children);\n if (hasOwnProperty.call(config, \"key\")) {\n children = getComponentNameFromType(type);\n var keys = Object.keys(config).filter(function (k) {\n return \"key\" !== k;\n });\n isStaticChildren =\n 0 < keys.length\n ? \"{key: someKey, \" + keys.join(\": ..., \") + \": ...}\"\n : \"{key: someKey}\";\n didWarnAboutKeySpread[children + isStaticChildren] ||\n ((keys =\n 0 < keys.length ? \"{\" + keys.join(\": ..., \") + \": ...}\" : \"{}\"),\n console.error(\n 'A props object containing a \"key\" prop is being spread into JSX:\\n let props = %s;\\n <%s {...props} />\\nReact keys must be passed directly to JSX without using spread:\\n let props = %s;\\n <%s key={someKey} {...props} />',\n isStaticChildren,\n children,\n keys,\n children\n ),\n (didWarnAboutKeySpread[children + isStaticChildren] = !0));\n }\n children = null;\n void 0 !== maybeKey &&\n (checkKeyStringCoercion(maybeKey), (children = \"\" + maybeKey));\n hasValidKey(config) &&\n (checkKeyStringCoercion(config.key), (children = \"\" + config.key));\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n children &&\n defineKeyPropWarningGetter(\n maybeKey,\n \"function\" === typeof type\n ? type.displayName || type.name || \"Unknown\"\n : type\n );\n return ReactElement(\n type,\n children,\n maybeKey,\n getOwner(),\n debugStack,\n debugTask\n );\n }\n function validateChildKeys(node) {\n isValidElement(node)\n ? node._store && (node._store.validated = 1)\n : \"object\" === typeof node &&\n null !== node &&\n node.$$typeof === REACT_LAZY_TYPE &&\n (\"fulfilled\" === node._payload.status\n ? isValidElement(node._payload.value) &&\n node._payload.value._store &&\n (node._payload.value._store.validated = 1)\n : node._store && (node._store.validated = 1));\n }\n function isValidElement(object) {\n return (\n \"object\" === typeof object &&\n null !== object &&\n object.$$typeof === REACT_ELEMENT_TYPE\n );\n }\n var React = require(\"react\"),\n REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\"),\n REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_SUSPENSE_LIST_TYPE = Symbol.for(\"react.suspense_list\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\"),\n REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\"),\n REACT_CLIENT_REFERENCE = Symbol.for(\"react.client.reference\"),\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n hasOwnProperty = Object.prototype.hasOwnProperty,\n isArrayImpl = Array.isArray,\n createTask = console.createTask\n ? console.createTask\n : function () {\n return null;\n };\n React = {\n react_stack_bottom_frame: function (callStackForError) {\n return callStackForError();\n }\n };\n var specialPropKeyWarningShown;\n var didWarnAboutElementRef = {};\n var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(\n React,\n UnknownOwner\n )();\n var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));\n var didWarnAboutKeySpread = {};\n exports.Fragment = REACT_FRAGMENT_TYPE;\n exports.jsx = function (type, config, maybeKey) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !1,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n exports.jsxs = function (type, config, maybeKey) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !0,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n })();\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import React from 'react';\r\nimport './Button.css';\r\nimport type { ButtonProps } from './types';\r\n\r\nexport const Button: React.FC<ButtonProps> = ({\r\n progress,\r\n variant = 'solid',\r\n size = 'md',\r\n radius = 'md',\r\n children,\r\n className = '',\r\n loading,\r\n ...props\r\n}) => {\r\n // Determine color based on progress\r\n const getColorClass = (progress: number): string => {\r\n if (progress === 0) return 'button--primary';\r\n if (progress === 100) return 'button--success';\r\n return 'button--secondary';\r\n };\r\n\r\n const colorClass = progress !== undefined ? getColorClass(progress) : 'button--primary';\r\n\r\n const buttonClasses = [\r\n 'button',\r\n `button--${size}`,\r\n `button--${variant}`,\r\n `button--radius-${radius}`,\r\n colorClass,\r\n loading && 'button--loading',\r\n className\r\n ].filter(Boolean).join(' ');\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n className={buttonClasses}\r\n data-progress={progress}\r\n disabled={loading || props.disabled}\r\n {...props}\r\n >\r\n {loading ? '加载中...' : children}\r\n </button>\r\n );\r\n};","// 内容手风琴组件类型定义\r\nimport type { KnowledgeItem, Lesson, Unit } from '../../types';\r\n\r\nexport interface ContentAccordionProps {\r\n /** 当前学习单元数据 */\r\n unit: Unit | null;\r\n /** 激活的课程ID列表 */\r\n activeLessonIds: string[];\r\n /** 切换课程激活状态的函数 */\r\n onToggleLesson: (lessonId: string) => void;\r\n /** 点击学习按钮的回调 */\r\n onLearnAction: (knowledgeItem: KnowledgeItem) => void;\r\n /** 加载状态 */\r\n loading?: boolean;\r\n /** 自定义类名 */\r\n className?: string;\r\n /** 空状态显示内容 */\r\n emptyState?: React.ReactNode;\r\n}\r\n\r\nexport interface ContentAccordionState {\r\n /** 内部展开状态管理 */\r\n expandedLessons: Set<string>;\r\n /** 动画状态 */\r\n isAnimating: boolean;\r\n}\r\n\r\nexport interface LessonItemProps {\r\n /** 课程数据 */\r\n lesson: Lesson;\r\n /** 是否展开状态 */\r\n isExpanded: boolean;\r\n /** 切换展开状态回调 */\r\n onToggle: (lessonId: string) => void;\r\n /** 学习按钮点击回调 */\r\n onLearnAction: (knowledgeItem: KnowledgeItem) => void;\r\n}\r\n\r\nexport interface KnowledgeCardProps {\r\n /** 知识点数据 */\r\n knowledgeItem: KnowledgeItem;\r\n /** 学习按钮点击回调 */\r\n onLearnAction: (knowledgeItem: KnowledgeItem) => void;\r\n}\r\n\r\n// 工具函数类型\r\nexport type GetButtonTextFn = (progress: number) => string;\r\nexport type CalculateLessonProgressFn = (knowledgeItems: KnowledgeItem[]) => number;\r\n\r\n// 进度按钮文本生成算法\r\nexport const getButtonText: GetButtonTextFn = (progress: number): string => {\r\n if (progress === 0) return '开始学习';\r\n if (progress === 100) return '复习';\r\n return '继续学习';\r\n};\r\n\r\n// 课程进度计算算法\r\nexport const calculateLessonProgress: CalculateLessonProgressFn = (knowledgeItems: KnowledgeItem[]): number => {\r\n if (knowledgeItems.length === 0) return 0;\r\n const totalProgress = knowledgeItems.reduce((sum, item) => sum + item.progress, 0);\r\n return Math.round(totalProgress / knowledgeItems.length);\r\n};","import React from 'react';\r\nimport { Progress } from '@heroui/progress';\r\nimport { Card, CardBody, CardFooter } from '@heroui/card';\r\nimport { Button } from '../Button';\r\nimport { ChevronDown, ChevronRight } from 'lucide-react';\r\nimport type { ContentAccordionProps, LessonItemProps, KnowledgeCardProps } from './types';\r\nimport { getButtonText, calculateLessonProgress } from './types';\r\nimport './ContentAccordion.css';\r\n\r\nconst KnowledgeCard: React.FC<KnowledgeCardProps> = ({ knowledgeItem, onLearnAction }) => {\r\n const handleLearnClick = () => {\r\n onLearnAction(knowledgeItem);\r\n };\r\n\r\n // 调试信息\r\n console.log('KnowledgeCard render:', {\r\n progress: knowledgeItem.progress,\r\n text: getButtonText(knowledgeItem.progress)\r\n });\r\n\r\n return (\r\n <Card className=\"content-accordion__knowledge-card\">\r\n <CardBody>\r\n <h3 className=\"content-accordion__knowledge-title\">{knowledgeItem.title}</h3>\r\n <p className=\"content-accordion__knowledge-description\">{knowledgeItem.description}</p>\r\n </CardBody>\r\n <CardFooter className=\"content-accordion__knowledge-actions\">\r\n <div className=\"content-accordion__progress-container\">\r\n <Progress\r\n value={knowledgeItem.progress}\r\n size=\"sm\"\r\n color=\"primary\"\r\n aria-label={`${knowledgeItem.title} 进度`}\r\n className=\"content-accordion__progress-bar\"\r\n />\r\n <span className=\"content-accordion__progress-text\">{knowledgeItem.progress}%</span>\r\n </div>\r\n <Button\r\n size=\"sm\"\r\n radius=\"md\"\r\n onClick={handleLearnClick}\r\n progress={knowledgeItem.progress}\r\n variant={knowledgeItem.progress === 100 ? 'light' : knowledgeItem.progress === 0 ? 'solid' : 'bordered'}\r\n className=\"content-accordion__learn-button\"\r\n >\r\n {getButtonText(knowledgeItem.progress)}\r\n </Button>\r\n </CardFooter>\r\n </Card>\r\n );\r\n};\r\n\r\nconst LessonItem: React.FC<LessonItemProps> = ({ lesson, isExpanded, onToggle, onLearnAction }) => {\r\n const handleToggle = () => {\r\n onToggle(lesson.id);\r\n };\r\n\r\n const lessonProgress = calculateLessonProgress(lesson.knowledgeItems);\r\n\r\n return (\r\n <div className={`content-accordion__lesson-item ${isExpanded ? 'content-accordion__lesson-item--expanded' : ''}`}>\r\n <div\r\n className=\"content-accordion__lesson-header\"\r\n onClick={handleToggle}\r\n role=\"button\"\r\n tabIndex={0}\r\n aria-expanded={isExpanded}\r\n aria-label={`${lesson.title},点击${isExpanded ? '收起' : '展开'}`}\r\n >\r\n <div className=\"content-accordion__lesson-header-content\">\r\n <h2 className=\"content-accordion__lesson-title\">{lesson.title}</h2>\r\n <span className=\"content-accordion__lesson-duration\">约 {lesson.duration} 分钟</span>\r\n </div>\r\n <div className=\"content-accordion__lesson-actions\">\r\n <span className=\"content-accordion__lesson-progress\">{lessonProgress}%</span>\r\n {isExpanded ? (\r\n <ChevronDown className=\"content-accordion__lesson-icon\" />\r\n ) : (\r\n <ChevronRight className=\"content-accordion__lesson-icon\" />\r\n )}\r\n </div>\r\n </div>\r\n\r\n {isExpanded && (\r\n <div className=\"content-accordion__knowledge-list\">\r\n {lesson.knowledgeItems.map((item) => (\r\n <KnowledgeCard\r\n key={item.id}\r\n knowledgeItem={item}\r\n onLearnAction={onLearnAction}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport const ContentAccordion: React.FC<ContentAccordionProps> = ({\r\n unit,\r\n activeLessonIds,\r\n onToggleLesson,\r\n onLearnAction,\r\n loading = false,\r\n className = '',\r\n emptyState\r\n}) => {\r\n if (loading) {\r\n return (\r\n <div className=\"content-accordion content-accordion--loading\">\r\n <div className=\"content-accordion__loading\">加载中...</div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!unit) {\r\n return (\r\n <div className=\"content-accordion content-accordion--empty\">\r\n {emptyState || <div className=\"content-accordion__empty\">暂无学习内容</div>}\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={`content-accordion ${className}`}>\r\n {/* 单元头部信息 */}\r\n <header className=\"content-accordion__header\">\r\n <h1 className=\"content-accordion__unit-title\">{unit.title}</h1>\r\n <p className=\"content-accordion__unit-description\">{unit.description}</p>\r\n <div className=\"content-accordion__unit-meta\">\r\n <span>总共 {unit.totalLessons} 节课</span>\r\n <span>•</span>\r\n <span>预计学习 {unit.estimatedDuration}</span>\r\n </div>\r\n </header>\r\n\r\n {/* 课程列表 */}\r\n <div className=\"content-accordion__lessons\">\r\n {unit.lessons.map((lesson) => (\r\n <LessonItem\r\n key={lesson.id}\r\n lesson={lesson}\r\n isExpanded={activeLessonIds.includes(lesson.id)}\r\n onToggle={onToggleLesson}\r\n onLearnAction={onLearnAction}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n};","// Sidebar 组件类型定义\r\n\r\nexport interface UnitProgressData {\r\n unitId: string;\r\n title: string;\r\n description: string;\r\n moduleCategory: string;\r\n estimatedDuration: string;\r\n totalLessons: number;\r\n completedLessons: number;\r\n progressPercentage: number;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n lastAccessed?: string;\r\n isActive: boolean;\r\n route: string;\r\n icon?: string;\r\n}\r\n\r\nexport interface UserGradeUnitsProgressData {\r\n userId: string;\r\n courseId: string;\r\n courseTitle: string;\r\n courseLevel: number;\r\n totalUnits: number;\r\n completedUnits: number;\r\n overallProgress: number;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n lastAccessed?: string;\r\n units: UnitProgressData[];\r\n}\r\n\r\nexport interface SidebarProps {\r\n // 核心数据 - 用户年级单元进度数据\r\n data: UserGradeUnitsProgressData | null;\r\n\r\n // 状态控制\r\n loading?: boolean;\r\n error?: Error | null;\r\n collapsed?: boolean;\r\n\r\n // 交互回调\r\n onToggleCollapse?: () => void;\r\n activeUnitId?: string | null;\r\n onUnitSelect?: (unitId: string) => void;\r\n\r\n // 自定义渲染\r\n renderUnitItem?: (unit: UnitProgressData, progress?: UnitProgressData) => React.ReactNode;\r\n\r\n // 样式配置\r\n className?: string;\r\n unitItemClassName?: string;\r\n style?: React.CSSProperties;\r\n unitItemStyle?: React.CSSProperties;\r\n}\r\n\r\n// 进度状态颜色映射\r\nexport const getProgressColor = (status: UnitProgressData['status']): 'success' | 'primary' | 'default' => {\r\n switch (status) {\r\n case 'completed':\r\n return 'success';\r\n case 'in-progress':\r\n return 'primary';\r\n case 'not-started':\r\n default:\r\n return 'default';\r\n }\r\n};","import React from 'react';\r\nimport { Progress } from '@heroui/react';\r\nimport type { SidebarProps, UnitProgressData } from './types';\r\nimport { getProgressColor } from './types';\r\nimport './Sidebar.css';\r\n\r\nexport const Sidebar: React.FC<SidebarProps> = ({\r\n data,\r\n loading = false,\r\n error = null,\r\n collapsed = false,\r\n onToggleCollapse,\r\n activeUnitId = null,\r\n onUnitSelect,\r\n renderUnitItem,\r\n className = '',\r\n unitItemClassName = '',\r\n style = {},\r\n unitItemStyle = {},\r\n}) => {\r\n const handleUnitSelect = (unitId: string, event: React.MouseEvent) => {\r\n event.preventDefault();\r\n onUnitSelect?.(unitId);\r\n };\r\n\r\n const handleToggleCollapse = () => {\r\n onToggleCollapse?.();\r\n };\r\n\r\n // 渲染默认单元项\r\n const renderDefaultUnitItem = (unit: UnitProgressData) => (\r\n <div\r\n key={unit.unitId}\r\n className={`sidebar__unit-item ${unitItemClassName} ${\r\n activeUnitId === unit.unitId ? 'sidebar__unit-item--active' : ''\r\n } ${unit.status ? `sidebar__unit-item--${unit.status}` : ''}`}\r\n style={unitItemStyle}\r\n onClick={(e) => handleUnitSelect(unit.unitId, e)}\r\n role=\"button\"\r\n tabIndex={0}\r\n aria-label={`${unit.title},进度 ${unit.progressPercentage}%`}\r\n >\r\n <div className=\"sidebar__unit-item__content\">\r\n {unit.icon && (\r\n <span className=\"sidebar__unit-item__icon\">{unit.icon}</span>\r\n )}\r\n {!collapsed && (\r\n <span className=\"sidebar__unit-item__title\">{unit.title}</span>\r\n )}\r\n </div>\r\n\r\n {!collapsed && unit.progressPercentage !== undefined && (\r\n <div className=\"sidebar__unit-item__progress\">\r\n <Progress\r\n value={unit.progressPercentage}\r\n size=\"sm\"\r\n color={getProgressColor(unit.status)}\r\n aria-label={`${unit.title} 进度`}\r\n />\r\n <span className=\"progress-percentage\">\r\n {unit.progressPercentage}%\r\n </span>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n\r\n // 渲染状态内容\r\n const renderContent = () => {\r\n if (loading) {\r\n return (\r\n <div className=\"sidebar__loading\">\r\n 加载中...\r\n </div>\r\n );\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div className=\"sidebar__error\">\r\n 加载失败: {error.message}\r\n </div>\r\n );\r\n }\r\n\r\n if (!data) {\r\n return (\r\n <div className=\"sidebar__empty\">\r\n 暂无课程数据\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <>\r\n <div className=\"sidebar__header\">\r\n <button\r\n className=\"sidebar__toggle-btn\"\r\n onClick={handleToggleCollapse}\r\n aria-label=\"切换侧边栏折叠状态\"\r\n >\r\n {collapsed ? '→' : '←'}\r\n </button>\r\n {!collapsed && (\r\n <div className=\"sidebar__course-info\">\r\n <h3 className=\"sidebar__course-title\">{data.courseTitle}</h3>\r\n <span className=\"sidebar__course-level\">{data.courseLevel}年级</span>\r\n </div>\r\n )}\r\n </div>\r\n\r\n <nav className=\"sidebar__content\">\r\n <ul className=\"sidebar__unit-list\">\r\n {data.units && data.units.length > 0 ? (\r\n data.units.map((unit) => (\r\n <li key={unit.unitId}>\r\n {renderUnitItem\r\n ? renderUnitItem(unit, unit)\r\n : renderDefaultUnitItem(unit)}\r\n </li>\r\n ))\r\n ) : (\r\n <div className=\"sidebar__empty\">\r\n 暂无单元数据\r\n </div>\r\n )}\r\n </ul>\r\n </nav>\r\n </>\r\n );\r\n };\r\n\r\n return (\r\n <aside\r\n className={`sidebar ${className} ${collapsed ? 'sidebar--collapsed' : ''} ${\r\n loading ? 'sidebar--loading' : ''\r\n } ${error ? 'sidebar--error' : ''}`}\r\n style={style}\r\n aria-label=\"课程导航侧边栏\"\r\n role=\"complementary\"\r\n >\r\n {renderContent()}\r\n </aside>\r\n );\r\n};","import React from 'react'\r\nimport './Submenu.css'\r\n\r\nexport interface SubmenuItem {\r\n id: string | number\r\n label?: React.ReactNode\r\n value?: unknown\r\n icon?: React.ReactNode\r\n disabled?: boolean\r\n onClick?: (item: SubmenuItem) => void\r\n [key: string]: unknown\r\n}\r\n\r\nexport interface SubmenuProps {\r\n trigger: React.ReactNode\r\n items: SubmenuItem[]\r\n position?: 'top' | 'bottom' | 'left' | 'right' | 'auto'\r\n alignment?: 'start' | 'center' | 'end'\r\n openDelay?: number\r\n closeDelay?: number\r\n onOpen?: () => void\r\n onClose?: () => void\r\n renderItem?: (item: SubmenuItem, config: TItemConfig) => React.ReactNode\r\n itemConfig?: TItemConfig\r\n className?: string\r\n menuClassName?: string\r\n itemClassName?: string\r\n activeItemClassName?: string\r\n}\r\n\r\ntype TItemConfig = {\r\n currentUserRole?: 'guest' | 'student' | 'teacher' | 'admin'\r\n theme?: 'light' | 'dark'\r\n [key: string]: unknown\r\n}\r\n\r\nconst Submenu: React.FC<SubmenuProps> = ({\r\n trigger,\r\n items,\r\n position = 'bottom',\r\n alignment = 'start',\r\n openDelay = 300,\r\n closeDelay = 100,\r\n onOpen,\r\n onClose,\r\n renderItem,\r\n itemConfig = {},\r\n className,\r\n menuClassName,\r\n itemClassName,\r\n // activeItemClassName is available for custom styling but not used in default implementation\r\n}) => {\r\n const [isOpen, setIsOpen] = React.useState(false)\r\n const openTimeoutRef = React.useRef<NodeJS.Timeout | null>(null)\r\n const closeTimeoutRef = React.useRef<NodeJS.Timeout | null>(null)\r\n\r\n const clearTimeouts = () => {\r\n if (openTimeoutRef.current) {\r\n clearTimeout(openTimeoutRef.current)\r\n }\r\n if (closeTimeoutRef.current) {\r\n clearTimeout(closeTimeoutRef.current)\r\n }\r\n }\r\n\r\n const handleMouseEnter = () => {\r\n clearTimeouts()\r\n openTimeoutRef.current = setTimeout(() => {\r\n setIsOpen(true)\r\n onOpen?.()\r\n }, openDelay)\r\n }\r\n\r\n const handleMouseLeave = () => {\r\n clearTimeouts()\r\n closeTimeoutRef.current = setTimeout(() => {\r\n setIsOpen(false)\r\n onClose?.()\r\n }, closeDelay)\r\n }\r\n\r\n const handleItemClick = (item: SubmenuItem) => {\r\n if (!item.disabled && item.onClick) {\r\n item.onClick(item)\r\n }\r\n }\r\n\r\n React.useEffect(() => {\r\n return () => clearTimeouts()\r\n }, [])\r\n\r\n const defaultRenderItem = (item: SubmenuItem) => (\r\n <div\r\n key={item.id}\r\n className={`submenu-item ${item.disabled ? 'is-disabled' : ''} ${itemClassName || ''}`}\r\n onClick={() => handleItemClick(item)}\r\n >\r\n {item.icon && <span className=\"submenu-item-icon\">{item.icon}</span>}\r\n <span>{item.label}</span>\r\n </div>\r\n )\r\n\r\n const getPanelClasses = () => {\r\n const classes = ['submenu-panel']\r\n \r\n if (menuClassName) {\r\n classes.push(menuClassName)\r\n }\r\n \r\n // Add position class\r\n classes.push(`position-${position}`)\r\n \r\n // Add alignment class if not 'start' (default)\r\n if (alignment !== 'start') {\r\n classes.push(`alignment-${alignment}`)\r\n }\r\n \r\n // Add open state class\r\n if (isOpen) {\r\n classes.push('is-open')\r\n }\r\n \r\n return classes.join(' ')\r\n }\r\n\r\n return (\r\n <div \r\n className={`submenu-container ${className || ''}`}\r\n onMouseEnter={handleMouseEnter}\r\n onMouseLeave={handleMouseLeave}\r\n >\r\n <div className=\"submenu-trigger\">\r\n {trigger}\r\n </div>\r\n \r\n <div className={getPanelClasses()}>\r\n {items.map(item => \r\n renderItem \r\n ? renderItem(item, itemConfig)\r\n : defaultRenderItem(item)\r\n )}\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport default Submenu","'use strict';\n\n/**\n * Create a bound version of a function with a specified `this` context\n *\n * @param {Function} fn - The function to bind\n * @param {*} thisArg - The value to be passed as the `this` parameter\n * @returns {Function} A new function that will call the original function with the specified `this` context\n */\nexport default function bind(fn, thisArg) {\n return function wrap() {\n return fn.apply(thisArg, arguments);\n };\n}\n","\"use strict\";\n\nimport bind from \"./helpers/bind.js\";\n\n// utils is a library of generic helper functions non-specific to axios\n\nconst { toString } = Object.prototype;\nconst { getPrototypeOf } = Object;\nconst { iterator, toStringTag } = Symbol;\n\nconst kindOf = ((cache) => (thing) => {\n const str = toString.call(thing);\n return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());\n})(Object.create(null));\n\nconst kindOfTest = (type) => {\n type = type.toLowerCase();\n return (thing) => kindOf(thing) === type;\n};\n\nconst typeOfTest = (type) => (thing) => typeof thing === type;\n\n/**\n * Determine if a value is a non-null object\n *\n * @param {Object} val The value to test\n *\n * @returns {boolean} True if value is an Array, otherwise false\n */\nconst { isArray } = Array;\n\n/**\n * Determine if a value is undefined\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if the value is undefined, otherwise false\n */\nconst isUndefined = typeOfTest(\"undefined\");\n\n/**\n * Determine if a value is a Buffer\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a Buffer, otherwise false\n */\nfunction isBuffer(val) {\n return (\n val !== null &&\n !isUndefined(val) &&\n val.constructor !== null &&\n !isUndefined(val.constructor) &&\n isFunction(val.constructor.isBuffer) &&\n val.constructor.isBuffer(val)\n );\n}\n\n/**\n * Determine if a value is an ArrayBuffer\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is an ArrayBuffer, otherwise false\n */\nconst isArrayBuffer = kindOfTest(\"ArrayBuffer\");\n\n/**\n * Determine if a value is a view on an ArrayBuffer\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false\n */\nfunction isArrayBufferView(val) {\n let result;\n if (typeof ArrayBuffer !== \"undefined\" && ArrayBuffer.isView) {\n result = ArrayBuffer.isView(val);\n } else {\n result = val && val.buffer && isArrayBuffer(val.buffer);\n }\n return result;\n}\n\n/**\n * Determine if a value is a String\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a String, otherwise false\n */\nconst isString = typeOfTest(\"string\");\n\n/**\n * Determine if a value is a Function\n *\n * @param {*} val The value to test\n * @returns {boolean} True if value is a Function, otherwise false\n */\nconst isFunction = typeOfTest(\"function\");\n\n/**\n * Determine if a value is a Number\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a Number, otherwise false\n */\nconst isNumber = typeOfTest(\"number\");\n\n/**\n * Determine if a value is an Object\n *\n * @param {*} thing The value to test\n *\n * @returns {boolean} True if value is an Object, otherwise false\n */\nconst isObject = (thing) => thing !== null && typeof thing === \"object\";\n\n/**\n * Determine if a value is a Boolean\n *\n * @param {*} thing The value to test\n * @returns {boolean} True if value is a Boolean, otherwise false\n */\nconst isBoolean = (thing) => thing === true || thing === false;\n\n/**\n * Determine if a value is a plain Object\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a plain Object, otherwise false\n */\nconst isPlainObject = (val) => {\n if (kindOf(val) !== \"object\") {\n return false;\n }\n\n const prototype = getPrototypeOf(val);\n return (\n (prototype === null ||\n prototype === Object.prototype ||\n Object.getPrototypeOf(prototype) === null) &&\n !(toStringTag in val) &&\n !(iterator in val)\n );\n};\n\n/**\n * Determine if a value is an empty object (safely handles Buffers)\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is an empty object, otherwise false\n */\nconst isEmptyObject = (val) => {\n // Early return for non-objects or Buffers to prevent RangeError\n if (!isObject(val) || isBuffer(val)) {\n return false;\n }\n\n try {\n return (\n Object.keys(val).length === 0 &&\n Object.getPrototypeOf(val) === Object.prototype\n );\n } catch (e) {\n // Fallback for any other objects that might cause RangeError with Object.keys()\n return false;\n }\n};\n\n/**\n * Determine if a value is a Date\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a Date, otherwise false\n */\nconst isDate = kindOfTest(\"Date\");\n\n/**\n * Determine if a value is a File\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a File, otherwise false\n */\nconst isFile = kindOfTest(\"File\");\n\n/**\n * Determine if a value is a Blob\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a Blob, otherwise false\n */\nconst isBlob = kindOfTest(\"Blob\");\n\n/**\n * Determine if a value is a FileList\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a File, otherwise false\n */\nconst isFileList = kindOfTest(\"FileList\");\n\n/**\n * Determine if a value is a Stream\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a Stream, otherwise false\n */\nconst isStream = (val) => isObject(val) && isFunction(val.pipe);\n\n/**\n * Determine if a value is a FormData\n *\n * @param {*} thing The value to test\n *\n * @returns {boolean} True if value is an FormData, otherwise false\n */\nconst isFormData = (thing) => {\n let kind;\n return (\n thing &&\n ((typeof FormData === \"function\" && thing instanceof FormData) ||\n (isFunction(thing.append) &&\n ((kind = kindOf(thing)) === \"formdata\" ||\n // detect form-data instance\n (kind === \"object\" &&\n isFunction(thing.toString) &&\n thing.toString() === \"[object FormData]\"))))\n );\n};\n\n/**\n * Determine if a value is a URLSearchParams object\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a URLSearchParams object, otherwise false\n */\nconst isURLSearchParams = kindOfTest(\"URLSearchParams\");\n\nconst [isReadableStream, isRequest, isResponse, isHeaders] = [\n \"ReadableStream\",\n \"Request\",\n \"Response\",\n \"Headers\",\n].map(kindOfTest);\n\n/**\n * Trim excess whitespace off the beginning and end of a string\n *\n * @param {String} str The String to trim\n *\n * @returns {String} The String freed of excess whitespace\n */\nconst trim = (str) =>\n str.trim ? str.trim() : str.replace(/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g, \"\");\n\n/**\n * Iterate over an Array or an Object invoking a function for each item.\n *\n * If `obj` is an Array callback will be called passing\n * the value, index, and complete array for each item.\n *\n * If 'obj' is an Object callback will be called passing\n * the value, key, and complete object for each property.\n *\n * @param {Object|Array<unknown>} obj The object to iterate\n * @param {Function} fn The callback to invoke for each item\n *\n * @param {Object} [options]\n * @param {Boolean} [options.allOwnKeys = false]\n * @returns {any}\n */\nfunction forEach(obj, fn, { allOwnKeys = false } = {}) {\n // Don't bother if no value provided\n if (obj === null || typeof obj === \"undefined\") {\n return;\n }\n\n let i;\n let l;\n\n // Force an array if not already something iterable\n if (typeof obj !== \"object\") {\n /*eslint no-param-reassign:0*/\n obj = [obj];\n }\n\n if (isArray(obj)) {\n // Iterate over array values\n for (i = 0, l = obj.length; i < l; i++) {\n fn.call(null, obj[i], i, obj);\n }\n } else {\n // Buffer check\n if (isBuffer(obj)) {\n return;\n }\n\n // Iterate over object keys\n const keys = allOwnKeys\n ? Object.getOwnPropertyNames(obj)\n : Object.keys(obj);\n const len = keys.length;\n let key;\n\n for (i = 0; i < len; i++) {\n key = keys[i];\n fn.call(null, obj[key], key, obj);\n }\n }\n}\n\nfunction findKey(obj, key) {\n if (isBuffer(obj)) {\n return null;\n }\n\n key = key.toLowerCase();\n const keys = Object.keys(obj);\n let i = keys.length;\n let _key;\n while (i-- > 0) {\n _key = keys[i];\n if (key === _key.toLowerCase()) {\n return _key;\n }\n }\n return null;\n}\n\nconst _global = (() => {\n /*eslint no-undef:0*/\n if (typeof globalThis !== \"undefined\") return globalThis;\n return typeof self !== \"undefined\"\n ? self\n : typeof window !== \"undefined\"\n ? window\n : global;\n})();\n\nconst isContextDefined = (context) =>\n !isUndefined(context) && context !== _global;\n\n/**\n * Accepts varargs expecting each argument to be an object, then\n * immutably merges the properties of each object and returns result.\n *\n * When multiple objects contain the same key the later object in\n * the arguments list will take precedence.\n *\n * Example:\n *\n * ```js\n * const result = merge({foo: 123}, {foo: 456});\n * console.log(result.foo); // outputs 456\n * ```\n *\n * @param {Object} obj1 Object to merge\n *\n * @returns {Object} Result of all merge properties\n */\nfunction merge(/* obj1, obj2, obj3, ... */) {\n const { caseless, skipUndefined } = (isContextDefined(this) && this) || {};\n const result = {};\n const assignValue = (val, key) => {\n // Skip dangerous property names to prevent prototype pollution\n if (key === \"__proto__\" || key === \"constructor\" || key === \"prototype\") {\n return;\n }\n\n const targetKey = (caseless && findKey(result, key)) || key;\n if (isPlainObject(result[targetKey]) && isPlainObject(val)) {\n result[targetKey] = merge(result[targetKey], val);\n } else if (isPlainObject(val)) {\n result[targetKey] = merge({}, val);\n } else if (isArray(val)) {\n result[targetKey] = val.slice();\n } else if (!skipUndefined || !isUndefined(val)) {\n result[targetKey] = val;\n }\n };\n\n for (let i = 0, l = arguments.length; i < l; i++) {\n arguments[i] && forEach(arguments[i], assignValue);\n }\n return result;\n}\n\n/**\n * Extends object a by mutably adding to it the properties of object b.\n *\n * @param {Object} a The object to be extended\n * @param {Object} b The object to copy properties from\n * @param {Object} thisArg The object to bind function to\n *\n * @param {Object} [options]\n * @param {Boolean} [options.allOwnKeys]\n * @returns {Object} The resulting value of object a\n */\nconst extend = (a, b, thisArg, { allOwnKeys } = {}) => {\n forEach(\n b,\n (val, key) => {\n if (thisArg && isFunction(val)) {\n Object.defineProperty(a, key, {\n value: bind(val, thisArg),\n writable: true,\n enumerable: true,\n configurable: true,\n });\n } else {\n Object.defineProperty(a, key, {\n value: val,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n },\n { allOwnKeys },\n );\n return a;\n};\n\n/**\n * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)\n *\n * @param {string} content with BOM\n *\n * @returns {string} content value without BOM\n */\nconst stripBOM = (content) => {\n if (content.charCodeAt(0) === 0xfeff) {\n content = content.slice(1);\n }\n return content;\n};\n\n/**\n * Inherit the prototype methods from one constructor into another\n * @param {function} constructor\n * @param {function} superConstructor\n * @param {object} [props]\n * @param {object} [descriptors]\n *\n * @returns {void}\n */\nconst inherits = (constructor, superConstructor, props, descriptors) => {\n constructor.prototype = Object.create(\n superConstructor.prototype,\n descriptors,\n );\n Object.defineProperty(constructor.prototype, \"constructor\", {\n value: constructor,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n Object.defineProperty(constructor, \"super\", {\n value: superConstructor.prototype,\n });\n props && Object.assign(constructor.prototype, props);\n};\n\n/**\n * Resolve object with deep prototype chain to a flat object\n * @param {Object} sourceObj source object\n * @param {Object} [destObj]\n * @param {Function|Boolean} [filter]\n * @param {Function} [propFilter]\n *\n * @returns {Object}\n */\nconst toFlatObject = (sourceObj, destObj, filter, propFilter) => {\n let props;\n let i;\n let prop;\n const merged = {};\n\n destObj = destObj || {};\n // eslint-disable-next-line no-eq-null,eqeqeq\n if (sourceObj == null) return destObj;\n\n do {\n props = Object.getOwnPropertyNames(sourceObj);\n i = props.length;\n while (i-- > 0) {\n prop = props[i];\n if (\n (!propFilter || propFilter(prop, sourceObj, destObj)) &&\n !merged[prop]\n ) {\n destObj[prop] = sourceObj[prop];\n merged[prop] = true;\n }\n }\n sourceObj = filter !== false && getPrototypeOf(sourceObj);\n } while (\n sourceObj &&\n (!filter || filter(sourceObj, destObj)) &&\n sourceObj !== Object.prototype\n );\n\n return destObj;\n};\n\n/**\n * Determines whether a string ends with the characters of a specified string\n *\n * @param {String} str\n * @param {String} searchString\n * @param {Number} [position= 0]\n *\n * @returns {boolean}\n */\nconst endsWith = (str, searchString, position) => {\n str = String(str);\n if (position === undefined || position > str.length) {\n position = str.length;\n }\n position -= searchString.length;\n const lastIndex = str.indexOf(searchString, position);\n return lastIndex !== -1 && lastIndex === position;\n};\n\n/**\n * Returns new array from array like object or null if failed\n *\n * @param {*} [thing]\n *\n * @returns {?Array}\n */\nconst toArray = (thing) => {\n if (!thing) return null;\n if (isArray(thing)) return thing;\n let i = thing.length;\n if (!isNumber(i)) return null;\n const arr = new Array(i);\n while (i-- > 0) {\n arr[i] = thing[i];\n }\n return arr;\n};\n\n/**\n * Checking if the Uint8Array exists and if it does, it returns a function that checks if the\n * thing passed in is an instance of Uint8Array\n *\n * @param {TypedArray}\n *\n * @returns {Array}\n */\n// eslint-disable-next-line func-names\nconst isTypedArray = ((TypedArray) => {\n // eslint-disable-next-line func-names\n return (thing) => {\n return TypedArray && thing instanceof TypedArray;\n };\n})(typeof Uint8Array !== \"undefined\" && getPrototypeOf(Uint8Array));\n\n/**\n * For each entry in the object, call the function with the key and value.\n *\n * @param {Object<any, any>} obj - The object to iterate over.\n * @param {Function} fn - The function to call for each entry.\n *\n * @returns {void}\n */\nconst forEachEntry = (obj, fn) => {\n const generator = obj && obj[iterator];\n\n const _iterator = generator.call(obj);\n\n let result;\n\n while ((result = _iterator.next()) && !result.done) {\n const pair = result.value;\n fn.call(obj, pair[0], pair[1]);\n }\n};\n\n/**\n * It takes a regular expression and a string, and returns an array of all the matches\n *\n * @param {string} regExp - The regular expression to match against.\n * @param {string} str - The string to search.\n *\n * @returns {Array<boolean>}\n */\nconst matchAll = (regExp, str) => {\n let matches;\n const arr = [];\n\n while ((matches = regExp.exec(str)) !== null) {\n arr.push(matches);\n }\n\n return arr;\n};\n\n/* Checking if the kindOfTest function returns true when passed an HTMLFormElement. */\nconst isHTMLForm = kindOfTest(\"HTMLFormElement\");\n\nconst toCamelCase = (str) => {\n return str\n .toLowerCase()\n .replace(/[-_\\s]([a-z\\d])(\\w*)/g, function replacer(m, p1, p2) {\n return p1.toUpperCase() + p2;\n });\n};\n\n/* Creating a function that will check if an object has a property. */\nconst hasOwnProperty = (\n ({ hasOwnProperty }) =>\n (obj, prop) =>\n hasOwnProperty.call(obj, prop)\n)(Object.prototype);\n\n/**\n * Determine if a value is a RegExp object\n *\n * @param {*} val The value to test\n *\n * @returns {boolean} True if value is a RegExp object, otherwise false\n */\nconst isRegExp = kindOfTest(\"RegExp\");\n\nconst reduceDescriptors = (obj, reducer) => {\n const descriptors = Object.getOwnPropertyDescriptors(obj);\n const reducedDescriptors = {};\n\n forEach(descriptors, (descriptor, name) => {\n let ret;\n if ((ret = reducer(descriptor, name, obj)) !== false) {\n reducedDescriptors[name] = ret || descriptor;\n }\n });\n\n Object.defineProperties(obj, reducedDescriptors);\n};\n\n/**\n * Makes all methods read-only\n * @param {Object} obj\n */\n\nconst freezeMethods = (obj) => {\n reduceDescriptors(obj, (descriptor, name) => {\n // skip restricted props in strict mode\n if (\n isFunction(obj) &&\n [\"arguments\", \"caller\", \"callee\"].indexOf(name) !== -1\n ) {\n return false;\n }\n\n const value = obj[name];\n\n if (!isFunction(value)) return;\n\n descriptor.enumerable = false;\n\n if (\"writable\" in descriptor) {\n descriptor.writable = false;\n return;\n }\n\n if (!descriptor.set) {\n descriptor.set = () => {\n throw Error(\"Can not rewrite read-only method '\" + name + \"'\");\n };\n }\n });\n};\n\nconst toObjectSet = (arrayOrString, delimiter) => {\n const obj = {};\n\n const define = (arr) => {\n arr.forEach((value) => {\n obj[value] = true;\n });\n };\n\n isArray(arrayOrString)\n ? define(arrayOrString)\n : define(String(arrayOrString).split(delimiter));\n\n return obj;\n};\n\nconst noop = () => {};\n\nconst toFiniteNumber = (value, defaultValue) => {\n return value != null && Number.isFinite((value = +value))\n ? value\n : defaultValue;\n};\n\n/**\n * If the thing is a FormData object, return true, otherwise return false.\n *\n * @param {unknown} thing - The thing to check.\n *\n * @returns {boolean}\n */\nfunction isSpecCompliantForm(thing) {\n return !!(\n thing &&\n isFunction(thing.append) &&\n thing[toStringTag] === \"FormData\" &&\n thing[iterator]\n );\n}\n\nconst toJSONObject = (obj) => {\n const stack = new Array(10);\n\n const visit = (source, i) => {\n if (isObject(source)) {\n if (stack.indexOf(source) >= 0) {\n return;\n }\n\n //Buffer check\n if (isBuffer(source)) {\n return source;\n }\n\n if (!(\"toJSON\" in source)) {\n stack[i] = source;\n const target = isArray(source) ? [] : {};\n\n forEach(source, (value, key) => {\n const reducedValue = visit(value, i + 1);\n !isUndefined(reducedValue) && (target[key] = reducedValue);\n });\n\n stack[i] = undefined;\n\n return target;\n }\n }\n\n return source;\n };\n\n return visit(obj, 0);\n};\n\nconst isAsyncFn = kindOfTest(\"AsyncFunction\");\n\nconst isThenable = (thing) =>\n thing &&\n (isObject(thing) || isFunction(thing)) &&\n isFunction(thing.then) &&\n isFunction(thing.catch);\n\n// original code\n// https://github.com/DigitalBrainJS/AxiosPromise/blob/16deab13710ec09779922131f3fa5954320f83ab/lib/utils.js#L11-L34\n\nconst _setImmediate = ((setImmediateSupported, postMessageSupported) => {\n if (setImmediateSupported) {\n return setImmediate;\n }\n\n return postMessageSupported\n ? ((token, callbacks) => {\n _global.addEventListener(\n \"message\",\n ({ source, data }) => {\n if (source === _global && data === token) {\n callbacks.length && callbacks.shift()();\n }\n },\n false,\n );\n\n return (cb) => {\n callbacks.push(cb);\n _global.postMessage(token, \"*\");\n };\n })(`axios@${Math.random()}`, [])\n : (cb) => setTimeout(cb);\n})(typeof setImmediate === \"function\", isFunction(_global.postMessage));\n\nconst asap =\n typeof queueMicrotask !== \"undefined\"\n ? queueMicrotask.bind(_global)\n : (typeof process !== \"undefined\" && process.nextTick) || _setImmediate;\n\n// *********************\n\nconst isIterable = (thing) => thing != null && isFunction(thing[iterator]);\n\nexport default {\n isArray,\n isArrayBuffer,\n isBuffer,\n isFormData,\n isArrayBufferView,\n isString,\n isNumber,\n isBoolean,\n isObject,\n isPlainObject,\n isEmptyObject,\n isReadableStream,\n isRequest,\n isResponse,\n isHeaders,\n isUndefined,\n isDate,\n isFile,\n isBlob,\n isRegExp,\n isFunction,\n isStream,\n isURLSearchParams,\n isTypedArray,\n isFileList,\n forEach,\n merge,\n extend,\n trim,\n stripBOM,\n inherits,\n toFlatObject,\n kindOf,\n kindOfTest,\n endsWith,\n toArray,\n forEachEntry,\n matchAll,\n isHTMLForm,\n hasOwnProperty,\n hasOwnProp: hasOwnProperty, // an alias to avoid ESLint no-prototype-builtins detection\n reduceDescriptors,\n freezeMethods,\n toObjectSet,\n toCamelCase,\n noop,\n toFiniteNumber,\n findKey,\n global: _global,\n isContextDefined,\n isSpecCompliantForm,\n toJSONObject,\n isAsyncFn,\n isThenable,\n setImmediate: _setImmediate,\n asap,\n isIterable,\n};\n","'use strict';\n\nimport utils from '../utils.js';\n\nclass AxiosError extends Error {\n static from(error, code, config, request, response, customProps) {\n const axiosError = new AxiosError(error.message, code || error.code, config, request, response);\n axiosError.cause = error;\n axiosError.name = error.name;\n customProps && Object.assign(axiosError, customProps);\n return axiosError;\n }\n\n /**\n * Create an Error with the specified message, config, error code, request and response.\n *\n * @param {string} message The error message.\n * @param {string} [code] The error code (for example, 'ECONNABORTED').\n * @param {Object} [config] The config.\n * @param {Object} [request] The request.\n * @param {Object} [response] The response.\n *\n * @returns {Error} The created error.\n */\n constructor(message, code, config, request, response) {\n super(message);\n this.name = 'AxiosError';\n this.isAxiosError = true;\n code && (this.code = code);\n config && (this.config = config);\n request && (this.request = request);\n if (response) {\n this.response = response;\n this.status = response.status;\n }\n }\n\n toJSON() {\n return {\n // Standard\n message: this.message,\n name: this.name,\n // Microsoft\n description: this.description,\n number: this.number,\n // Mozilla\n fileName: this.fileName,\n lineNumber: this.lineNumber,\n columnNumber: this.columnNumber,\n stack: this.stack,\n // Axios\n config: utils.toJSONObject(this.config),\n code: this.code,\n status: this.status,\n };\n }\n}\n\n// This can be changed to static properties as soon as the parser options in .eslint.cjs are updated.\nAxiosError.ERR_BAD_OPTION_VALUE = 'ERR_BAD_OPTION_VALUE';\nAxiosError.ERR_BAD_OPTION = 'ERR_BAD_OPTION';\nAxiosError.ECONNABORTED = 'ECONNABORTED';\nAxiosError.ETIMEDOUT = 'ETIMEDOUT';\nAxiosError.ERR_NETWORK = 'ERR_NETWORK';\nAxiosError.ERR_FR_TOO_MANY_REDIRECTS = 'ERR_FR_TOO_MANY_REDIRECTS';\nAxiosError.ERR_DEPRECATED = 'ERR_DEPRECATED';\nAxiosError.ERR_BAD_RESPONSE = 'ERR_BAD_RESPONSE';\nAxiosError.ERR_BAD_REQUEST = 'ERR_BAD_REQUEST';\nAxiosError.ERR_CANCELED = 'ERR_CANCELED';\nAxiosError.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT';\nAxiosError.ERR_INVALID_URL = 'ERR_INVALID_URL';\n\nexport default AxiosError;\n","// eslint-disable-next-line strict\nexport default null;\n","'use strict';\n\nimport utils from '../utils.js';\nimport AxiosError from '../core/AxiosError.js';\n// temporary hotfix to avoid circular references until AxiosURLSearchParams is refactored\nimport PlatformFormData from '../platform/node/classes/FormData.js';\n\n/**\n * Determines if the given thing is a array or js object.\n *\n * @param {string} thing - The object or array to be visited.\n *\n * @returns {boolean}\n */\nfunction isVisitable(thing) {\n return utils.isPlainObject(thing) || utils.isArray(thing);\n}\n\n/**\n * It removes the brackets from the end of a string\n *\n * @param {string} key - The key of the parameter.\n *\n * @returns {string} the key without the brackets.\n */\nfunction removeBrackets(key) {\n return utils.endsWith(key, '[]') ? key.slice(0, -2) : key;\n}\n\n/**\n * It takes a path, a key, and a boolean, and returns a string\n *\n * @param {string} path - The path to the current key.\n * @param {string} key - The key of the current object being iterated over.\n * @param {string} dots - If true, the key will be rendered with dots instead of brackets.\n *\n * @returns {string} The path to the current key.\n */\nfunction renderKey(path, key, dots) {\n if (!path) return key;\n return path.concat(key).map(function each(token, i) {\n // eslint-disable-next-line no-param-reassign\n token = removeBrackets(token);\n return !dots && i ? '[' + token + ']' : token;\n }).join(dots ? '.' : '');\n}\n\n/**\n * If the array is an array and none of its elements are visitable, then it's a flat array.\n *\n * @param {Array<any>} arr - The array to check\n *\n * @returns {boolean}\n */\nfunction isFlatArray(arr) {\n return utils.isArray(arr) && !arr.some(isVisitable);\n}\n\nconst predicates = utils.toFlatObject(utils, {}, null, function filter(prop) {\n return /^is[A-Z]/.test(prop);\n});\n\n/**\n * Convert a data object to FormData\n *\n * @param {Object} obj\n * @param {?Object} [formData]\n * @param {?Object} [options]\n * @param {Function} [options.visitor]\n * @param {Boolean} [options.metaTokens = true]\n * @param {Boolean} [options.dots = false]\n * @param {?Boolean} [options.indexes = false]\n *\n * @returns {Object}\n **/\n\n/**\n * It converts an object into a FormData object\n *\n * @param {Object<any, any>} obj - The object to convert to form data.\n * @param {string} formData - The FormData object to append to.\n * @param {Object<string, any>} options\n *\n * @returns\n */\nfunction toFormData(obj, formData, options) {\n if (!utils.isObject(obj)) {\n throw new TypeError('target must be an object');\n }\n\n // eslint-disable-next-line no-param-reassign\n formData = formData || new (PlatformFormData || FormData)();\n\n // eslint-disable-next-line no-param-reassign\n options = utils.toFlatObject(options, {\n metaTokens: true,\n dots: false,\n indexes: false\n }, false, function defined(option, source) {\n // eslint-disable-next-line no-eq-null,eqeqeq\n return !utils.isUndefined(source[option]);\n });\n\n const metaTokens = options.metaTokens;\n // eslint-disable-next-line no-use-before-define\n const visitor = options.visitor || defaultVisitor;\n const dots = options.dots;\n const indexes = options.indexes;\n const _Blob = options.Blob || typeof Blob !== 'undefined' && Blob;\n const useBlob = _Blob && utils.isSpecCompliantForm(formData);\n\n if (!utils.isFunction(visitor)) {\n throw new TypeError('visitor must be a function');\n }\n\n function convertValue(value) {\n if (value === null) return '';\n\n if (utils.isDate(value)) {\n return value.toISOString();\n }\n\n if (utils.isBoolean(value)) {\n return value.toString();\n }\n\n if (!useBlob && utils.isBlob(value)) {\n throw new AxiosError('Blob is not supported. Use a Buffer instead.');\n }\n\n if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) {\n return useBlob && typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value);\n }\n\n return value;\n }\n\n /**\n * Default visitor.\n *\n * @param {*} value\n * @param {String|Number} key\n * @param {Array<String|Number>} path\n * @this {FormData}\n *\n * @returns {boolean} return true to visit the each prop of the value recursively\n */\n function defaultVisitor(value, key, path) {\n let arr = value;\n\n if (value && !path && typeof value === 'object') {\n if (utils.endsWith(key, '{}')) {\n // eslint-disable-next-line no-param-reassign\n key = metaTokens ? key : key.slice(0, -2);\n // eslint-disable-next-line no-param-reassign\n value = JSON.stringify(value);\n } else if (\n (utils.isArray(value) && isFlatArray(value)) ||\n ((utils.isFileList(value) || utils.endsWith(key, '[]')) && (arr = utils.toArray(value))\n )) {\n // eslint-disable-next-line no-param-reassign\n key = removeBrackets(key);\n\n arr.forEach(function each(el, index) {\n !(utils.isUndefined(el) || el === null) && formData.append(\n // eslint-disable-next-line no-nested-ternary\n indexes === true ? renderKey([key], index, dots) : (indexes === null ? key : key + '[]'),\n convertValue(el)\n );\n });\n return false;\n }\n }\n\n if (isVisitable(value)) {\n return true;\n }\n\n formData.append(renderKey(path, key, dots), convertValue(value));\n\n return false;\n }\n\n const stack = [];\n\n const exposedHelpers = Object.assign(predicates, {\n defaultVisitor,\n convertValue,\n isVisitable\n });\n\n function build(value, path) {\n if (utils.isUndefined(value)) return;\n\n if (stack.indexOf(value) !== -1) {\n throw Error('Circular reference detected in ' + path.join('.'));\n }\n\n stack.push(value);\n\n utils.forEach(value, function each(el, key) {\n const result = !(utils.isUndefined(el) || el === null) && visitor.call(\n formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers\n );\n\n if (result === true) {\n build(el, path ? path.concat(key) : [key]);\n }\n });\n\n stack.pop();\n }\n\n if (!utils.isObject(obj)) {\n throw new TypeError('data must be an object');\n }\n\n build(obj);\n\n return formData;\n}\n\nexport default toFormData;\n","'use strict';\n\nimport toFormData from './toFormData.js';\n\n/**\n * It encodes a string by replacing all characters that are not in the unreserved set with\n * their percent-encoded equivalents\n *\n * @param {string} str - The string to encode.\n *\n * @returns {string} The encoded string.\n */\nfunction encode(str) {\n const charMap = {\n '!': '%21',\n \"'\": '%27',\n '(': '%28',\n ')': '%29',\n '~': '%7E',\n '%20': '+',\n '%00': '\\x00'\n };\n return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) {\n return charMap[match];\n });\n}\n\n/**\n * It takes a params object and converts it to a FormData object\n *\n * @param {Object<string, any>} params - The parameters to be converted to a FormData object.\n * @param {Object<string, any>} options - The options object passed to the Axios constructor.\n *\n * @returns {void}\n */\nfunction AxiosURLSearchParams(params, options) {\n this._pairs = [];\n\n params && toFormData(params, this, options);\n}\n\nconst prototype = AxiosURLSearchParams.prototype;\n\nprototype.append = function append(name, value) {\n this._pairs.push([name, value]);\n};\n\nprototype.toString = function toString(encoder) {\n const _encode = encoder ? function(value) {\n return encoder.call(this, value, encode);\n } : encode;\n\n return this._pairs.map(function each(pair) {\n return _encode(pair[0]) + '=' + _encode(pair[1]);\n }, '').join('&');\n};\n\nexport default AxiosURLSearchParams;\n","'use strict';\n\nimport utils from '../utils.js';\nimport AxiosURLSearchParams from '../helpers/AxiosURLSearchParams.js';\n\n/**\n * It replaces all instances of the characters `:`, `$`, `,`, `+`, `[`, and `]` with their\n * URI encoded counterparts\n *\n * @param {string} val The value to be encoded.\n *\n * @returns {string} The encoded value.\n */\nfunction encode(val) {\n return encodeURIComponent(val).\n replace(/%3A/gi, ':').\n replace(/%24/g, '$').\n replace(/%2C/gi, ',').\n replace(/%20/g, '+');\n}\n\n/**\n * Build a URL by appending params to the end\n *\n * @param {string} url The base of the url (e.g., http://www.google.com)\n * @param {object} [params] The params to be appended\n * @param {?(object|Function)} options\n *\n * @returns {string} The formatted url\n */\nexport default function buildURL(url, params, options) {\n if (!params) {\n return url;\n }\n\n const _encode = options && options.encode || encode;\n\n const _options = utils.isFunction(options) ? {\n serialize: options\n } : options;\n\n const serializeFn = _options && _options.serialize;\n\n let serializedParams;\n\n if (serializeFn) {\n serializedParams = serializeFn(params, _options);\n } else {\n serializedParams = utils.isURLSearchParams(params) ?\n params.toString() :\n new AxiosURLSearchParams(params, _options).toString(_encode);\n }\n\n if (serializedParams) {\n const hashmarkIndex = url.indexOf(\"#\");\n\n if (hashmarkIndex !== -1) {\n url = url.slice(0, hashmarkIndex);\n }\n url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;\n }\n\n return url;\n}\n","'use strict';\n\nimport utils from '../utils.js';\n\nclass InterceptorManager {\n constructor() {\n this.handlers = [];\n }\n\n /**\n * Add a new interceptor to the stack\n *\n * @param {Function} fulfilled The function to handle `then` for a `Promise`\n * @param {Function} rejected The function to handle `reject` for a `Promise`\n * @param {Object} options The options for the interceptor, synchronous and runWhen\n *\n * @return {Number} An ID used to remove interceptor later\n */\n use(fulfilled, rejected, options) {\n this.handlers.push({\n fulfilled,\n rejected,\n synchronous: options ? options.synchronous : false,\n runWhen: options ? options.runWhen : null\n });\n return this.handlers.length - 1;\n }\n\n /**\n * Remove an interceptor from the stack\n *\n * @param {Number} id The ID that was returned by `use`\n *\n * @returns {void}\n */\n eject(id) {\n if (this.handlers[id]) {\n this.handlers[id] = null;\n }\n }\n\n /**\n * Clear all interceptors from the stack\n *\n * @returns {void}\n */\n clear() {\n if (this.handlers) {\n this.handlers = [];\n }\n }\n\n /**\n * Iterate over all the registered interceptors\n *\n * This method is particularly useful for skipping over any\n * interceptors that may have become `null` calling `eject`.\n *\n * @param {Function} fn The function to call for each interceptor\n *\n * @returns {void}\n */\n forEach(fn) {\n utils.forEach(this.handlers, function forEachHandler(h) {\n if (h !== null) {\n fn(h);\n }\n });\n }\n}\n\nexport default InterceptorManager;\n","'use strict';\n\nexport default {\n silentJSONParsing: true,\n forcedJSONParsing: true,\n clarifyTimeoutError: false,\n legacyInterceptorReqResOrdering: true\n};\n","'use strict';\n\nimport AxiosURLSearchParams from '../../../helpers/AxiosURLSearchParams.js';\nexport default typeof URLSearchParams !== 'undefined' ? URLSearchParams : AxiosURLSearchParams;\n","'use strict';\n\nexport default typeof FormData !== 'undefined' ? FormData : null;\n","'use strict'\n\nexport default typeof Blob !== 'undefined' ? Blob : null\n","import URLSearchParams from './classes/URLSearchParams.js'\nimport FormData from './classes/FormData.js'\nimport Blob from './classes/Blob.js'\n\nexport default {\n isBrowser: true,\n classes: {\n URLSearchParams,\n FormData,\n Blob\n },\n protocols: ['http', 'https', 'file', 'blob', 'url', 'data']\n};\n","const hasBrowserEnv = typeof window !== 'undefined' && typeof document !== 'undefined';\n\nconst _navigator = typeof navigator === 'object' && navigator || undefined;\n\n/**\n * Determine if we're running in a standard browser environment\n *\n * This allows axios to run in a web worker, and react-native.\n * Both environments support XMLHttpRequest, but not fully standard globals.\n *\n * web workers:\n * typeof window -> undefined\n * typeof document -> undefined\n *\n * react-native:\n * navigator.product -> 'ReactNative'\n * nativescript\n * navigator.product -> 'NativeScript' or 'NS'\n *\n * @returns {boolean}\n */\nconst hasStandardBrowserEnv = hasBrowserEnv &&\n (!_navigator || ['ReactNative', 'NativeScript', 'NS'].indexOf(_navigator.product) < 0);\n\n/**\n * Determine if we're running in a standard browser webWorker environment\n *\n * Although the `isStandardBrowserEnv` method indicates that\n * `allows axios to run in a web worker`, the WebWorker will still be\n * filtered out due to its judgment standard\n * `typeof window !== 'undefined' && typeof document !== 'undefined'`.\n * This leads to a problem when axios post `FormData` in webWorker\n */\nconst hasStandardBrowserWebWorkerEnv = (() => {\n return (\n typeof WorkerGlobalScope !== 'undefined' &&\n // eslint-disable-next-line no-undef\n self instanceof WorkerGlobalScope &&\n typeof self.importScripts === 'function'\n );\n})();\n\nconst origin = hasBrowserEnv && window.location.href || 'http://localhost';\n\nexport {\n hasBrowserEnv,\n hasStandardBrowserWebWorkerEnv,\n hasStandardBrowserEnv,\n _navigator as navigator,\n origin\n}\n","import platform from './node/index.js';\nimport * as utils from './common/utils.js';\n\nexport default {\n ...utils,\n ...platform\n}\n","'use strict';\n\nimport utils from '../utils.js';\nimport toFormData from './toFormData.js';\nimport platform from '../platform/index.js';\n\nexport default function toURLEncodedForm(data, options) {\n return toFormData(data, new platform.classes.URLSearchParams(), {\n visitor: function(value, key, path, helpers) {\n if (platform.isNode && utils.isBuffer(value)) {\n this.append(key, value.toString('base64'));\n return false;\n }\n\n return helpers.defaultVisitor.apply(this, arguments);\n },\n ...options\n });\n}\n","'use strict';\n\nimport utils from '../utils.js';\n\n/**\n * It takes a string like `foo[x][y][z]` and returns an array like `['foo', 'x', 'y', 'z']\n *\n * @param {string} name - The name of the property to get.\n *\n * @returns An array of strings.\n */\nfunction parsePropPath(name) {\n // foo[x][y][z]\n // foo.x.y.z\n // foo-x-y-z\n // foo x y z\n return utils.matchAll(/\\w+|\\[(\\w*)]/g, name).map(match => {\n return match[0] === '[]' ? '' : match[1] || match[0];\n });\n}\n\n/**\n * Convert an array to an object.\n *\n * @param {Array<any>} arr - The array to convert to an object.\n *\n * @returns An object with the same keys and values as the array.\n */\nfunction arrayToObject(arr) {\n const obj = {};\n const keys = Object.keys(arr);\n let i;\n const len = keys.length;\n let key;\n for (i = 0; i < len; i++) {\n key = keys[i];\n obj[key] = arr[key];\n }\n return obj;\n}\n\n/**\n * It takes a FormData object and returns a JavaScript object\n *\n * @param {string} formData The FormData object to convert to JSON.\n *\n * @returns {Object<string, any> | null} The converted object.\n */\nfunction formDataToJSON(formData) {\n function buildPath(path, value, target, index) {\n let name = path[index++];\n\n if (name === '__proto__') return true;\n\n const isNumericKey = Number.isFinite(+name);\n const isLast = index >= path.length;\n name = !name && utils.isArray(target) ? target.length : name;\n\n if (isLast) {\n if (utils.hasOwnProp(target, name)) {\n target[name] = [target[name], value];\n } else {\n target[name] = value;\n }\n\n return !isNumericKey;\n }\n\n if (!target[name] || !utils.isObject(target[name])) {\n target[name] = [];\n }\n\n const result = buildPath(path, value, target[name], index);\n\n if (result && utils.isArray(target[name])) {\n target[name] = arrayToObject(target[name]);\n }\n\n return !isNumericKey;\n }\n\n if (utils.isFormData(formData) && utils.isFunction(formData.entries)) {\n const obj = {};\n\n utils.forEachEntry(formData, (name, value) => {\n buildPath(parsePropPath(name), value, obj, 0);\n });\n\n return obj;\n }\n\n return null;\n}\n\nexport default formDataToJSON;\n","'use strict';\n\nimport utils from '../utils.js';\nimport AxiosError from '../core/AxiosError.js';\nimport transitionalDefaults from './transitional.js';\nimport toFormData from '../helpers/toFormData.js';\nimport toURLEncodedForm from '../helpers/toURLEncodedForm.js';\nimport platform from '../platform/index.js';\nimport formDataToJSON from '../helpers/formDataToJSON.js';\n\n/**\n * It takes a string, tries to parse it, and if it fails, it returns the stringified version\n * of the input\n *\n * @param {any} rawValue - The value to be stringified.\n * @param {Function} parser - A function that parses a string into a JavaScript object.\n * @param {Function} encoder - A function that takes a value and returns a string.\n *\n * @returns {string} A stringified version of the rawValue.\n */\nfunction stringifySafely(rawValue, parser, encoder) {\n if (utils.isString(rawValue)) {\n try {\n (parser || JSON.parse)(rawValue);\n return utils.trim(rawValue);\n } catch (e) {\n if (e.name !== 'SyntaxError') {\n throw e;\n }\n }\n }\n\n return (encoder || JSON.stringify)(rawValue);\n}\n\nconst defaults = {\n\n transitional: transitionalDefaults,\n\n adapter: ['xhr', 'http', 'fetch'],\n\n transformRequest: [function transformRequest(data, headers) {\n const contentType = headers.getContentType() || '';\n const hasJSONContentType = contentType.indexOf('application/json') > -1;\n const isObjectPayload = utils.isObject(data);\n\n if (isObjectPayload && utils.isHTMLForm(data)) {\n data = new FormData(data);\n }\n\n const isFormData = utils.isFormData(data);\n\n if (isFormData) {\n return hasJSONContentType ? JSON.stringify(formDataToJSON(data)) : data;\n }\n\n if (utils.isArrayBuffer(data) ||\n utils.isBuffer(data) ||\n utils.isStream(data) ||\n utils.isFile(data) ||\n utils.isBlob(data) ||\n utils.isReadableStream(data)\n ) {\n return data;\n }\n if (utils.isArrayBufferView(data)) {\n return data.buffer;\n }\n if (utils.isURLSearchParams(data)) {\n headers.setContentType('application/x-www-form-urlencoded;charset=utf-8', false);\n return data.toString();\n }\n\n let isFileList;\n\n if (isObjectPayload) {\n if (contentType.indexOf('application/x-www-form-urlencoded') > -1) {\n return toURLEncodedForm(data, this.formSerializer).toString();\n }\n\n if ((isFileList = utils.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1) {\n const _FormData = this.env && this.env.FormData;\n\n return toFormData(\n isFileList ? {'files[]': data} : data,\n _FormData && new _FormData(),\n this.formSerializer\n );\n }\n }\n\n if (isObjectPayload || hasJSONContentType ) {\n headers.setContentType('application/json', false);\n return stringifySafely(data);\n }\n\n return data;\n }],\n\n transformResponse: [function transformResponse(data) {\n const transitional = this.transitional || defaults.transitional;\n const forcedJSONParsing = transitional && transitional.forcedJSONParsing;\n const JSONRequested = this.responseType === 'json';\n\n if (utils.isResponse(data) || utils.isReadableStream(data)) {\n return data;\n }\n\n if (data && utils.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) {\n const silentJSONParsing = transitional && transitional.silentJSONParsing;\n const strictJSONParsing = !silentJSONParsing && JSONRequested;\n\n try {\n return JSON.parse(data, this.parseReviver);\n } catch (e) {\n if (strictJSONParsing) {\n if (e.name === 'SyntaxError') {\n throw AxiosError.from(e, AxiosError.ERR_BAD_RESPONSE, this, null, this.response);\n }\n throw e;\n }\n }\n }\n\n return data;\n }],\n\n /**\n * A timeout in milliseconds to abort a request. If set to 0 (default) a\n * timeout is not created.\n */\n timeout: 0,\n\n xsrfCookieName: 'XSRF-TOKEN',\n xsrfHeaderName: 'X-XSRF-TOKEN',\n\n maxContentLength: -1,\n maxBodyLength: -1,\n\n env: {\n FormData: platform.classes.FormData,\n Blob: platform.classes.Blob\n },\n\n validateStatus: function validateStatus(status) {\n return status >= 200 && status < 300;\n },\n\n headers: {\n common: {\n 'Accept': 'application/json, text/plain, */*',\n 'Content-Type': undefined\n }\n }\n};\n\nutils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch'], (method) => {\n defaults.headers[method] = {};\n});\n\nexport default defaults;\n","'use strict';\n\nimport utils from '../utils.js';\n\n// RawAxiosHeaders whose duplicates are ignored by node\n// c.f. https://nodejs.org/api/http.html#http_message_headers\nconst ignoreDuplicateOf = utils.toObjectSet([\n 'age', 'authorization', 'content-length', 'content-type', 'etag',\n 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since',\n 'last-modified', 'location', 'max-forwards', 'proxy-authorization',\n 'referer', 'retry-after', 'user-agent'\n]);\n\n/**\n * Parse headers into an object\n *\n * ```\n * Date: Wed, 27 Aug 2014 08:58:49 GMT\n * Content-Type: application/json\n * Connection: keep-alive\n * Transfer-Encoding: chunked\n * ```\n *\n * @param {String} rawHeaders Headers needing to be parsed\n *\n * @returns {Object} Headers parsed into an object\n */\nexport default rawHeaders => {\n const parsed = {};\n let key;\n let val;\n let i;\n\n rawHeaders && rawHeaders.split('\\n').forEach(function parser(line) {\n i = line.indexOf(':');\n key = line.substring(0, i).trim().toLowerCase();\n val = line.substring(i + 1).trim();\n\n if (!key || (parsed[key] && ignoreDuplicateOf[key])) {\n return;\n }\n\n if (key === 'set-cookie') {\n if (parsed[key]) {\n parsed[key].push(val);\n } else {\n parsed[key] = [val];\n }\n } else {\n parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n }\n });\n\n return parsed;\n};\n","'use strict';\n\nimport utils from '../utils.js';\nimport parseHeaders from '../helpers/parseHeaders.js';\n\nconst $internals = Symbol('internals');\n\nfunction normalizeHeader(header) {\n return header && String(header).trim().toLowerCase();\n}\n\nfunction normalizeValue(value) {\n if (value === false || value == null) {\n return value;\n }\n\n return utils.isArray(value) ? value.map(normalizeValue) : String(value);\n}\n\nfunction parseTokens(str) {\n const tokens = Object.create(null);\n const tokensRE = /([^\\s,;=]+)\\s*(?:=\\s*([^,;]+))?/g;\n let match;\n\n while ((match = tokensRE.exec(str))) {\n tokens[match[1]] = match[2];\n }\n\n return tokens;\n}\n\nconst isValidHeaderName = (str) => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str.trim());\n\nfunction matchHeaderValue(context, value, header, filter, isHeaderNameFilter) {\n if (utils.isFunction(filter)) {\n return filter.call(this, value, header);\n }\n\n if (isHeaderNameFilter) {\n value = header;\n }\n\n if (!utils.isString(value)) return;\n\n if (utils.isString(filter)) {\n return value.indexOf(filter) !== -1;\n }\n\n if (utils.isRegExp(filter)) {\n return filter.test(value);\n }\n}\n\nfunction formatHeader(header) {\n return header.trim()\n .toLowerCase().replace(/([a-z\\d])(\\w*)/g, (w, char, str) => {\n return char.toUpperCase() + str;\n });\n}\n\nfunction buildAccessors(obj, header) {\n const accessorName = utils.toCamelCase(' ' + header);\n\n ['get', 'set', 'has'].forEach(methodName => {\n Object.defineProperty(obj, methodName + accessorName, {\n value: function(arg1, arg2, arg3) {\n return this[methodName].call(this, header, arg1, arg2, arg3);\n },\n configurable: true\n });\n });\n}\n\nclass AxiosHeaders {\n constructor(headers) {\n headers && this.set(headers);\n }\n\n set(header, valueOrRewrite, rewrite) {\n const self = this;\n\n function setHeader(_value, _header, _rewrite) {\n const lHeader = normalizeHeader(_header);\n\n if (!lHeader) {\n throw new Error('header name must be a non-empty string');\n }\n\n const key = utils.findKey(self, lHeader);\n\n if(!key || self[key] === undefined || _rewrite === true || (_rewrite === undefined && self[key] !== false)) {\n self[key || _header] = normalizeValue(_value);\n }\n }\n\n const setHeaders = (headers, _rewrite) =>\n utils.forEach(headers, (_value, _header) => setHeader(_value, _header, _rewrite));\n\n if (utils.isPlainObject(header) || header instanceof this.constructor) {\n setHeaders(header, valueOrRewrite)\n } else if(utils.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) {\n setHeaders(parseHeaders(header), valueOrRewrite);\n } else if (utils.isObject(header) && utils.isIterable(header)) {\n let obj = {}, dest, key;\n for (const entry of header) {\n if (!utils.isArray(entry)) {\n throw TypeError('Object iterator must return a key-value pair');\n }\n\n obj[key = entry[0]] = (dest = obj[key]) ?\n (utils.isArray(dest) ? [...dest, entry[1]] : [dest, entry[1]]) : entry[1];\n }\n\n setHeaders(obj, valueOrRewrite)\n } else {\n header != null && setHeader(valueOrRewrite, header, rewrite);\n }\n\n return this;\n }\n\n get(header, parser) {\n header = normalizeHeader(header);\n\n if (header) {\n const key = utils.findKey(this, header);\n\n if (key) {\n const value = this[key];\n\n if (!parser) {\n return value;\n }\n\n if (parser === true) {\n return parseTokens(value);\n }\n\n if (utils.isFunction(parser)) {\n return parser.call(this, value, key);\n }\n\n if (utils.isRegExp(parser)) {\n return parser.exec(value);\n }\n\n throw new TypeError('parser must be boolean|regexp|function');\n }\n }\n }\n\n has(header, matcher) {\n header = normalizeHeader(header);\n\n if (header) {\n const key = utils.findKey(this, header);\n\n return !!(key && this[key] !== undefined && (!matcher || matchHeaderValue(this, this[key], key, matcher)));\n }\n\n return false;\n }\n\n delete(header, matcher) {\n const self = this;\n let deleted = false;\n\n function deleteHeader(_header) {\n _header = normalizeHeader(_header);\n\n if (_header) {\n const key = utils.findKey(self, _header);\n\n if (key && (!matcher || matchHeaderValue(self, self[key], key, matcher))) {\n delete self[key];\n\n deleted = true;\n }\n }\n }\n\n if (utils.isArray(header)) {\n header.forEach(deleteHeader);\n } else {\n deleteHeader(header);\n }\n\n return deleted;\n }\n\n clear(matcher) {\n const keys = Object.keys(this);\n let i = keys.length;\n let deleted = false;\n\n while (i--) {\n const key = keys[i];\n if(!matcher || matchHeaderValue(this, this[key], key, matcher, true)) {\n delete this[key];\n deleted = true;\n }\n }\n\n return deleted;\n }\n\n normalize(format) {\n const self = this;\n const headers = {};\n\n utils.forEach(this, (value, header) => {\n const key = utils.findKey(headers, header);\n\n if (key) {\n self[key] = normalizeValue(value);\n delete self[header];\n return;\n }\n\n const normalized = format ? formatHeader(header) : String(header).trim();\n\n if (normalized !== header) {\n delete self[header];\n }\n\n self[normalized] = normalizeValue(value);\n\n headers[normalized] = true;\n });\n\n return this;\n }\n\n concat(...targets) {\n return this.constructor.concat(this, ...targets);\n }\n\n toJSON(asStrings) {\n const obj = Object.create(null);\n\n utils.forEach(this, (value, header) => {\n value != null && value !== false && (obj[header] = asStrings && utils.isArray(value) ? value.join(', ') : value);\n });\n\n return obj;\n }\n\n [Symbol.iterator]() {\n return Object.entries(this.toJSON())[Symbol.iterator]();\n }\n\n toString() {\n return Object.entries(this.toJSON()).map(([header, value]) => header + ': ' + value).join('\\n');\n }\n\n getSetCookie() {\n return this.get(\"set-cookie\") || [];\n }\n\n get [Symbol.toStringTag]() {\n return 'AxiosHeaders';\n }\n\n static from(thing) {\n return thing instanceof this ? thing : new this(thing);\n }\n\n static concat(first, ...targets) {\n const computed = new this(first);\n\n targets.forEach((target) => computed.set(target));\n\n return computed;\n }\n\n static accessor(header) {\n const internals = this[$internals] = (this[$internals] = {\n accessors: {}\n });\n\n const accessors = internals.accessors;\n const prototype = this.prototype;\n\n function defineAccessor(_header) {\n const lHeader = normalizeHeader(_header);\n\n if (!accessors[lHeader]) {\n buildAccessors(prototype, _header);\n accessors[lHeader] = true;\n }\n }\n\n utils.isArray(header) ? header.forEach(defineAccessor) : defineAccessor(header);\n\n return this;\n }\n}\n\nAxiosHeaders.accessor(['Content-Type', 'Content-Length', 'Accept', 'Accept-Encoding', 'User-Agent', 'Authorization']);\n\n// reserved names hotfix\nutils.reduceDescriptors(AxiosHeaders.prototype, ({value}, key) => {\n let mapped = key[0].toUpperCase() + key.slice(1); // map `set` => `Set`\n return {\n get: () => value,\n set(headerValue) {\n this[mapped] = headerValue;\n }\n }\n});\n\nutils.freezeMethods(AxiosHeaders);\n\nexport default AxiosHeaders;\n","'use strict';\n\nimport utils from '../utils.js';\nimport defaults from '../defaults/index.js';\nimport AxiosHeaders from '../core/AxiosHeaders.js';\n\n/**\n * Transform the data for a request or a response\n *\n * @param {Array|Function} fns A single function or Array of functions\n * @param {?Object} response The response object\n *\n * @returns {*} The resulting transformed data\n */\nexport default function transformData(fns, response) {\n const config = this || defaults;\n const context = response || config;\n const headers = AxiosHeaders.from(context.headers);\n let data = context.data;\n\n utils.forEach(fns, function transform(fn) {\n data = fn.call(config, data, headers.normalize(), response ? response.status : undefined);\n });\n\n headers.normalize();\n\n return data;\n}\n","'use strict';\n\nexport default function isCancel(value) {\n return !!(value && value.__CANCEL__);\n}\n","'use strict';\n\nimport AxiosError from '../core/AxiosError.js';\n\nclass CanceledError extends AxiosError {\n /**\n * A `CanceledError` is an object that is thrown when an operation is canceled.\n *\n * @param {string=} message The message.\n * @param {Object=} config The config.\n * @param {Object=} request The request.\n *\n * @returns {CanceledError} The created error.\n */\n constructor(message, config, request) {\n super(message == null ? 'canceled' : message, AxiosError.ERR_CANCELED, config, request);\n this.name = 'CanceledError';\n this.__CANCEL__ = true;\n }\n}\n\nexport default CanceledError;\n","'use strict';\n\nimport AxiosError from './AxiosError.js';\n\n/**\n * Resolve or reject a Promise based on response status.\n *\n * @param {Function} resolve A function that resolves the promise.\n * @param {Function} reject A function that rejects the promise.\n * @param {object} response The response.\n *\n * @returns {object} The response.\n */\nexport default function settle(resolve, reject, response) {\n const validateStatus = response.config.validateStatus;\n if (!response.status || !validateStatus || validateStatus(response.status)) {\n resolve(response);\n } else {\n reject(new AxiosError(\n 'Request failed with status code ' + response.status,\n [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4],\n response.config,\n response.request,\n response\n ));\n }\n}\n","'use strict';\n\nexport default function parseProtocol(url) {\n const match = /^([-+\\w]{1,25})(:?\\/\\/|:)/.exec(url);\n return match && match[1] || '';\n}\n","'use strict';\n\n/**\n * Calculate data maxRate\n * @param {Number} [samplesCount= 10]\n * @param {Number} [min= 1000]\n * @returns {Function}\n */\nfunction speedometer(samplesCount, min) {\n samplesCount = samplesCount || 10;\n const bytes = new Array(samplesCount);\n const timestamps = new Array(samplesCount);\n let head = 0;\n let tail = 0;\n let firstSampleTS;\n\n min = min !== undefined ? min : 1000;\n\n return function push(chunkLength) {\n const now = Date.now();\n\n const startedAt = timestamps[tail];\n\n if (!firstSampleTS) {\n firstSampleTS = now;\n }\n\n bytes[head] = chunkLength;\n timestamps[head] = now;\n\n let i = tail;\n let bytesCount = 0;\n\n while (i !== head) {\n bytesCount += bytes[i++];\n i = i % samplesCount;\n }\n\n head = (head + 1) % samplesCount;\n\n if (head === tail) {\n tail = (tail + 1) % samplesCount;\n }\n\n if (now - firstSampleTS < min) {\n return;\n }\n\n const passed = startedAt && now - startedAt;\n\n return passed ? Math.round(bytesCount * 1000 / passed) : undefined;\n };\n}\n\nexport default speedometer;\n","/**\n * Throttle decorator\n * @param {Function} fn\n * @param {Number} freq\n * @return {Function}\n */\nfunction throttle(fn, freq) {\n let timestamp = 0;\n let threshold = 1000 / freq;\n let lastArgs;\n let timer;\n\n const invoke = (args, now = Date.now()) => {\n timestamp = now;\n lastArgs = null;\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n fn(...args);\n }\n\n const throttled = (...args) => {\n const now = Date.now();\n const passed = now - timestamp;\n if ( passed >= threshold) {\n invoke(args, now);\n } else {\n lastArgs = args;\n if (!timer) {\n timer = setTimeout(() => {\n timer = null;\n invoke(lastArgs)\n }, threshold - passed);\n }\n }\n }\n\n const flush = () => lastArgs && invoke(lastArgs);\n\n return [throttled, flush];\n}\n\nexport default throttle;\n","import speedometer from \"./speedometer.js\";\nimport throttle from \"./throttle.js\";\nimport utils from \"../utils.js\";\n\nexport const progressEventReducer = (listener, isDownloadStream, freq = 3) => {\n let bytesNotified = 0;\n const _speedometer = speedometer(50, 250);\n\n return throttle(e => {\n const loaded = e.loaded;\n const total = e.lengthComputable ? e.total : undefined;\n const progressBytes = loaded - bytesNotified;\n const rate = _speedometer(progressBytes);\n const inRange = loaded <= total;\n\n bytesNotified = loaded;\n\n const data = {\n loaded,\n total,\n progress: total ? (loaded / total) : undefined,\n bytes: progressBytes,\n rate: rate ? rate : undefined,\n estimated: rate && total && inRange ? (total - loaded) / rate : undefined,\n event: e,\n lengthComputable: total != null,\n [isDownloadStream ? 'download' : 'upload']: true\n };\n\n listener(data);\n }, freq);\n}\n\nexport const progressEventDecorator = (total, throttled) => {\n const lengthComputable = total != null;\n\n return [(loaded) => throttled[0]({\n lengthComputable,\n total,\n loaded\n }), throttled[1]];\n}\n\nexport const asyncDecorator = (fn) => (...args) => utils.asap(() => fn(...args));\n","import platform from '../platform/index.js';\n\nexport default platform.hasStandardBrowserEnv ? ((origin, isMSIE) => (url) => {\n url = new URL(url, platform.origin);\n\n return (\n origin.protocol === url.protocol &&\n origin.host === url.host &&\n (isMSIE || origin.port === url.port)\n );\n})(\n new URL(platform.origin),\n platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent)\n) : () => true;\n","import utils from '../utils.js';\nimport platform from '../platform/index.js';\n\nexport default platform.hasStandardBrowserEnv ?\n\n // Standard browser envs support document.cookie\n {\n write(name, value, expires, path, domain, secure, sameSite) {\n if (typeof document === 'undefined') return;\n\n const cookie = [`${name}=${encodeURIComponent(value)}`];\n\n if (utils.isNumber(expires)) {\n cookie.push(`expires=${new Date(expires).toUTCString()}`);\n }\n if (utils.isString(path)) {\n cookie.push(`path=${path}`);\n }\n if (utils.isString(domain)) {\n cookie.push(`domain=${domain}`);\n }\n if (secure === true) {\n cookie.push('secure');\n }\n if (utils.isString(sameSite)) {\n cookie.push(`SameSite=${sameSite}`);\n }\n\n document.cookie = cookie.join('; ');\n },\n\n read(name) {\n if (typeof document === 'undefined') return null;\n const match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'));\n return match ? decodeURIComponent(match[1]) : null;\n },\n\n remove(name) {\n this.write(name, '', Date.now() - 86400000, '/');\n }\n }\n\n :\n\n // Non-standard browser env (web workers, react-native) lack needed support.\n {\n write() {},\n read() {\n return null;\n },\n remove() {}\n };\n\n","'use strict';\n\n/**\n * Determines whether the specified URL is absolute\n *\n * @param {string} url The URL to test\n *\n * @returns {boolean} True if the specified URL is absolute, otherwise false\n */\nexport default function isAbsoluteURL(url) {\n // A URL is considered absolute if it begins with \"<scheme>://\" or \"//\" (protocol-relative URL).\n // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed\n // by any combination of letters, digits, plus, period, or hyphen.\n if (typeof url !== 'string') {\n return false;\n }\n\n return /^([a-z][a-z\\d+\\-.]*:)?\\/\\//i.test(url);\n}\n\n","'use strict';\n\n/**\n * Creates a new URL by combining the specified URLs\n *\n * @param {string} baseURL The base URL\n * @param {string} relativeURL The relative URL\n *\n * @returns {string} The combined URL\n */\nexport default function combineURLs(baseURL, relativeURL) {\n return relativeURL\n ? baseURL.replace(/\\/?\\/$/, '') + '/' + relativeURL.replace(/^\\/+/, '')\n : baseURL;\n}\n","'use strict';\n\nimport isAbsoluteURL from '../helpers/isAbsoluteURL.js';\nimport combineURLs from '../helpers/combineURLs.js';\n\n/**\n * Creates a new URL by combining the baseURL with the requestedURL,\n * only when the requestedURL is not already an absolute URL.\n * If the requestURL is absolute, this function returns the requestedURL untouched.\n *\n * @param {string} baseURL The base URL\n * @param {string} requestedURL Absolute or relative URL to combine\n *\n * @returns {string} The combined full path\n */\nexport default function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) {\n let isRelativeUrl = !isAbsoluteURL(requestedURL);\n if (baseURL && (isRelativeUrl || allowAbsoluteUrls == false)) {\n return combineURLs(baseURL, requestedURL);\n }\n return requestedURL;\n}\n","\"use strict\";\n\nimport utils from \"../utils.js\";\nimport AxiosHeaders from \"./AxiosHeaders.js\";\n\nconst headersToObject = (thing) =>\n thing instanceof AxiosHeaders ? { ...thing } : thing;\n\n/**\n * Config-specific merge-function which creates a new config-object\n * by merging two configuration objects together.\n *\n * @param {Object} config1\n * @param {Object} config2\n *\n * @returns {Object} New object resulting from merging config2 to config1\n */\nexport default function mergeConfig(config1, config2) {\n // eslint-disable-next-line no-param-reassign\n config2 = config2 || {};\n const config = {};\n\n function getMergedValue(target, source, prop, caseless) {\n if (utils.isPlainObject(target) && utils.isPlainObject(source)) {\n return utils.merge.call({ caseless }, target, source);\n } else if (utils.isPlainObject(source)) {\n return utils.merge({}, source);\n } else if (utils.isArray(source)) {\n return source.slice();\n }\n return source;\n }\n\n function mergeDeepProperties(a, b, prop, caseless) {\n if (!utils.isUndefined(b)) {\n return getMergedValue(a, b, prop, caseless);\n } else if (!utils.isUndefined(a)) {\n return getMergedValue(undefined, a, prop, caseless);\n }\n }\n\n // eslint-disable-next-line consistent-return\n function valueFromConfig2(a, b) {\n if (!utils.isUndefined(b)) {\n return getMergedValue(undefined, b);\n }\n }\n\n // eslint-disable-next-line consistent-return\n function defaultToConfig2(a, b) {\n if (!utils.isUndefined(b)) {\n return getMergedValue(undefined, b);\n } else if (!utils.isUndefined(a)) {\n return getMergedValue(undefined, a);\n }\n }\n\n // eslint-disable-next-line consistent-return\n function mergeDirectKeys(a, b, prop) {\n if (prop in config2) {\n return getMergedValue(a, b);\n } else if (prop in config1) {\n return getMergedValue(undefined, a);\n }\n }\n\n const mergeMap = {\n url: valueFromConfig2,\n method: valueFromConfig2,\n data: valueFromConfig2,\n baseURL: defaultToConfig2,\n transformRequest: defaultToConfig2,\n transformResponse: defaultToConfig2,\n paramsSerializer: defaultToConfig2,\n timeout: defaultToConfig2,\n timeoutMessage: defaultToConfig2,\n withCredentials: defaultToConfig2,\n withXSRFToken: defaultToConfig2,\n adapter: defaultToConfig2,\n responseType: defaultToConfig2,\n xsrfCookieName: defaultToConfig2,\n xsrfHeaderName: defaultToConfig2,\n onUploadProgress: defaultToConfig2,\n onDownloadProgress: defaultToConfig2,\n decompress: defaultToConfig2,\n maxContentLength: defaultToConfig2,\n maxBodyLength: defaultToConfig2,\n beforeRedirect: defaultToConfig2,\n transport: defaultToConfig2,\n httpAgent: defaultToConfig2,\n httpsAgent: defaultToConfig2,\n cancelToken: defaultToConfig2,\n socketPath: defaultToConfig2,\n responseEncoding: defaultToConfig2,\n validateStatus: mergeDirectKeys,\n headers: (a, b, prop) =>\n mergeDeepProperties(headersToObject(a), headersToObject(b), prop, true),\n };\n\n utils.forEach(\n Object.keys({ ...config1, ...config2 }),\n function computeConfigValue(prop) {\n if (\n prop === \"__proto__\" ||\n prop === \"constructor\" ||\n prop === \"prototype\"\n )\n return;\n const merge = utils.hasOwnProp(mergeMap, prop)\n ? mergeMap[prop]\n : mergeDeepProperties;\n const configValue = merge(config1[prop], config2[prop], prop);\n (utils.isUndefined(configValue) && merge !== mergeDirectKeys) ||\n (config[prop] = configValue);\n },\n );\n\n return config;\n}\n","import platform from \"../platform/index.js\";\nimport utils from \"../utils.js\";\nimport isURLSameOrigin from \"./isURLSameOrigin.js\";\nimport cookies from \"./cookies.js\";\nimport buildFullPath from \"../core/buildFullPath.js\";\nimport mergeConfig from \"../core/mergeConfig.js\";\nimport AxiosHeaders from \"../core/AxiosHeaders.js\";\nimport buildURL from \"./buildURL.js\";\n\nexport default (config) => {\n const newConfig = mergeConfig({}, config);\n\n let { data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth } = newConfig;\n\n newConfig.headers = headers = AxiosHeaders.from(headers);\n\n newConfig.url = buildURL(buildFullPath(newConfig.baseURL, newConfig.url, newConfig.allowAbsoluteUrls), config.params, config.paramsSerializer);\n\n // HTTP basic authentication\n if (auth) {\n headers.set('Authorization', 'Basic ' +\n btoa((auth.username || '') + ':' + (auth.password ? unescape(encodeURIComponent(auth.password)) : ''))\n );\n }\n\n if (utils.isFormData(data)) {\n if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) {\n headers.setContentType(undefined); // browser handles it\n } else if (utils.isFunction(data.getHeaders)) {\n // Node.js FormData (like form-data package)\n const formHeaders = data.getHeaders();\n // Only set safe headers to avoid overwriting security headers\n const allowedHeaders = ['content-type', 'content-length'];\n Object.entries(formHeaders).forEach(([key, val]) => {\n if (allowedHeaders.includes(key.toLowerCase())) {\n headers.set(key, val);\n }\n });\n }\n } \n\n // Add xsrf header\n // This is only done if running in a standard browser environment.\n // Specifically not if we're in a web worker, or react-native.\n\n if (platform.hasStandardBrowserEnv) {\n withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig));\n\n if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(newConfig.url))) {\n // Add xsrf header\n const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName);\n\n if (xsrfValue) {\n headers.set(xsrfHeaderName, xsrfValue);\n }\n }\n }\n\n return newConfig;\n}\n\n","import utils from '../utils.js';\nimport settle from '../core/settle.js';\nimport transitionalDefaults from '../defaults/transitional.js';\nimport AxiosError from '../core/AxiosError.js';\nimport CanceledError from '../cancel/CanceledError.js';\nimport parseProtocol from '../helpers/parseProtocol.js';\nimport platform from '../platform/index.js';\nimport AxiosHeaders from '../core/AxiosHeaders.js';\nimport {progressEventReducer} from '../helpers/progressEventReducer.js';\nimport resolveConfig from \"../helpers/resolveConfig.js\";\n\nconst isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined';\n\nexport default isXHRAdapterSupported && function (config) {\n return new Promise(function dispatchXhrRequest(resolve, reject) {\n const _config = resolveConfig(config);\n let requestData = _config.data;\n const requestHeaders = AxiosHeaders.from(_config.headers).normalize();\n let {responseType, onUploadProgress, onDownloadProgress} = _config;\n let onCanceled;\n let uploadThrottled, downloadThrottled;\n let flushUpload, flushDownload;\n\n function done() {\n flushUpload && flushUpload(); // flush events\n flushDownload && flushDownload(); // flush events\n\n _config.cancelToken && _config.cancelToken.unsubscribe(onCanceled);\n\n _config.signal && _config.signal.removeEventListener('abort', onCanceled);\n }\n\n let request = new XMLHttpRequest();\n\n request.open(_config.method.toUpperCase(), _config.url, true);\n\n // Set the request timeout in MS\n request.timeout = _config.timeout;\n\n function onloadend() {\n if (!request) {\n return;\n }\n // Prepare the response\n const responseHeaders = AxiosHeaders.from(\n 'getAllResponseHeaders' in request && request.getAllResponseHeaders()\n );\n const responseData = !responseType || responseType === 'text' || responseType === 'json' ?\n request.responseText : request.response;\n const response = {\n data: responseData,\n status: request.status,\n statusText: request.statusText,\n headers: responseHeaders,\n config,\n request\n };\n\n settle(function _resolve(value) {\n resolve(value);\n done();\n }, function _reject(err) {\n reject(err);\n done();\n }, response);\n\n // Clean up request\n request = null;\n }\n\n if ('onloadend' in request) {\n // Use onloadend if available\n request.onloadend = onloadend;\n } else {\n // Listen for ready state to emulate onloadend\n request.onreadystatechange = function handleLoad() {\n if (!request || request.readyState !== 4) {\n return;\n }\n\n // The request errored out and we didn't get a response, this will be\n // handled by onerror instead\n // With one exception: request that using file: protocol, most browsers\n // will return status as 0 even though it's a successful request\n if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {\n return;\n }\n // readystate handler is calling before onerror or ontimeout handlers,\n // so we should call onloadend on the next 'tick'\n setTimeout(onloadend);\n };\n }\n\n // Handle browser request cancellation (as opposed to a manual cancellation)\n request.onabort = function handleAbort() {\n if (!request) {\n return;\n }\n\n reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request));\n\n // Clean up request\n request = null;\n };\n\n // Handle low level network errors\n request.onerror = function handleError(event) {\n // Browsers deliver a ProgressEvent in XHR onerror\n // (message may be empty; when present, surface it)\n // See https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/error_event\n const msg = event && event.message ? event.message : 'Network Error';\n const err = new AxiosError(msg, AxiosError.ERR_NETWORK, config, request);\n // attach the underlying event for consumers who want details\n err.event = event || null;\n reject(err);\n request = null;\n };\n \n // Handle timeout\n request.ontimeout = function handleTimeout() {\n let timeoutErrorMessage = _config.timeout ? 'timeout of ' + _config.timeout + 'ms exceeded' : 'timeout exceeded';\n const transitional = _config.transitional || transitionalDefaults;\n if (_config.timeoutErrorMessage) {\n timeoutErrorMessage = _config.timeoutErrorMessage;\n }\n reject(new AxiosError(\n timeoutErrorMessage,\n transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,\n config,\n request));\n\n // Clean up request\n request = null;\n };\n\n // Remove Content-Type if data is undefined\n requestData === undefined && requestHeaders.setContentType(null);\n\n // Add headers to the request\n if ('setRequestHeader' in request) {\n utils.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) {\n request.setRequestHeader(key, val);\n });\n }\n\n // Add withCredentials to request if needed\n if (!utils.isUndefined(_config.withCredentials)) {\n request.withCredentials = !!_config.withCredentials;\n }\n\n // Add responseType to request if needed\n if (responseType && responseType !== 'json') {\n request.responseType = _config.responseType;\n }\n\n // Handle progress if needed\n if (onDownloadProgress) {\n ([downloadThrottled, flushDownload] = progressEventReducer(onDownloadProgress, true));\n request.addEventListener('progress', downloadThrottled);\n }\n\n // Not all browsers support upload events\n if (onUploadProgress && request.upload) {\n ([uploadThrottled, flushUpload] = progressEventReducer(onUploadProgress));\n\n request.upload.addEventListener('progress', uploadThrottled);\n\n request.upload.addEventListener('loadend', flushUpload);\n }\n\n if (_config.cancelToken || _config.signal) {\n // Handle cancellation\n // eslint-disable-next-line func-names\n onCanceled = cancel => {\n if (!request) {\n return;\n }\n reject(!cancel || cancel.type ? new CanceledError(null, config, request) : cancel);\n request.abort();\n request = null;\n };\n\n _config.cancelToken && _config.cancelToken.subscribe(onCanceled);\n if (_config.signal) {\n _config.signal.aborted ? onCanceled() : _config.signal.addEventListener('abort', onCanceled);\n }\n }\n\n const protocol = parseProtocol(_config.url);\n\n if (protocol && platform.protocols.indexOf(protocol) === -1) {\n reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config));\n return;\n }\n\n\n // Send the request\n request.send(requestData || null);\n });\n}\n","import CanceledError from \"../cancel/CanceledError.js\";\nimport AxiosError from \"../core/AxiosError.js\";\nimport utils from '../utils.js';\n\nconst composeSignals = (signals, timeout) => {\n const {length} = (signals = signals ? signals.filter(Boolean) : []);\n\n if (timeout || length) {\n let controller = new AbortController();\n\n let aborted;\n\n const onabort = function (reason) {\n if (!aborted) {\n aborted = true;\n unsubscribe();\n const err = reason instanceof Error ? reason : this.reason;\n controller.abort(err instanceof AxiosError ? err : new CanceledError(err instanceof Error ? err.message : err));\n }\n }\n\n let timer = timeout && setTimeout(() => {\n timer = null;\n onabort(new AxiosError(`timeout of ${timeout}ms exceeded`, AxiosError.ETIMEDOUT))\n }, timeout)\n\n const unsubscribe = () => {\n if (signals) {\n timer && clearTimeout(timer);\n timer = null;\n signals.forEach(signal => {\n signal.unsubscribe ? signal.unsubscribe(onabort) : signal.removeEventListener('abort', onabort);\n });\n signals = null;\n }\n }\n\n signals.forEach((signal) => signal.addEventListener('abort', onabort));\n\n const {signal} = controller;\n\n signal.unsubscribe = () => utils.asap(unsubscribe);\n\n return signal;\n }\n}\n\nexport default composeSignals;\n","\nexport const streamChunk = function* (chunk, chunkSize) {\n let len = chunk.byteLength;\n\n if (!chunkSize || len < chunkSize) {\n yield chunk;\n return;\n }\n\n let pos = 0;\n let end;\n\n while (pos < len) {\n end = pos + chunkSize;\n yield chunk.slice(pos, end);\n pos = end;\n }\n}\n\nexport const readBytes = async function* (iterable, chunkSize) {\n for await (const chunk of readStream(iterable)) {\n yield* streamChunk(chunk, chunkSize);\n }\n}\n\nconst readStream = async function* (stream) {\n if (stream[Symbol.asyncIterator]) {\n yield* stream;\n return;\n }\n\n const reader = stream.getReader();\n try {\n for (;;) {\n const {done, value} = await reader.read();\n if (done) {\n break;\n }\n yield value;\n }\n } finally {\n await reader.cancel();\n }\n}\n\nexport const trackStream = (stream, chunkSize, onProgress, onFinish) => {\n const iterator = readBytes(stream, chunkSize);\n\n let bytes = 0;\n let done;\n let _onFinish = (e) => {\n if (!done) {\n done = true;\n onFinish && onFinish(e);\n }\n }\n\n return new ReadableStream({\n async pull(controller) {\n try {\n const {done, value} = await iterator.next();\n\n if (done) {\n _onFinish();\n controller.close();\n return;\n }\n\n let len = value.byteLength;\n if (onProgress) {\n let loadedBytes = bytes += len;\n onProgress(loadedBytes);\n }\n controller.enqueue(new Uint8Array(value));\n } catch (err) {\n _onFinish(err);\n throw err;\n }\n },\n cancel(reason) {\n _onFinish(reason);\n return iterator.return();\n }\n }, {\n highWaterMark: 2\n })\n}\n","import platform from \"../platform/index.js\";\nimport utils from \"../utils.js\";\nimport AxiosError from \"../core/AxiosError.js\";\nimport composeSignals from \"../helpers/composeSignals.js\";\nimport {trackStream} from \"../helpers/trackStream.js\";\nimport AxiosHeaders from \"../core/AxiosHeaders.js\";\nimport {progressEventReducer, progressEventDecorator, asyncDecorator} from \"../helpers/progressEventReducer.js\";\nimport resolveConfig from \"../helpers/resolveConfig.js\";\nimport settle from \"../core/settle.js\";\n\nconst DEFAULT_CHUNK_SIZE = 64 * 1024;\n\nconst {isFunction} = utils;\n\nconst globalFetchAPI = (({Request, Response}) => ({\n Request, Response\n}))(utils.global);\n\nconst {\n ReadableStream, TextEncoder\n} = utils.global;\n\n\nconst test = (fn, ...args) => {\n try {\n return !!fn(...args);\n } catch (e) {\n return false\n }\n}\n\nconst factory = (env) => {\n env = utils.merge.call({\n skipUndefined: true\n }, globalFetchAPI, env);\n\n const {fetch: envFetch, Request, Response} = env;\n const isFetchSupported = envFetch ? isFunction(envFetch) : typeof fetch === 'function';\n const isRequestSupported = isFunction(Request);\n const isResponseSupported = isFunction(Response);\n\n if (!isFetchSupported) {\n return false;\n }\n\n const isReadableStreamSupported = isFetchSupported && isFunction(ReadableStream);\n\n const encodeText = isFetchSupported && (typeof TextEncoder === 'function' ?\n ((encoder) => (str) => encoder.encode(str))(new TextEncoder()) :\n async (str) => new Uint8Array(await new Request(str).arrayBuffer())\n );\n\n const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => {\n let duplexAccessed = false;\n\n const hasContentType = new Request(platform.origin, {\n body: new ReadableStream(),\n method: 'POST',\n get duplex() {\n duplexAccessed = true;\n return 'half';\n },\n }).headers.has('Content-Type');\n\n return duplexAccessed && !hasContentType;\n });\n\n const supportsResponseStream = isResponseSupported && isReadableStreamSupported &&\n test(() => utils.isReadableStream(new Response('').body));\n\n const resolvers = {\n stream: supportsResponseStream && ((res) => res.body)\n };\n\n isFetchSupported && ((() => {\n ['text', 'arrayBuffer', 'blob', 'formData', 'stream'].forEach(type => {\n !resolvers[type] && (resolvers[type] = (res, config) => {\n let method = res && res[type];\n\n if (method) {\n return method.call(res);\n }\n\n throw new AxiosError(`Response type '${type}' is not supported`, AxiosError.ERR_NOT_SUPPORT, config);\n })\n });\n })());\n\n const getBodyLength = async (body) => {\n if (body == null) {\n return 0;\n }\n\n if (utils.isBlob(body)) {\n return body.size;\n }\n\n if (utils.isSpecCompliantForm(body)) {\n const _request = new Request(platform.origin, {\n method: 'POST',\n body,\n });\n return (await _request.arrayBuffer()).byteLength;\n }\n\n if (utils.isArrayBufferView(body) || utils.isArrayBuffer(body)) {\n return body.byteLength;\n }\n\n if (utils.isURLSearchParams(body)) {\n body = body + '';\n }\n\n if (utils.isString(body)) {\n return (await encodeText(body)).byteLength;\n }\n }\n\n const resolveBodyLength = async (headers, body) => {\n const length = utils.toFiniteNumber(headers.getContentLength());\n\n return length == null ? getBodyLength(body) : length;\n }\n\n return async (config) => {\n let {\n url,\n method,\n data,\n signal,\n cancelToken,\n timeout,\n onDownloadProgress,\n onUploadProgress,\n responseType,\n headers,\n withCredentials = 'same-origin',\n fetchOptions\n } = resolveConfig(config);\n\n let _fetch = envFetch || fetch;\n\n responseType = responseType ? (responseType + '').toLowerCase() : 'text';\n\n let composedSignal = composeSignals([signal, cancelToken && cancelToken.toAbortSignal()], timeout);\n\n let request = null;\n\n const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => {\n composedSignal.unsubscribe();\n });\n\n let requestContentLength;\n\n try {\n if (\n onUploadProgress && supportsRequestStream && method !== 'get' && method !== 'head' &&\n (requestContentLength = await resolveBodyLength(headers, data)) !== 0\n ) {\n let _request = new Request(url, {\n method: 'POST',\n body: data,\n duplex: \"half\"\n });\n\n let contentTypeHeader;\n\n if (utils.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {\n headers.setContentType(contentTypeHeader)\n }\n\n if (_request.body) {\n const [onProgress, flush] = progressEventDecorator(\n requestContentLength,\n progressEventReducer(asyncDecorator(onUploadProgress))\n );\n\n data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush);\n }\n }\n\n if (!utils.isString(withCredentials)) {\n withCredentials = withCredentials ? 'include' : 'omit';\n }\n\n // Cloudflare Workers throws when credentials are defined\n // see https://github.com/cloudflare/workerd/issues/902\n const isCredentialsSupported = isRequestSupported && \"credentials\" in Request.prototype;\n\n const resolvedOptions = {\n ...fetchOptions,\n signal: composedSignal,\n method: method.toUpperCase(),\n headers: headers.normalize().toJSON(),\n body: data,\n duplex: \"half\",\n credentials: isCredentialsSupported ? withCredentials : undefined\n };\n\n request = isRequestSupported && new Request(url, resolvedOptions);\n\n let response = await (isRequestSupported ? _fetch(request, fetchOptions) : _fetch(url, resolvedOptions));\n\n const isStreamResponse = supportsResponseStream && (responseType === 'stream' || responseType === 'response');\n\n if (supportsResponseStream && (onDownloadProgress || (isStreamResponse && unsubscribe))) {\n const options = {};\n\n ['status', 'statusText', 'headers'].forEach(prop => {\n options[prop] = response[prop];\n });\n\n const responseContentLength = utils.toFiniteNumber(response.headers.get('content-length'));\n\n const [onProgress, flush] = onDownloadProgress && progressEventDecorator(\n responseContentLength,\n progressEventReducer(asyncDecorator(onDownloadProgress), true)\n ) || [];\n\n response = new Response(\n trackStream(response.body, DEFAULT_CHUNK_SIZE, onProgress, () => {\n flush && flush();\n unsubscribe && unsubscribe();\n }),\n options\n );\n }\n\n responseType = responseType || 'text';\n\n let responseData = await resolvers[utils.findKey(resolvers, responseType) || 'text'](response, config);\n\n !isStreamResponse && unsubscribe && unsubscribe();\n\n return await new Promise((resolve, reject) => {\n settle(resolve, reject, {\n data: responseData,\n headers: AxiosHeaders.from(response.headers),\n status: response.status,\n statusText: response.statusText,\n config,\n request\n })\n })\n } catch (err) {\n unsubscribe && unsubscribe();\n\n if (err && err.name === 'TypeError' && /Load failed|fetch/i.test(err.message)) {\n throw Object.assign(\n new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request, err && err.response),\n {\n cause: err.cause || err\n }\n )\n }\n\n throw AxiosError.from(err, err && err.code, config, request, err && err.response);\n }\n }\n}\n\nconst seedCache = new Map();\n\nexport const getFetch = (config) => {\n let env = (config && config.env) || {};\n const {fetch, Request, Response} = env;\n const seeds = [\n Request, Response, fetch\n ];\n\n let len = seeds.length, i = len,\n seed, target, map = seedCache;\n\n while (i--) {\n seed = seeds[i];\n target = map.get(seed);\n\n target === undefined && map.set(seed, target = (i ? new Map() : factory(env)))\n\n map = target;\n }\n\n return target;\n};\n\nconst adapter = getFetch();\n\nexport default adapter;\n","import utils from '../utils.js';\nimport httpAdapter from './http.js';\nimport xhrAdapter from './xhr.js';\nimport * as fetchAdapter from './fetch.js';\nimport AxiosError from \"../core/AxiosError.js\";\n\n/**\n * Known adapters mapping.\n * Provides environment-specific adapters for Axios:\n * - `http` for Node.js\n * - `xhr` for browsers\n * - `fetch` for fetch API-based requests\n * \n * @type {Object<string, Function|Object>}\n */\nconst knownAdapters = {\n http: httpAdapter,\n xhr: xhrAdapter,\n fetch: {\n get: fetchAdapter.getFetch,\n }\n};\n\n// Assign adapter names for easier debugging and identification\nutils.forEach(knownAdapters, (fn, value) => {\n if (fn) {\n try {\n Object.defineProperty(fn, 'name', { value });\n } catch (e) {\n // eslint-disable-next-line no-empty\n }\n Object.defineProperty(fn, 'adapterName', { value });\n }\n});\n\n/**\n * Render a rejection reason string for unknown or unsupported adapters\n * \n * @param {string} reason\n * @returns {string}\n */\nconst renderReason = (reason) => `- ${reason}`;\n\n/**\n * Check if the adapter is resolved (function, null, or false)\n * \n * @param {Function|null|false} adapter\n * @returns {boolean}\n */\nconst isResolvedHandle = (adapter) => utils.isFunction(adapter) || adapter === null || adapter === false;\n\n/**\n * Get the first suitable adapter from the provided list.\n * Tries each adapter in order until a supported one is found.\n * Throws an AxiosError if no adapter is suitable.\n * \n * @param {Array<string|Function>|string|Function} adapters - Adapter(s) by name or function.\n * @param {Object} config - Axios request configuration\n * @throws {AxiosError} If no suitable adapter is available\n * @returns {Function} The resolved adapter function\n */\nfunction getAdapter(adapters, config) {\n adapters = utils.isArray(adapters) ? adapters : [adapters];\n\n const { length } = adapters;\n let nameOrAdapter;\n let adapter;\n\n const rejectedReasons = {};\n\n for (let i = 0; i < length; i++) {\n nameOrAdapter = adapters[i];\n let id;\n\n adapter = nameOrAdapter;\n\n if (!isResolvedHandle(nameOrAdapter)) {\n adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()];\n\n if (adapter === undefined) {\n throw new AxiosError(`Unknown adapter '${id}'`);\n }\n }\n\n if (adapter && (utils.isFunction(adapter) || (adapter = adapter.get(config)))) {\n break;\n }\n\n rejectedReasons[id || '#' + i] = adapter;\n }\n\n if (!adapter) {\n const reasons = Object.entries(rejectedReasons)\n .map(([id, state]) => `adapter ${id} ` +\n (state === false ? 'is not supported by the environment' : 'is not available in the build')\n );\n\n let s = length ?\n (reasons.length > 1 ? 'since :\\n' + reasons.map(renderReason).join('\\n') : ' ' + renderReason(reasons[0])) :\n 'as no adapter specified';\n\n throw new AxiosError(\n `There is no suitable adapter to dispatch the request ` + s,\n 'ERR_NOT_SUPPORT'\n );\n }\n\n return adapter;\n}\n\n/**\n * Exports Axios adapters and utility to resolve an adapter\n */\nexport default {\n /**\n * Resolve an adapter from a list of adapter names or functions.\n * @type {Function}\n */\n getAdapter,\n\n /**\n * Exposes all known adapters\n * @type {Object<string, Function|Object>}\n */\n adapters: knownAdapters\n};\n","'use strict';\n\nimport transformData from './transformData.js';\nimport isCancel from '../cancel/isCancel.js';\nimport defaults from '../defaults/index.js';\nimport CanceledError from '../cancel/CanceledError.js';\nimport AxiosHeaders from '../core/AxiosHeaders.js';\nimport adapters from \"../adapters/adapters.js\";\n\n/**\n * Throws a `CanceledError` if cancellation has been requested.\n *\n * @param {Object} config The config that is to be used for the request\n *\n * @returns {void}\n */\nfunction throwIfCancellationRequested(config) {\n if (config.cancelToken) {\n config.cancelToken.throwIfRequested();\n }\n\n if (config.signal && config.signal.aborted) {\n throw new CanceledError(null, config);\n }\n}\n\n/**\n * Dispatch a request to the server using the configured adapter.\n *\n * @param {object} config The config that is to be used for the request\n *\n * @returns {Promise} The Promise to be fulfilled\n */\nexport default function dispatchRequest(config) {\n throwIfCancellationRequested(config);\n\n config.headers = AxiosHeaders.from(config.headers);\n\n // Transform request data\n config.data = transformData.call(\n config,\n config.transformRequest\n );\n\n if (['post', 'put', 'patch'].indexOf(config.method) !== -1) {\n config.headers.setContentType('application/x-www-form-urlencoded', false);\n }\n\n const adapter = adapters.getAdapter(config.adapter || defaults.adapter, config);\n\n return adapter(config).then(function onAdapterResolution(response) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n response.data = transformData.call(\n config,\n config.transformResponse,\n response\n );\n\n response.headers = AxiosHeaders.from(response.headers);\n\n return response;\n }, function onAdapterRejection(reason) {\n if (!isCancel(reason)) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n if (reason && reason.response) {\n reason.response.data = transformData.call(\n config,\n config.transformResponse,\n reason.response\n );\n reason.response.headers = AxiosHeaders.from(reason.response.headers);\n }\n }\n\n return Promise.reject(reason);\n });\n}\n","export const VERSION = \"1.13.5\";","'use strict';\n\nimport {VERSION} from '../env/data.js';\nimport AxiosError from '../core/AxiosError.js';\n\nconst validators = {};\n\n// eslint-disable-next-line func-names\n['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach((type, i) => {\n validators[type] = function validator(thing) {\n return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type;\n };\n});\n\nconst deprecatedWarnings = {};\n\n/**\n * Transitional option validator\n *\n * @param {function|boolean?} validator - set to false if the transitional option has been removed\n * @param {string?} version - deprecated version / removed since version\n * @param {string?} message - some message with additional info\n *\n * @returns {function}\n */\nvalidators.transitional = function transitional(validator, version, message) {\n function formatMessage(opt, desc) {\n return '[Axios v' + VERSION + '] Transitional option \\'' + opt + '\\'' + desc + (message ? '. ' + message : '');\n }\n\n // eslint-disable-next-line func-names\n return (value, opt, opts) => {\n if (validator === false) {\n throw new AxiosError(\n formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')),\n AxiosError.ERR_DEPRECATED\n );\n }\n\n if (version && !deprecatedWarnings[opt]) {\n deprecatedWarnings[opt] = true;\n // eslint-disable-next-line no-console\n console.warn(\n formatMessage(\n opt,\n ' has been deprecated since v' + version + ' and will be removed in the near future'\n )\n );\n }\n\n return validator ? validator(value, opt, opts) : true;\n };\n};\n\nvalidators.spelling = function spelling(correctSpelling) {\n return (value, opt) => {\n // eslint-disable-next-line no-console\n console.warn(`${opt} is likely a misspelling of ${correctSpelling}`);\n return true;\n }\n};\n\n/**\n * Assert object's properties type\n *\n * @param {object} options\n * @param {object} schema\n * @param {boolean?} allowUnknown\n *\n * @returns {object}\n */\n\nfunction assertOptions(options, schema, allowUnknown) {\n if (typeof options !== 'object') {\n throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE);\n }\n const keys = Object.keys(options);\n let i = keys.length;\n while (i-- > 0) {\n const opt = keys[i];\n const validator = schema[opt];\n if (validator) {\n const value = options[opt];\n const result = value === undefined || validator(value, opt, options);\n if (result !== true) {\n throw new AxiosError('option ' + opt + ' must be ' + result, AxiosError.ERR_BAD_OPTION_VALUE);\n }\n continue;\n }\n if (allowUnknown !== true) {\n throw new AxiosError('Unknown option ' + opt, AxiosError.ERR_BAD_OPTION);\n }\n }\n}\n\nexport default {\n assertOptions,\n validators\n};\n","'use strict';\n\nimport utils from '../utils.js';\nimport buildURL from '../helpers/buildURL.js';\nimport InterceptorManager from './InterceptorManager.js';\nimport dispatchRequest from './dispatchRequest.js';\nimport mergeConfig from './mergeConfig.js';\nimport buildFullPath from './buildFullPath.js';\nimport validator from '../helpers/validator.js';\nimport AxiosHeaders from './AxiosHeaders.js';\nimport transitionalDefaults from '../defaults/transitional.js';\n\nconst validators = validator.validators;\n\n/**\n * Create a new instance of Axios\n *\n * @param {Object} instanceConfig The default config for the instance\n *\n * @return {Axios} A new instance of Axios\n */\nclass Axios {\n constructor(instanceConfig) {\n this.defaults = instanceConfig || {};\n this.interceptors = {\n request: new InterceptorManager(),\n response: new InterceptorManager()\n };\n }\n\n /**\n * Dispatch a request\n *\n * @param {String|Object} configOrUrl The config specific for this request (merged with this.defaults)\n * @param {?Object} config\n *\n * @returns {Promise} The Promise to be fulfilled\n */\n async request(configOrUrl, config) {\n try {\n return await this._request(configOrUrl, config);\n } catch (err) {\n if (err instanceof Error) {\n let dummy = {};\n\n Error.captureStackTrace ? Error.captureStackTrace(dummy) : (dummy = new Error());\n\n // slice off the Error: ... line\n const stack = dummy.stack ? dummy.stack.replace(/^.+\\n/, '') : '';\n try {\n if (!err.stack) {\n err.stack = stack;\n // match without the 2 top stack lines\n } else if (stack && !String(err.stack).endsWith(stack.replace(/^.+\\n.+\\n/, ''))) {\n err.stack += '\\n' + stack\n }\n } catch (e) {\n // ignore the case where \"stack\" is an un-writable property\n }\n }\n\n throw err;\n }\n }\n\n _request(configOrUrl, config) {\n /*eslint no-param-reassign:0*/\n // Allow for axios('example/url'[, config]) a la fetch API\n if (typeof configOrUrl === 'string') {\n config = config || {};\n config.url = configOrUrl;\n } else {\n config = configOrUrl || {};\n }\n\n config = mergeConfig(this.defaults, config);\n\n const {transitional, paramsSerializer, headers} = config;\n\n if (transitional !== undefined) {\n validator.assertOptions(transitional, {\n silentJSONParsing: validators.transitional(validators.boolean),\n forcedJSONParsing: validators.transitional(validators.boolean),\n clarifyTimeoutError: validators.transitional(validators.boolean),\n legacyInterceptorReqResOrdering: validators.transitional(validators.boolean)\n }, false);\n }\n\n if (paramsSerializer != null) {\n if (utils.isFunction(paramsSerializer)) {\n config.paramsSerializer = {\n serialize: paramsSerializer\n }\n } else {\n validator.assertOptions(paramsSerializer, {\n encode: validators.function,\n serialize: validators.function\n }, true);\n }\n }\n\n // Set config.allowAbsoluteUrls\n if (config.allowAbsoluteUrls !== undefined) {\n // do nothing\n } else if (this.defaults.allowAbsoluteUrls !== undefined) {\n config.allowAbsoluteUrls = this.defaults.allowAbsoluteUrls;\n } else {\n config.allowAbsoluteUrls = true;\n }\n\n validator.assertOptions(config, {\n baseUrl: validators.spelling('baseURL'),\n withXsrfToken: validators.spelling('withXSRFToken')\n }, true);\n\n // Set config.method\n config.method = (config.method || this.defaults.method || 'get').toLowerCase();\n\n // Flatten headers\n let contextHeaders = headers && utils.merge(\n headers.common,\n headers[config.method]\n );\n\n headers && utils.forEach(\n ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],\n (method) => {\n delete headers[method];\n }\n );\n\n config.headers = AxiosHeaders.concat(contextHeaders, headers);\n\n // filter out skipped interceptors\n const requestInterceptorChain = [];\n let synchronousRequestInterceptors = true;\n this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {\n if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {\n return;\n }\n\n synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;\n\n const transitional = config.transitional || transitionalDefaults;\n const legacyInterceptorReqResOrdering = transitional && transitional.legacyInterceptorReqResOrdering;\n\n if (legacyInterceptorReqResOrdering) {\n requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);\n } else {\n requestInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);\n }\n });\n\n const responseInterceptorChain = [];\n this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {\n responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);\n });\n\n let promise;\n let i = 0;\n let len;\n\n if (!synchronousRequestInterceptors) {\n const chain = [dispatchRequest.bind(this), undefined];\n chain.unshift(...requestInterceptorChain);\n chain.push(...responseInterceptorChain);\n len = chain.length;\n\n promise = Promise.resolve(config);\n\n while (i < len) {\n promise = promise.then(chain[i++], chain[i++]);\n }\n\n return promise;\n }\n\n len = requestInterceptorChain.length;\n\n let newConfig = config;\n\n while (i < len) {\n const onFulfilled = requestInterceptorChain[i++];\n const onRejected = requestInterceptorChain[i++];\n try {\n newConfig = onFulfilled(newConfig);\n } catch (error) {\n onRejected.call(this, error);\n break;\n }\n }\n\n try {\n promise = dispatchRequest.call(this, newConfig);\n } catch (error) {\n return Promise.reject(error);\n }\n\n i = 0;\n len = responseInterceptorChain.length;\n\n while (i < len) {\n promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]);\n }\n\n return promise;\n }\n\n getUri(config) {\n config = mergeConfig(this.defaults, config);\n const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);\n return buildURL(fullPath, config.params, config.paramsSerializer);\n }\n}\n\n// Provide aliases for supported request methods\nutils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {\n /*eslint func-names:0*/\n Axios.prototype[method] = function(url, config) {\n return this.request(mergeConfig(config || {}, {\n method,\n url,\n data: (config || {}).data\n }));\n };\n});\n\nutils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {\n /*eslint func-names:0*/\n\n function generateHTTPMethod(isForm) {\n return function httpMethod(url, data, config) {\n return this.request(mergeConfig(config || {}, {\n method,\n headers: isForm ? {\n 'Content-Type': 'multipart/form-data'\n } : {},\n url,\n data\n }));\n };\n }\n\n Axios.prototype[method] = generateHTTPMethod();\n\n Axios.prototype[method + 'Form'] = generateHTTPMethod(true);\n});\n\nexport default Axios;\n","'use strict';\n\nimport CanceledError from './CanceledError.js';\n\n/**\n * A `CancelToken` is an object that can be used to request cancellation of an operation.\n *\n * @param {Function} executor The executor function.\n *\n * @returns {CancelToken}\n */\nclass CancelToken {\n constructor(executor) {\n if (typeof executor !== 'function') {\n throw new TypeError('executor must be a function.');\n }\n\n let resolvePromise;\n\n this.promise = new Promise(function promiseExecutor(resolve) {\n resolvePromise = resolve;\n });\n\n const token = this;\n\n // eslint-disable-next-line func-names\n this.promise.then(cancel => {\n if (!token._listeners) return;\n\n let i = token._listeners.length;\n\n while (i-- > 0) {\n token._listeners[i](cancel);\n }\n token._listeners = null;\n });\n\n // eslint-disable-next-line func-names\n this.promise.then = onfulfilled => {\n let _resolve;\n // eslint-disable-next-line func-names\n const promise = new Promise(resolve => {\n token.subscribe(resolve);\n _resolve = resolve;\n }).then(onfulfilled);\n\n promise.cancel = function reject() {\n token.unsubscribe(_resolve);\n };\n\n return promise;\n };\n\n executor(function cancel(message, config, request) {\n if (token.reason) {\n // Cancellation has already been requested\n return;\n }\n\n token.reason = new CanceledError(message, config, request);\n resolvePromise(token.reason);\n });\n }\n\n /**\n * Throws a `CanceledError` if cancellation has been requested.\n */\n throwIfRequested() {\n if (this.reason) {\n throw this.reason;\n }\n }\n\n /**\n * Subscribe to the cancel signal\n */\n\n subscribe(listener) {\n if (this.reason) {\n listener(this.reason);\n return;\n }\n\n if (this._listeners) {\n this._listeners.push(listener);\n } else {\n this._listeners = [listener];\n }\n }\n\n /**\n * Unsubscribe from the cancel signal\n */\n\n unsubscribe(listener) {\n if (!this._listeners) {\n return;\n }\n const index = this._listeners.indexOf(listener);\n if (index !== -1) {\n this._listeners.splice(index, 1);\n }\n }\n\n toAbortSignal() {\n const controller = new AbortController();\n\n const abort = (err) => {\n controller.abort(err);\n };\n\n this.subscribe(abort);\n\n controller.signal.unsubscribe = () => this.unsubscribe(abort);\n\n return controller.signal;\n }\n\n /**\n * Returns an object that contains a new `CancelToken` and a function that, when called,\n * cancels the `CancelToken`.\n */\n static source() {\n let cancel;\n const token = new CancelToken(function executor(c) {\n cancel = c;\n });\n return {\n token,\n cancel\n };\n }\n}\n\nexport default CancelToken;\n","'use strict';\n\n/**\n * Syntactic sugar for invoking a function and expanding an array for arguments.\n *\n * Common use case would be to use `Function.prototype.apply`.\n *\n * ```js\n * function f(x, y, z) {}\n * const args = [1, 2, 3];\n * f.apply(null, args);\n * ```\n *\n * With `spread` this example can be re-written.\n *\n * ```js\n * spread(function(x, y, z) {})([1, 2, 3]);\n * ```\n *\n * @param {Function} callback\n *\n * @returns {Function}\n */\nexport default function spread(callback) {\n return function wrap(arr) {\n return callback.apply(null, arr);\n };\n}\n","'use strict';\n\nimport utils from '../utils.js';\n\n/**\n * Determines whether the payload is an error thrown by Axios\n *\n * @param {*} payload The value to test\n *\n * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false\n */\nexport default function isAxiosError(payload) {\n return utils.isObject(payload) && (payload.isAxiosError === true);\n}\n","const HttpStatusCode = {\n Continue: 100,\n SwitchingProtocols: 101,\n Processing: 102,\n EarlyHints: 103,\n Ok: 200,\n Created: 201,\n Accepted: 202,\n NonAuthoritativeInformation: 203,\n NoContent: 204,\n ResetContent: 205,\n PartialContent: 206,\n MultiStatus: 207,\n AlreadyReported: 208,\n ImUsed: 226,\n MultipleChoices: 300,\n MovedPermanently: 301,\n Found: 302,\n SeeOther: 303,\n NotModified: 304,\n UseProxy: 305,\n Unused: 306,\n TemporaryRedirect: 307,\n PermanentRedirect: 308,\n BadRequest: 400,\n Unauthorized: 401,\n PaymentRequired: 402,\n Forbidden: 403,\n NotFound: 404,\n MethodNotAllowed: 405,\n NotAcceptable: 406,\n ProxyAuthenticationRequired: 407,\n RequestTimeout: 408,\n Conflict: 409,\n Gone: 410,\n LengthRequired: 411,\n PreconditionFailed: 412,\n PayloadTooLarge: 413,\n UriTooLong: 414,\n UnsupportedMediaType: 415,\n RangeNotSatisfiable: 416,\n ExpectationFailed: 417,\n ImATeapot: 418,\n MisdirectedRequest: 421,\n UnprocessableEntity: 422,\n Locked: 423,\n FailedDependency: 424,\n TooEarly: 425,\n UpgradeRequired: 426,\n PreconditionRequired: 428,\n TooManyRequests: 429,\n RequestHeaderFieldsTooLarge: 431,\n UnavailableForLegalReasons: 451,\n InternalServerError: 500,\n NotImplemented: 501,\n BadGateway: 502,\n ServiceUnavailable: 503,\n GatewayTimeout: 504,\n HttpVersionNotSupported: 505,\n VariantAlsoNegotiates: 506,\n InsufficientStorage: 507,\n LoopDetected: 508,\n NotExtended: 510,\n NetworkAuthenticationRequired: 511,\n WebServerIsDown: 521,\n ConnectionTimedOut: 522,\n OriginIsUnreachable: 523,\n TimeoutOccurred: 524,\n SslHandshakeFailed: 525,\n InvalidSslCertificate: 526,\n};\n\nObject.entries(HttpStatusCode).forEach(([key, value]) => {\n HttpStatusCode[value] = key;\n});\n\nexport default HttpStatusCode;\n","'use strict';\n\nimport utils from './utils.js';\nimport bind from './helpers/bind.js';\nimport Axios from './core/Axios.js';\nimport mergeConfig from './core/mergeConfig.js';\nimport defaults from './defaults/index.js';\nimport formDataToJSON from './helpers/formDataToJSON.js';\nimport CanceledError from './cancel/CanceledError.js';\nimport CancelToken from './cancel/CancelToken.js';\nimport isCancel from './cancel/isCancel.js';\nimport {VERSION} from './env/data.js';\nimport toFormData from './helpers/toFormData.js';\nimport AxiosError from './core/AxiosError.js';\nimport spread from './helpers/spread.js';\nimport isAxiosError from './helpers/isAxiosError.js';\nimport AxiosHeaders from \"./core/AxiosHeaders.js\";\nimport adapters from './adapters/adapters.js';\nimport HttpStatusCode from './helpers/HttpStatusCode.js';\n\n/**\n * Create an instance of Axios\n *\n * @param {Object} defaultConfig The default config for the instance\n *\n * @returns {Axios} A new instance of Axios\n */\nfunction createInstance(defaultConfig) {\n const context = new Axios(defaultConfig);\n const instance = bind(Axios.prototype.request, context);\n\n // Copy axios.prototype to instance\n utils.extend(instance, Axios.prototype, context, {allOwnKeys: true});\n\n // Copy context to instance\n utils.extend(instance, context, null, {allOwnKeys: true});\n\n // Factory for creating new instances\n instance.create = function create(instanceConfig) {\n return createInstance(mergeConfig(defaultConfig, instanceConfig));\n };\n\n return instance;\n}\n\n// Create the default instance to be exported\nconst axios = createInstance(defaults);\n\n// Expose Axios class to allow class inheritance\naxios.Axios = Axios;\n\n// Expose Cancel & CancelToken\naxios.CanceledError = CanceledError;\naxios.CancelToken = CancelToken;\naxios.isCancel = isCancel;\naxios.VERSION = VERSION;\naxios.toFormData = toFormData;\n\n// Expose AxiosError class\naxios.AxiosError = AxiosError;\n\n// alias for CanceledError for backward compatibility\naxios.Cancel = axios.CanceledError;\n\n// Expose all/spread\naxios.all = function all(promises) {\n return Promise.all(promises);\n};\n\naxios.spread = spread;\n\n// Expose isAxiosError\naxios.isAxiosError = isAxiosError;\n\n// Expose mergeConfig\naxios.mergeConfig = mergeConfig;\n\naxios.AxiosHeaders = AxiosHeaders;\n\naxios.formToJSON = thing => formDataToJSON(utils.isHTMLForm(thing) ? new FormData(thing) : thing);\n\naxios.getAdapter = adapters.getAdapter;\n\naxios.HttpStatusCode = HttpStatusCode;\n\naxios.default = axios;\n\n// this module should only have a default export\nexport default axios\n","import axios from './lib/axios.js';\n\n// This module is intended to unwrap Axios default export as named.\n// Keep top-level export same with static properties\n// so that it can keep same with es module or cjs\nconst {\n Axios,\n AxiosError,\n CanceledError,\n isCancel,\n CancelToken,\n VERSION,\n all,\n Cancel,\n isAxiosError,\n spread,\n toFormData,\n AxiosHeaders,\n HttpStatusCode,\n formToJSON,\n getAdapter,\n mergeConfig\n} = axios;\n\nexport {\n axios as default,\n Axios,\n AxiosError,\n CanceledError,\n isCancel,\n CancelToken,\n VERSION,\n all,\n Cancel,\n isAxiosError,\n spread,\n toFormData,\n AxiosHeaders,\n HttpStatusCode,\n formToJSON,\n getAdapter,\n mergeConfig\n}\n","import React from 'react';\r\nimport { Avatar } from \"@heroui/react\";\r\nimport Submenu from \"../Submenu/Submenu\";\r\nimport type { SubmenuItem } from \"../Submenu/Submenu\";\r\nimport axios from \"axios\";\r\nimport type { UserData } from '../../types';\r\nimport './UserProfile.css';\r\n\r\n// 图标组件定义\r\nconst UserIcon = () => <span style={{ marginRight: 8, fontSize: '1.2em' }}>👤</span>;\r\nconst SettingsIcon = () => <span style={{ marginRight: 8, fontSize: '1.2em' }}>⚙️</span>;\r\nconst HelpIcon = () => <span style={{ marginRight: 8, fontSize: '1.2em' }}>❓</span>;\r\nconst LogoutIcon = () => <span style={{ marginRight: 8, fontSize: '1.2em' }}>🚪</span>;\r\n\r\n// API 配置类型\r\nexport interface ApiConfig {\r\n baseURL: string;\r\n endpoints: {\r\n userProfile: string;\r\n };\r\n headers?: Record<string, string>;\r\n}\r\n\r\n\r\n// 默认菜单项配置\r\nconst DEFAULT_MENU_ITEMS: SubmenuItem[] = [\r\n { id: 'profile', label: '个人主页', icon: <UserIcon /> },\r\n { id: 'settings', label: '设置', icon: <SettingsIcon /> },\r\n { id: 'help', label: '帮助', icon: <HelpIcon /> },\r\n { id: 'logout', label: '退出', icon: <LogoutIcon /> }\r\n];\r\n\r\nexport interface UserProfileProps {\r\n // 用户数据配置\r\n userId?: string;\r\n userName?: string;\r\n userAvatar?: string;\r\n \r\n // API 配置\r\n apiConfig?: ApiConfig;\r\n \r\n // 菜单配置\r\n menuItems?: SubmenuItem[];\r\n \r\n // 样式配置\r\n avatarSize?: 'sm' | 'md' | 'lg';\r\n avatarClassName?: string;\r\n userNameClassName?: string;\r\n containerClassName?: string;\r\n \r\n // 状态控制\r\n isLoading?: boolean;\r\n error?: Error | null;\r\n \r\n // 事件回调\r\n onMenuOpen?: () => void;\r\n onMenuClose?: () => void;\r\n onMenuItemClick?: (itemId: string) => void;\r\n onLogout?: () => void;\r\n \r\n // 定制化渲染\r\n renderMenuItem?: (item: SubmenuItem, userData: UserData) => React.ReactNode;\r\n renderUserInfo?: (userData: UserData) => React.ReactNode;\r\n}\r\n\r\nconst UserProfile: React.FC<UserProfileProps> = ({\r\n userId,\r\n userName: initialUserName,\r\n userAvatar: initialUserAvatar,\r\n apiConfig,\r\n menuItems = DEFAULT_MENU_ITEMS,\r\n avatarSize = 'md',\r\n isLoading = false,\r\n error = null,\r\n avatarClassName,\r\n userNameClassName,\r\n containerClassName,\r\n onMenuOpen,\r\n onMenuClose,\r\n onMenuItemClick,\r\n onLogout,\r\n renderMenuItem,\r\n renderUserInfo\r\n}) => {\r\n const [userData, setUserData] = React.useState<UserData>({\r\n id: userId || '',\r\n name: initialUserName || '',\r\n avatar: initialUserAvatar || '',\r\n level: 0,\r\n badges: []\r\n });\r\n \r\n const [loading, setLoading] = React.useState(isLoading);\r\n const [errorState, setErrorState] = React.useState<Error | null>(error);\r\n\r\n // 数据获取逻辑\r\n React.useEffect(() => {\r\n if (userId && apiConfig && !initialUserName && !initialUserAvatar) {\r\n fetchUserData();\r\n }\r\n }, [userId, apiConfig, initialUserName, initialUserAvatar]);\r\n\r\n const fetchUserData = async () => {\r\n setLoading(true);\r\n setErrorState(null);\r\n \r\n try {\r\n const endpoint = apiConfig!.endpoints.userProfile.replace(':userId', userId!);\r\n const response = await axios.get(`${apiConfig!.baseURL}${endpoint}`, {\r\n headers: apiConfig!.headers\r\n });\r\n \r\n setUserData(response.data);\r\n } catch (err) {\r\n setErrorState(err as Error);\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n // 处理菜单项点击\r\n const handleMenuItemClick = (item: SubmenuItem) => {\r\n onMenuItemClick?.(item.id as string);\r\n \r\n if (item.id === 'logout') {\r\n onLogout?.();\r\n }\r\n };\r\n\r\n // 处理菜单打开\r\n const handleMenuOpen = () => {\r\n onMenuOpen?.();\r\n };\r\n\r\n // 处理菜单关闭\r\n const handleMenuClose = () => {\r\n onMenuClose?.();\r\n };\r\n\r\n // 渲染用户信息区域\r\n const renderDefaultUserInfo = () => (\r\n <div className=\"user-profile-trigger\">\r\n <Avatar\r\n src={userData.avatar}\r\n size={avatarSize}\r\n className={avatarClassName}\r\n alt=\"用户头像\"\r\n />\r\n <span className={`user-name ${userNameClassName || ''}`}>\r\n {userData.name}\r\n </span>\r\n </div>\r\n );\r\n\r\n // 渲染默认菜单项\r\n const _renderDefaultMenuItem = (item: SubmenuItem) => (\r\n <div\r\n key={item.id}\r\n className=\"submenu-item\"\r\n onClick={() => handleMenuItemClick(item)}\r\n >\r\n {item.icon && <span className=\"submenu-item-icon\">{item.icon}</span>}\r\n <span>{item.label}</span>\r\n </div>\r\n );\r\n\r\n if (loading) {\r\n return (\r\n <div className={`user-profile-container ${containerClassName || ''} is-loading`}>\r\n <div className=\"user-profile-loading\">加载中...</div>\r\n </div>\r\n );\r\n }\r\n\r\n if (errorState) {\r\n return (\r\n <div className={`user-profile-container ${containerClassName || ''} has-error`}>\r\n <div className=\"user-profile-error\">\r\n 错误: {errorState.message}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!userData.name) {\r\n return (\r\n <div className={`user-profile-container ${containerClassName || ''}`}>\r\n <div className=\"user-profile-loading\">未登录</div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={`user-profile-container ${containerClassName || ''}`}>\r\n <Submenu\r\n trigger={renderUserInfo ? renderUserInfo(userData) : renderDefaultUserInfo()}\r\n items={menuItems.map(item => ({\r\n ...item,\r\n onClick: () => handleMenuItemClick(item)\r\n }))}\r\n position=\"bottom\"\r\n alignment=\"end\"\r\n onOpen={handleMenuOpen}\r\n onClose={handleMenuClose}\r\n renderItem={renderMenuItem ? (item) => renderMenuItem(item, userData) : _renderDefaultMenuItem}\r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default UserProfile;","import React from 'react';\r\nimport Submenu from '../Submenu/Submenu';\r\nimport UserProfile from '../UserProfile/UserProfile';\r\nimport type { SubmenuItem } from '../Submenu/Submenu';\r\nimport type { MathWizHeaderProps, ExploreItem } from './MathWizHeader.types';\r\nimport './MathWizHeader.css';\r\n\r\n// 默认探索菜单项渲染函数\r\nconst defaultRenderExploreItem = (item: ExploreItem) => (\r\n <div\r\n key={item.id}\r\n className=\"explore-menu-item\"\r\n onClick={() => item.onClick?.(item)}\r\n >\r\n <span className=\"explore-item-label\">{item.label}</span>\r\n {item.status && (\r\n <span className={`explore-item-status status-${item.status.toLowerCase().replace('%', '').replace(' ', '-')}`}>\r\n {item.status}\r\n </span>\r\n )}\r\n </div>\r\n);\r\n\r\n// 默认探索菜单触发器\r\nconst _ExploreTrigger = ({ className }: { className?: string }) => (\r\n <button className={className} aria-label=\"探索数学课程\">\r\n <span className=\"explore-icon\">🌍</span>\r\n <span className=\"explore-text\">探索</span>\r\n </button>\r\n);\r\n\r\nconst MathWizHeader: React.FC<MathWizHeaderProps> = ({\r\n // 通用Props\r\n className = '',\r\n style,\r\n logoHref = '/',\r\n logoText = 'MathWiz',\r\n onLogoClick,\r\n\r\n // 探索菜单Props\r\n exploreItems = [],\r\n exploreMenuOpen = false,\r\n onExploreMenuToggle,\r\n onExploreItemClick,\r\n renderExploreItem = defaultRenderExploreItem,\r\n\r\n // 用户资料Props\r\n userData,\r\n userMenuItems,\r\n onUserMenuItemClick,\r\n onLogout,\r\n\r\n // 状态控制Props\r\n isLoading = false,\r\n error = null,\r\n\r\n // 样式定制Props\r\n headerClassName = '',\r\n logoClassName = '',\r\n exploreClassName = '',\r\n userProfileClassName = '',\r\n\r\n // 新增参数化样式Props\r\n variant = 'gradient',\r\n color,\r\n background,\r\n height,\r\n gradientFrom,\r\n gradientTo,\r\n gradientVia,\r\n logoColor,\r\n logoSize = 'md',\r\n exploreButtonVariant = 'flat',\r\n exploreButtonColor = 'primary',\r\n\r\n // 无障碍访问Props\r\n 'aria-label': ariaLabel,\r\n 'aria-labelledby': ariaLabelledBy,\r\n\r\n ...restProps\r\n}) => {\r\n // 准备探索菜单项数据 - 纯数据转换,无业务逻辑\r\n const preparedExploreItems: SubmenuItem[] = exploreItems.map(item => ({\r\n id: item.id,\r\n label: renderExploreItem(item),\r\n onClick: () => onExploreItemClick?.(item)\r\n }));\r\n\r\n // 构建动态类名\r\n const headerClassNames = [\r\n 'mathwiz-header',\r\n `mathwiz-header--${variant}`,\r\n color && `mathwiz-header--color-${color}`,\r\n headerClassName,\r\n className\r\n ].filter(Boolean).join(' ');\r\n\r\n const logoClassNames = [\r\n 'logo',\r\n `logo--${logoSize}`,\r\n logoClassName\r\n ].filter(Boolean).join(' ');\r\n\r\n const exploreButtonClassNames = [\r\n 'explore-button',\r\n `explore-button--${exploreButtonVariant}`,\r\n `explore-button--color-${exploreButtonColor}`,\r\n exploreClassName\r\n ].filter(Boolean).join(' ');\r\n\r\n // 构建内联样式\r\n const headerStyles: React.CSSProperties = {\r\n ...style,\r\n ...(height && { height: typeof height === 'number' ? `${height}px` : height }),\r\n ...(background && { '--custom-bg': background } as React.CSSProperties),\r\n ...(logoColor && { '--logo-color': logoColor } as React.CSSProperties),\r\n ...(gradientFrom && gradientTo && {\r\n '--header-bg': gradientVia\r\n ? `linear-gradient(to right, ${gradientFrom}, ${gradientVia}, ${gradientTo})`\r\n : `linear-gradient(to right, ${gradientFrom}, ${gradientTo})`\r\n } as React.CSSProperties)\r\n };\r\n\r\n return (\r\n <header\r\n className={headerClassNames}\r\n style={headerStyles}\r\n aria-label={ariaLabel}\r\n aria-labelledby={ariaLabelledBy}\r\n role=\"banner\"\r\n {...restProps}\r\n >\r\n <div className=\"header-content\">\r\n {/* 左侧:探索菜单 */}\r\n <div className=\"header-section left\">\r\n <Submenu\r\n trigger={<_ExploreTrigger className={exploreButtonClassNames} />}\r\n items={preparedExploreItems}\r\n position=\"bottom\"\r\n alignment=\"start\"\r\n openDelay={300}\r\n closeDelay={100}\r\n onOpen={() => onExploreMenuToggle?.(true)}\r\n onClose={() => onExploreMenuToggle?.(false)}\r\n className=\"explore-submenu\"\r\n menuClassName=\"explore-panel\"\r\n />\r\n </div>\r\n\r\n {/* 中间:Logo */}\r\n <div className=\"header-section center\">\r\n <a\r\n href={logoHref}\r\n className={logoClassNames}\r\n onClick={onLogoClick}\r\n aria-label=\"MathWiz 首页\"\r\n >\r\n {logoText}\r\n </a>\r\n </div>\r\n\r\n {/* 右侧:用户资料 */}\r\n <div className=\"header-section right\">\r\n <UserProfile\r\n userName={userData?.name}\r\n userAvatar={userData?.avatar}\r\n menuItems={userMenuItems}\r\n onMenuItemClick={onUserMenuItemClick}\r\n onLogout={onLogout}\r\n containerClassName={userProfileClassName}\r\n isLoading={isLoading}\r\n error={error}\r\n />\r\n </div>\r\n </div>\r\n </header>\r\n );\r\n};\r\n\r\n// 使用 React.memo 优化性能,避免不必要的重渲染\r\nexport default React.memo(MathWizHeader, (prevProps, nextProps) => {\r\n // 自定义比较函数,只在相关props变化时重渲染\r\n return (\r\n prevProps.logoText === nextProps.logoText &&\r\n prevProps.logoHref === nextProps.logoHref &&\r\n prevProps.className === nextProps.className &&\r\n prevProps.headerClassName === nextProps.headerClassName &&\r\n prevProps.logoClassName === nextProps.logoClassName &&\r\n prevProps.exploreClassName === nextProps.exploreClassName &&\r\n prevProps.userProfileClassName === nextProps.userProfileClassName &&\r\n prevProps['aria-label'] === nextProps['aria-label'] &&\r\n prevProps['aria-labelledby'] === nextProps['aria-labelledby'] &&\r\n prevProps.isLoading === nextProps.isLoading &&\r\n prevProps.error === nextProps.error &&\r\n // 新增样式参数比较\r\n prevProps.variant === nextProps.variant &&\r\n prevProps.color === nextProps.color &&\r\n prevProps.background === nextProps.background &&\r\n prevProps.height === nextProps.height &&\r\n prevProps.gradientFrom === nextProps.gradientFrom &&\r\n prevProps.gradientTo === nextProps.gradientTo &&\r\n prevProps.gradientVia === nextProps.gradientVia &&\r\n prevProps.logoColor === nextProps.logoColor &&\r\n prevProps.logoSize === nextProps.logoSize &&\r\n prevProps.exploreButtonVariant === nextProps.exploreButtonVariant &&\r\n prevProps.exploreButtonColor === nextProps.exploreButtonColor &&\r\n // 深度比较数组\r\n JSON.stringify(prevProps.exploreItems) === JSON.stringify(nextProps.exploreItems) &&\r\n // 深度比较对象\r\n JSON.stringify(prevProps.userData) === JSON.stringify(nextProps.userData) &&\r\n JSON.stringify(prevProps.userMenuItems) === JSON.stringify(nextProps.userMenuItems)\r\n );\r\n});","import React, { useMemo, useEffect } from 'react';\r\nimport { renderToString } from 'katex';\r\nimport './EquationRender.css';\r\nimport type { EquationRenderProps } from './types';\r\n\r\n\r\nconst EquationRender: React.FC<EquationRenderProps> = React.memo(\r\n ({\r\n parts = [],\r\n children = null,\r\n fontSize = '1rem',\r\n color = '#333333',\r\n displayMode = false,\r\n className = ''\r\n }) => {\r\n // 开发环境警告:提醒用户引入 KaTeX CSS\r\n useEffect(() => {\r\n if (process.env.NODE_ENV === 'development' && typeof window !== 'undefined') {\r\n // 检查是否已加载 KaTeX CSS\r\n const hasKaTeXCSS = Array.from(document.styleSheets).some(sheet => {\r\n try {\r\n return sheet.href && sheet.href.includes('katex');\r\n } catch {\r\n // 跨域样式表会抛出安全错误\r\n return false;\r\n }\r\n });\r\n\r\n if (!hasKaTeXCSS) {\r\n console.warn(\r\n 'EquationRender: KaTeX CSS 未检测到。请确保在项目入口文件中导入 KaTeX CSS:\\n' +\r\n \"import 'katex/dist/katex.min.css';\\n\" +\r\n '更多详情请参考组件库文档。'\r\n );\r\n }\r\n }\r\n }, []);\r\n\r\n // 使用 useMemo 缓存 KaTeX 渲染结果\r\n const renderedParts = useMemo(() => {\r\n // Handle empty parts array\r\n if (parts.length === 0) {\r\n return [];\r\n }\r\n\r\n // 使用 KaTeX 渲染公式\r\n return parts.map((part, index) => {\r\n try {\r\n return renderToString(part, {\r\n displayMode,\r\n throwOnError: false,\r\n errorColor: '#ff0000'\r\n });\r\n } catch (error) {\r\n console.error(`KaTeX rendering error in part ${index}:`, error);\r\n return `<span style=\"color: red;\">KaTeX Error</span>`;\r\n }\r\n });\r\n }, [parts, displayMode]);\r\n\r\n // Handle empty parts array\r\n if (parts.length === 0) {\r\n return null;\r\n }\r\n\r\n // Determine root element type\r\n const RootElement = displayMode ? 'div' : 'span';\r\n\r\n // Convert children to array for consistent handling\r\n const childrenArray = React.Children.toArray(children);\r\n\r\n // Build render content by interleaving rendered parts and children\r\n const renderContent: React.ReactNode[] = [];\r\n renderedParts.forEach((renderedPart, index) => {\r\n renderContent.push(\r\n <span\r\n key={`part-${index}`}\r\n dangerouslySetInnerHTML={{ __html: renderedPart }}\r\n style={{ display: 'inline-block' }}\r\n />\r\n );\r\n\r\n // Insert children between parts (only if we have children for this slot)\r\n if (index < childrenArray.length && index < parts.length - 1) {\r\n renderContent.push(\r\n <span key={`slot-${index}`} style={{ display: 'inline-block' }}>\r\n {childrenArray[index]}\r\n </span>\r\n );\r\n }\r\n });\r\n\r\n return (\r\n <RootElement\r\n className={`equation-render ${className}`.trim()}\r\n style={{\r\n fontSize,\r\n color,\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '0.3em',\r\n ...(displayMode ? { justifyContent: 'center', margin: '1em 0' } : {})\r\n }}\r\n >\r\n {renderContent}\r\n </RootElement>\r\n );\r\n }\r\n);\r\n\r\nexport default EquationRender;","// ========== 统一变换类型定义 ==========\r\n// 这个文件定义了统一的变换类型,用于替代现有的TransformConfig\r\n// 解决空composite数组问题,提供清晰的类型系统\r\n\r\nimport type { SingleTransform } from './primitives';\r\nimport type { CompositeTransformConfig } from './composition';\r\n\r\n// 统一的变换类型(替代现有的TransformConfig)\r\nexport type TransformConfig = SingleTransform | CompositeTransformConfig;\r\n\r\n// 类型守卫函数\r\nexport function isSingleTransform(config: TransformConfig): config is SingleTransform {\r\n return config.type !== 'composite';\r\n}\r\n\r\nexport function isCompositeTransform(config: TransformConfig): config is CompositeTransformConfig {\r\n return config.type === 'composite';\r\n}\r\n\r\n// 验证变换配置\r\nexport function validateTransformConfig(config: TransformConfig): boolean {\r\n if (isSingleTransform(config)) {\r\n // 导入validateSingleTransform函数\r\n // 这里暂时简化,实际应该从primitives.ts导入\r\n return config.type !== undefined && config.config !== undefined;\r\n } else if (isCompositeTransform(config)) {\r\n // 导入validateCompositeTransformConfig函数\r\n // 这里暂时简化\r\n return config.type === 'composite' && Array.isArray(config.transforms);\r\n }\r\n return false;\r\n}\r\n\r\n// 获取变换信息(统一接口)\r\nexport function getTransformInfo(config: TransformConfig) {\r\n if (isSingleTransform(config)) {\r\n return {\r\n count: 1,\r\n types: [config.type],\r\n groups: config.targetGroup ? [config.targetGroup] : [],\r\n executionMode: 'sequential' as const,\r\n };\r\n } else {\r\n // 从composition.ts导入getTransformInfo函数\r\n // 这里暂时简化\r\n const types = config.transforms.map(t => t.type);\r\n const groups = Array.from(\r\n new Set(\r\n config.transforms\r\n .map(t => t.targetGroup)\r\n .filter((group): group is string => group !== undefined)\r\n )\r\n );\r\n\r\n return {\r\n count: config.transforms.length,\r\n types,\r\n groups,\r\n executionMode: config.executionMode,\r\n };\r\n }\r\n}\r\n\r\n// 检查是否为空配置(用于解决空composite数组问题)\r\nexport function isEmptyTransform(config: TransformConfig): boolean {\r\n if (isCompositeTransform(config)) {\r\n return config.transforms.length === 0;\r\n }\r\n return false;\r\n}\r\n\r\n// 创建默认变换配置(向后兼容性辅助函数)\r\nexport function createDefaultTransform(): TransformConfig {\r\n // 返回一个简单的平移变换作为默认值\r\n return {\r\n type: 'translation',\r\n config: {\r\n direction: 'horizontal',\r\n distance: 0,\r\n },\r\n };\r\n}\r\n\r\n// 转换函数:从旧格式转换为新格式\r\nexport function convertLegacyTransformConfig(legacyConfig: any): TransformConfig {\r\n // 这是一个简化的转换函数,实际实现需要考虑更多细节\r\n if (!legacyConfig) {\r\n return createDefaultTransform();\r\n }\r\n\r\n // 如果已经是新格式的composite变换,递归转换其中的子变换\r\n if (legacyConfig.type === 'composite' && Array.isArray(legacyConfig.transforms)) {\r\n // 递归转换每个子变换,确保它们都是新格式\r\n const transforms: SingleTransform[] = legacyConfig.transforms.map((transform: any) => {\r\n // 递归转换子变换\r\n return convertLegacyTransformConfig(transform) as SingleTransform;\r\n });\r\n\r\n return {\r\n type: 'composite',\r\n transforms,\r\n executionMode: legacyConfig.executionMode || 'sequential',\r\n } as CompositeTransformConfig;\r\n }\r\n\r\n if (legacyConfig.type && legacyConfig.config) {\r\n return legacyConfig as SingleTransform;\r\n }\r\n\r\n // 处理旧的TransformConfig格式\r\n const oldConfig = legacyConfig as {\r\n type: 'rotation' | 'translation' | 'scale' | 'composite';\r\n rotation?: any;\r\n translation?: any;\r\n scale?: any;\r\n composite?: any[];\r\n targetGroup?: string;\r\n };\r\n\r\n if (oldConfig.type === 'composite' && Array.isArray(oldConfig.composite)) {\r\n // 转换旧的composite格式\r\n const transforms: SingleTransform[] = oldConfig.composite.map((item, _index) => {\r\n // 递归转换子配置\r\n const converted = convertLegacyTransformConfig(item) as SingleTransform;\r\n return converted;\r\n });\r\n\r\n return {\r\n type: 'composite',\r\n transforms,\r\n executionMode: 'sequential', // 默认顺序执行\r\n };\r\n }\r\n\r\n // 转换单一变换\r\n let config: any;\r\n let type: 'translation' | 'rotation' | 'scale' = 'translation';\r\n\r\n if (oldConfig.rotation) {\r\n type = 'rotation';\r\n config = oldConfig.rotation;\r\n } else if (oldConfig.translation) {\r\n type = 'translation';\r\n config = oldConfig.translation;\r\n } else if (oldConfig.scale) {\r\n type = 'scale';\r\n config = oldConfig.scale;\r\n } else {\r\n // 默认值\r\n type = 'translation';\r\n config = { direction: 'horizontal', distance: 0 };\r\n }\r\n\r\n return {\r\n type,\r\n config,\r\n targetGroup: oldConfig.targetGroup,\r\n };\r\n}","import type { GeometryShape } from '../types';\r\nimport type { TransformConfig } from '../types/transform';\r\nimport { isSingleTransform, isCompositeTransform, convertLegacyTransformConfig } from '../types/transform';\r\n\r\n/**\r\n * 计算多边形的质心\r\n */\r\nexport const calculateCentroid = (vertices: Array<[number, number]>): [number, number] => {\r\n if (vertices.length === 0) return [0, 0];\r\n\r\n let sumX = 0;\r\n let sumY = 0;\r\n\r\n for (const [x, y] of vertices) {\r\n sumX += x;\r\n sumY += y;\r\n }\r\n\r\n return [sumX / vertices.length, sumY / vertices.length];\r\n};\r\n\r\n/**\r\n * 计算多边形的面积(用于刚体变换验证)\r\n */\r\nexport const calculatePolygonArea = (vertices: Array<[number, number]>): number => {\r\n if (vertices.length < 3) return 0;\r\n\r\n let area = 0;\r\n const n = vertices.length;\r\n\r\n for (let i = 0; i < n; i++) {\r\n const [x1, y1] = vertices[i];\r\n const [x2, y2] = vertices[(i + 1) % n];\r\n area += x1 * y2 - x2 * y1;\r\n }\r\n\r\n return Math.abs(area) / 2;\r\n};\r\n\r\n/**\r\n * 计算两点之间的距离\r\n */\r\nexport const calculateDistance = (point1: [number, number], point2: [number, number]): number => {\r\n const [x1, y1] = point1;\r\n const [x2, y2] = point2;\r\n return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));\r\n};\r\n\r\n/**\r\n * 验证单个变换配置的有效性\r\n */\r\nexport const validateSingleTransformConfig = (config: TransformConfig): string | null => {\r\n // 检查是否是单一变换\r\n if (isSingleTransform(config)) {\r\n const transform = config;\r\n if (!transform.config) {\r\n return `${transform.type}变换缺少配置`;\r\n }\r\n\r\n switch (transform.type) {\r\n case 'translation':\r\n if ((transform.config as any).distance <= 0) return '平移距离必须大于0';\r\n break;\r\n case 'rotation':\r\n if ((transform.config as any).startAngle === (transform.config as any).endAngle) {\r\n return '旋转起始角度和结束角度不能相同';\r\n }\r\n break;\r\n case 'scale':\r\n const scaleConfig = transform.config as any;\r\n if (scaleConfig.startScale <= 0 || scaleConfig.endScale <= 0) {\r\n return '缩放比例必须大于0';\r\n }\r\n break;\r\n }\r\n return null;\r\n }\r\n\r\n // 检查是否是复合变换\r\n if (isCompositeTransform(config)) {\r\n const compositeConfig = config;\r\n if (!compositeConfig.transforms) {\r\n return '复合变换缺少transforms字段';\r\n }\r\n\r\n // 允许空数组(根据用户决策)\r\n // 递归验证子变换\r\n for (const subConfig of compositeConfig.transforms) {\r\n const error = validateSingleTransformConfig(subConfig);\r\n if (error) return `复合变换子配置错误: ${error}`;\r\n }\r\n return null;\r\n }\r\n\r\n // 未知的变换类型\r\n return '未知的变换配置类型';\r\n};\r\n\r\n/**\r\n * 验证几何配置的有效性(支持形状专属transform)\r\n */\r\nexport const validateGeometryConfig = (\r\n base: number,\r\n height: number,\r\n shapes: { static: GeometryShape[]; animated: GeometryShape[] },\r\n transform: TransformConfig\r\n): string | null => {\r\n // 验证基础参数\r\n if (base <= 0) return '底边长度必须大于0';\r\n if (height <= 0) return '高度必须大于0';\r\n\r\n // 验证图形数据(允许空图形数组,用于加载状态)\r\n // 注意:空图形数组是有效的,表示加载状态或初始状态\r\n if (shapes.animated.length === 0) {\r\n return '至少需要一个动画图形';\r\n }\r\n\r\n // 验证全局变换配置\r\n const globalTransformError = validateSingleTransformConfig(transform);\r\n if (globalTransformError) {\r\n return `全局变换配置错误: ${globalTransformError}`;\r\n }\r\n\r\n // 验证每个动画图形的形状专属transform\r\n for (const shape of shapes.animated) {\r\n if (shape.transform) {\r\n // 将旧的transform格式转换为新格式进行验证\r\n const newShapeTransform = convertLegacyTransformConfig(shape.transform);\r\n const shapeTransformError = validateSingleTransformConfig(newShapeTransform);\r\n if (shapeTransformError) {\r\n return `形状\"${shape.metadata?.id || '未知'}\"专属变换配置错误: ${shapeTransformError}`;\r\n }\r\n }\r\n }\r\n\r\n // 验证形状顶点数据\r\n for (const shape of [...shapes.static, ...shapes.animated]) {\r\n if (!shape.vertices || shape.vertices.length < 2) {\r\n return `形状\"${shape.metadata?.id || '未知'}\"缺少有效的顶点数据`;\r\n }\r\n for (const vertex of shape.vertices) {\r\n if (!Array.isArray(vertex) || vertex.length !== 2) {\r\n return `形状\"${shape.metadata?.id || '未知'}\"顶点格式错误`;\r\n }\r\n const [x, y] = vertex;\r\n if (typeof x !== 'number' || typeof y !== 'number' || !isFinite(x) || !isFinite(y)) {\r\n return `形状\"${shape.metadata?.id || '未知'}\"顶点坐标无效`;\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n};","import type { GeometryTransformProps, GeometryTransformError } from '../types';\r\nimport { validateGeometryConfig as validateGeometry } from './geometryCalculations';\r\nimport { convertLegacyTransformConfig } from '../types/transform';\r\n\r\n/**\r\n * 验证几何配置并返回错误对象\r\n */\r\nexport const validateGeometryConfig = (\r\n props: Pick<GeometryTransformProps, 'base' | 'height' | 'shapes' | 'transform'>\r\n): GeometryTransformError | null => {\r\n const { base, height, shapes, transform } = props;\r\n\r\n // 将旧的transform格式转换为新格式进行验证\r\n const newTransform = convertLegacyTransformConfig(transform);\r\n\r\n const errorMessage = validateGeometry(base, height, shapes, newTransform);\r\n\r\n if (errorMessage) {\r\n return {\r\n code: 'INVALID_CONFIG',\r\n message: errorMessage,\r\n timestamp: new Date().toISOString()\r\n };\r\n }\r\n\r\n return null;\r\n};\r\n\r\n/**\r\n * 验证动画配置\r\n * 注意:slider配置是可选的,因为组件使用HeroUI Slider而不是JSXGraph slider\r\n */\r\nexport const validateAnimationConfig = (\r\n animation: GeometryTransformProps['animation']\r\n): string | null => {\r\n // slider配置是可选的\r\n if (animation.slider) {\r\n const { slider } = animation;\r\n\r\n if (slider.length <= 0) {\r\n return '滑块长度必须大于0';\r\n }\r\n\r\n if (slider.min !== undefined && slider.max !== undefined && slider.min >= slider.max) {\r\n return '滑块最小值必须小于最大值';\r\n }\r\n\r\n if (slider.step !== undefined && slider.step <= 0) {\r\n return '滑块步长必须大于0';\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\n/**\r\n * 验证画板配置\r\n */\r\nexport const validateBoardConfig = (\r\n boardConfig: GeometryTransformProps['boardConfig']\r\n): string | null => {\r\n if (!boardConfig) return null;\r\n\r\n if (boardConfig.boundingBox) {\r\n const [left, top, right, bottom] = boardConfig.boundingBox;\r\n if (left >= right || top <= bottom) {\r\n return '画板边界框配置无效:left < right 且 top > bottom';\r\n }\r\n }\r\n\r\n if (boardConfig.gridSize !== undefined && boardConfig.gridSize <= 0) {\r\n return '网格大小必须大于0';\r\n }\r\n\r\n return null;\r\n};\r\n\r\n/**\r\n * 完整的配置验证\r\n */\r\nexport const validateAllConfigs = (\r\n props: GeometryTransformProps\r\n): GeometryTransformError | null => {\r\n // 验证几何配置\r\n const geometryError = validateGeometryConfig({\r\n base: props.base,\r\n height: props.height,\r\n shapes: props.shapes,\r\n transform: props.transform\r\n });\r\n\r\n if (geometryError) return geometryError;\r\n\r\n // 验证动画配置\r\n const animationError = validateAnimationConfig(props.animation);\r\n if (animationError) {\r\n return {\r\n code: 'INVALID_CONFIG',\r\n message: animationError,\r\n timestamp: new Date().toISOString()\r\n };\r\n }\r\n\r\n // 验证画板配置\r\n const boardError = validateBoardConfig(props.boardConfig);\r\n if (boardError) {\r\n return {\r\n code: 'INVALID_CONFIG',\r\n message: boardError,\r\n timestamp: new Date().toISOString()\r\n };\r\n }\r\n\r\n // 验证自动完成阈值\r\n if (props.autoCompleteThreshold !== undefined) {\r\n if (props.autoCompleteThreshold < 0 || props.autoCompleteThreshold > 1) {\r\n return {\r\n code: 'INVALID_CONFIG',\r\n message: '自动完成阈值必须在0到1之间',\r\n timestamp: new Date().toISOString()\r\n };\r\n }\r\n }\r\n\r\n return null;\r\n};","// ========== 变换执行器接口定义 ==========\r\n// 这个文件定义了变换执行器的接口,作为三层架构的第一层核心\r\n\r\nimport type {\r\n TransformPrimitiveConfig,\r\n} from '../types/primitives';\r\n\r\n// 顶点类型\r\nexport type Vertex = [number, number];\r\n\r\n// 验证结果接口\r\nexport interface ValidationResult {\r\n isValid: boolean;\r\n errors?: string[];\r\n warnings?: string[];\r\n}\r\n\r\n// 变换执行器接口(泛型接口,支持不同类型的配置)\r\nexport interface ITransformExecutor<TConfig extends TransformPrimitiveConfig> {\r\n readonly type: string;\r\n\r\n /**\r\n * 执行变换算法\r\n * @param vertices 原始顶点数组\r\n * @param progress 进度值(0-1)\r\n * @param config 变换配置\r\n * @returns 变换后的顶点数组\r\n */\r\n execute(vertices: Vertex[], progress: number, config: TConfig): Vertex[];\r\n\r\n /**\r\n * 验证配置是否有效\r\n * @param config 变换配置\r\n * @returns 验证结果\r\n */\r\n validate(config: TConfig): ValidationResult;\r\n\r\n /**\r\n * 获取配置的默认值\r\n * @returns 默认配置\r\n */\r\n getDefaultConfig(): TConfig;\r\n\r\n /**\r\n * 获取变换的显示名称\r\n * @returns 显示名称\r\n */\r\n getDisplayName(): string;\r\n\r\n /**\r\n * 获取变换的描述信息\r\n * @returns 描述信息\r\n */\r\n getDescription(): string;\r\n}\r\n\r\n// 抽象基类,提供一些通用功能\r\nexport abstract class BaseTransformExecutor<TConfig extends TransformPrimitiveConfig>\r\n implements ITransformExecutor<TConfig> {\r\n\r\n abstract readonly type: string;\r\n\r\n abstract execute(vertices: Vertex[], progress: number, config: TConfig): Vertex[];\r\n\r\n abstract validate(config: TConfig): ValidationResult;\r\n\r\n abstract getDefaultConfig(): TConfig;\r\n\r\n abstract getDisplayName(): string;\r\n\r\n abstract getDescription(): string;\r\n\r\n // 通用验证方法\r\n protected validateNumber(value: number, fieldName: string, min?: number, max?: number): string | undefined {\r\n if (typeof value !== 'number' || isNaN(value)) {\r\n return `${fieldName}必须是有效的数字`;\r\n }\r\n\r\n if (min !== undefined && value < min) {\r\n return `${fieldName}不能小于${min}`;\r\n }\r\n\r\n if (max !== undefined && value > max) {\r\n return `${fieldName}不能大于${max}`;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n protected validateArray(value: any[], fieldName: string, length?: number): string | undefined {\r\n if (!Array.isArray(value)) {\r\n return `${fieldName}必须是数组`;\r\n }\r\n\r\n if (length !== undefined && value.length !== length) {\r\n return `${fieldName}必须是长度为${length}的数组`;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n protected validateString(value: string, fieldName: string, options?: string[]): string | undefined {\r\n if (typeof value !== 'string') {\r\n return `${fieldName}必须是字符串`;\r\n }\r\n\r\n if (options !== undefined && !options.includes(value)) {\r\n return `${fieldName}必须是以下值之一: ${options.join(', ')}`;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n // 创建验证结果\r\n protected createValidationResult(\r\n isValid: boolean,\r\n errors?: string[],\r\n warnings?: string[]\r\n ): ValidationResult {\r\n return {\r\n isValid,\r\n errors: errors?.filter(Boolean),\r\n warnings: warnings?.filter(Boolean),\r\n };\r\n }\r\n\r\n // 通用顶点验证\r\n protected validateVertices(vertices: Vertex[]): string | undefined {\r\n if (!Array.isArray(vertices) || vertices.length === 0) {\r\n return '顶点数组不能为空';\r\n }\r\n\r\n for (let i = 0; i < vertices.length; i++) {\r\n const vertex = vertices[i];\r\n const error = this.validateArray(vertex, `顶点[${i}]`, 2);\r\n if (error) return error;\r\n\r\n const [x, y] = vertex;\r\n const xError = this.validateNumber(x, `顶点[${i}].x`);\r\n const yError = this.validateNumber(y, `顶点[${i}].y`);\r\n\r\n if (xError || yError) {\r\n return `${xError || yError} (顶点[${i}])`;\r\n }\r\n }\r\n\r\n return undefined;\r\n }\r\n}","import type { TransformConfig, TranslationConfig, RotationConfig, ScaleConfig, GeometryShape } from '../types';\r\nimport { calculateCentroid } from './geometryCalculations';\r\n\r\n/**\r\n * 平移变换算法\r\n */\r\nexport const calculateTranslation = (\r\n vertices: [number, number][],\r\n progress: number,\r\n config: TranslationConfig\r\n): [number, number][] => {\r\n // 调试日志\r\n if (process.env.NODE_ENV === 'development') {\r\n console.log('🔧 [calculateTranslation] 调试信息:', {\r\n vertices,\r\n progress,\r\n config,\r\n distance: config.distance,\r\n distanceType: typeof config.distance,\r\n direction: config.direction,\r\n directionType: typeof config.direction,\r\n configType: typeof config,\r\n configKeys: Object.keys(config)\r\n });\r\n }\r\n\r\n let directionVector: [number, number];\r\n\r\n if (config.direction === 'horizontal') {\r\n directionVector = [config.distance, 0];\r\n } else if (config.direction === 'vertical') {\r\n directionVector = [0, config.distance];\r\n } else {\r\n // direction 是数组,需要乘以 distance 得到实际移动向量\r\n directionVector = [\r\n config.direction[0] * config.distance,\r\n config.direction[1] * config.distance\r\n ];\r\n }\r\n\r\n const offsetX = directionVector[0] * progress;\r\n const offsetY = directionVector[1] * progress;\r\n\r\n // 调试日志:计算后的偏移量\r\n if (process.env.NODE_ENV === 'development') {\r\n console.log('📐 [calculateTranslation] 计算结果:', {\r\n directionVector,\r\n offsetX,\r\n offsetY,\r\n firstVertexOriginal: vertices[0],\r\n firstVertexTransformed: [vertices[0][0] + offsetX, vertices[0][1] + offsetY]\r\n });\r\n }\r\n\r\n return vertices.map(([x, y]) => [x + offsetX, y + offsetY]);\r\n};\r\n\r\n/**\r\n * 旋转变换算法(刚体旋转)\r\n */\r\nexport const calculateRotation = (\r\n vertices: [number, number][],\r\n progress: number,\r\n config: RotationConfig\r\n): [number, number][] => {\r\n // 计算旋转中心\r\n const center = config.center === 'auto'\r\n ? calculateCentroid(vertices)\r\n : config.center;\r\n\r\n const [cx, cy] = center;\r\n const angleRange = config.endAngle - config.startAngle;\r\n const direction = config.direction === 'clockwise' ? -1 : 1;\r\n const currentAngle = config.startAngle + (angleRange * progress * direction);\r\n\r\n return vertices.map(([x, y]) => {\r\n const dx = x - cx;\r\n const dy = y - cy;\r\n const cos = Math.cos(currentAngle);\r\n const sin = Math.sin(currentAngle);\r\n\r\n return [\r\n cx + dx * cos - dy * sin,\r\n cy + dx * sin + dy * cos\r\n ];\r\n });\r\n};\r\n\r\n/**\r\n * 缩放变换算法\r\n */\r\nexport const calculateScale = (\r\n vertices: [number, number][],\r\n progress: number,\r\n config: ScaleConfig\r\n): [number, number][] => {\r\n // 计算缩放中心\r\n const center = config.center === 'centroid'\r\n ? calculateCentroid(vertices)\r\n : config.center;\r\n\r\n const [cx, cy] = center;\r\n const scaleRange = config.endScale - config.startScale;\r\n const currentScale = config.startScale + (scaleRange * progress);\r\n\r\n return vertices.map(([x, y]) => {\r\n const dx = x - cx;\r\n const dy = y - cy;\r\n return [\r\n cx + dx * currentScale,\r\n cy + dy * currentScale\r\n ];\r\n });\r\n};\r\n\r\n/**\r\n * 获取有效的变换配置(优先使用形状专属transform)\r\n */\r\nexport const getEffectiveTransform = (\r\n shape: GeometryShape,\r\n globalTransform: TransformConfig\r\n): TransformConfig => {\r\n // 优先使用形状专属transform\r\n if (shape.transform) {\r\n return shape.transform;\r\n }\r\n return globalTransform;\r\n};\r\n\r\n/**\r\n * 过滤变换配置,仅保留适用于当前形状的配置\r\n */\r\nexport const filterTransformConfigs = (\r\n configs: TransformConfig[],\r\n shapeGroup?: string\r\n): TransformConfig[] => {\r\n return configs.filter(config => {\r\n // 如果配置没有targetGroup,适用于所有形状\r\n if (!config.targetGroup) {\r\n return true;\r\n }\r\n // 如果配置有targetGroup,仅适用于匹配的形状组\r\n return config.targetGroup === shapeGroup;\r\n });\r\n};\r\n\r\n/**\r\n * 复合变换算法(支持按组过滤)\r\n */\r\nexport const calculateComposite = (\r\n vertices: [number, number][],\r\n progress: number,\r\n configs: TransformConfig[],\r\n shapeGroup?: string\r\n): [number, number][] => {\r\n // 过滤配置,仅保留适用于当前形状组的配置\r\n const applicableConfigs = filterTransformConfigs(configs, shapeGroup);\r\n\r\n if (applicableConfigs.length === 0) {\r\n return vertices;\r\n }\r\n\r\n let transformedVertices = vertices;\r\n\r\n for (const config of applicableConfigs) {\r\n transformedVertices = calculateTransformedVertices(\r\n transformedVertices,\r\n progress,\r\n config\r\n );\r\n }\r\n\r\n return transformedVertices;\r\n};\r\n\r\n/**\r\n * 主变换计算函数(支持形状metadata和按组过滤)\r\n */\r\nexport const calculateTransformedVertices = (\r\n vertices: [number, number][],\r\n progress: number,\r\n config: TransformConfig,\r\n shapeMetadata?: any\r\n): [number, number][] => {\r\n // 调试日志\r\n if (process.env.NODE_ENV === 'development') {\r\n console.log('🔧 [calculateTransformedVertices] 调试信息:', {\r\n configType: config.type,\r\n config,\r\n vertices,\r\n progress,\r\n shapeMetadata\r\n });\r\n }\r\n\r\n switch (config.type) {\r\n case 'translation':\r\n if (!config.translation) return vertices;\r\n return calculateTranslation(vertices, progress, config.translation);\r\n\r\n case 'rotation':\r\n if (!config.rotation) return vertices;\r\n return calculateRotation(vertices, progress, config.rotation);\r\n\r\n case 'scale':\r\n if (!config.scale) return vertices;\r\n return calculateScale(vertices, progress, config.scale);\r\n\r\n case 'composite':\r\n if (!config.composite) return vertices;\r\n // 传递形状组信息给复合变换算法\r\n const shapeGroup = shapeMetadata?.rotationGroup;\r\n return calculateComposite(vertices, progress, config.composite, shapeGroup);\r\n\r\n default:\r\n return vertices;\r\n }\r\n};\r\n\r\n/**\r\n * 计算形状的变换顶点(整合所有逻辑)\r\n */\r\nexport const calculateShapeTransformedVertices = (\r\n shape: GeometryShape,\r\n progress: number,\r\n globalTransform: TransformConfig\r\n): [number, number][] => {\r\n // 获取有效的变换配置\r\n const effectiveTransform = getEffectiveTransform(shape, globalTransform);\r\n\r\n // 计算变换后的顶点\r\n return calculateTransformedVertices(\r\n shape.vertices,\r\n progress,\r\n effectiveTransform,\r\n shape.metadata\r\n );\r\n};\r\n\r\n/**\r\n * 进度映射算法\r\n */\r\nexport const mapProgressToDistance = (progress: number, base: number): number => {\r\n return progress * base;\r\n};\r\n\r\n/**\r\n * 自动完成检测算法\r\n */\r\nexport const shouldAutoComplete = (\r\n currentProgress: number,\r\n threshold: number = 0.95\r\n): boolean => {\r\n return currentProgress >= threshold;\r\n};","// ========== 平移执行器 ==========\r\n// 这个文件实现了平移变换执行器\r\n\r\nimport { BaseTransformExecutor } from './TransformExecutor';\r\nimport type { TranslationConfig } from '../types/primitives';\r\nimport type { ValidationResult, Vertex } from './TransformExecutor';\r\nimport { calculateTranslation } from '../utils/transformAlgorithms';\r\n\r\n// 平移执行器类\r\nexport class TranslationExecutor extends BaseTransformExecutor<TranslationConfig> {\r\n readonly type = 'translation';\r\n\r\n getDisplayName(): string {\r\n return '平移变换';\r\n }\r\n\r\n getDescription(): string {\r\n return '将图形沿着指定方向移动一定距离';\r\n }\r\n\r\n getDefaultConfig(): TranslationConfig {\r\n return {\r\n direction: 'horizontal',\r\n distance: 5,\r\n startOffset: 0,\r\n };\r\n }\r\n\r\n execute(vertices: Vertex[], progress: number, config: TranslationConfig): Vertex[] {\r\n // 使用现有的计算算法\r\n return calculateTranslation(vertices, progress, config);\r\n }\r\n\r\n validate(config: TranslationConfig): ValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // 验证direction\r\n if (typeof config.direction === 'string') {\r\n // 字符串方向:'horizontal' 或 'vertical'\r\n const directionError = this.validateString(\r\n config.direction,\r\n 'direction',\r\n ['horizontal', 'vertical']\r\n );\r\n if (directionError) errors.push(directionError);\r\n } else if (Array.isArray(config.direction)) {\r\n // 数组方向:[x, y]\r\n const directionError = this.validateArray(config.direction, 'direction', 2);\r\n if (directionError) {\r\n errors.push(directionError);\r\n } else {\r\n // 验证数组元素\r\n const [x, y] = config.direction;\r\n const xError = this.validateNumber(x, 'direction[0]');\r\n const yError = this.validateNumber(y, 'direction[1]');\r\n if (xError) errors.push(xError);\r\n if (yError) errors.push(yError);\r\n }\r\n } else {\r\n errors.push('direction必须是字符串或数组');\r\n }\r\n\r\n // 验证distance\r\n const distanceError = this.validateNumber(config.distance, 'distance', 0);\r\n if (distanceError) errors.push(distanceError);\r\n\r\n // 验证startOffset(可选)\r\n if (config.startOffset !== undefined) {\r\n const offsetError = this.validateNumber(config.startOffset, 'startOffset', 0, 1);\r\n if (offsetError) warnings.push(offsetError);\r\n }\r\n\r\n // 检查方向向量的长度\r\n if (Array.isArray(config.direction)) {\r\n const [x, y] = config.direction;\r\n const length = Math.sqrt(x * x + y * y);\r\n if (length < 0.001) {\r\n warnings.push('方向向量长度过小,可能导致变换效果不明显');\r\n }\r\n }\r\n\r\n return this.createValidationResult(errors.length === 0, errors, warnings);\r\n }\r\n\r\n // 辅助方法:获取方向向量\r\n private getDirectionVector(config: TranslationConfig): [number, number] {\r\n if (config.direction === 'horizontal') {\r\n return [1, 0];\r\n } else if (config.direction === 'vertical') {\r\n return [0, 1];\r\n } else {\r\n return config.direction;\r\n }\r\n }\r\n\r\n // 辅助方法:计算实际移动向量\r\n calculateMovementVector(config: TranslationConfig, progress: number): [number, number] {\r\n const directionVector = this.getDirectionVector(config);\r\n const startOffset = config.startOffset || 0;\r\n const effectiveProgress = Math.max(0, Math.min(1, progress - startOffset)) / (1 - startOffset);\r\n\r\n return [\r\n directionVector[0] * config.distance * effectiveProgress,\r\n directionVector[1] * config.distance * effectiveProgress,\r\n ];\r\n }\r\n}","// ========== 旋转执行器 ==========\r\n// 这个文件实现了旋转变换执行器\r\n\r\nimport { BaseTransformExecutor } from './TransformExecutor';\r\nimport type { RotationConfig } from '../types/primitives';\r\nimport type { ValidationResult, Vertex } from './TransformExecutor';\r\nimport { calculateRotation } from '../utils/transformAlgorithms';\r\nimport { calculateCentroid } from '../utils/geometryCalculations';\r\n\r\n// 旋转执行器类\r\nexport class RotationExecutor extends BaseTransformExecutor<RotationConfig> {\r\n readonly type = 'rotation';\r\n\r\n getDisplayName(): string {\r\n return '旋转变换';\r\n }\r\n\r\n getDescription(): string {\r\n return '将图形围绕指定中心旋转一定角度';\r\n }\r\n\r\n getDefaultConfig(): RotationConfig {\r\n return {\r\n center: 'auto',\r\n startAngle: 0,\r\n endAngle: Math.PI, // 180度\r\n direction: 'clockwise',\r\n };\r\n }\r\n\r\n execute(vertices: Vertex[], progress: number, config: RotationConfig): Vertex[] {\r\n // 使用现有的计算算法\r\n return calculateRotation(vertices, progress, config);\r\n }\r\n\r\n validate(config: RotationConfig): ValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // 验证center\r\n if (config.center === 'auto') {\r\n // 'auto' 是有效的,表示使用质心\r\n } else if (Array.isArray(config.center)) {\r\n const centerError = this.validateArray(config.center, 'center', 2);\r\n if (centerError) {\r\n errors.push(centerError);\r\n } else {\r\n const [x, y] = config.center;\r\n const xError = this.validateNumber(x, 'center[0]');\r\n const yError = this.validateNumber(y, 'center[1]');\r\n if (xError) errors.push(xError);\r\n if (yError) errors.push(yError);\r\n }\r\n } else {\r\n errors.push('center必须是\"auto\"或数组[x, y]');\r\n }\r\n\r\n // 验证startAngle\r\n const startAngleError = this.validateNumber(config.startAngle, 'startAngle');\r\n if (startAngleError) errors.push(startAngleError);\r\n\r\n // 验证endAngle\r\n const endAngleError = this.validateNumber(config.endAngle, 'endAngle');\r\n if (endAngleError) errors.push(endAngleError);\r\n\r\n // 验证角度范围\r\n if (!startAngleError && !endAngleError) {\r\n const angleRange = Math.abs(config.endAngle - config.startAngle);\r\n if (angleRange < 0.001) {\r\n warnings.push('角度范围过小,可能导致变换效果不明显');\r\n }\r\n if (angleRange > 4 * Math.PI) {\r\n warnings.push('角度范围过大,可能超过2圈');\r\n }\r\n }\r\n\r\n // 验证direction\r\n const directionError = this.validateString(\r\n config.direction,\r\n 'direction',\r\n ['clockwise', 'counterclockwise', 'horizontal', 'vertical']\r\n );\r\n if (directionError) errors.push(directionError);\r\n\r\n // 检查旋转中心是否在图形内部(警告)\r\n // 注意:由于validate接口不支持vertices参数,暂时禁用此检查\r\n // if (Array.isArray(config.center) && vertices.length > 0) {\r\n // const [cx, cy] = config.center;\r\n // const bounds = this.calculateBounds(vertices);\r\n // const isInside = cx >= bounds.minX && cx <= bounds.maxX && cy >= bounds.minY && cy <= bounds.maxY;\r\n // if (!isInside) {\r\n // warnings.push('旋转中心不在图形内部,可能导致旋转效果不符合预期');\r\n // }\r\n // }\r\n\r\n return this.createValidationResult(errors.length === 0, errors, warnings);\r\n }\r\n\r\n // 辅助方法:计算顶点的边界框\r\n // @ts-ignore: private method defined but unused\r\n private _calculateBounds(vertices: Vertex[]): { minX: number; maxX: number; minY: number; maxY: number } {\r\n if (vertices.length === 0) {\r\n return { minX: 0, maxX: 0, minY: 0, maxY: 0 };\r\n }\r\n\r\n let minX = vertices[0][0];\r\n let maxX = vertices[0][0];\r\n let minY = vertices[0][1];\r\n let maxY = vertices[0][1];\r\n\r\n for (let i = 1; i < vertices.length; i++) {\r\n const [x, y] = vertices[i];\r\n minX = Math.min(minX, x);\r\n maxX = Math.max(maxX, x);\r\n minY = Math.min(minY, y);\r\n maxY = Math.max(maxY, y);\r\n }\r\n\r\n return { minX, maxX, minY, maxY };\r\n }\r\n\r\n // 辅助方法:获取实际的旋转中心\r\n getActualCenter(vertices: Vertex[], config: RotationConfig): [number, number] {\r\n if (config.center === 'auto') {\r\n return calculateCentroid(vertices);\r\n }\r\n return config.center;\r\n }\r\n\r\n // 辅助方法:计算当前角度\r\n calculateCurrentAngle(config: RotationConfig, progress: number): number {\r\n const angleRange = config.endAngle - config.startAngle;\r\n const direction = config.direction === 'clockwise' ? -1 : 1;\r\n return config.startAngle + (angleRange * progress * direction);\r\n }\r\n}","// ========== 缩放执行器 ==========\r\n// 这个文件实现了缩放变换执行器\r\n\r\nimport { BaseTransformExecutor } from './TransformExecutor';\r\nimport type { ScaleConfig } from '../types/primitives';\r\nimport type { ValidationResult, Vertex } from './TransformExecutor';\r\nimport { calculateScale } from '../utils/transformAlgorithms';\r\nimport { calculateCentroid } from '../utils/geometryCalculations';\r\n\r\n// 缩放执行器类\r\nexport class ScaleExecutor extends BaseTransformExecutor<ScaleConfig> {\r\n readonly type = 'scale';\r\n\r\n getDisplayName(): string {\r\n return '缩放变换';\r\n }\r\n\r\n getDescription(): string {\r\n return '将图形以指定中心进行缩放';\r\n }\r\n\r\n getDefaultConfig(): ScaleConfig {\r\n return {\r\n center: 'centroid',\r\n startScale: 1,\r\n endScale: 2,\r\n uniform: true,\r\n };\r\n }\r\n\r\n execute(vertices: Vertex[], progress: number, config: ScaleConfig): Vertex[] {\r\n // 使用现有的计算算法\r\n return calculateScale(vertices, progress, config);\r\n }\r\n\r\n validate(config: ScaleConfig): ValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // 验证center\r\n if (config.center === 'centroid') {\r\n // 'centroid' 是有效的,表示使用质心\r\n } else if (Array.isArray(config.center)) {\r\n const centerError = this.validateArray(config.center, 'center', 2);\r\n if (centerError) {\r\n errors.push(centerError);\r\n } else {\r\n const [x, y] = config.center;\r\n const xError = this.validateNumber(x, 'center[0]');\r\n const yError = this.validateNumber(y, 'center[1]');\r\n if (xError) errors.push(xError);\r\n if (yError) errors.push(yError);\r\n }\r\n } else {\r\n errors.push('center必须是\"centroid\"或数组[x, y]');\r\n }\r\n\r\n // 验证startScale\r\n const startScaleError = this.validateNumber(config.startScale, 'startScale', 0.01);\r\n if (startScaleError) errors.push(startScaleError);\r\n\r\n // 验证endScale\r\n const endScaleError = this.validateNumber(config.endScale, 'endScale', 0.01);\r\n if (endScaleError) errors.push(endScaleError);\r\n\r\n // 验证缩放比例范围\r\n if (!startScaleError && !endScaleError) {\r\n const scaleRatio = config.endScale / config.startScale;\r\n\r\n if (Math.abs(config.endScale - config.startScale) < 0.01) {\r\n warnings.push('缩放比例变化过小,可能导致变换效果不明显');\r\n }\r\n\r\n if (scaleRatio > 10) {\r\n warnings.push('缩放比例过大,可能导致图形变形严重');\r\n }\r\n\r\n if (scaleRatio < 0.1) {\r\n warnings.push('缩放比例过小,可能导致图形几乎不可见');\r\n }\r\n }\r\n\r\n // 验证uniform\r\n if (typeof config.uniform !== 'boolean') {\r\n errors.push('uniform必须是布尔值');\r\n } else if (!config.uniform) {\r\n warnings.push('非均匀缩放可能导致图形变形');\r\n }\r\n\r\n // 检查缩放中心是否在图形内部(警告)\r\n // 注意:由于validate接口不支持vertices参数,暂时禁用此检查\r\n // if (Array.isArray(config.center) && vertices && vertices.length > 0) {\r\n // // 注意:这里vertices可能为空,在实际使用时需要检查\r\n // warnings.push('缩放中心验证需要顶点数据,将在执行时进行');\r\n // }\r\n\r\n return this.createValidationResult(errors.length === 0, errors, warnings);\r\n }\r\n\r\n // 辅助方法:获取实际的缩放中心\r\n getActualCenter(vertices: Vertex[], config: ScaleConfig): [number, number] {\r\n if (config.center === 'centroid') {\r\n return calculateCentroid(vertices);\r\n }\r\n return config.center;\r\n }\r\n\r\n // 辅助方法:计算当前缩放比例\r\n calculateCurrentScale(config: ScaleConfig, progress: number): number {\r\n const scaleRange = config.endScale - config.startScale;\r\n return config.startScale + (scaleRange * progress);\r\n }\r\n\r\n // 辅助方法:计算缩放后的尺寸变化\r\n calculateSizeChange(vertices: Vertex[], config: ScaleConfig, progress: number): {\r\n widthChange: number;\r\n heightChange: number;\r\n areaChange: number;\r\n } {\r\n if (vertices.length < 2) {\r\n return { widthChange: 0, heightChange: 0, areaChange: 0 };\r\n }\r\n\r\n const bounds = this.calculateBounds(vertices);\r\n const originalWidth = bounds.maxX - bounds.minX;\r\n const originalHeight = bounds.maxY - bounds.minY;\r\n const originalArea = originalWidth * originalHeight;\r\n\r\n const currentScale = this.calculateCurrentScale(config, progress);\r\n const scaleFactor = config.uniform ? currentScale : currentScale;\r\n\r\n const newWidth = originalWidth * scaleFactor;\r\n const newHeight = originalHeight * scaleFactor;\r\n const newArea = newWidth * newHeight;\r\n\r\n return {\r\n widthChange: (newWidth - originalWidth) / originalWidth,\r\n heightChange: (newHeight - originalHeight) / originalHeight,\r\n areaChange: (newArea - originalArea) / originalArea,\r\n };\r\n }\r\n\r\n // 辅助方法:计算顶点的边界框\r\n private calculateBounds(vertices: Vertex[]): { minX: number; maxX: number; minY: number; maxY: number } {\r\n if (vertices.length === 0) {\r\n return { minX: 0, maxX: 0, minY: 0, maxY: 0 };\r\n }\r\n\r\n let minX = vertices[0][0];\r\n let maxX = vertices[0][0];\r\n let minY = vertices[0][1];\r\n let maxY = vertices[0][1];\r\n\r\n for (let i = 1; i < vertices.length; i++) {\r\n const [x, y] = vertices[i];\r\n minX = Math.min(minX, x);\r\n maxX = Math.max(maxX, x);\r\n minY = Math.min(minY, y);\r\n maxY = Math.max(maxY, y);\r\n }\r\n\r\n return { minX, maxX, minY, maxY };\r\n }\r\n}","// ========== 颜色工具函数 ==========\r\n// 这个文件提供颜色插值、格式转换等工具函数\r\n\r\n/**\r\n * 将十六进制颜色字符串转换为RGB数值数组\r\n * @param hex 十六进制颜色字符串,支持格式: #RGB, #RGBA, #RRGGBB, #RRGGBBAA\r\n * @returns RGB数组 [r, g, b],值范围 0-255\r\n * @throws 如果颜色格式无效\r\n */\r\nexport function hexToRgb(hex: string): [number, number, number] {\r\n // 移除前缀\r\n let cleanHex = hex.trim().replace(/^#/, '');\r\n\r\n // 处理缩写格式\r\n if (cleanHex.length === 3 || cleanHex.length === 4) {\r\n cleanHex = cleanHex.split('').map(ch => ch + ch).join('');\r\n }\r\n\r\n if (cleanHex.length !== 6 && cleanHex.length !== 8) {\r\n throw new Error(`无效的十六进制颜色格式: ${hex}`);\r\n }\r\n\r\n // 提取RGB部分(忽略可选的Alpha通道)\r\n const r = parseInt(cleanHex.substring(0, 2), 16);\r\n const g = parseInt(cleanHex.substring(2, 4), 16);\r\n const b = parseInt(cleanHex.substring(4, 6), 16);\r\n\r\n if (isNaN(r) || isNaN(g) || isNaN(b)) {\r\n throw new Error(`无效的十六进制颜色值: ${hex}`);\r\n }\r\n\r\n return [r, g, b];\r\n}\r\n\r\n/**\r\n * 将RGB数值转换为十六进制颜色字符串\r\n * @param r 红色分量 (0-255)\r\n * @param g 绿色分量 (0-255)\r\n * @param b 蓝色分量 (0-255)\r\n * @returns 十六进制颜色字符串,格式: #RRGGBB\r\n */\r\nexport function rgbToHex(r: number, g: number, b: number): string {\r\n // 确保值在有效范围内\r\n const clamp = (value: number) => Math.max(0, Math.min(255, Math.round(value)));\r\n\r\n const rHex = clamp(r).toString(16).padStart(2, '0');\r\n const gHex = clamp(g).toString(16).padStart(2, '0');\r\n const bHex = clamp(b).toString(16).padStart(2, '0');\r\n\r\n return `#${rHex}${gHex}${bHex}`.toUpperCase();\r\n}\r\n\r\n/**\r\n * 解析颜色字符串,支持十六进制和RGB格式\r\n * @param color 颜色字符串,支持格式: #RGB, #RGBA, #RRGGBB, #RRGGBBAA, rgb(r,g,b), rgba(r,g,b,a)\r\n * @returns RGB数组 [r, g, b],值范围 0-255\r\n * @throws 如果颜色格式无效\r\n */\r\nexport function parseColor(color: string): [number, number, number] {\r\n const trimmed = color.trim();\r\n\r\n // 十六进制格式\r\n if (trimmed.startsWith('#')) {\r\n return hexToRgb(trimmed);\r\n }\r\n\r\n // RGB/RGBA格式\r\n const rgbMatch = trimmed.match(/^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(?:,\\s*[\\d.]+)?\\s*\\)$/i);\r\n if (rgbMatch) {\r\n const r = parseInt(rgbMatch[1], 10);\r\n const g = parseInt(rgbMatch[2], 10);\r\n const b = parseInt(rgbMatch[3], 10);\r\n\r\n if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) {\r\n return [r, g, b];\r\n }\r\n }\r\n\r\n // 简单的颜色名称映射(支持常见颜色)\r\n const colorMap: Record<string, string> = {\r\n red: '#FF0000',\r\n green: '#00FF00',\r\n blue: '#0000FF',\r\n yellow: '#FFFF00',\r\n cyan: '#00FFFF',\r\n magenta: '#FF00FF',\r\n black: '#000000',\r\n white: '#FFFFFF',\r\n gray: '#808080',\r\n grey: '#808080',\r\n transparent: 'transparent'\r\n };\r\n\r\n const lowerColor = trimmed.toLowerCase();\r\n if (colorMap[lowerColor]) {\r\n if (lowerColor === 'transparent') {\r\n return [0, 0, 0]; // 透明返回黑色(透明度由其他机制处理)\r\n }\r\n return hexToRgb(colorMap[lowerColor]);\r\n }\r\n\r\n throw new Error(`无法解析的颜色格式: ${color}`);\r\n}\r\n\r\n/**\r\n * 验证颜色字符串是否有效\r\n * @param color 颜色字符串\r\n * @returns 是否有效\r\n */\r\nexport function isValidColor(color: string): boolean {\r\n try {\r\n parseColor(color);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * 在两个颜色之间进行线性插值\r\n * @param from 起始颜色\r\n * @param to 目标颜色\r\n * @param progress 插值进度 (0-1)\r\n * @returns 插值后的颜色(十六进制格式)\r\n */\r\nexport function interpolateColor(from: string, to: string, progress: number): string {\r\n // 处理边界情况\r\n if (progress <= 0) return from;\r\n if (progress >= 1) return to;\r\n\r\n try {\r\n const fromRgb = parseColor(from);\r\n const toRgb = parseColor(to);\r\n\r\n // 线性插值\r\n const r = fromRgb[0] + (toRgb[0] - fromRgb[0]) * progress;\r\n const g = fromRgb[1] + (toRgb[1] - fromRgb[1]) * progress;\r\n const b = fromRgb[2] + (toRgb[2] - fromRgb[2]) * progress;\r\n\r\n return rgbToHex(r, g, b);\r\n } catch (error) {\r\n console.warn('颜色插值失败,返回起始颜色:', error);\r\n return from;\r\n }\r\n}\r\n\r\n/**\r\n * 在两个颜色之间进行HSL插值(更自然的颜色过渡)\r\n * @param from 起始颜色\r\n * @param to 目标颜色\r\n * @param progress 插值进度 (0-1)\r\n * @returns 插值后的颜色(十六进制格式)\r\n */\r\nexport function interpolateColorHsl(from: string, to: string, progress: number): string {\r\n // 简化的HSL插值 - 先实现RGB插值,后续可扩展为真正的HSL插值\r\n return interpolateColor(from, to, progress);\r\n}\r\n\r\n/**\r\n * 应用缓动函数的颜色插值\r\n * @param from 起始颜色\r\n * @param to 目标颜色\r\n * @param progress 原始进度 (0-1)\r\n * @param easing 缓动函数类型\r\n * @returns 插值后的颜色\r\n */\r\nexport function interpolateColorWithEasing(\r\n from: string,\r\n to: string,\r\n progress: number,\r\n easing: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'step' = 'linear'\r\n): string {\r\n // 应用缓动函数\r\n let easedProgress = progress;\r\n\r\n switch (easing) {\r\n case 'ease-in':\r\n easedProgress = progress * progress;\r\n break;\r\n case 'ease-out':\r\n easedProgress = 1 - (1 - progress) * (1 - progress);\r\n break;\r\n case 'ease-in-out':\r\n easedProgress = progress < 0.5\r\n ? 2 * progress * progress\r\n : 1 - Math.pow(-2 * progress + 2, 2) / 2;\r\n break;\r\n case 'step':\r\n easedProgress = progress >= 1 ? 1 : 0;\r\n break;\r\n case 'linear':\r\n default:\r\n // 保持线性\r\n break;\r\n }\r\n\r\n return interpolateColor(from, to, easedProgress);\r\n}\r\n\r\n/**\r\n * 生成颜色渐变数组\r\n * @param colors 颜色数组\r\n * @param steps 渐变步数\r\n * @returns 渐变颜色数组\r\n */\r\nexport function generateColorGradient(colors: string[], steps: number): string[] {\r\n if (colors.length === 0) return [];\r\n if (colors.length === 1) return Array(steps).fill(colors[0]);\r\n\r\n const gradient: string[] = [];\r\n const segmentSteps = Math.floor(steps / (colors.length - 1));\r\n\r\n for (let i = 0; i < colors.length - 1; i++) {\r\n const fromColor = colors[i];\r\n const toColor = colors[i + 1];\r\n const currentSteps = i === colors.length - 2 ? steps - gradient.length : segmentSteps;\r\n\r\n for (let j = 0; j < currentSteps; j++) {\r\n const progress = j / currentSteps;\r\n gradient.push(interpolateColor(fromColor, toColor, progress));\r\n }\r\n }\r\n\r\n // 确保总数正确\r\n return gradient.slice(0, steps);\r\n}\r\n\r\n/**\r\n * 计算颜色亮度(相对亮度)\r\n * @param color 颜色字符串\r\n * @returns 亮度值 (0-1)\r\n */\r\nexport function calculateLuminance(color: string): number {\r\n try {\r\n const [r, g, b] = parseColor(color);\r\n\r\n // 标准化到 0-1 范围\r\n const rs = r / 255;\r\n const gs = g / 255;\r\n const bs = b / 255;\r\n\r\n // 相对亮度公式 (WCAG 2.0)\r\n const rr = rs <= 0.03928 ? rs / 12.92 : Math.pow((rs + 0.055) / 1.055, 2.4);\r\n const gg = gs <= 0.03928 ? gs / 12.92 : Math.pow((gs + 0.055) / 1.055, 2.4);\r\n const bb = bs <= 0.03928 ? bs / 12.92 : Math.pow((bs + 0.055) / 1.055, 2.4);\r\n\r\n return 0.2126 * rr + 0.7152 * gg + 0.0722 * bb;\r\n } catch {\r\n return 0.5; // 默认值\r\n }\r\n}\r\n\r\n/**\r\n * 检查颜色是否足够对比(用于无障碍设计)\r\n * @param color1 颜色1\r\n * @param color2 颜色2\r\n * @returns 对比度比值 (WCAG 要求至少 4.5:1 用于正常文本)\r\n */\r\nexport function calculateContrastRatio(color1: string, color2: string): number {\r\n const lum1 = calculateLuminance(color1);\r\n const lum2 = calculateLuminance(color2);\r\n\r\n const lighter = Math.max(lum1, lum2);\r\n const darker = Math.min(lum1, lum2);\r\n\r\n return (lighter + 0.05) / (darker + 0.05);\r\n}","// ========== 颜色设置执行器 ==========\r\n// 这个文件实现了颜色变换执行器\r\n\r\nimport { BaseTransformExecutor } from './TransformExecutor';\r\nimport type { FillColorSetConfig } from '../types/primitives';\r\nimport type { ValidationResult, Vertex } from './TransformExecutor';\r\nimport { interpolateColorWithEasing, isValidColor } from '../utils/colorUtils';\r\n\r\n// 颜色设置执行器类\r\nexport class FillColorSetExecutor extends BaseTransformExecutor<FillColorSetConfig> {\r\n readonly type = 'fillcolor_set';\r\n\r\n getDisplayName(): string {\r\n return '颜色变换';\r\n }\r\n\r\n getDescription(): string {\r\n return '将图形的填充颜色从起始颜色渐变到目标颜色';\r\n }\r\n\r\n getDefaultConfig(): FillColorSetConfig {\r\n return {\r\n targetColor: '#000000',\r\n startAt: 0,\r\n endAt: 1,\r\n easing: 'linear',\r\n fromColor: undefined // 默认使用图形当前颜色\r\n };\r\n }\r\n\r\n execute(vertices: Vertex[], _progress: number, _config: FillColorSetConfig): Vertex[] {\r\n // 颜色变换不改变顶点位置,只更新渲染属性\r\n // 实际的颜色变换逻辑在 GeometryTransform.tsx 中处理\r\n return vertices;\r\n }\r\n\r\n validate(config: FillColorSetConfig): ValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // 验证 targetColor\r\n if (!config.targetColor || typeof config.targetColor !== 'string') {\r\n errors.push('targetColor 是必需的且必须是字符串');\r\n } else if (!isValidColor(config.targetColor)) {\r\n errors.push(`targetColor 格式无效: ${config.targetColor}`);\r\n }\r\n\r\n // 验证 fromColor(如果提供)\r\n if (config.fromColor !== undefined) {\r\n if (typeof config.fromColor !== 'string') {\r\n errors.push('fromColor 必须是字符串');\r\n } else if (!isValidColor(config.fromColor)) {\r\n errors.push(`fromColor 格式无效: ${config.fromColor}`);\r\n }\r\n }\r\n\r\n // 验证 startAt\r\n if (config.startAt !== undefined) {\r\n const startAtError = this.validateNumber(config.startAt, 'startAt', 0, 1);\r\n if (startAtError) errors.push(startAtError);\r\n }\r\n\r\n // 验证 endAt\r\n if (config.endAt !== undefined) {\r\n const endAtError = this.validateNumber(config.endAt, 'endAt', 0, 1);\r\n if (endAtError) errors.push(endAtError);\r\n }\r\n\r\n // 验证 startAt 和 endAt 的关系\r\n if (config.startAt !== undefined && config.endAt !== undefined) {\r\n if (config.startAt >= config.endAt) {\r\n errors.push('startAt 必须小于 endAt');\r\n }\r\n }\r\n\r\n // 验证 easing\r\n if (config.easing !== undefined) {\r\n const easingError = this.validateString(\r\n config.easing,\r\n 'easing',\r\n ['linear', 'ease-in', 'ease-out', 'ease-in-out', 'step']\r\n );\r\n if (easingError) errors.push(easingError);\r\n }\r\n\r\n // 检查颜色对比度(警告)\r\n if (config.targetColor && config.fromColor) {\r\n try {\r\n // 这里可以添加对比度检查逻辑\r\n // 暂时留空,后续可以扩展\r\n } catch {\r\n // 忽略颜色解析错误\r\n }\r\n }\r\n\r\n return this.createValidationResult(errors.length === 0, errors, warnings);\r\n }\r\n\r\n /**\r\n * 计算当前进度对应的颜色\r\n * @param progress 全局进度 (0-1)\r\n * @param config 颜色配置\r\n * @param currentColor 图形的当前颜色\r\n * @returns 计算后的颜色值\r\n */\r\n calculateCurrentColor(\r\n progress: number,\r\n config: FillColorSetConfig,\r\n currentColor: string\r\n ): string {\r\n // 确定起始颜色\r\n const fromColor = config.fromColor || currentColor;\r\n const targetColor = config.targetColor;\r\n\r\n // 计算有效进度\r\n const effectiveProgress = this.calculateEffectiveProgress(progress, config);\r\n\r\n // 应用缓动函数插值\r\n return interpolateColorWithEasing(\r\n fromColor,\r\n targetColor,\r\n effectiveProgress,\r\n config.easing\r\n );\r\n }\r\n\r\n /**\r\n * 计算有效进度(考虑 startAt 和 endAt)\r\n * @param progress 全局进度 (0-1)\r\n * @param config 颜色配置\r\n * @returns 有效进度 (0-1)\r\n */\r\n private calculateEffectiveProgress(\r\n progress: number,\r\n config: FillColorSetConfig\r\n ): number {\r\n const startAt = config.startAt ?? 0;\r\n const endAt = config.endAt ?? 1;\r\n\r\n if (progress <= startAt) return 0;\r\n if (progress >= endAt) return 1;\r\n\r\n // 线性映射到 [0, 1] 范围\r\n return (progress - startAt) / (endAt - startAt);\r\n }\r\n\r\n /**\r\n * 检查颜色变换是否处于活动状态\r\n * @param progress 全局进度\r\n * @param config 颜色配置\r\n * @returns 是否处于活动状态\r\n */\r\n isActive(progress: number, config: FillColorSetConfig): boolean {\r\n const startAt = config.startAt ?? 0;\r\n const endAt = config.endAt ?? 1;\r\n\r\n return progress >= startAt && progress <= endAt;\r\n }\r\n}","// ========== 变换执行器注册表 ==========\r\n// 这个文件实现了变换执行器的注册表,支持插件化扩展\r\n\r\nimport type { ITransformExecutor, ValidationResult } from './TransformExecutor';\r\nimport type { TransformPrimitiveConfig, TransformPrimitiveType } from '../types/primitives';\r\nimport { TranslationExecutor } from './TranslationExecutor';\r\nimport { RotationExecutor } from './RotationExecutor';\r\nimport { ScaleExecutor } from './ScaleExecutor';\r\nimport { FillColorSetExecutor } from './FillColorSetExecutor';\r\n\r\n// 执行器注册表类\r\nexport class TransformExecutorRegistry {\r\n private executors: Map<TransformPrimitiveType, ITransformExecutor<any>> = new Map();\r\n\r\n /**\r\n * 注册执行器\r\n * @param executor 执行器实例\r\n */\r\n register<T extends TransformPrimitiveConfig>(executor: ITransformExecutor<T>): void {\r\n if (this.executors.has(executor.type as TransformPrimitiveType)) {\r\n console.warn(`执行器类型 \"${executor.type}\" 已存在,将被覆盖`);\r\n }\r\n\r\n this.executors.set(executor.type as TransformPrimitiveType, executor);\r\n }\r\n\r\n /**\r\n * 获取执行器\r\n * @param type 执行器类型\r\n * @returns 执行器实例,如果不存在则返回undefined\r\n */\r\n get<T extends TransformPrimitiveConfig>(type: TransformPrimitiveType): ITransformExecutor<T> | undefined {\r\n return this.executors.get(type) as ITransformExecutor<T> | undefined;\r\n }\r\n\r\n /**\r\n * 检查是否支持指定的变换类型\r\n * @param type 变换类型\r\n * @returns 是否支持\r\n */\r\n has(type: TransformPrimitiveType): boolean {\r\n return this.executors.has(type);\r\n }\r\n\r\n /**\r\n * 获取所有支持的变换类型\r\n * @returns 支持的变换类型数组\r\n */\r\n getSupportedTypes(): TransformPrimitiveType[] {\r\n return Array.from(this.executors.keys());\r\n }\r\n\r\n /**\r\n * 获取所有执行器的显示名称\r\n * @returns 类型到显示名称的映射\r\n */\r\n getExecutorDisplayNames(): Record<TransformPrimitiveType, string> {\r\n const result: Record<string, string> = {};\r\n\r\n for (const [type, executor] of this.executors) {\r\n result[type] = executor.getDisplayName();\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 验证配置\r\n * @param type 变换类型\r\n * @param config 配置\r\n * @returns 验证结果\r\n */\r\n validateConfig<T extends TransformPrimitiveConfig>(\r\n type: TransformPrimitiveType,\r\n config: T\r\n ): ValidationResult {\r\n const executor = this.get<T>(type);\r\n if (!executor) {\r\n return {\r\n isValid: false,\r\n errors: [`不支持变换类型: ${type}`],\r\n };\r\n }\r\n\r\n return executor.validate(config);\r\n }\r\n\r\n /**\r\n * 执行变换\r\n * @param type 变换类型\r\n * @param vertices 顶点数组\r\n * @param progress 进度\r\n * @param config 配置\r\n * @returns 变换后的顶点数组\r\n */\r\n executeTransform<T extends TransformPrimitiveConfig>(\r\n type: TransformPrimitiveType,\r\n vertices: [number, number][],\r\n progress: number,\r\n config: T\r\n ): [number, number][] {\r\n const executor = this.get<T>(type);\r\n if (!executor) {\r\n console.error(`不支持变换类型: ${type}`);\r\n return vertices;\r\n }\r\n\r\n // 验证配置\r\n const validationResult = executor.validate(config);\r\n if (!validationResult.isValid) {\r\n console.error(`配置验证失败:`, validationResult.errors);\r\n return vertices;\r\n }\r\n\r\n return executor.execute(vertices, progress, config);\r\n }\r\n\r\n /**\r\n * 批量执行多个变换\r\n * @param transforms 变换列表(类型和配置)\r\n * @param vertices 顶点数组\r\n * @param progress 进度\r\n * @returns 变换后的顶点数组\r\n */\r\n executeTransforms(\r\n transforms: Array<{ type: TransformPrimitiveType; config: TransformPrimitiveConfig }>,\r\n vertices: [number, number][],\r\n progress: number\r\n ): [number, number][] {\r\n let result = vertices;\r\n\r\n for (const transform of transforms) {\r\n const executor = this.get(transform.type);\r\n if (!executor) {\r\n console.warn(`跳过不支持的变换类型: ${transform.type}`);\r\n continue;\r\n }\r\n\r\n result = executor.execute(result, progress, transform.config);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 获取默认配置\r\n * @param type 变换类型\r\n * @returns 默认配置\r\n */\r\n getDefaultConfig<T extends TransformPrimitiveConfig>(type: TransformPrimitiveType): T | undefined {\r\n const executor = this.get<T>(type);\r\n return executor?.getDefaultConfig();\r\n }\r\n\r\n /**\r\n * 清除所有执行器\r\n */\r\n clear(): void {\r\n this.executors.clear();\r\n }\r\n\r\n /**\r\n * 获取执行器数量\r\n * @returns 执行器数量\r\n */\r\n size(): number {\r\n return this.executors.size;\r\n }\r\n}\r\n\r\n// 全局默认注册表实例(单例模式)\r\nlet defaultRegistry: TransformExecutorRegistry | null = null;\r\n\r\n/**\r\n * 获取默认注册表实例\r\n * @returns 默认注册表实例\r\n */\r\nexport function getDefaultRegistry(): TransformExecutorRegistry {\r\n if (!defaultRegistry) {\r\n defaultRegistry = new TransformExecutorRegistry();\r\n // 注册默认执行器\r\n defaultRegistry.register(new TranslationExecutor());\r\n defaultRegistry.register(new RotationExecutor());\r\n defaultRegistry.register(new ScaleExecutor());\r\n defaultRegistry.register(new FillColorSetExecutor());\r\n }\r\n return defaultRegistry;\r\n}\r\n\r\n/**\r\n * 重置默认注册表\r\n */\r\nexport function resetDefaultRegistry(): void {\r\n defaultRegistry = null;\r\n}","// ========== 组匹配工具类 ==========\r\n// 这个文件实现了通用的组匹配逻辑,支持多种匹配策略\r\n\r\nimport type { GroupMatchConfig, SimpleGroupMatchConfig } from '../types/groupMatching';\r\n\r\nexport class GroupMatcher {\r\n /**\r\n * 检查形状是否匹配组配置\r\n */\r\n static matchesShape(\r\n shapeMetadata: any,\r\n groupMatch?: GroupMatchConfig | SimpleGroupMatchConfig,\r\n fallbackGroup?: string\r\n ): boolean {\r\n if (!groupMatch) {\r\n // 如果没有配置组匹配,使用fallbackGroup或默认行为\r\n return !fallbackGroup || this.extractGroupId(shapeMetadata) === fallbackGroup;\r\n }\r\n\r\n // 处理简化的targetGroup配置(向后兼容)\r\n if ('targetGroup' in groupMatch && groupMatch.targetGroup) {\r\n return this.matchesSimpleGroup(shapeMetadata, groupMatch.targetGroup, groupMatch.metadataField);\r\n }\r\n\r\n // 处理完整的GroupMatchConfig\r\n if ('pattern' in groupMatch) {\r\n // 对于'any'策略,即使pattern为空也调用matchesWithConfig\r\n if (groupMatch.strategy === 'any') {\r\n return this.matchesWithConfig(shapeMetadata, groupMatch);\r\n }\r\n // 对于其他策略,需要pattern不为空\r\n if (groupMatch.pattern) {\r\n return this.matchesWithConfig(shapeMetadata, groupMatch);\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * 简化的组匹配(支持通配符)\r\n */\r\n private static matchesSimpleGroup(\r\n metadata: any,\r\n targetGroup: string,\r\n metadataField?: string\r\n ): boolean {\r\n const groupId = this.extractGroupId(metadata, metadataField);\r\n if (!groupId) return false;\r\n\r\n // 支持通配符\r\n if (targetGroup.includes('*')) {\r\n const pattern = targetGroup.replace(/\\*/g, '.*');\r\n return new RegExp(`^${pattern}$`).test(groupId);\r\n }\r\n\r\n return groupId === targetGroup;\r\n }\r\n\r\n /**\r\n * 使用完整配置进行组匹配\r\n */\r\n private static matchesWithConfig(\r\n metadata: any,\r\n config: GroupMatchConfig\r\n ): boolean {\r\n const groupId = this.extractGroupId(metadata, config.metadataField);\r\n if (!groupId) return false;\r\n\r\n const pattern = config.pattern;\r\n const strategy = config.strategy || 'exact';\r\n const caseSensitive = config.caseSensitive || false;\r\n\r\n switch (strategy) {\r\n case 'exact':\r\n return caseSensitive\r\n ? groupId === pattern\r\n : groupId.toLowerCase() === (pattern as string).toLowerCase();\r\n\r\n case 'wildcard':\r\n const wildcardPattern = (pattern as string).replace(/\\*/g, '.*');\r\n return new RegExp(`^${wildcardPattern}$`, caseSensitive ? '' : 'i').test(groupId);\r\n\r\n case 'regex':\r\n const regex = pattern instanceof RegExp\r\n ? pattern\r\n : new RegExp(pattern as string, caseSensitive ? '' : 'i');\r\n return regex.test(groupId);\r\n\r\n case 'multiple':\r\n const patterns = Array.isArray(pattern) ? pattern : (pattern as string).split(',');\r\n return patterns.some(p => this.matchesSimpleGroup(metadata, p, config.metadataField));\r\n\r\n case 'any':\r\n return true; // 匹配任意组\r\n\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * 从元数据中提取组标识\r\n */\r\n static extractGroupId(\r\n metadata: any,\r\n fieldName: string = 'rotationGroup'\r\n ): string | undefined {\r\n if (!metadata) return undefined;\r\n\r\n // 支持嵌套字段访问(如metadata.transform.group)\r\n const fields = fieldName.split('.');\r\n let value: any = metadata;\r\n\r\n for (const field of fields) {\r\n if (value == null) return undefined;\r\n value = value[field];\r\n }\r\n\r\n return typeof value === 'string' ? value : undefined;\r\n }\r\n\r\n /**\r\n * 验证组匹配配置\r\n */\r\n static validateConfig(config: GroupMatchConfig): {\r\n isValid: boolean;\r\n errors: string[];\r\n warnings: string[];\r\n } {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // 验证基本结构\r\n if (!config || typeof config !== 'object') {\r\n errors.push('配置必须是对象');\r\n return { isValid: false, errors, warnings };\r\n }\r\n\r\n // 验证pattern\r\n if (!config.pattern) {\r\n errors.push('pattern不能为空');\r\n }\r\n\r\n // 根据strategy验证pattern类型\r\n switch (config.strategy) {\r\n case 'exact':\r\n case 'wildcard':\r\n if (typeof config.pattern !== 'string') {\r\n errors.push(`${config.strategy}策略的pattern必须是字符串`);\r\n }\r\n break;\r\n\r\n case 'regex':\r\n if (!(config.pattern instanceof RegExp) && typeof config.pattern !== 'string') {\r\n errors.push('regex策略的pattern必须是RegExp对象或字符串');\r\n }\r\n break;\r\n\r\n case 'multiple':\r\n if (!Array.isArray(config.pattern) && typeof config.pattern !== 'string') {\r\n errors.push('multiple策略的pattern必须是数组或逗号分隔的字符串');\r\n }\r\n break;\r\n\r\n case 'any':\r\n // any策略不需要验证pattern\r\n break;\r\n\r\n default:\r\n errors.push(`未知的匹配策略: ${config.strategy}`);\r\n }\r\n\r\n // 验证metadataField\r\n if (config.metadataField !== undefined && typeof config.metadataField !== 'string') {\r\n errors.push('metadataField必须是字符串');\r\n }\r\n\r\n // 验证caseSensitive\r\n if (config.caseSensitive !== undefined && typeof config.caseSensitive !== 'boolean') {\r\n errors.push('caseSensitive必须是布尔值');\r\n }\r\n\r\n // 性能警告\r\n if (config.strategy === 'regex') {\r\n warnings.push('正则表达式匹配可能影响性能,请确保模式简单高效');\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n warnings\r\n };\r\n }\r\n\r\n /**\r\n * 将简化的targetGroup转换为GroupMatchConfig\r\n */\r\n static convertToGroupMatchConfig(\r\n targetGroup?: string,\r\n metadataField?: string\r\n ): GroupMatchConfig | undefined {\r\n if (!targetGroup) {\r\n return undefined;\r\n }\r\n\r\n // 检查是否包含通配符\r\n const strategy: 'exact' | 'wildcard' = targetGroup.includes('*') ? 'wildcard' : 'exact';\r\n\r\n return {\r\n pattern: targetGroup,\r\n strategy,\r\n metadataField\r\n };\r\n }\r\n}","// ========== 复合变换类型定义 ==========\r\n// 这个文件定义了复合变换类型,作为三层架构的第二层\r\n\r\nimport type { SingleTransform } from './primitives';\r\nimport type { GroupMatchConfig } from './groupMatching';\r\nimport { GroupMatcher } from '../utils/GroupMatcher';\r\n\r\n// 执行模式:顺序执行或并行执行\r\nexport type ExecutionMode = 'sequential' | 'parallel';\r\n\r\n// 复合变换配置\r\nexport interface CompositeTransformConfig {\r\n type: 'composite';\r\n transforms: SingleTransform[];\r\n executionMode: ExecutionMode;\r\n targetGroup?: string; // 向后兼容的targetGroup\r\n groupMatch?: GroupMatchConfig; // 通用组匹配配置\r\n}\r\n\r\n// 变换信息查询结果\r\nexport interface TransformInfo {\r\n count: number;\r\n types: string[];\r\n groups: string[];\r\n executionMode: ExecutionMode;\r\n}\r\n\r\n// 类型守卫函数\r\nexport function isCompositeTransformConfig(config: any): config is CompositeTransformConfig {\r\n return (\r\n config &&\r\n config.type === 'composite' &&\r\n Array.isArray(config.transforms) &&\r\n (config.executionMode === 'sequential' || config.executionMode === 'parallel')\r\n );\r\n}\r\n\r\n// 验证复合变换配置\r\nexport function validateCompositeTransformConfig(config: CompositeTransformConfig): boolean {\r\n if (!config || config.type !== 'composite') {\r\n return false;\r\n }\r\n\r\n if (!Array.isArray(config.transforms) || config.transforms.length === 0) {\r\n return false;\r\n }\r\n\r\n if (config.executionMode !== 'sequential' && config.executionMode !== 'parallel') {\r\n return false;\r\n }\r\n\r\n // 验证所有子变换\r\n return config.transforms.every(_transform => {\r\n // 这里假设有validateSingleTransform函数可用\r\n // 实际上应该从primitives.ts导入\r\n return true; // 暂时返回true,后续实现完整的验证\r\n });\r\n}\r\n\r\n// 获取变换信息\r\nexport function getTransformInfo(config: CompositeTransformConfig): TransformInfo {\r\n const types = config.transforms.map(t => t.type);\r\n const groups = Array.from(\r\n new Set(\r\n config.transforms\r\n .map(t => t.targetGroup)\r\n .filter((group): group is string => group !== undefined)\r\n )\r\n );\r\n\r\n return {\r\n count: config.transforms.length,\r\n types,\r\n groups,\r\n executionMode: config.executionMode,\r\n };\r\n}\r\n\r\n// 按组过滤变换\r\nexport function filterTransformsByGroup(\r\n transforms: SingleTransform[],\r\n targetGroup?: string,\r\n shapeMetadata?: any\r\n): SingleTransform[] {\r\n if (!targetGroup && !shapeMetadata) {\r\n // 没有目标组,返回没有目标组的变换(全局变换)\r\n return transforms.filter(t => !t.targetGroup && !t.groupMatch);\r\n }\r\n\r\n return transforms.filter(transform => {\r\n // 优先使用groupMatch配置\r\n if (transform.groupMatch && shapeMetadata) {\r\n return GroupMatcher.matchesShape(shapeMetadata, transform.groupMatch);\r\n }\r\n\r\n // 向后兼容:使用targetGroup\r\n if (transform.targetGroup) {\r\n if (!targetGroup) return false;\r\n\r\n // 支持通配符\r\n if (transform.targetGroup.includes('*')) {\r\n const pattern = transform.targetGroup.replace(/\\*/g, '.*');\r\n return new RegExp(`^${pattern}$`).test(targetGroup);\r\n }\r\n\r\n return transform.targetGroup === targetGroup;\r\n }\r\n\r\n // 既没有groupMatch也没有targetGroup:全局变换\r\n // 全局变换只在没有指定targetGroup时匹配\r\n return !targetGroup;\r\n });\r\n}\r\n\r\n// 检查配置是否为空(用于解决空composite数组问题)\r\nexport function isEmptyComposite(config: CompositeTransformConfig): boolean {\r\n return config.transforms.length === 0;\r\n}\r\n\r\n// 创建空复合变换(向后兼容性辅助函数)\r\nexport function createEmptyComposite(): CompositeTransformConfig {\r\n return {\r\n type: 'composite',\r\n transforms: [],\r\n executionMode: 'parallel',\r\n };\r\n}","// ========== 变换组合器 ==========\r\n// 这个文件实现了变换组合器,作为三层架构的第二层核心\r\n// 负责执行复合变换,支持顺序和并行执行模式\r\n\r\nimport type { Vertex, ValidationResult } from '../executors/TransformExecutor';\r\nimport { getDefaultRegistry, type TransformExecutorRegistry } from '../executors/TransformExecutorRegistry';\r\nimport type {\r\n CompositeTransformConfig,\r\n TransformInfo,\r\n // @ts-ignore: ExecutionMode is indirectly used via CompositeTransformConfig\r\n ExecutionMode\r\n} from '../types/composition';\r\nimport type { SingleTransform } from '../types/primitives';\r\nimport { filterTransformsByGroup as filterTransformsByGroupFn } from '../types/composition';\r\n\r\n// 变换组合器类\r\nexport class TransformCompositor {\r\n private registry: TransformExecutorRegistry;\r\n\r\n /**\r\n * 构造函数\r\n * @param registry 执行器注册表,默认为全局注册表\r\n */\r\n constructor(registry?: TransformExecutorRegistry) {\r\n this.registry = registry || this.getDefaultRegistry();\r\n }\r\n\r\n /**\r\n * 执行复合变换\r\n * @param vertices 原始顶点数组\r\n * @param progress 进度值(0-1)\r\n * @param config 复合变换配置\r\n * @param targetGroup 目标组标识(用于按组过滤)\r\n * @param shapeMetadata 形状元数据,用于groupMatch配置匹配\r\n * @returns 变换后的顶点数组\r\n */\r\n execute(\r\n vertices: Vertex[],\r\n progress: number,\r\n config: CompositeTransformConfig,\r\n targetGroup?: string,\r\n shapeMetadata?: any\r\n ): Vertex[] {\r\n // 验证配置\r\n const validationResult = this.validate(config);\r\n if (!validationResult.isValid) {\r\n console.error('复合变换配置验证失败:', validationResult.errors);\r\n return vertices;\r\n }\r\n\r\n // 按组过滤变换\r\n const filteredTransforms = this.filterTransformsByGroup(config.transforms, targetGroup, shapeMetadata);\r\n\r\n if (filteredTransforms.length === 0) {\r\n return vertices;\r\n }\r\n\r\n // 根据执行模式执行变换\r\n switch (config.executionMode) {\r\n case 'sequential':\r\n return this.executeSequentially(vertices, progress, filteredTransforms);\r\n case 'parallel':\r\n return this.executeInParallel(vertices, progress, filteredTransforms);\r\n default:\r\n console.warn(`未知的执行模式: ${config.executionMode},使用顺序执行`);\r\n return this.executeSequentially(vertices, progress, filteredTransforms);\r\n }\r\n }\r\n\r\n /**\r\n * 验证复合变换配置\r\n * @param config 复合变换配置\r\n * @returns 验证结果\r\n */\r\n validate(config: CompositeTransformConfig): ValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // 验证基本结构\r\n if (!config || config.type !== 'composite') {\r\n errors.push('配置必须是复合变换类型');\r\n return this.createValidationResult(false, errors, warnings);\r\n }\r\n\r\n if (!Array.isArray(config.transforms)) {\r\n errors.push('transforms必须是数组');\r\n return this.createValidationResult(false, errors, warnings);\r\n }\r\n\r\n if (config.transforms.length === 0) {\r\n warnings.push('复合变换没有子变换,这可能表示配置为空');\r\n }\r\n\r\n if (config.executionMode !== 'sequential' && config.executionMode !== 'parallel') {\r\n errors.push('executionMode必须是\"sequential\"或\"parallel\"');\r\n }\r\n\r\n // 验证每个子变换\r\n for (let i = 0; i < config.transforms.length; i++) {\r\n const transform = config.transforms[i];\r\n const transformError = this.validateSingleTransform(transform, i);\r\n if (transformError) {\r\n errors.push(transformError);\r\n }\r\n }\r\n\r\n // 检查是否有重复的id\r\n const ids = config.transforms.map(t => t.id).filter(Boolean);\r\n const uniqueIds = new Set(ids);\r\n if (ids.length !== uniqueIds.size) {\r\n warnings.push('发现重复的变换ID,可能导致不可预测的行为');\r\n }\r\n\r\n return this.createValidationResult(errors.length === 0, errors, warnings);\r\n }\r\n\r\n /**\r\n * 获取变换信息\r\n * @param config 复合变换配置\r\n * @returns 变换信息\r\n */\r\n getTransformInfo(config: CompositeTransformConfig): TransformInfo {\r\n const types = config.transforms.map(t => t.type);\r\n const groups = Array.from(\r\n new Set(\r\n config.transforms\r\n .map(t => t.targetGroup)\r\n .filter((group): group is string => group !== undefined)\r\n )\r\n );\r\n\r\n return {\r\n count: config.transforms.length,\r\n types,\r\n groups,\r\n executionMode: config.executionMode,\r\n };\r\n }\r\n\r\n /**\r\n * 按组过滤变换\r\n * @param transforms 变换数组\r\n * @param targetGroup 目标组标识\r\n * @param shapeMetadata 形状元数据,用于groupMatch配置匹配\r\n * @returns 过滤后的变换数组\r\n */\r\n filterTransformsByGroup(\r\n transforms: SingleTransform[],\r\n targetGroup?: string,\r\n shapeMetadata?: any\r\n ): SingleTransform[] {\r\n return filterTransformsByGroupFn(transforms, targetGroup, shapeMetadata);\r\n }\r\n\r\n /**\r\n * 获取适用于指定目标组的变换列表\r\n * @param config 复合变换配置\r\n * @param targetGroup 目标组标识\r\n * @param shapeMetadata 形状元数据,用于groupMatch配置匹配\r\n * @returns 适用于目标组的变换列表\r\n */\r\n getTransformsForGroup(\r\n config: CompositeTransformConfig,\r\n targetGroup?: string,\r\n shapeMetadata?: any\r\n ): SingleTransform[] {\r\n return this.filterTransformsByGroup(config.transforms, targetGroup, shapeMetadata);\r\n }\r\n\r\n /**\r\n * 检查复合变换是否为空\r\n * @param config 复合变换配置\r\n * @returns 是否为空\r\n */\r\n isEmpty(config: CompositeTransformConfig): boolean {\r\n return config.transforms.length === 0;\r\n }\r\n\r\n // 私有方法:顺序执行变换\r\n private executeSequentially(\r\n vertices: Vertex[],\r\n progress: number,\r\n transforms: SingleTransform[]\r\n ): Vertex[] {\r\n let result = vertices;\r\n\r\n for (const transform of transforms) {\r\n const executor = this.registry.get(transform.type);\r\n if (!executor) {\r\n console.warn(`跳过不支持的变换类型: ${transform.type}`);\r\n continue;\r\n }\r\n\r\n // 验证子变换配置\r\n const validationResult = executor.validate(transform.config);\r\n if (!validationResult.isValid) {\r\n console.warn(`子变换配置验证失败: ${transform.type}`, validationResult.errors);\r\n continue;\r\n }\r\n\r\n result = executor.execute(result, progress, transform.config);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n // 私有方法:并行执行变换\r\n private executeInParallel(\r\n vertices: Vertex[],\r\n progress: number,\r\n transforms: SingleTransform[]\r\n ): Vertex[] {\r\n if (transforms.length === 0) {\r\n return vertices;\r\n }\r\n\r\n if (transforms.length === 1) {\r\n // 只有一个变换,顺序和并行执行结果相同\r\n return this.executeSequentially(vertices, progress, transforms);\r\n }\r\n\r\n // 并行执行:所有变换同时应用于原始顶点,然后取平均值\r\n // 注意:这种处理方式可能不适用于所有场景,但提供了并行执行的基本实现\r\n const transformedResults: Vertex[][] = [];\r\n\r\n for (const transform of transforms) {\r\n const executor = this.registry.get(transform.type);\r\n if (!executor) {\r\n console.warn(`跳过不支持的变换类型: ${transform.type}`);\r\n continue;\r\n }\r\n\r\n // 验证子变换配置\r\n const validationResult = executor.validate(transform.config);\r\n if (!validationResult.isValid) {\r\n console.warn(`子变换配置验证失败: ${transform.type}`, validationResult.errors);\r\n continue;\r\n }\r\n\r\n const transformed = executor.execute(vertices, progress, transform.config);\r\n transformedResults.push(transformed);\r\n }\r\n\r\n if (transformedResults.length === 0) {\r\n return vertices;\r\n }\r\n\r\n // 计算所有变换结果的平均值\r\n return this.calculateAverageVertices(transformedResults);\r\n }\r\n\r\n // 私有方法:计算顶点数组的平均值\r\n private calculateAverageVertices(vertexArrays: Vertex[][]): Vertex[] {\r\n if (vertexArrays.length === 0) {\r\n return [];\r\n }\r\n\r\n // 所有顶点数组必须具有相同的长度\r\n const length = vertexArrays[0].length;\r\n for (const array of vertexArrays) {\r\n if (array.length !== length) {\r\n console.error('顶点数组长度不一致,无法计算平均值');\r\n return vertexArrays[0]; // 返回第一个数组作为回退\r\n }\r\n }\r\n\r\n // 计算每个顶点的平均值\r\n const result: Vertex[] = [];\r\n\r\n for (let i = 0; i < length; i++) {\r\n let sumX = 0;\r\n let sumY = 0;\r\n\r\n for (const array of vertexArrays) {\r\n sumX += array[i][0];\r\n sumY += array[i][1];\r\n }\r\n\r\n result.push([sumX / vertexArrays.length, sumY / vertexArrays.length]);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n // 私有方法:验证单个变换\r\n private validateSingleTransform(transform: SingleTransform, index: number): string | undefined {\r\n if (!transform || typeof transform !== 'object') {\r\n return `变换[${index}]必须是对象`;\r\n }\r\n\r\n if (!transform.type) {\r\n return `变换[${index}]缺少type字段`;\r\n }\r\n\r\n if (!transform.config) {\r\n return `变换[${index}]缺少config字段`;\r\n }\r\n\r\n // 检查是否支持该变换类型\r\n const executor = this.registry.get(transform.type);\r\n if (!executor) {\r\n return `变换[${index}]不支持的变换类型: ${transform.type}`;\r\n }\r\n\r\n // 使用执行器验证配置\r\n const validationResult = executor.validate(transform.config);\r\n if (!validationResult.isValid) {\r\n return `变换[${index}]配置验证失败: ${validationResult.errors?.join(', ')}`;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n // 私有方法:创建验证结果\r\n private createValidationResult(\r\n isValid: boolean,\r\n errors?: string[],\r\n warnings?: string[]\r\n ): ValidationResult {\r\n return {\r\n isValid,\r\n errors: errors?.filter(Boolean),\r\n warnings: warnings?.filter(Boolean),\r\n };\r\n }\r\n\r\n // 私有方法:获取默认注册表\r\n private getDefaultRegistry(): TransformExecutorRegistry {\r\n return getDefaultRegistry();\r\n }\r\n}","// ========== 变换管道 ==========\r\n// 这个文件实现了变换管道,作为三层架构的第三层核心\r\n// 负责协调全局transform和形状专属transform,处理优先级逻辑\r\n\r\nimport type { Vertex } from '../executors/TransformExecutor';\r\nimport { getDefaultRegistry, type TransformExecutorRegistry } from '../executors/TransformExecutorRegistry';\r\nimport type { TransformConfig } from '../types/transform';\r\nimport type { SingleTransform } from '../types/primitives';\r\nimport type { GeometryShape } from '../types';\r\nimport { TransformCompositor } from './TransformCompositor';\r\nimport { isSingleTransform, isCompositeTransform } from '../types/transform';\r\nimport { GroupMatcher } from '../utils/GroupMatcher';\r\n\r\n// 变换管道类\r\nexport class TransformPipeline {\r\n private registry: TransformExecutorRegistry;\r\n private compositor: TransformCompositor;\r\n\r\n /**\r\n * 构造函数\r\n * @param registry 执行器注册表,默认为全局注册表\r\n */\r\n constructor(registry?: TransformExecutorRegistry) {\r\n this.registry = registry || this.getDefaultRegistry();\r\n this.compositor = new TransformCompositor(this.registry);\r\n }\r\n\r\n /**\r\n * 执行形状的变换(主入口点)\r\n * @param shape 几何形状\r\n * @param progress 进度值(0-1)\r\n * @param globalTransform 全局变换配置\r\n * @returns 变换后的顶点数组\r\n */\r\n executeShapeTransform(\r\n shape: GeometryShape,\r\n progress: number,\r\n globalTransform?: TransformConfig\r\n ): Vertex[] {\r\n // 获取有效的变换配置\r\n const effectiveTransform = this.getEffectiveTransform(shape, globalTransform);\r\n\r\n // 如果没有有效的变换,返回原始顶点\r\n if (!effectiveTransform) {\r\n return shape.vertices;\r\n }\r\n\r\n // 执行变换\r\n return this.executeTransform(shape.vertices, progress, effectiveTransform, shape.metadata);\r\n }\r\n\r\n /**\r\n * 执行变换(通用方法)\r\n * @param vertices 原始顶点数组\r\n * @param progress 进度值(0-1)\r\n * @param transform 变换配置\r\n * @param metadata 形状元数据(用于按组过滤)\r\n * @returns 变换后的顶点数组\r\n */\r\n executeTransform(\r\n vertices: Vertex[],\r\n progress: number,\r\n transform: TransformConfig,\r\n metadata?: any\r\n ): Vertex[] {\r\n if (!transform) {\r\n return vertices;\r\n }\r\n\r\n // 提取形状组信息(使用默认字段名'rotationGroup',向后兼容)\r\n const shapeGroup = GroupMatcher.extractGroupId(metadata, 'rotationGroup');\r\n\r\n if (isSingleTransform(transform)) {\r\n // 单一变换\r\n return this.executeSingleTransform(vertices, progress, transform, metadata, shapeGroup);\r\n } else if (isCompositeTransform(transform)) {\r\n // 复合变换 - 传递shapeGroup和metadata给compositor\r\n return this.compositor.execute(vertices, progress, transform, shapeGroup, metadata);\r\n }\r\n\r\n // 未知的变换类型\r\n console.error('未知的变换类型:', transform);\r\n return vertices;\r\n }\r\n\r\n /**\r\n * 获取有效的变换配置(处理形状专属transform的优先级)\r\n * @param shape 几何形状\r\n * @param globalTransform 全局变换配置\r\n * @returns 有效的变换配置\r\n */\r\n getEffectiveTransform(\r\n shape: GeometryShape,\r\n globalTransform?: TransformConfig\r\n ): TransformConfig | undefined {\r\n // 优先使用形状专属的transform\r\n if (shape.transform) {\r\n return shape.transform as TransformConfig;\r\n }\r\n\r\n // 否则使用全局transform\r\n return globalTransform;\r\n }\r\n\r\n /**\r\n * 获取变换信息\r\n * @param transform 变换配置\r\n * @returns 变换信息\r\n */\r\n getTransformInfo(transform?: TransformConfig) {\r\n if (!transform) {\r\n return {\r\n count: 0,\r\n types: [],\r\n groups: [],\r\n hasTransform: false\r\n };\r\n }\r\n\r\n if (isSingleTransform(transform)) {\r\n return {\r\n count: 1,\r\n types: [transform.type],\r\n groups: transform.targetGroup ? [transform.targetGroup] : [],\r\n hasTransform: true\r\n };\r\n } else if (isCompositeTransform(transform)) {\r\n const info = this.compositor.getTransformInfo(transform);\r\n return {\r\n ...info,\r\n hasTransform: true\r\n };\r\n }\r\n\r\n return {\r\n count: 0,\r\n types: [],\r\n groups: [],\r\n hasTransform: false\r\n };\r\n }\r\n\r\n /**\r\n * 验证变换配置\r\n * @param transform 变换配置\r\n * @returns 验证结果\r\n */\r\n validateTransform(transform: TransformConfig) {\r\n if (!transform) {\r\n return {\r\n isValid: true,\r\n errors: [],\r\n warnings: ['变换配置为空']\r\n };\r\n }\r\n\r\n if (isSingleTransform(transform)) {\r\n return this.validateSingleTransform(transform);\r\n } else if (isCompositeTransform(transform)) {\r\n return this.compositor.validate(transform);\r\n }\r\n\r\n return {\r\n isValid: false,\r\n errors: ['未知的变换类型'],\r\n warnings: []\r\n };\r\n }\r\n\r\n /**\r\n * 检查是否为空变换(用于解决空composite数组问题)\r\n * @param transform 变换配置\r\n * @returns 是否为空变换\r\n */\r\n isEmptyTransform(transform?: TransformConfig): boolean {\r\n if (!transform) {\r\n return true;\r\n }\r\n\r\n if (isSingleTransform(transform)) {\r\n return false; // 单一变换不为空\r\n } else if (isCompositeTransform(transform)) {\r\n return this.compositor.isEmpty(transform);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * 批量执行多个形状的变换\r\n * @param shapes 形状数组\r\n * @param progress 进度值(0-1)\r\n * @param globalTransform 全局变换配置\r\n * @returns 变换后的形状数组\r\n */\r\n executeBatchTransform(\r\n shapes: GeometryShape[],\r\n progress: number,\r\n globalTransform?: TransformConfig\r\n ): GeometryShape[] {\r\n return shapes.map(shape => ({\r\n ...shape,\r\n vertices: this.executeShapeTransform(shape, progress, globalTransform)\r\n }));\r\n }\r\n\r\n // 私有方法:执行单一变换\r\n private executeSingleTransform(\r\n vertices: Vertex[],\r\n progress: number,\r\n transform: SingleTransform,\r\n metadata?: any,\r\n shapeGroup?: string\r\n ): Vertex[] {\r\n // 检查变换是否适用于当前形状\r\n const matches = GroupMatcher.matchesShape(\r\n metadata,\r\n transform.groupMatch || (transform.targetGroup ? { targetGroup: transform.targetGroup } : undefined),\r\n shapeGroup\r\n );\r\n\r\n if (!matches) {\r\n return vertices;\r\n }\r\n\r\n // 获取执行器\r\n const executor = this.registry.get(transform.type);\r\n if (!executor) {\r\n console.error(`不支持变换类型: ${transform.type}`);\r\n return vertices;\r\n }\r\n\r\n // 验证配置\r\n const validationResult = executor.validate(transform.config);\r\n if (!validationResult.isValid) {\r\n console.error(`变换配置验证失败:`, validationResult.errors);\r\n return vertices;\r\n }\r\n\r\n // 执行变换\r\n return executor.execute(vertices, progress, transform.config);\r\n }\r\n\r\n // 私有方法:验证单一变换\r\n private validateSingleTransform(transform: SingleTransform) {\r\n const executor = this.registry.get(transform.type);\r\n if (!executor) {\r\n return {\r\n isValid: false,\r\n errors: [`不支持变换类型: ${transform.type}`],\r\n warnings: []\r\n };\r\n }\r\n\r\n return executor.validate(transform.config);\r\n }\r\n\r\n // 私有方法:获取默认注册表\r\n private getDefaultRegistry(): TransformExecutorRegistry {\r\n return getDefaultRegistry();\r\n }\r\n}","import { useCallback, useRef } from 'react';\r\nimport { shouldAutoComplete } from '../utils/transformAlgorithms';\r\n\r\n/**\r\n * 变换进度管理 Hook\r\n */\r\nexport const useTransformProgress = () => {\r\n const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);\r\n\r\n /**\r\n * 处理进度变化(带防抖)\r\n */\r\n const handleProgressChange = useCallback((\r\n newProgress: number,\r\n callback?: (progress: number) => void,\r\n debounceMs: number = 50\r\n ) => {\r\n // 清除之前的定时器\r\n if (debounceTimerRef.current) {\r\n clearTimeout(debounceTimerRef.current);\r\n }\r\n\r\n // 设置新的定时器\r\n debounceTimerRef.current = setTimeout(() => {\r\n if (callback) {\r\n callback(newProgress);\r\n }\r\n }, debounceMs);\r\n }, []);\r\n\r\n /**\r\n * 获取进度标签文本\r\n */\r\n const getProgressLabel = useCallback((progress: number, stages?: number): string => {\r\n const percentage = Math.round(progress * 100);\r\n\r\n if (stages && stages > 1) {\r\n // 处理边界情况:当progress为1时,stage应该是stages\r\n // 当progress接近1但不等于1时,使用Math.floor\r\n const stage = progress >= 1 ? stages : Math.min(Math.floor(progress * stages) + 1, stages);\r\n return `阶段 ${stage}/${stages} (${percentage}%)`;\r\n }\r\n\r\n return `${percentage}%`;\r\n }, []);\r\n\r\n /**\r\n * 重置进度\r\n */\r\n const resetProgress = useCallback(() => {\r\n if (debounceTimerRef.current) {\r\n clearTimeout(debounceTimerRef.current);\r\n debounceTimerRef.current = null;\r\n }\r\n return 0;\r\n }, []);\r\n\r\n return {\r\n handleProgressChange,\r\n shouldAutoComplete,\r\n getProgressLabel,\r\n resetProgress\r\n };\r\n};","import { useCallback } from 'react';\r\n\r\n/**\r\n * 键盘导航 Hook\r\n */\r\nexport const useKeyboardNavigation = () => {\r\n /**\r\n * 处理键盘事件\r\n */\r\n const handleKeyDown = useCallback((\r\n event: KeyboardEvent,\r\n currentProgress: number,\r\n step: number = 0.05\r\n ): number | null => {\r\n let newProgress = currentProgress;\r\n\r\n switch (event.key) {\r\n case 'ArrowRight':\r\n case 'ArrowUp':\r\n newProgress = Math.min(currentProgress + step, 1);\r\n break;\r\n\r\n case 'ArrowLeft':\r\n case 'ArrowDown':\r\n newProgress = Math.max(currentProgress - step, 0);\r\n break;\r\n\r\n case 'Home':\r\n newProgress = 0;\r\n break;\r\n\r\n case 'End':\r\n newProgress = 1;\r\n break;\r\n\r\n case 'PageUp':\r\n newProgress = Math.min(currentProgress + step * 2, 1);\r\n break;\r\n\r\n case 'PageDown':\r\n newProgress = Math.max(currentProgress - step * 2, 0);\r\n break;\r\n\r\n case ' ':\r\n case 'Enter':\r\n // 空格或回车键切换完成状态\r\n newProgress = currentProgress >= 0.95 ? 0 : 1;\r\n break;\r\n\r\n case 'Escape':\r\n newProgress = 0;\r\n break;\r\n\r\n default:\r\n return null;\r\n }\r\n\r\n // 防止默认行为\r\n event.preventDefault();\r\n\r\n return newProgress;\r\n }, []);\r\n\r\n /**\r\n * 获取键盘导航说明\r\n */\r\n const getNavigationInstructions = useCallback((): string => {\r\n return [\r\n '键盘导航说明:',\r\n '←/→ 或 ↑/↓: 调整进度 (±5%)',\r\n 'Home/End: 跳转到开始/结束',\r\n 'Page Up/Down: 快速调整 (±10%)',\r\n '空格/回车: 切换完成状态',\r\n 'Esc: 重置进度'\r\n ].join('\\n');\r\n }, []);\r\n\r\n return {\r\n handleKeyDown,\r\n getNavigationInstructions\r\n };\r\n};","import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';\r\nimport JSXGraph from 'jsxgraph';\r\nimport type { GeometryTransformProps, GeometryTransformError, GeometryShape } from './types';\r\nimport { validateAllConfigs } from './utils/validation';\r\nimport { TransformPipeline } from './composition/TransformPipeline';\r\nimport { convertLegacyTransformConfig } from './types/transform';\r\nimport { interpolateColorWithEasing, isValidColor } from './utils/colorUtils';\r\nimport { useTransformProgress } from './hooks/useTransformProgress';\r\nimport { useKeyboardNavigation } from './hooks/useKeyboardNavigation';\r\nimport './GeometryTransform.css';\r\n\r\n// 导入 HeroUI 组件\r\nimport { Card, CardBody } from '@heroui/react';\r\nimport { Slider } from '@heroui/react';\r\n// import { Progress } from '@heroui/react';\r\n\r\n// 获取 JSXGraph 实例\r\nconst JXG = JSXGraph.JSXGraph;\r\n\r\nconst GeometryTransform: React.FC<GeometryTransformProps> = (props) => {\r\n const {\r\n base,\r\n height,\r\n unit,\r\n layoutDensity = 'default',\r\n boardHeight,\r\n shapes,\r\n transform,\r\n animation,\r\n boardConfig = {},\r\n theme = 'light',\r\n className = '',\r\n // @ts-ignore: unused prop\r\n enableRigidityVerification = false,\r\n enableKeyboardNavigation = true,\r\n autoCompleteThreshold = 0.95,\r\n boardWidth,\r\n onTransformStart,\r\n onTransformChange,\r\n onTransformComplete,\r\n onError\r\n } = props;\r\n\r\n // 状态管理\r\n const [progress, setProgress] = useState(0);\r\n const [error, setError] = useState<GeometryTransformError | null>(null);\r\n // @ts-ignore: state defined but unused\r\n const [_currentStage, setCurrentStage] = useState(0);\r\n const [board, setBoard] = useState<any>(null);\r\n\r\n // ✅ 新增:容器尺寸状态(像 GraphContent 一样)\r\n const [containerSize, setContainerSize] = useState({\r\n width: 800,\r\n height: 560\r\n });\r\n // 变换管道实例\r\n const transformPipeline = useMemo(() => new TransformPipeline(), []);\r\n\r\n // 转换旧的transform配置到新格式\r\n const newTransformConfig = useMemo(() =>\r\n convertLegacyTransformConfig(transform)\r\n , [transform]);\r\n\r\n // Refs\r\n const boardContainerRef = useRef<HTMLDivElement>(null);\r\n const shapeElementsRef = useRef<Record<string, any>>({});\r\n // ✅ 新增:外层容器引用(用于 ResizeObserver)\r\n const outerContainerRef = useRef<HTMLDivElement>(null);\r\n const {\r\n handleProgressChange: handleProgressChangeDebounced,\r\n shouldAutoComplete,\r\n resetProgress\r\n } = useTransformProgress();\r\n\r\n const {\r\n handleKeyDown,\r\n getNavigationInstructions\r\n } = useKeyboardNavigation();\r\n\r\n // 计算面积\r\n const area = base * height;\r\n // @ts-ignore: calculated but unused\r\n const _areaText = `面积 = 底 × 高 = ${base} × ${height} = ${area}${unit}²`;\r\n\r\n // ✅ 新增:监听容器尺寸变化并动态计算画板高度\r\n useEffect(() => {\r\n const updateSize = () => {\r\n if (outerContainerRef.current) {\r\n const { clientWidth } = outerContainerRef.current;\r\n\r\n if (clientWidth > 0) {\r\n // 从 boardConfig 中提取 boundingBox\r\n const bbox = boardConfig.boundingBox || [0, 7, 10, 0];\r\n const bboxWidth = bbox[2] - bbox[0]; // xMax - xMin\r\n const bboxHeight = bbox[1] - bbox[3]; // yMax - yMin\r\n\r\n // 如果外部传入了 boardHeight,使用固定高度;否则根据宽高比计算\r\n let calculatedHeight: number;\r\n\r\n if (boardHeight) {\r\n calculatedHeight = boardHeight;\r\n } else {\r\n // 根据 boundingBox 的宽高比计算高度\r\n calculatedHeight = Math.round(clientWidth * (bboxHeight / bboxWidth));\r\n }\r\n\r\n console.log('🎯 GeometryTransform 容器尺寸更新:', {\r\n boundingBox: bbox,\r\n ratio: `${bboxHeight}:${bboxWidth}`,\r\n containerWidth: clientWidth,\r\n calculatedHeight,\r\n isCustomHeight: !!boardHeight\r\n });\r\n\r\n setContainerSize({\r\n width: clientWidth,\r\n height: calculatedHeight\r\n });\r\n }\r\n }\r\n };\r\n\r\n // 初始化尺寸\r\n updateSize();\r\n\r\n // 监听窗口大小变化\r\n window.addEventListener('resize', updateSize);\r\n\r\n // 使用 ResizeObserver 监听容器尺寸变化\r\n const resizeObserver = new ResizeObserver(updateSize);\r\n if (outerContainerRef.current) {\r\n resizeObserver.observe(outerContainerRef.current);\r\n }\r\n\r\n return () => {\r\n window.removeEventListener('resize', updateSize);\r\n resizeObserver.disconnect();\r\n };\r\n }, [boardConfig.boundingBox, boardHeight]);\r\n\r\n // 画板尺寸样式(使用计算后的固定像素值)\r\n const boardSizeStyle = {\r\n width: boardWidth ?? `${containerSize.width}px`,\r\n height: `${containerSize.height}px`\r\n };\r\n\r\n\r\n // 计算动态外观属性\r\n const computeDynamicAppearance = useCallback((\r\n shape: GeometryShape,\r\n progress: number\r\n ) => {\r\n console.log('🔍 computeDynamicAppearance called:', {\r\n shapeId: shape.metadata?.id,\r\n shapeType: shape.type,\r\n progress,\r\n hasMetadata: !!shape.metadata,\r\n hasDynamicAppearance: !!shape.metadata?.dynamicAppearance,\r\n dynamicAppearance: shape.metadata?.dynamicAppearance\r\n });\r\n\r\n const dynamicAppearance = shape.metadata?.dynamicAppearance;\r\n const baseStyle = shape.style || {};\r\n\r\n // 处理 fillcolor_set 变换(优先级高于 dynamicAppearance.color)\r\n let transformColor: string | undefined = undefined;\r\n if (shape.transform?.type === 'fillcolor_set' && shape.transform.fillColorSet) {\r\n const colorConfig = shape.transform.fillColorSet;\r\n const { targetColor, startAt = 0, endAt = 1, easing = 'linear', fromColor } = colorConfig;\r\n\r\n // 验证颜色格式\r\n if (isValidColor(targetColor) && (!fromColor || isValidColor(fromColor))) {\r\n // 计算有效进度\r\n let effectiveProgress = progress;\r\n if (progress < startAt) {\r\n effectiveProgress = 0;\r\n } else if (progress > endAt) {\r\n effectiveProgress = 1;\r\n } else {\r\n effectiveProgress = (progress - startAt) / (endAt - startAt);\r\n }\r\n\r\n // 确定起始颜色\r\n const startColor = fromColor || baseStyle.fillColor || '#FFFFFF';\r\n transformColor = interpolateColorWithEasing(startColor, targetColor, effectiveProgress, easing);\r\n\r\n console.log('🎨 fillcolor_set applied:', {\r\n shapeId: shape.metadata?.id,\r\n progress,\r\n effectiveProgress,\r\n startColor,\r\n targetColor,\r\n resultColor: transformColor\r\n });\r\n } else {\r\n console.warn('⚠️ fillcolor_set: 颜色格式无效', { targetColor, fromColor });\r\n }\r\n }\r\n\r\n // 如果没有动态外观配置,返回基础样式(包含可能的变换颜色)\r\n if (!dynamicAppearance) {\r\n console.log('📝 No dynamicAppearance, returning base style');\r\n if (transformColor) {\r\n return { ...baseStyle, fillColor: transformColor };\r\n }\r\n return baseStyle;\r\n }\r\n\r\n // 计算VisibilityConfig的值 (0-1)\r\n const computeVisibilityValue = (config: any): number => {\r\n if (!config) return 1; // 默认可见\r\n\r\n const threshold = config.threshold ?? 0.5;\r\n const startValue = config.startValue ?? 0;\r\n const endValue = config.endValue ?? 1;\r\n const type = config.type ?? 'step';\r\n\r\n if (type === 'step') {\r\n // 步进式:超过阈值时切换\r\n return progress >= threshold ? endValue : startValue;\r\n } else if (type === 'fade') {\r\n // 渐隐式:在阈值附近渐变\r\n if (progress < threshold) {\r\n return startValue;\r\n } else {\r\n // 简单线性渐变\r\n const fadeProgress = Math.min((progress - threshold) / (1 - threshold), 1);\r\n return startValue + (endValue - startValue) * fadeProgress;\r\n }\r\n }\r\n\r\n return 1; // 默认可见\r\n };\r\n\r\n const resultStyle = { ...baseStyle };\r\n let visible = true; // 默认可见\r\n\r\n // 计算可见性值\r\n const visibilityValue = computeVisibilityValue(dynamicAppearance.visibility);\r\n const labelVisibilityValue = computeVisibilityValue(dynamicAppearance.labelVisibility);\r\n\r\n console.log('📊 Visibility values:', {\r\n shapeId: shape.metadata?.id,\r\n progress,\r\n visibilityValue,\r\n labelVisibilityValue,\r\n hasVisibility: !!dynamicAppearance.visibility,\r\n hasLabelVisibility: !!dynamicAppearance.labelVisibility\r\n });\r\n\r\n // 处理图形可见性\r\n if (dynamicAppearance.visibility) {\r\n // 将可见性应用于透明度(0=完全透明,1=完全不透明)\r\n if (resultStyle.fillOpacity === undefined) {\r\n resultStyle.fillOpacity = 1; // 默认不透明\r\n }\r\n resultStyle.fillOpacity *= visibilityValue;\r\n\r\n // 当完全不可见时,隐藏描边\r\n if (visibilityValue === 0) {\r\n resultStyle.strokeWidth = 0;\r\n console.log('👁️ Shape hidden, strokeWidth set to 0');\r\n }\r\n\r\n if (resultStyle.strokeColor) {\r\n // 对于描边颜色,通过透明度控制可见性\r\n // 这里保持原样,由JSXGraph处理透明度\r\n }\r\n\r\n // 设置可见性标志\r\n visible = visibilityValue > 0;\r\n console.log('👁️ Shape visibility:', { shapeId: shape.metadata?.id, visible, visibilityValue });\r\n }\r\n\r\n // 处理标签可见性\r\n if (dynamicAppearance.labelVisibility) {\r\n const labelVisible = labelVisibilityValue > 0;\r\n resultStyle.labelVisible = labelVisible;\r\n console.log('🏷️ Label visibility:', {\r\n shapeId: shape.metadata?.id,\r\n labelVisible,\r\n labelVisibilityValue,\r\n hasLabel: !!shape.metadata?.label\r\n });\r\n }\r\n\r\n // 处理透明度\r\n if (dynamicAppearance.opacity) {\r\n const opacity = dynamicAppearance.opacity;\r\n const startAt = opacity.startAt ?? 0;\r\n const endAt = opacity.endAt ?? 1;\r\n const from = opacity.from ?? 1;\r\n const to = opacity.to ?? 1;\r\n const type = opacity.type ?? 'linear';\r\n\r\n let opacityValue = from;\r\n\r\n if (progress < startAt) {\r\n opacityValue = from;\r\n } else if (progress > endAt) {\r\n opacityValue = to;\r\n } else {\r\n // 在变化区间内\r\n const rangeProgress = (progress - startAt) / (endAt - startAt);\r\n\r\n if (type === 'linear') {\r\n opacityValue = from + (to - from) * rangeProgress;\r\n } else {\r\n // 自定义缓动函数\r\n opacityValue = from + (to - from) * rangeProgress;\r\n }\r\n }\r\n\r\n resultStyle.fillOpacity = opacityValue;\r\n }\r\n\r\n // 处理颜色渐变(如果已经有变换颜色,则使用变换颜色)\r\n if (transformColor) {\r\n resultStyle.fillColor = transformColor;\r\n console.log('🎨 Using transform color instead of dynamicAppearance.color:', {\r\n shapeId: shape.metadata?.id,\r\n transformColor\r\n });\r\n } else if (dynamicAppearance.color) {\r\n const color = dynamicAppearance.color;\r\n const startAt = color.startAt ?? 0;\r\n const endAt = color.endAt ?? 1;\r\n const from = color.from ?? resultStyle.fillColor;\r\n const to = color.to ?? resultStyle.fillColor;\r\n const type = color.type ?? 'gradient';\r\n\r\n if (from && to) {\r\n if (progress < startAt) {\r\n resultStyle.fillColor = from;\r\n } else if (progress > endAt) {\r\n resultStyle.fillColor = to;\r\n } else {\r\n // 在变化区间内\r\n const rangeProgress = (progress - startAt) / (endAt - startAt);\r\n\r\n if (type === 'gradient') {\r\n // 简单的线性插值(实际项目中可能需要颜色解析库)\r\n resultStyle.fillColor = to; // 简化处理,使用目标颜色\r\n } else {\r\n resultStyle.fillColor = rangeProgress >= 0.5 ? to : from;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // 设置可见性属性\r\n resultStyle.visible = visible;\r\n\r\n // 设置标签可见性属性(如果未设置,默认为false - 取消文字标记)\r\n if (resultStyle.labelVisible === undefined) {\r\n resultStyle.labelVisible = false; // 默认隐藏标签(取消文字标记)\r\n }\r\n\r\n console.log('📋 Final computed style:', {\r\n shapeId: shape.metadata?.id,\r\n visible: resultStyle.visible,\r\n labelVisible: resultStyle.labelVisible,\r\n fillOpacity: resultStyle.fillOpacity,\r\n strokeWidth: resultStyle.strokeWidth\r\n });\r\n\r\n return resultStyle;\r\n }, []);\r\n\r\n // 创建几何图形\r\n const createShape = useCallback((\r\n board: any,\r\n shape: GeometryShape,\r\n isStatic: boolean = false,\r\n progress: number = 0\r\n ) => {\r\n console.log('🎨 createShape called:', {\r\n shapeId: shape.metadata?.id,\r\n shapeType: shape.type,\r\n isStatic,\r\n progress,\r\n verticesLength: shape.vertices?.length,\r\n hasMetadata: !!shape.metadata,\r\n hasDynamicAppearance: !!shape.metadata?.dynamicAppearance\r\n });\r\n\r\n // 验证顶点:point类型只需要1个顶点,其他类型需要至少2个顶点\r\n const minVertices = shape.type === 'point' ? 1 : 2;\r\n if (!board || !shape.vertices || shape.vertices.length < minVertices) {\r\n console.warn(`⚠️ createShape: invalid board or vertices for ${shape.type}`, {\r\n shapeId: shape.metadata?.id,\r\n shapeType: shape.type,\r\n verticesLength: shape.vertices?.length,\r\n minVertices\r\n });\r\n return null;\r\n }\r\n\r\n // 计算动态外观样式\r\n const computedStyle = computeDynamicAppearance(shape, progress);\r\n let element: any;\r\n\r\n switch (shape.type) {\r\n case 'triangle':\r\n case 'rectangle':\r\n case 'parallelogram':\r\n case 'trapezoid':\r\n case 'polygon':\r\n // 确定是否显示标签:优先使用 computedStyle.labelVisible,其次使用 shape.style.labelVisible\r\n const shouldShowLabel = computedStyle.labelVisible !== undefined\r\n ? computedStyle.labelVisible\r\n : (shape.style?.labelVisible !== undefined ? shape.style.labelVisible : false);\r\n\r\n // 确定标签文本:优先使用 metadata.label,其次使用 metadata.id\r\n const labelText = shape.metadata?.label || shape.metadata?.id || '';\r\n\r\n element = board.create('polygon', shape.vertices, {\r\n name: labelText,\r\n fillColor: computedStyle.fillColor !== undefined ? computedStyle.fillColor : (isStatic ? '#8ec5fc' : '#6a5acd'),\r\n fillOpacity: computedStyle.fillOpacity !== undefined ? computedStyle.fillOpacity : (isStatic ? 0.3 : 0.7),\r\n strokeColor: computedStyle.strokeColor !== undefined ? computedStyle.strokeColor : (isStatic ? '#0074d9' : '#4b0082'),\r\n strokeWidth: computedStyle.strokeWidth !== undefined ? computedStyle.strokeWidth : (isStatic ? 1 : 2),\r\n dash: computedStyle.dashStyle !== undefined ? computedStyle.dashStyle : 0,\r\n fixed: isStatic,\r\n highlight: !isStatic,\r\n withLabel: shouldShowLabel,\r\n visible: computedStyle.visible !== undefined ? computedStyle.visible : true\r\n });\r\n break;\r\n\r\n case 'circle':\r\n if (shape.vertices.length >= 2) {\r\n const [center, radiusPoint] = shape.vertices;\r\n // 确定是否显示标签:优先使用 computedStyle.labelVisible,其次使用 shape.style.labelVisible\r\n const shouldShowLabel = computedStyle.labelVisible !== undefined\r\n ? computedStyle.labelVisible\r\n : (shape.style?.labelVisible !== undefined ? shape.style.labelVisible : false);\r\n\r\n // 确定标签文本:优先使用 metadata.label,其次使用 metadata.id\r\n const labelText = shape.metadata?.label || shape.metadata?.id || '';\r\n\r\n element = board.create('circle', [center, radiusPoint], {\r\n name: labelText,\r\n fillColor: computedStyle.fillColor !== undefined ? computedStyle.fillColor : (isStatic ? '#8ec5fc' : '#6a5acd'),\r\n fillOpacity: computedStyle.fillOpacity !== undefined ? computedStyle.fillOpacity : (isStatic ? 0.3 : 0.7),\r\n strokeColor: computedStyle.strokeColor !== undefined ? computedStyle.strokeColor : (isStatic ? '#0074d9' : '#4b0082'),\r\n strokeWidth: computedStyle.strokeWidth !== undefined ? computedStyle.strokeWidth : (isStatic ? 1 : 2),\r\n dash: computedStyle.dashStyle !== undefined ? computedStyle.dashStyle : 0,\r\n fixed: isStatic,\r\n highlight: !isStatic,\r\n withLabel: shouldShowLabel\r\n });\r\n }\r\n break;\r\n\r\n case 'point':\r\n if (shape.vertices.length >= 1) {\r\n const [x, y] = shape.vertices[0];\r\n // 确定是否显示标签:优先使用 computedStyle.labelVisible,其次使用 shape.style.labelVisible\r\n const shouldShowLabel = computedStyle.labelVisible !== undefined\r\n ? computedStyle.labelVisible\r\n : (shape.style?.labelVisible !== undefined ? shape.style.labelVisible : false);\r\n\r\n // 确定标签文本:优先使用 metadata.label,其次使用 metadata.id\r\n const labelText = shape.metadata?.label || shape.metadata?.id || '';\r\n\r\n // 参考MathGraph/GraphContainer的点创建逻辑\r\n element = board.create('point', [x, y], {\r\n name: labelText,\r\n withLabel: shouldShowLabel,\r\n fixed: isStatic,\r\n size: 4, // 点的大小,参考MathGraph默认值\r\n strokeColor: computedStyle.strokeColor !== undefined ? computedStyle.strokeColor : (isStatic ? '#0074d9' : '#4b0082'),\r\n fillColor: computedStyle.fillColor !== undefined ? computedStyle.fillColor : (isStatic ? '#8ec5fc' : '#6a5acd'),\r\n visible: computedStyle.visible !== undefined ? computedStyle.visible : true,\r\n highlight: !isStatic\r\n });\r\n }\r\n break;\r\n\r\n default:\r\n console.warn(`Unsupported shape type: ${shape.type}`);\r\n return null;\r\n }\r\n\r\n console.log('✅ createShape finished:', {\r\n shapeId: shape.metadata?.id,\r\n elementType: element?.type,\r\n elementName: element?.name,\r\n fillOpacity: element?.getAttribute?.('fillOpacity'),\r\n strokeWidth: element?.getAttribute?.('strokeWidth'),\r\n labelVisible: computedStyle.labelVisible,\r\n hasLabel: !!shape.metadata?.label,\r\n withLabel: !!shape.metadata?.label && computedStyle.labelVisible\r\n });\r\n\r\n return element;\r\n }, [computeDynamicAppearance]);\r\n\r\n // 验证配置\r\n useEffect(() => {\r\n // 等待必需数据就绪 - 严格检查\r\n const isDataReady = base > 0 && height > 0 && shapes?.animated?.length > 0;\r\n if (!isDataReady) {\r\n console.log('🔍 GeometryTransform: 数据未就绪,跳过验证', {\r\n base,\r\n height,\r\n shapesAnimatedLength: shapes?.animated?.length,\r\n isBaseValid: base > 0,\r\n isHeightValid: height > 0,\r\n hasAnimatedShapes: shapes?.animated?.length > 0\r\n });\r\n return;\r\n }\r\n\r\n console.log('🔍 GeometryTransform: 验证配置,props =', {\r\n base: props.base,\r\n height: props.height,\r\n unit: props.unit,\r\n shapes: props.shapes,\r\n shapesAnimatedLength: props.shapes?.animated?.length,\r\n shapesStaticLength: props.shapes?.static?.length,\r\n transform: props.transform,\r\n animation: props.animation,\r\n boardConfig: props.boardConfig\r\n });\r\n const validationError = validateAllConfigs(props);\r\n console.log('🔍 GeometryTransform: 验证结果 =', validationError);\r\n setError(validationError);\r\n\r\n if (validationError && onError) {\r\n onError(validationError);\r\n }\r\n }, [base, height, shapes, transform, animation, boardConfig, onError, props]);\r\n\r\n // 初始化 JSXGraph Board - 只运行一次\r\n useEffect(() => {\r\n if (!boardContainerRef.current) return;\r\n\r\n try {\r\n const defaultBoundingBox = boardConfig.boundingBox || [0, 7, 10, 0];\r\n const isDark = theme === 'dark';\r\n console.warn('🔍 JSXGraph Board Initialization:');\r\n console.warn(' - Received boundingBox:', boardConfig.boundingBox);\r\n console.warn(' - Container dimensions:', containerSize.width, 'x', containerSize.height);\r\n console.warn(' - Container actual dimensions:', boardContainerRef.current.clientWidth, 'x', boardContainerRef.current.clientHeight);\r\n const newBoard = JXG.initBoard(boardContainerRef.current, {\r\n boundingbox: defaultBoundingBox,\r\n keepaspectratio: boardConfig.keepAspectRatio ?? true,\r\n showCopyright: false,\r\n showNavigation: false,\r\n axis: boardConfig.showAxis ?? true,\r\n grid: boardConfig.showGrid ?? true,\r\n pan: { enabled: false },\r\n zoom: { enabled: false }\r\n } as any);\r\n\r\n // 设置主题颜色\r\n const axisColor = boardConfig.axisColor || (isDark ? '#ffffff' : '#000000');\r\n const gridColor = boardConfig.gridColor || (isDark ? '#444444' : '#dddddd');\r\n\r\n if ((newBoard as any).defaultAxes?.x) {\r\n (newBoard as any).defaultAxes.x.setAttribute({ strokeColor: axisColor });\r\n }\r\n if ((newBoard as any).defaultAxes?.y) {\r\n (newBoard as any).defaultAxes.y.setAttribute({ strokeColor: axisColor });\r\n }\r\n if ((newBoard as any).defaultGrid) {\r\n (newBoard as any).defaultGrid.setAttribute({ strokeColor: gridColor });\r\n }\r\n\r\n setBoard(newBoard);\r\n } catch (error) {\r\n const jsxgraphError: GeometryTransformError = {\r\n code: 'JSXGRAPH_ERROR',\r\n message: 'JSXGraph 画板初始化失败',\r\n details: error,\r\n timestamp: new Date().toISOString()\r\n };\r\n setError(jsxgraphError);\r\n onError?.(jsxgraphError);\r\n }\r\n\r\n return () => {\r\n if (board) {\r\n try {\r\n JXG.freeBoard(board);\r\n } catch (e) {\r\n // 忽略cleanup错误(Storybook HMR时可能抛出AbortError)\r\n if (e instanceof Error && e.name !== 'AbortError') {\r\n console.warn('Board cleanup warning:', e);\r\n }\r\n }\r\n }\r\n };\r\n }, [containerSize]);\r\n\r\n // 渲染图形 - 在 board 创建后运行\r\n useEffect(() => {\r\n if (!board) return;\r\n\r\n try {\r\n board.suspendUpdate();\r\n\r\n // 清除旧图形\r\n Object.values(shapeElementsRef.current).forEach((element: any) => {\r\n if (element && board.removeObject) {\r\n try {\r\n board.removeObject(element);\r\n } catch (e) {\r\n // 忽略移除错误\r\n }\r\n }\r\n });\r\n shapeElementsRef.current = {};\r\n\r\n // 绘制静态图形\r\n shapes.static.forEach((shape, index) => {\r\n const id = shape.metadata?.id || `static-${index}`;\r\n const element = createShape(board, shape, true, 0);\r\n if (element) {\r\n shapeElementsRef.current[id] = element;\r\n }\r\n });\r\n\r\n // 绘制动画图形(初始位置)\r\n shapes.animated.forEach((shape, index) => {\r\n const id = shape.metadata?.id || `animated-${index}`;\r\n const element = createShape(board, shape, false, 0);\r\n if (element) {\r\n shapeElementsRef.current[id] = element;\r\n }\r\n });\r\n\r\n board.unsuspendUpdate();\r\n\r\n // 触发开始回调\r\n if (onTransformStart) {\r\n onTransformStart();\r\n }\r\n } catch (error) {\r\n const renderError: GeometryTransformError = {\r\n code: 'RENDER_ERROR',\r\n message: '图形渲染失败',\r\n details: error,\r\n timestamp: new Date().toISOString()\r\n };\r\n setError(renderError);\r\n onError?.(renderError);\r\n }\r\n }, [board, shapes, base, height]);\r\n\r\n // 更新图形变换 - 通过重绘动画图形实现\r\n useEffect(() => {\r\n if (!board) return;\r\n\r\n board.suspendUpdate();\r\n\r\n try {\r\n // 1. 移除旧的动画图形\r\n shapes.animated.forEach((shape, index) => {\r\n const id = shape.metadata?.id || `animated-${index}`;\r\n const element = shapeElementsRef.current[id];\r\n if (element) {\r\n try {\r\n board.removeObject(element);\r\n } catch (e) {\r\n // 忽略移除错误\r\n }\r\n delete shapeElementsRef.current[id];\r\n }\r\n });\r\n\r\n // 2. 使用变换算法计算新位置并重新绘制\r\n shapes.animated.forEach((shape, index) => {\r\n const id = shape.metadata?.id || `animated-${index}`;\r\n\r\n // 转换形状的transform字段到新格式(如果存在)\r\n const convertedShape = shape.transform ? {\r\n ...shape,\r\n transform: convertLegacyTransformConfig(shape.transform)\r\n } : shape;\r\n\r\n // 计算变换后的顶点(支持形状专属transform)\r\n const transformedVertices = transformPipeline.executeShapeTransform(\r\n convertedShape,\r\n progress,\r\n newTransformConfig\r\n );\r\n\r\n // 创建变换后的图形定义\r\n const transformedShape = {\r\n ...shape,\r\n vertices: transformedVertices,\r\n metadata: {\r\n ...shape.metadata,\r\n id, // Use the computed id with fallback\r\n transformSource: (shape.transform ? 'shape' : 'global') as 'shape' | 'global' // Use the computed transformSource with fallback\r\n }\r\n };\r\n\r\n // 在新位置绘制图形\r\n const element = createShape(board, transformedShape, false, progress);\r\n if (element) {\r\n shapeElementsRef.current[id] = element;\r\n }\r\n });\r\n\r\n // 3. 更新当前阶段\r\n const progressStages = animation.progressIndicator?.stages || 1;\r\n const newStage = Math.min(Math.floor(progress * progressStages), progressStages - 1);\r\n setCurrentStage(newStage);\r\n\r\n } catch (error) {\r\n // 忽略AbortError(Storybook环境中常见)\r\n if (error instanceof Error && error.name === 'AbortError') {\r\n return;\r\n }\r\n console.warn('Transform update failed:', error);\r\n } finally {\r\n try {\r\n board.unsuspendUpdate();\r\n } catch (e) {\r\n // 忽略unsuspendUpdate错误\r\n }\r\n }\r\n }, [board, progress, shapes, transform, animation, createShape, newTransformConfig, transformPipeline]);\r\n\r\n // 处理滑块变化\r\n const handleSliderChange = useCallback((value: number | number[]) => {\r\n const progressValue = Array.isArray(value) ? value[0] : value;\r\n setProgress(progressValue);\r\n\r\n // 使用防抖处理回调\r\n handleProgressChangeDebounced(progressValue, (debouncedValue) => {\r\n onTransformChange?.(debouncedValue);\r\n });\r\n\r\n // 检查是否达到自动完成阈值\r\n if (shouldAutoComplete(progressValue, autoCompleteThreshold)) {\r\n setProgress(1);\r\n onTransformComplete?.();\r\n }\r\n }, [onTransformChange, onTransformComplete, autoCompleteThreshold, handleProgressChangeDebounced, shouldAutoComplete]);\r\n\r\n // 键盘导航处理\r\n useEffect(() => {\r\n if (!enableKeyboardNavigation) return;\r\n\r\n const handleGlobalKeyDown = (e: KeyboardEvent) => {\r\n const newProgress = handleKeyDown(e, progress);\r\n if (newProgress !== null && newProgress !== progress) {\r\n handleSliderChange(newProgress);\r\n }\r\n };\r\n\r\n window.addEventListener('keydown', handleGlobalKeyDown);\r\n return () => {\r\n window.removeEventListener('keydown', handleGlobalKeyDown);\r\n };\r\n }, [enableKeyboardNavigation, progress, handleSliderChange, handleKeyDown]);\r\n\r\n // 重置进度\r\n // @ts-ignore: defined but unused\r\n const _handleResetProgress = useCallback(() => {\r\n setProgress(0);\r\n setCurrentStage(0);\r\n resetProgress();\r\n }, [resetProgress]);\r\n\r\n // 重试错误处理\r\n const handleRetry = useCallback(() => {\r\n setError(null);\r\n setProgress(0);\r\n setCurrentStage(0);\r\n resetProgress();\r\n // 重新触发初始化 - useEffect 会基于 boardContainerRef.current 重新运行\r\n }, [resetProgress]);\r\n\r\n // 检查数据是否就绪\r\n const isDataReady = base > 0 && height > 0 && shapes?.animated?.length > 0;\r\n\r\n // 如果数据未就绪,显示加载状态\r\n if (!isDataReady) {\r\n console.log('🔍 GeometryTransform: 数据未就绪,显示加载状态', {\r\n base,\r\n height,\r\n shapesAnimatedLength: shapes?.animated?.length,\r\n error\r\n });\r\n return (\r\n <Card\r\n data-testid=\"card\"\r\n className={`geometry-transform geometry-transform__loading ${className}`}\r\n >\r\n <CardBody data-testid=\"card-body\">\r\n <div className=\"geometry-transform__loading-message\">\r\n 正在加载几何变换演示...\r\n </div>\r\n </CardBody>\r\n </Card>\r\n );\r\n }\r\n\r\n // 数据就绪,如果有错误,显示错误状态\r\n if (error) {\r\n return (\r\n <Card\r\n data-testid=\"card\"\r\n className={`geometry-transform geometry-transform__error ${className}`}\r\n >\r\n <CardBody data-testid=\"card-body\">\r\n <div\r\n className=\"geometry-transform__error-message\"\r\n role=\"alert\"\r\n aria-live=\"assertive\"\r\n aria-atomic=\"true\"\r\n >\r\n {/* 错误图标 */}\r\n <div className=\"geometry-transform__error-icon\" aria-hidden=\"true\">\r\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\r\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\r\n </svg>\r\n </div>\r\n\r\n <h3>几何变换演示加载失败</h3>\r\n <p>{error.message}</p>\r\n\r\n {error.details && (\r\n <details className=\"geometry-transform__error-details-wrapper\">\r\n <summary>查看错误详情</summary>\r\n <pre className=\"geometry-transform__error-details\">\r\n {JSON.stringify(error.details, null, 2)}\r\n </pre>\r\n </details>\r\n )}\r\n\r\n {/* 重试按钮 */}\r\n <div className=\"geometry-transform__error-actions\">\r\n <button\r\n type=\"button\"\r\n className=\"geometry-transform__retry-button\"\r\n onClick={handleRetry}\r\n aria-label=\"重试加载几何变换演示\"\r\n >\r\n 重试加载\r\n </button>\r\n </div>\r\n </div>\r\n </CardBody>\r\n </Card>\r\n );\r\n }\r\n\r\n return (\r\n <Card\r\n data-testid=\"card\"\r\n className={`geometry-transform ${layoutDensity === 'compact' ? 'geometry-transform--compact' : ''} ${theme === 'dark' ? 'geometry-transform--dark' : ''} ${className}`}\r\n >\r\n <CardBody data-testid=\"card-body\">\r\n {/* 画板区域 */}\r\n <div ref={outerContainerRef} className=\"geometry-transform__board-container\">\r\n <div\r\n ref={boardContainerRef}\r\n id=\"geometry-board\"\r\n className=\"geometry-transform__board\"\r\n style={boardSizeStyle}\r\n data-testid=\"geometry-board\"\r\n role=\"application\"\r\n aria-label=\"几何变换演示画板\"\r\n aria-describedby=\"geometry-board-description\"\r\n />\r\n <div id=\"geometry-board-description\" className=\"sr-only\">\r\n 交互式几何变换画板,显示几何图形及其变换过程。\r\n 使用滑块控制变换进度,支持键盘导航。\r\n </div>\r\n </div>\r\n\r\n {/* 控制区域 */}\r\n <div className=\"geometry-transform__controls\">\r\n {/* 滑块控制 */}\r\n <div className=\"geometry-transform__slider-group\">\r\n <Slider\r\n id=\"transform-slider\"\r\n\r\n data-testid=\"slider\"\r\n value={progress}\r\n onChange={handleSliderChange}\r\n minValue={0}\r\n maxValue={1}\r\n step={0.01}\r\n size=\"lg\"\r\n color=\"primary\"\r\n className=\"geometry-transform__slider\"\r\n //className=\"max-w-md\"\r\n label=\"变换进度\"\r\n showTooltip={false}\r\n formatOptions={{ style: \"percent\" }}\r\n aria-label=\"几何变换进度控制\"\r\n />\r\n </div>\r\n\r\n {/* 进度指示器 */}\r\n {/* 进度指示器暂时隐藏 */}\r\n\r\n {/* 信息面板精简:直接移除尺寸/面积/类型显示 */}\r\n\r\n {/* 控制按钮 */}\r\n {/* 删除重置按钮,交互由滑块与自动完成控制 */}\r\n\r\n {/* 键盘导航提示 */}\r\n {enableKeyboardNavigation && (\r\n <div className=\"geometry-transform__keyboard-hint\" role=\"note\" aria-label=\"键盘导航提示\">\r\n <details>\r\n <summary>键盘导航说明</summary>\r\n <pre className=\"geometry-transform__keyboard-instructions\">\r\n {getNavigationInstructions()}\r\n </pre>\r\n </details>\r\n </div>\r\n )}\r\n </div>\r\n </CardBody>\r\n </Card>\r\n );\r\n};\r\n\r\n// 使用 React.memo 优化性能,避免不必要的重渲染\r\nconst MemoizedGeometryTransform = React.memo(GeometryTransform, (prevProps, nextProps) => {\r\n // 自定义比较函数,优化性能\r\n // 比较基础值类型 props\r\n if (\r\n prevProps.base !== nextProps.base ||\r\n prevProps.height !== nextProps.height ||\r\n prevProps.unit !== nextProps.unit ||\r\n prevProps.theme !== nextProps.theme ||\r\n prevProps.className !== nextProps.className ||\r\n prevProps.enableRigidityVerification !== nextProps.enableRigidityVerification ||\r\n prevProps.enableKeyboardNavigation !== nextProps.enableKeyboardNavigation ||\r\n prevProps.autoCompleteThreshold !== nextProps.autoCompleteThreshold\r\n ) {\r\n return false; // props 变化,需要重渲染\r\n }\r\n\r\n // 比较回调函数 - 如果引用相同,可以认为是相同的\r\n // 注意:回调函数应该使用 useCallback 稳定引用\r\n if (\r\n prevProps.onTransformStart !== nextProps.onTransformStart ||\r\n prevProps.onTransformChange !== nextProps.onTransformChange ||\r\n prevProps.onTransformComplete !== nextProps.onTransformComplete ||\r\n prevProps.onError !== nextProps.onError\r\n ) {\r\n return false;\r\n }\r\n\r\n // 对于复杂对象,使用 JSON.stringify 简单比较(注意性能)\r\n // 在实际应用中,可以考虑更精细的比较策略\r\n const prevConfig = JSON.stringify({\r\n shapes: prevProps.shapes,\r\n transform: prevProps.transform,\r\n animation: prevProps.animation,\r\n boardConfig: prevProps.boardConfig\r\n });\r\n\r\n const nextConfig = JSON.stringify({\r\n shapes: nextProps.shapes,\r\n transform: nextProps.transform,\r\n animation: nextProps.animation,\r\n boardConfig: nextProps.boardConfig\r\n });\r\n\r\n return prevConfig === nextConfig;\r\n});\r\n\r\nexport default MemoizedGeometryTransform;","import { create } from 'zustand';\r\nimport { useShallow } from 'zustand/shallow';\r\nimport type { DragState } from './HundredChart.types';\r\n\r\n/**\r\n * HundredChart 组件状态管理 Store\r\n */\r\ninterface HundredChartStore {\r\n // 内部状态\r\n internalValue: number;\r\n isDragging: boolean;\r\n dragState: DragState;\r\n\r\n // Actions\r\n setInternalValue: (value: number) => void;\r\n startDrag: (startIndex: number) => void;\r\n updateDrag: (currentIndex: number) => void;\r\n endDrag: () => void;\r\n resetDrag: () => void;\r\n}\r\n\r\n/**\r\n * 创建 HundredChart Store\r\n */\r\nexport const useHundredChartStore = create<HundredChartStore>((set, get) => ({\r\n // 初始状态\r\n internalValue: 0,\r\n isDragging: false,\r\n dragState: {\r\n isDragging: false,\r\n startIndex: -1,\r\n currentIndex: -1,\r\n direction: null\r\n },\r\n\r\n // Actions\r\n setInternalValue: (value: number) => {\r\n set({ internalValue: Math.max(0, Math.min(1, value)) });\r\n },\r\n\r\n startDrag: (startIndex: number) => {\r\n set({\r\n isDragging: true,\r\n dragState: {\r\n isDragging: true,\r\n startIndex,\r\n currentIndex: startIndex,\r\n direction: null\r\n }\r\n });\r\n },\r\n\r\n updateDrag: (currentIndex: number) => {\r\n const { dragState } = get();\r\n\r\n // 计算拖拽方向\r\n let direction: DragState['direction'] = null;\r\n if (dragState.startIndex !== -1 && currentIndex !== -1) {\r\n const startRow = Math.floor(dragState.startIndex / 10);\r\n const startCol = dragState.startIndex % 10;\r\n const currentRow = Math.floor(currentIndex / 10);\r\n const currentCol = currentIndex % 10;\r\n\r\n if (currentRow === startRow) {\r\n direction = currentCol > startCol ? 'ltr' : 'rtl';\r\n } else if (currentCol === startCol) {\r\n direction = currentRow > startRow ? 'ttb' : 'btt';\r\n }\r\n }\r\n\r\n set({\r\n dragState: {\r\n ...dragState,\r\n currentIndex,\r\n direction\r\n }\r\n });\r\n },\r\n\r\n endDrag: () => {\r\n set({\r\n isDragging: false,\r\n dragState: {\r\n isDragging: false,\r\n startIndex: -1,\r\n currentIndex: -1,\r\n direction: null\r\n }\r\n });\r\n },\r\n\r\n resetDrag: () => {\r\n set({\r\n isDragging: false,\r\n dragState: {\r\n isDragging: false,\r\n startIndex: -1,\r\n currentIndex: -1,\r\n direction: null\r\n }\r\n });\r\n }\r\n}));\r\n\r\n/**\r\n * 状态选择器 Hook - 使用 useShallow 避免不必要的重渲染\r\n */\r\nexport const useHundredChartValue = () =>\r\n useHundredChartStore(\r\n useShallow((state) => ({\r\n internalValue: state.internalValue,\r\n setInternalValue: state.setInternalValue\r\n }))\r\n );\r\n\r\n/**\r\n * 拖拽状态选择器 Hook\r\n */\r\nexport const useHundredChartDrag = () =>\r\n useHundredChartStore(\r\n useShallow((state) => ({\r\n isDragging: state.isDragging,\r\n dragState: state.dragState,\r\n startDrag: state.startDrag,\r\n updateDrag: state.updateDrag,\r\n endDrag: state.endDrag,\r\n resetDrag: state.resetDrag\r\n }))\r\n );","import type {\r\n FillAlgorithmConfig,\r\n FillAlgorithmResult,\r\n CellData\r\n} from './HundredChart.types';\r\n\r\n/**\r\n * 计算填充的单元格\r\n * @param config 填充算法配置\r\n * @returns 填充算法结果\r\n */\r\nexport const calculateFilledCells = (\r\n config: FillAlgorithmConfig\r\n): FillAlgorithmResult => {\r\n const { totalCells, fillRatio, direction, rows, cols } = config;\r\n\r\n // 计算需要填充的单元格数量\r\n const filledCount = Math.round(totalCells * fillRatio);\r\n const filledCells: number[] = [];\r\n\r\n if (direction === 'ltr') {\r\n // 从左到右填充\r\n for (let i = 0; i < filledCount; i++) {\r\n filledCells.push(i);\r\n }\r\n } else {\r\n // 从上到下填充\r\n for (let row = 0; row < rows; row++) {\r\n for (let col = 0; col < cols; col++) {\r\n const index = row * cols + col;\r\n if (filledCells.length < filledCount) {\r\n filledCells.push(index);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n filledCells,\r\n filledCount,\r\n actualRatio: filledCount / totalCells\r\n };\r\n};\r\n\r\n/**\r\n * 生成单元格数据\r\n * @param rows 行数\r\n * @param cols 列数\r\n * @param cellSize 单元格尺寸\r\n * @param filledCells 填充的单元格索引\r\n * @returns 单元格数据数组\r\n */\r\nexport const generateCellData = (\r\n rows: number,\r\n cols: number,\r\n cellSize: number,\r\n filledCells: number[]\r\n): CellData[] => {\r\n const cells: CellData[] = [];\r\n\r\n for (let row = 0; row < rows; row++) {\r\n for (let col = 0; col < cols; col++) {\r\n const index = row * cols + col;\r\n cells.push({\r\n index,\r\n row,\r\n col,\r\n filled: filledCells.includes(index),\r\n x: col * cellSize,\r\n y: row * cellSize\r\n });\r\n }\r\n }\r\n\r\n return cells;\r\n};\r\n\r\n/**\r\n * 计算拖拽范围内的单元格\r\n * @param startIndex 起始单元格索引\r\n * @param currentIndex 当前单元格索引\r\n * @param direction 拖拽方向\r\n * @param rows 行数\r\n * @param cols 列数\r\n * @returns 拖拽范围内的单元格索引数组\r\n */\r\nexport const calculateDragRange = (\r\n startIndex: number,\r\n currentIndex: number,\r\n direction: 'ltr' | 'rtl' | 'ttb' | 'btt' | null,\r\n _rows: number,\r\n cols: number\r\n): number[] => {\r\n if (startIndex === -1 || currentIndex === -1 || !direction) {\r\n return [];\r\n }\r\n\r\n const startRow = Math.floor(startIndex / cols);\r\n const startCol = startIndex % cols;\r\n const currentRow = Math.floor(currentIndex / cols);\r\n const currentCol = currentIndex % cols;\r\n\r\n const range: number[] = [];\r\n\r\n switch (direction) {\r\n case 'ltr':\r\n // 从左到右拖拽\r\n for (let col = startCol; col <= currentCol; col++) {\r\n range.push(startRow * cols + col);\r\n }\r\n break;\r\n\r\n case 'rtl':\r\n // 从右到左拖拽\r\n for (let col = startCol; col >= currentCol; col--) {\r\n range.push(startRow * cols + col);\r\n }\r\n break;\r\n\r\n case 'ttb':\r\n // 从上到下拖拽\r\n for (let row = startRow; row <= currentRow; row++) {\r\n range.push(row * cols + startCol);\r\n }\r\n break;\r\n\r\n case 'btt':\r\n // 从下到上拖拽\r\n for (let row = startRow; row >= currentRow; row--) {\r\n range.push(row * cols + startCol);\r\n }\r\n break;\r\n }\r\n\r\n return range;\r\n};\r\n\r\n/**\r\n * 根据拖拽范围计算新的值\r\n * @param dragRange 拖拽范围内的单元格索引\r\n * @param totalCells 总单元格数\r\n * @returns 新的值(0-1之间)\r\n */\r\nexport const calculateValueFromDrag = (\r\n dragRange: number[],\r\n totalCells: number\r\n): number => {\r\n return Math.max(0, Math.min(1, dragRange.length / totalCells));\r\n};\r\n\r\n/**\r\n * 验证值是否在有效范围内\r\n * @param value 要验证的值\r\n * @returns 验证后的值(0-1之间)\r\n */\r\nexport const validateValue = (value: number): number => {\r\n return Math.max(0, Math.min(1, value));\r\n};\r\n\r\n/**\r\n * 格式化值为百分比字符串\r\n * @param value 数值(0-1之间)\r\n * @returns 百分比字符串\r\n */\r\nexport const formatPercentage = (value: number): string => {\r\n return `${Math.round(value * 100)}%`;\r\n};","import React, { useMemo, useCallback, useState } from 'react';\r\nimport type { HundredChartProps, CellData } from './HundredChart.types';\r\nimport { useHundredChartValue, useHundredChartDrag } from './HundredChart.store';\r\nimport {\r\n calculateFilledCells,\r\n generateCellData,\r\n calculateDragRange,\r\n calculateValueFromDrag,\r\n validateValue\r\n} from './HundredChart.utils';\r\nimport './HundredChart.css';\r\n\r\n/**\r\n * HundredChart 组件 - 百格图组件\r\n * 用于可视化数值比例,支持点击和拖拽交互\r\n */\r\nconst HundredChart: React.FC<HundredChartProps> = ({\r\n value,\r\n defaultValue = 0,\r\n mode = 'readonly',\r\n onChange,\r\n rows = 10,\r\n cols = 10,\r\n cellSize = 12,\r\n fillColor = '#3b82f6',\r\n baseColor = '#f3f4f6',\r\n strokeColor = '#d1d5db',\r\n shadingDirection = 'ltr',\r\n hasShadow = true,\r\n className = ''\r\n}) => {\r\n // 状态管理\r\n const { internalValue, setInternalValue } = useHundredChartValue();\r\n const { isDragging, dragState, startDrag, updateDrag, endDrag } = useHundredChartDrag();\r\n\r\n // 受控/非受控模式处理\r\n const isControlled = value !== undefined;\r\n const currentValue = isControlled ? validateValue(value) : internalValue;\r\n\r\n // 初始化默认值\r\n const [initialized, setInitialized] = useState(false);\r\n if (!initialized && !isControlled) {\r\n setInternalValue(validateValue(defaultValue));\r\n setInitialized(true);\r\n }\r\n\r\n // 计算填充的单元格\r\n const filledCells = useMemo(() => {\r\n const totalCells = rows * cols;\r\n const config = {\r\n totalCells,\r\n fillRatio: currentValue,\r\n direction: shadingDirection,\r\n rows,\r\n cols\r\n };\r\n return calculateFilledCells(config).filledCells;\r\n }, [currentValue, rows, cols, shadingDirection]);\r\n\r\n // 生成单元格数据\r\n const cellData = useMemo(() => {\r\n return generateCellData(rows, cols, cellSize, filledCells);\r\n }, [rows, cols, cellSize, filledCells]);\r\n\r\n // 拖拽范围计算\r\n const dragRange = useMemo(() => {\r\n if (!isDragging || dragState.startIndex === -1 || dragState.currentIndex === -1) {\r\n return [];\r\n }\r\n return calculateDragRange(\r\n dragState.startIndex,\r\n dragState.currentIndex,\r\n dragState.direction,\r\n rows,\r\n cols\r\n );\r\n }, [isDragging, dragState, rows, cols]);\r\n\r\n // 处理单元格点击\r\n const handleCellClick = useCallback((cellIndex: number) => {\r\n if (mode !== 'edit') return;\r\n\r\n const newValue = validateValue((cellIndex + 1) / (rows * cols));\r\n\r\n if (isControlled) {\r\n onChange?.(newValue);\r\n } else {\r\n setInternalValue(newValue);\r\n onChange?.(newValue);\r\n }\r\n }, [mode, rows, cols, isControlled, onChange, setInternalValue]);\r\n\r\n // 处理鼠标事件\r\n const handleMouseDown = useCallback((cellIndex: number) => {\r\n if (mode !== 'edit') return;\r\n startDrag(cellIndex);\r\n }, [mode, startDrag]);\r\n\r\n const handleMouseEnter = useCallback((cellIndex: number) => {\r\n if (mode !== 'edit' || !isDragging) return;\r\n updateDrag(cellIndex);\r\n }, [mode, isDragging, updateDrag]);\r\n\r\n const handleMouseUp = useCallback(() => {\r\n if (mode !== 'edit' || !isDragging) return;\r\n\r\n if (dragRange.length > 0) {\r\n const newValue = calculateValueFromDrag(dragRange, rows * cols);\r\n\r\n if (isControlled) {\r\n onChange?.(newValue);\r\n } else {\r\n setInternalValue(newValue);\r\n onChange?.(newValue);\r\n }\r\n }\r\n\r\n endDrag();\r\n }, [mode, isDragging, dragRange, rows, cols, isControlled, onChange, setInternalValue, endDrag]);\r\n\r\n // 计算 SVG 尺寸\r\n const svgWidth = cols * cellSize;\r\n const svgHeight = rows * cellSize;\r\n\r\n // 构建 CSS 类名\r\n const containerClasses = [\r\n 'hundred-chart-container',\r\n `hundred-chart--${mode}`,\r\n hasShadow && 'hundred-chart--has-shadow',\r\n className\r\n ].filter(Boolean).join(' ');\r\n\r\n // 计算填充百分比\r\n const fillPercentage = Math.round(currentValue * 100);\r\n\r\n return (\r\n <div\r\n className={containerClasses}\r\n data-testid=\"hundred-chart-container\"\r\n >\r\n <svg\r\n width={svgWidth}\r\n height={svgHeight}\r\n className=\"hundred-chart-svg\"\r\n data-testid=\"hundred-chart-svg\"\r\n role=\"img\"\r\n aria-label={`百格图 - ${fillPercentage}% 已填充`}\r\n >\r\n {cellData.map((cell: CellData) => {\r\n const isFilled = filledCells.includes(cell.index);\r\n const isInDragRange = dragRange.includes(cell.index);\r\n const isActive = isFilled || isInDragRange;\r\n\r\n return (\r\n <rect\r\n key={cell.index}\r\n x={cell.x}\r\n y={cell.y}\r\n width={cellSize}\r\n height={cellSize}\r\n fill={isActive ? fillColor : baseColor}\r\n stroke={strokeColor}\r\n strokeWidth={1}\r\n className=\"hundred-chart-cell\"\r\n data-testid=\"hundred-chart-cell\"\r\n data-filled={isFilled}\r\n data-drag={isInDragRange}\r\n aria-label={`第${cell.row + 1}行第${cell.col + 1}列,${isActive ? '已填充' : '未填充'}`}\r\n tabIndex={mode === 'edit' ? 0 : -1}\r\n onClick={() => handleCellClick(cell.index)}\r\n onMouseDown={() => handleMouseDown(cell.index)}\r\n onMouseEnter={() => handleMouseEnter(cell.index)}\r\n onMouseUp={handleMouseUp}\r\n onKeyDown={(e) => {\r\n if (mode === 'edit' && e.key === 'Enter') {\r\n handleCellClick(cell.index);\r\n }\r\n }}\r\n />\r\n );\r\n })}\r\n </svg>\r\n </div>\r\n );\r\n};\r\n\r\nexport default HundredChart;","import React from 'react';\r\nimport type { MathCardV2ContextType } from './MathCardV2.types';\r\n\r\n// 创建上下文\r\nexport const MathCardV2Context = React.createContext<MathCardV2ContextType | undefined>(undefined);\r\n\r\n// 上下文 Hook\r\nexport const useMathCardV2Context = () => {\r\n const context = React.useContext(MathCardV2Context);\r\n if (!context) {\r\n throw new Error('useMathCardV2Context must be used within a MathCardV2 component');\r\n }\r\n return context;\r\n};","import { useMemo } from 'react';\r\nimport type { MathProblemDocument, MathCardV2Scene } from '../MathCardV2.types';\r\n\r\n/**\r\n * 数据适配器 Hook\r\n * 根据场景选择合适的内容、布局和渲染器配置\r\n */\r\nexport const useDataAdapter = (\r\n data: MathProblemDocument,\r\n scene: MathCardV2Scene\r\n) => {\r\n return useMemo(() => {\r\n const sceneData = data.scenes?.[scene];\r\n\r\n return {\r\n ...data,\r\n content: sceneData?.content || data.content,\r\n layout: sceneData?.layout || data.layout,\r\n renderer: sceneData?.renderer || data.renderer\r\n };\r\n }, [data, scene]);\r\n};","import React from 'react';\r\nimport type { CardLayoutProps } from '../../MathCardV2.types';\r\nimport './CardLayout.css';\r\n\r\nexport const CardLayout: React.FC<CardLayoutProps> = ({\r\n children,\r\n padding,\r\n shadow = true,\r\n border = true,\r\n theme = 'light',\r\n className = ''\r\n}) => {\r\n const themeClass = theme === 'dark' ? 'theme-dark' : '';\r\n const shadowClass = shadow ? 'with-shadow' : '';\r\n const borderClass = border ? 'with-border' : '';\r\n\r\n // 使用 CSS 变量处理 padding,如果提供则覆盖默认值\r\n const style = padding ? { '--mc-card-padding': padding } as React.CSSProperties : undefined;\r\n\r\n return (\r\n <div\r\n className={`mathcard-v2-card ${themeClass} ${shadowClass} ${borderClass} ${className}`}\r\n style={style}\r\n data-testid=\"mathcard-v2-container\"\r\n >\r\n {children}\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport type { GridLayoutProps } from '../../MathCardV2.types';\r\nimport './GridLayout.css';\r\n\r\nexport const GridLayout: React.FC<GridLayoutProps> = ({\r\n children,\r\n columns,\r\n gap,\r\n responsive = true,\r\n className = ''\r\n}) => {\r\n // 使用 CSS 变量处理动态值\r\n const style = {\r\n '--grid-columns': columns,\r\n '--grid-gap': gap\r\n } as React.CSSProperties;\r\n\r\n const responsiveClass = responsive ? 'mathcard-v2-grid-responsive' : '';\r\n\r\n return (\r\n <div\r\n style={style}\r\n className={`mathcard-v2-grid ${responsiveClass} ${className}`}\r\n data-testid=\"grid-layout\"\r\n >\r\n {children}\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport type { FlowLayoutProps } from '../../MathCardV2.types';\r\nimport './FlowLayout.css';\r\n\r\nexport const FlowLayout: React.FC<FlowLayoutProps> = ({\r\n children,\r\n direction = 'vertical',\r\n gap,\r\n wrap = false,\r\n className = ''\r\n}) => {\r\n // 使用 CSS 变量处理动态值\r\n const style = {\r\n '--flow-gap': gap,\r\n '--flow-direction': direction === 'horizontal' ? 'row' : 'column',\r\n '--flow-wrap': wrap ? 'wrap' : 'nowrap'\r\n } as React.CSSProperties;\r\n\r\n const directionClass = direction === 'horizontal' ? 'horizontal' : '';\r\n const wrapClass = wrap ? 'wrap' : '';\r\n\r\n return (\r\n <div\r\n style={style}\r\n className={`mathcard-v2-flow ${directionClass} ${wrapClass} ${className}`}\r\n data-testid=\"flow-layout\"\r\n >\r\n {children}\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport type { TextContentProps } from '../../MathCardV2.types';\r\n\r\nexport const TextContent: React.FC<TextContentProps> = ({\r\n content,\r\n style = {},\r\n onInteraction,\r\n className = ''\r\n}) => {\r\n return (\r\n <div\r\n className={`mathcard-v2-text ${className}`}\r\n style={style}\r\n onClick={() => onInteraction?.({ type: 'click', content })}\r\n data-testid=\"text-content\"\r\n >\r\n {content}\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport EquationRender from '../../../EquationRender/EquationRender';\r\nimport type { FormulaContentProps } from '../../MathCardV2.types';\r\n\r\nexport const FormulaContent: React.FC<FormulaContentProps> = ({\r\n parts,\r\n children,\r\n displayMode = false,\r\n style = {},\r\n className = ''\r\n}) => {\r\n return (\r\n <div className={`mathcard-v2-formula ${className}`} style={style} data-testid=\"equation-render\">\r\n <EquationRender\r\n parts={parts}\r\n children={children}\r\n displayMode={displayMode}\r\n />\r\n </div>\r\n );\r\n};","/**\r\n * MathGraph 错误边界组件\r\n * 捕获并处理 MathGraph 组件中的错误\r\n */\r\n\r\nimport React from 'react';\r\n\r\ninterface MathGraphErrorBoundaryState {\r\n hasError: boolean;\r\n error: Error | null;\r\n}\r\n\r\nexport class MathGraphErrorBoundary extends React.Component<\r\n { children: React.ReactNode },\r\n MathGraphErrorBoundaryState\r\n> {\r\n state: MathGraphErrorBoundaryState = { hasError: false, error: null };\r\n\r\n static getDerivedStateFromError(error: Error): MathGraphErrorBoundaryState {\r\n return { hasError: true, error };\r\n }\r\n\r\n componentDidCatch(error: Error, info: React.ErrorInfo) {\r\n console.error('MathGraph Error:', error, info.componentStack);\r\n }\r\n\r\n render() {\r\n if (this.state.hasError) {\r\n return (\r\n <div className=\"border border-red-200 rounded-lg p-4 bg-red-50\">\r\n <h3 className=\"font-bold text-red-800\">绘图组件加载失败</h3>\r\n <p className=\"text-red-700\">{this.state.error?.message}</p>\r\n <button\r\n className=\"mt-2 px-3 py-1 bg-red-100 hover:bg-red-200 rounded\"\r\n onClick={() => this.setState({ hasError: false })}\r\n >\r\n 重试\r\n </button>\r\n </div>\r\n );\r\n }\r\n\r\n return this.props.children;\r\n }\r\n}","/**\n * Transform 参数转换工具函数\n * 将 AnimationConfig 转换为 JSXGraph Transform 参数\n */\n\nimport type {\n TransformParams,\n ParamValue,\n JSXTransformConfig,\n TranslateParams,\n ScaleParams,\n RotateParams,\n ReflectParams,\n ShearParams,\n GenericParams,\n MatrixParams,\n AnimationConfig\n} from '../animation.types';\n\n/**\n * 解析函数字符串为数学表达式\n * CSP-safe version that doesn't use eval() or new Function()\n *\n * @example\n * parseFunctionString(\"() => progress * Math.PI * 2\")\n * // Returns function that computes: progress * Math.PI * 2\n *\n * @param fnStr - 函数字符串,格式:\"() => expression\" 或 \"(progress) => expression\"\n * @returns 可执行的函数\n * @throws 当字符串格式无效时抛出错误\n */\nexport function parseFunctionString(fnStr: string): (progress: number) => number {\n if (typeof fnStr !== 'string') {\n throw new Error(`parseFunctionString expects a string, got ${typeof fnStr}`);\n }\n\n const cleanStr = fnStr.trim();\n\n // 匹配箭头函数格式\n const arrowMatch = cleanStr.match(/^(?:\\(\\s*\\)\\s*=\\>|\\(\\s*([^,)]+)\\s*\\)\\s*=\\>|([^=]+)\\s*=\\>)\\s*(?:\\{?\\s*return\\s+([^;]+);?\\s*\\}?|(.+))$/);\n\n if (arrowMatch) {\n const expression = (arrowMatch[3] || arrowMatch[4] || '').trim();\n\n if (!expression) {\n throw new Error(`Invalid function string: no expression found in \"${cleanStr}\"`);\n }\n\n try {\n // CSP-safe: Parse the expression manually instead of using new Function()\n return createSafeMathFunction(expression);\n } catch (error) {\n throw new Error(`Failed to create function from \"${cleanStr}\": ${error}`);\n }\n }\n\n throw new Error(`Invalid function string format: \"${cleanStr}\". Expected arrow function like \"() => progress * Math.PI\"`);\n}\n\n/**\n * 创建 CSP 安全的数学函数(使用模式匹配)\n * 支持常见的数学表达式模式\n */\nfunction createSafeMathFunction(expression: string): (progress: number) => number {\n const expr = expression.trim();\n\n // 模式 1: progress * Math.PI\n if (expr === 'progress * Math.PI' || expr === 'progress*Math.PI') {\n return (progress: number) => progress * Math.PI;\n }\n\n // 模式 2: progress * Math.PI * 2\n if (expr === 'progress * Math.PI * 2' || expr === 'progress*Math.PI*2') {\n return (progress: number) => progress * Math.PI * 2;\n }\n\n // 模式 3: progress * Number (通用)\n const numberPattern = /^progress\\s*\\*\\s*([0-9.]+)$/;\n const numberMatch = expr.match(numberPattern);\n if (numberMatch) {\n const multiplier = parseFloat(numberMatch[1]);\n return (progress: number) => progress * multiplier;\n }\n\n // 模式 4: progress * Math.PI * Number\n const piMultiplierPattern = /^progress\\s*\\*\\s*Math\\.PI\\s*\\*\\s*([0-9.]+)$/;\n const piMultiplierMatch = expr.match(piMultiplierPattern);\n if (piMultiplierMatch) {\n const multiplier = parseFloat(piMultiplierMatch[1]);\n return (progress: number) => progress * Math.PI * multiplier;\n }\n\n // 模式 5: Math.sin(progress * Math.PI)\n if (expr.includes('Math.sin') && expr.includes('progress')) {\n return (progress: number) => Math.sin(progress * Math.PI);\n }\n\n // 模式 6: Math.cos(progress * Math.PI)\n if (expr.includes('Math.cos') && expr.includes('progress')) {\n return (progress: number) => Math.cos(progress * Math.PI);\n }\n\n // 模式 7: 常量值\n const constantPattern = /^([0-9.]+)$/;\n const constantMatch = expr.match(constantPattern);\n if (constantMatch) {\n const value = parseFloat(constantMatch[1]);\n return () => value;\n }\n\n // 模式 8: 直接使用 progress\n if (expr === 'progress') {\n return (progress: number) => progress;\n }\n\n // 模式 9: control.value (占位,实际在 parseParamsWithControl 中处理)\n if (expr.includes('control.value')) {\n console.warn(`Expression contains control.value: ${expr}. Will be handled by parseParamsWithControl.`);\n return (progress: number) => progress * Math.PI; // 占位函数\n }\n\n // 不支持的表达式 - 回退到通用求值器\n console.warn(`Unsupported expression pattern: \"${expr}\". Using generic evaluator.`);\n return (progress: number) => {\n let evalExpr = expr.replace(/\\bprogress\\b/g, progress.toString());\n evalExpr = evalExpr.replace(/Math\\.PI/g, Math.PI.toString());\n evalExpr = evalExpr.replace(/Math\\.E/g, Math.E.toString());\n // ... 其他 Math 常量\n return evaluateExpression(evalExpr);\n };\n}\n\n/**\n * 手动求值数学表达式 (不使用 eval)\n * 支持: 数字, +, -, *, /, (), 空格\n *\n * @param expr - 表达式字符串\n * @returns 计算结果\n */\nfunction evaluateExpression(expr: string): number {\n // 移除所有空格\n const cleanExpr = expr.replace(/\\s/g, '');\n\n // 递归求值带括号的表达式\n function evaluate(expr: string): number {\n // 处理括号\n while (expr.includes('(')) {\n // 找到最内层的括号\n const match = expr.match(/\\(([^()]+)\\)/);\n if (!match) break;\n\n const innerValue = evaluate(match[1]);\n expr = expr.replace(match[0], innerValue.toString());\n }\n\n // 处理乘除(从左到右)\n const mdMatch = expr.match(/(-?\\d+\\.?\\d*)([*/])(-?\\d+\\.?\\d*)/);\n if (mdMatch) {\n const left = parseFloat(mdMatch[1]);\n const op = mdMatch[2];\n const right = parseFloat(mdMatch[3]);\n const result = op === '*' ? left * right : left / right;\n expr = expr.replace(mdMatch[0], result.toString());\n return evaluate(expr);\n }\n\n // 处理加减(从左到右)\n const asMatch = expr.match(/(-?\\d+\\.?\\d*)([+\\-])(-?\\d+\\.?\\d*)/);\n if (asMatch) {\n const left = parseFloat(asMatch[1]);\n const op = asMatch[2];\n const right = parseFloat(asMatch[3]);\n const result = op === '+' ? left + right : left - right;\n expr = expr.replace(asMatch[0], result.toString());\n return evaluate(expr);\n }\n\n // 应该是纯数字\n const value = parseFloat(expr);\n if (isNaN(value)) {\n throw new Error(`Invalid expression: ${expr}`);\n }\n return value;\n }\n\n return evaluate(cleanExpr);\n}\n\n/**\n * 判断参数是否为函数字符串\n */\nexport function isFunctionString(value: any): boolean {\n return typeof value === 'string' &&\n (value.includes('=>') || value.includes('progress'));\n}\n\n/**\n * 获取参数在指定进度下的值\n * 支持静态值和动态函数\n *\n * @param param - 参数值(静态数字或动态函数)\n * @param progress - 动画进度(0-1)\n * @returns 计算后的数值\n */\nexport function evalParamValue(param: ParamValue, progress: number = 0): number {\n if (typeof param === 'function') {\n return param(progress);\n }\n return param;\n}\n\n/**\n * 将 Transform 参数转换为 JSXGraph 格式\n *\n * @param config - JSXGraph Transform 配置\n * @param progress - 动画进度(0-1)\n * @returns JSXGraph 可接受的参数数组\n * @throws 当 Transform 类型不支持时抛出错误\n */\nexport function getJSXGraphParams(\n config: JSXTransformConfig, \n progress: number,\n control?: any // ✅ 新增:接收 slider/glider 控制对象\n): any[] {\n switch (config.params.type) {\n case 'translate': {\n const params = config.params as TranslateParams;\n \n // ✅ 如果参数是函数且有 control,返回函数对象让 JSXGraph 自动调用\n const xParam = (typeof params.x === 'function' && control)\n ? function() {\n const currentProgress = control.Value();\n return (params.x as Function)(currentProgress);\n }\n : evalParamValue(params.x, progress);\n \n const yParam = (typeof params.y === 'function' && control)\n ? function() {\n const currentProgress = control.Value();\n return (params.y as Function)(currentProgress);\n }\n : evalParamValue(params.y, progress);\n \n return [xParam, yParam];\n }\n\n case 'rotate': {\n const params = config.params as RotateParams;\n const center = params.center || [0, 0];\n \n // ✅ 如果 angle 是函数且有 control,返回函数对象让 JSXGraph 自动调用\n if (typeof params.angle === 'function' && control) {\n return [\n function() { // ✅ 返回函数对象!JSXGraph 会在渲染时调用\n const currentProgress = control.Value();\n return (params.angle as Function)(currentProgress);\n },\n center[0],\n center[1]\n ];\n }\n \n // 静态值或无 control 时立即求值\n const angle = evalParamValue(params.angle, progress);\n return [angle, center[0], center[1]];\n }\n\n case 'scale': {\n const params = config.params as ScaleParams;\n \n // ✅ scaleX 和 scaleY 也可能是动态的\n const scaleXParam = (typeof params.scaleX === 'function' && control)\n ? function() {\n const currentProgress = control.Value();\n return (params.scaleX as Function)(currentProgress);\n }\n : evalParamValue(params.scaleX, progress);\n \n const scaleYParam = (typeof params.scaleY === 'function' && control)\n ? function() {\n const currentProgress = control.Value();\n return (params.scaleY as Function)(currentProgress);\n }\n : evalParamValue(params.scaleY, progress);\n \n return [scaleXParam, scaleYParam];\n }\n\n case 'reflect': {\n const params = config.params as ReflectParams;\n\n // 三种方式支持:\n // 1. 直线 ID\n if (params.line) {\n // JSXGraph 会解析为直线对象\n return [params.line];\n }\n\n // 2. 两点 ID 确定直线\n if (params.point1 && params.point2) {\n return [params.point1, params.point2];\n }\n\n // 3. 两点坐标确定直线\n if (params.p1 && params.p2) {\n return [params.p1, params.p2];\n }\n\n throw new Error(\n `Reflect transform requires one of: \\n` +\n `1. line ID (string)\\n` +\n `2. point1 + point2 IDs\\n` +\n `3. p1 + p2 coordinates\\n` +\n `Received: ${JSON.stringify(params)}`\n );\n }\n\n case 'shear': {\n const params = config.params as ShearParams;\n const shearX = evalParamValue(params.shearX, progress);\n const shearY = evalParamValue(params.shearY, progress);\n return [shearX, shearY];\n }\n\n case 'generic': {\n const params = config.params as GenericParams;\n return [\n evalParamValue(params.a, progress), evalParamValue(params.b, progress), evalParamValue(params.c, progress),\n evalParamValue(params.d, progress), evalParamValue(params.e, progress), evalParamValue(params.f, progress),\n evalParamValue(params.g, progress), evalParamValue(params.h, progress), evalParamValue(params.i, progress)\n ];\n }\n\n case 'matrix': {\n const params = config.params as MatrixParams;\n // 确认是 3x3 矩阵\n if (!Array.isArray(params.matrix) || params.matrix.length !== 3 ||\n !params.matrix.every(row => Array.isArray(row) && row.length === 3)) {\n throw new Error('Matrix transform requires a 3x3 matrix array');\n }\n return [params.matrix];\n }\n\n default:\n throw new Error(`Unsupported transform type: ${(config.params as any).type}`);\n }\n}\n\n/**\n * 解析可能包含函数字符串的原始参数\n * 将字符串函数转换为可执行函数\n *\n * @param rawParams - 原始参数(可能包含函数字符串)\n * @returns 解析后的参数\n */\nexport function resolveDynamicParams(rawParams: Record<string, any>): Record<string, ParamValue> {\n const resolved: Record<string, ParamValue> = {};\n\n Object.entries(rawParams).forEach(([key, value]) => {\n // 如果是函数字符串,解析为函数\n if (typeof value === 'string' && isFunctionString(value)) {\n try {\n resolved[key] = parseFunctionString(value);\n } catch (error) {\n console.warn(`Failed to parse function string for ${key}: ${value}`, error);\n // 解析失败时返回一个默认函数(返回0)\n resolved[key] = () => 0;\n }\n } else {\n // 如果是静态值或已经解析的函数,直接使用\n resolved[key] = value;\n }\n });\n\n return resolved;\n}\n\n/**\n * 加载 RawAnimationConfig 并解析其中的函数字符串\n *\n * @param rawConfig - 原始动画配置\n * @returns 解析后的 AnimationConfig\n */\nexport function loadAnimationConfig(rawConfig: any): AnimationConfig {\n if (typeof rawConfig === 'object' && rawConfig.transformConfigs) {\n // TriangleAdapterV2 格式兼容\n return v2toV3Config(rawConfig);\n }\n\n // 已经是合法的 AnimationConfig\n if (typeof rawConfig === 'object' && rawConfig.transforms) {\n return rawConfig as AnimationConfig;\n }\n\n throw new Error('Invalid animation config format');\n}\n\n/**\n * 将 TriangleAdapterV2 格式转换为 v3 格式\n * 用于向后兼容\n *\n * @param v2Config - TriangleAdapterV2 格式的配置\n * @returns v3 格式的 AnimationConfig\n */\nfunction v2toV3Config(v2Config: any): AnimationConfig {\n // 简化的转换逻辑,实际转换会更复杂\n return {\n id: v2Config.id || 'converted-from-v2',\n transforms: [], // 根据具体格式转换\n visualEffects: v2Config.visualEffects || []\n };\n}\n\n/**\n * 验证 AnimationConfig 的有效性\n *\n * @param config - 动画配置\n * @returns 验证结果,包含是否有效和错误信息\n */\nexport function validateAnimationConfig(config: any): { valid: boolean; errors?: string[] } {\n if (!config || typeof config !== 'object') {\n return { valid: false, errors: ['Config must be an object'] };\n }\n\n const errors: string[] = [];\n\n // 验证 id - must exist and be a non-empty string\n if (!config.id || typeof config.id !== 'string' || config.id.trim() === '') {\n errors.push('Config must have a valid id (string)');\n }\n\n // 验证 transforms\n if (!Array.isArray(config.transforms)) {\n errors.push('Config must have a transforms array');\n } else {\n config.transforms.forEach((transform: any, index: number) => {\n // 验证每个 transform\n if (!transform.id || typeof transform.id !== 'string') {\n errors.push(`Transform at index ${index} must have a valid id`);\n }\n\n if (!transform.type || typeof transform.type !== 'string') {\n errors.push(`Transform at index ${index} must have a valid type`);\n }\n\n if (!transform.params || typeof transform.params !== 'object') {\n errors.push(`Transform at index ${index} must have valid params`);\n }\n\n if (!Array.isArray(transform.targetShapes)) {\n errors.push(`Transform at index ${index} must have targetShapes array`);\n } else if (transform.targetShapes.length === 0) {\n errors.push(`targetShapes must not be empty`);\n }\n });\n }\n\n return {\n valid: errors.length === 0,\n errors: errors.length > 0 ? errors : undefined\n };\n}\n\n/**\n * 计算剪裁变换(Clip Path Transform)\n * 在某些场景下需要将图形限制在特定区域内\n *\n * @param bounds - 边界框 [xmin, xmax, ymin, ymax]\n * @returns 剪裁变换参数\n */\nexport function createClipTransform(bounds: [number, number, number, number]): GenericParams {\n const [xmin, _xmax, ymin, _ymax] = bounds;\n\n return {\n type: 'generic',\n a: 1, b: 0, c: -xmin,\n d: 0, e: 1, f: -ymin,\n g: 0, h: 0, i: 1\n };\n}\n\n/**\n * 创建围绕某点缩放的复合变换\n * 因为 JSXGraph scale 不支持 center 参数\n *\n * @param scaleX - X 方向缩放比例\n * @param scaleY - Y 方向缩放比例\n * @param center - 缩放中心点 [x, y]\n * @returns 包含三个变换的数组(平移、缩放、平移)\n */\nexport function createScaleWithCenter(\n scaleX: number,\n scaleY: number,\n center: [number, number]\n): Exclude<TransformParams, ReflectParams | ShearParams | GenericParams | MatrixParams>[] {\n const [cx, cy] = center;\n\n // Handle negative zero case - convert -0 to 0\n const negCX = cx === 0 ? 0 : -cx;\n const negCY = cy === 0 ? 0 : -cy;\n\n return [\n {\n type: 'translate',\n x: negCX,\n y: negCY\n },\n {\n type: 'scale',\n scaleX,\n scaleY\n },\n {\n type: 'translate',\n x: cx,\n y: cy\n }\n ];\n}\n\n/**\n * 解析包含 control.value 引用的参数 (CSP-safe version)\n * 将 control.value 替换为 control.Value(),不使用 eval() 或 new Function()\n *\n * @example\n * // 输入: { angle: \"() => control.value * Math.PI\", center: [5, 4] }\n * // 输出: [3.14159, 5, 4] (当 control.Value() = 1)\n *\n * @param rawParams - 原始参数对象\n * @param control - JSXGraph 控制组件(Slider 或 Glider)\n * @returns JSXGraph 参数数组\n */\nexport function parseParamsWithControl(\n rawParams: Record<string, any>,\n control: any\n): any[] {\n const resolved: Record<string, any> = { ...rawParams };\n\n // 解析函数字符串,替换 control.value\n Object.entries(rawParams).forEach(([key, value]) => {\n if (typeof value === 'string' && value.includes('control.value')) {\n // 提取表达式部分\n const match = value.match(/=>\\s*(.+)$/);\n if (match) {\n const expression = match[1].trim();\n try {\n // CSP-safe evaluation\n const controlValue = control ? control.Value() : 0;\n // 使用安全的表达式求值\n const evalValue = evaluateControlExpression(expression, controlValue);\n resolved[key] = evalValue;\n } catch (error) {\n console.warn(`Failed to evaluate param ${key}: ${value}`, error);\n resolved[key] = 0; // 回退到默认值\n }\n } else {\n console.warn(`Invalid function format: ${value}`);\n resolved[key] = 0; // 回退到默认值\n }\n }\n });\n\n // 使用现有的 getJSXGraphParams 进行最终转换\n const mockConfig = {\n params: resolved,\n type: rawParams.type\n } as JSXTransformConfig;\n\n return getJSXGraphParams(mockConfig, 0);\n}\n\n/**\n * CSP 安全地计算包含 control.value 的表达式(使用模式匹配)\n */\nfunction evaluateControlExpression(expression: string, controlValue: number): number {\n const expr = expression.trim();\n\n // 移除箭头函数包装(如果有)\n const cleanExpr = expr.replace(/^\\(\\s*\\)\\s*=>\\s*/, '').trim();\n\n // 模式 1: control.value * Math.PI\n if (cleanExpr === 'control.value * Math.PI' || cleanExpr === 'control.value*Math.PI') {\n return controlValue * Math.PI;\n }\n\n // 模式 2: control.value * Math.PI * Number\n const piMultiplierPattern = /^control\\.value\\s*\\*\\s*Math\\.PI\\s*\\*\\s*([0-9.]+)$/;\n const piMultiplierMatch = cleanExpr.match(piMultiplierPattern);\n if (piMultiplierMatch) {\n const multiplier = parseFloat(piMultiplierMatch[1]);\n return controlValue * Math.PI * multiplier;\n }\n\n // 模式 3: control.value * Number\n const numberPattern = /^control\\.value\\s*\\*\\s*([0-9.]+)$/;\n const numberMatch = cleanExpr.match(numberPattern);\n if (numberMatch) {\n const multiplier = parseFloat(numberMatch[1]);\n return controlValue * multiplier;\n }\n\n // 模式 4: 直接 control.value\n if (cleanExpr === 'control.value') {\n return controlValue;\n }\n\n // 不支持的表达式 - 回退到通用求值器\n console.warn(`Unsupported control.value expression: \"${cleanExpr}\". Using generic evaluator.`);\n let evalExpr = cleanExpr.replace(/control\\.value/g, controlValue.toString());\n evalExpr = evalExpr.replace(/Math\\.PI/g, Math.PI.toString());\n evalExpr = evalExpr.replace(/Math\\.E/g, Math.E.toString());\n // ... 其他 Math 常量\n return evaluateExpression(evalExpr);\n}\n\n// 导出所有类型以便单元测试使用\nexport * from '../animation.types';\n","/**\r\n * GraphContainer 组件\r\n * JSXGraph 适配层,负责 JSXGraph Board 的初始化和图形渲染\r\n */\r\n\r\nimport React, { useRef, useState, useEffect, useCallback } from 'react';\r\nimport type { MathGraphProps, Shape, Point } from './types';\r\nimport type { AnimationConfig, JSXTransformConfig } from './animation.types';\r\nimport { getJSXGraphParams } from './utils/transformUtils';\r\n\r\n// JSXGraph 导入 - 通过 npm 安装的版本\r\nimport JSXGraph from 'jsxgraph';\r\n\r\n// 获取 JSXGraph 实例和常量\r\nconst JXG = JSXGraph.JSXGraph;\r\n\r\ninterface GraphContainerProps extends Omit<MathGraphProps, 'width' | 'height' | 'className'> {\r\n animation?: AnimationConfig;\r\n animationProgress?: number;\r\n}\r\n\r\nexport const GraphContainer: React.FC<GraphContainerProps> = (props) => {\r\n console.warn('🔍 GraphContainer props:', {\r\n hasAnimation: !!props.animation,\r\n animationId: props.animation?.id,\r\n hasControl: !!props.animation?.control,\r\n controlConfig: props.animation?.control,\r\n animationProgress: props.animationProgress\r\n });\r\n\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const [board, setBoard] = useState<JSXGraph.Board | null>(null);\r\n const [, setShapeElements] = useState<Record<string, any>>({});\r\n const [shapesReady, setShapesReady] = useState(false);\r\n const transformsRef = useRef<Record<string, any>>({});\r\n const shapeElementsRef = useRef<Record<string, any>>({});\r\n const controlRef = useRef<any>(null);\r\n const sliderListenersRef = useRef<Record<string, Function>>({});\r\n\r\n // 处理形状变化回调\r\n const handleShapeChange = useCallback((_shapeId: string, _newPosition: Point) => {\r\n if (props.onShapeChange) {\r\n // 这里需要更新整个 shapes 数组,但当前实现只传递了单个形状的变化\r\n // 暂时注释掉,需要重新设计这个回调\r\n // props.onShapeChange(shapeId, newPosition);\r\n }\r\n }, [props.onShapeChange]);\r\n\r\n // 处理选择变化回调\r\n const handleSelectionChange = useCallback((shapeId: string | null) => {\r\n if (props.onSelectionChange) {\r\n props.onSelectionChange(shapeId ? [shapeId] : []);\r\n }\r\n }, [props.onSelectionChange]);\r\n\r\n // 初始化 JSXGraph Board\r\n useEffect(() => {\r\n if (!containerRef.current) return;\r\n\r\n try {\r\n const boundingBox = props.boundingBox || [-10, 10, 10, -10];\r\n console.warn('🔍 JSXGraph Board Initialization:');\r\n console.warn(' - Received boundingBox:', boundingBox);\r\n console.warn(' - Container dimensions:', containerRef.current.clientWidth, 'x', containerRef.current.clientHeight);\r\n\r\n const board = JXG.initBoard(containerRef.current, {\r\n boundingbox: boundingBox,\r\n axis: props.showAxis ?? true,\r\n grid: props.showGrid ?? true,\r\n showNavigation: false,\r\n pan: { enabled: props.mode === 'edit' },\r\n keepaspectratio: true,\r\n showCopyright: false\r\n });\r\n\r\n // 检查实际设置的边界框\r\n console.warn(' - Board actual boundingbox:', board.getBoundingBox());\r\n // console.log(' - Board viewport:', board.getViewport()); // 这个方法可能不存在\r\n // console.log(' - Board origin:', board.getOrigin()); // 这个方法可能不存在\r\n // console.log(' - Board scale:', board.getScale()); // 这个方法可能不存在\r\n\r\n // 验证坐标转换\r\n setTimeout(() => {\r\n console.warn(' - 验证坐标转换:');\r\n console.warn(' * 理论边界框:', boundingBox);\r\n console.warn(' * 实际边界框:', board.getBoundingBox());\r\n console.warn(' * 实际显示范围:', {\r\n left: board.getBoundingBox()[0],\r\n top: board.getBoundingBox()[1],\r\n right: board.getBoundingBox()[2],\r\n bottom: board.getBoundingBox()[3]\r\n });\r\n }, 100);\r\n\r\n setBoard(board);\r\n } catch (error) {\r\n console.error('JSXGraph initialization failed:', error);\r\n }\r\n\r\n return () => {\r\n if (board) {\r\n JXG.freeBoard(board);\r\n }\r\n };\r\n }, []);\r\n\r\n // 创建和管理控制组件(Slider/Glider)\r\n useEffect(() => {\r\n console.warn('🔍 Control useEffect triggered:', {\r\n hasBoard: !!board,\r\n hasAnimation: !!props.animation,\r\n hasControl: !!props.animation?.control,\r\n animationId: props.animation?.id,\r\n controlType: props.animation?.control?.type,\r\n controlPosition: (props.animation?.control as any)?.position,\r\n controlRange: props.animation?.control?.range\r\n });\r\n\r\n if (!board || !props.animation?.control) {\r\n console.warn('❌ Control creation skipped: board=' + !!board + ', control=' + !!props.animation?.control);\r\n // 清理控制组件\r\n if (controlRef.current) {\r\n try {\r\n if (controlRef.current.remove) {\r\n controlRef.current.remove();\r\n }\r\n } catch (error) {\r\n console.warn('Failed to remove control:', error);\r\n }\r\n controlRef.current = null;\r\n }\r\n return;\r\n }\r\n\r\n const controlConfig = props.animation.control;\r\n console.warn('✨ Creating Control Component:', {\r\n type: controlConfig.type,\r\n config: controlConfig,\r\n position: (controlConfig as any).position,\r\n range: controlConfig.range\r\n });\r\n\r\n try {\r\n if (controlConfig.type === 'slider') {\r\n // 创建水平滑块\r\n const endX = controlConfig.position[0] + (controlConfig.length || 5);\r\n console.warn('📐 Slider creation parameters:', {\r\n startPoint: controlConfig.position,\r\n endPoint: [endX, controlConfig.position[1]],\r\n values: [controlConfig.range[0], controlConfig.initial || 0, controlConfig.range[1]],\r\n label: controlConfig.label,\r\n snapWidth: controlConfig.snapWidth || 0.01\r\n });\r\n\r\n const slider = board.create('slider', [\r\n controlConfig.position, // 起点\r\n [endX, controlConfig.position[1]], // 终点\r\n [controlConfig.range[0], controlConfig.initial || 0, controlConfig.range[1]] // 最小值, 初始值, 最大值\r\n ], {\r\n name: controlConfig.label || 'control',\r\n snapWidth: controlConfig.snapWidth || 0.01,\r\n withLabel: controlConfig.showLabel !== undefined ? controlConfig.showLabel : true,\r\n visible: true, // ← 显式设置可见性\r\n strokeColor: '#4CAF50',\r\n fillColor: '#4CAF50',\r\n highlightFillColor: '#66BB6A'\r\n });\r\n\r\n controlRef.current = slider;\r\n console.warn('✅ Slider created:', {\r\n id: slider.id,\r\n name: slider.name,\r\n initialValue: slider.Value(),\r\n startPoint: controlConfig.position,\r\n endPoint: [endX, controlConfig.position[1]],\r\n boundingBox: board.getBoundingBox(),\r\n visProp: slider.visProp\r\n });\r\n\r\n // 验证滑块是否在 board.objectsList 中\r\n const allObjects = board.objectsList.map((obj: any) => ({\r\n id: obj.id,\r\n type: obj.elType,\r\n name: obj.name,\r\n visible: obj.visProp?.visible\r\n }));\r\n const sliderInList = allObjects.find((obj: any) => obj.id === slider.id);\r\n console.warn('📊 Slider in board.objectsList:', !!sliderInList, sliderInList);\r\n console.warn('📊 All board objects count:', allObjects.length);\r\n\r\n // 可选:监听滑块变化并触发 React 回调\r\n if (props.onAnimationChange) {\r\n let isUpdating = false;\r\n slider.on('drag', () => {\r\n if (isUpdating) return;\r\n isUpdating = true;\r\n\r\n const value = slider.Value();\r\n const normalizedValue = (value - controlConfig.range[0]) / (controlConfig.range[1] - controlConfig.range[0]);\r\n props.onAnimationChange?.(normalizedValue);\r\n\r\n isUpdating = false;\r\n });\r\n }\r\n } else if (controlConfig.type === 'glider') {\r\n // 创建 Glider(需要参考线)\r\n const line = board.select(controlConfig.line, true);\r\n if (line) {\r\n const glider = board.create('glider', [\r\n controlConfig.initial || 0, 0, line\r\n ], {\r\n name: controlConfig.label || 'control',\r\n snapWidth: controlConfig.snapWidth || 0.01\r\n });\r\n\r\n controlRef.current = glider;\r\n console.warn('✅ Glider created:', {\r\n id: (glider as any).id,\r\n name: (glider as any).name\r\n });\r\n\r\n if (props.onAnimationChange) {\r\n let isUpdating = false;\r\n (glider as any).on('drag', () => {\r\n if (isUpdating) return;\r\n isUpdating = true;\r\n\r\n const value = (glider as any).Value();\r\n props.onAnimationChange?.(value);\r\n\r\n isUpdating = false;\r\n });\r\n }\r\n } else {\r\n console.warn(`Reference line not found for glider: ${controlConfig.line}`);\r\n }\r\n }\r\n } catch (error) {\r\n console.error('Failed to create control component:', error);\r\n }\r\n\r\n // 清理函数\r\n return () => {\r\n if (controlRef.current) {\r\n try {\r\n controlRef.current.remove();\r\n } catch (error) {\r\n console.warn('Failed to remove control on cleanup:', error);\r\n }\r\n controlRef.current = null;\r\n }\r\n };\r\n }, [board, props.animation?.control]);\r\n\r\n // 创建和管理 Transform 对象\r\n useEffect(() => {\r\n if (!board || !props.animation) {\r\n // 清理 Transform\r\n if (Object.keys(transformsRef.current).length > 0) {\r\n transformsRef.current = {};\r\n }\r\n return;\r\n }\r\n\r\n try {\r\n console.warn('✨ Creating Transforms:', {\r\n animationId: props.animation.id,\r\n transformCount: props.animation.transforms.length\r\n });\r\n\r\n // 清理旧的 Transform\r\n Object.values(transformsRef.current).forEach((transform: any) => {\r\n try {\r\n if (transform && transform.remove) {\r\n transform.remove();\r\n }\r\n } catch (error) {\r\n console.warn('Failed to remove transform:', error);\r\n }\r\n });\r\n transformsRef.current = {};\r\n\r\n // 创建新的 Transform 对象(阶段 1)\r\n const newTransforms: Record<string, any> = {};\r\n const progress = props.animationProgress ?? 0;\r\n\r\n props.animation.transforms.forEach((config: JSXTransformConfig) => {\r\n try {\r\n // 检查是否需要使用 control.value\r\n let params: any[];\r\n let transform: any;\r\n const usesControl = config.usesControl || false;\r\n\r\n if (controlRef.current && usesControl) {\r\n // ✅ 传递 control 对象,获取包含函数的参数(而不是静态数字)\r\n params = getJSXGraphParams(config, progress, controlRef.current);\r\n\r\n console.warn(`🔧 Creating transform ${config.id} (with dynamic params):`, {\r\n type: config.type,\r\n paramsTypes: params.map(p => typeof p), // ✅ 应该看到 'function'\r\n targetShapes: config.targetShapes,\r\n controlValue: controlRef.current.Value()\r\n });\r\n\r\n // ✅ 创建 Transform 对象 - JSXGraph 会在每次渲染时调用参数中的函数\r\n transform = board.create('transform', params, {\r\n type: config.type,\r\n id: `transform_${config.id}`\r\n });\r\n\r\n // ✅ 只需监听 drag 触发重绘和通知,不需要手动更新参数\r\n const triggerUpdate = () => {\r\n if (!controlRef.current) return;\r\n\r\n // ✅ JSXGraph 会自动调用参数函数重新计算,只需触发重绘\r\n board.update();\r\n\r\n const controlValue = controlRef.current.Value();\r\n console.warn(`🎯 Slider drag - transform ${config.id} auto-updated (controlValue: ${controlValue})`);\r\n\r\n // 触发回调通知 React 组件\r\n if (props.onAnimationChange) {\r\n // 将 control 值映射到 0-1 的 progress 范围\r\n const range = props.animation?.control?.range || [0, 1];\r\n const progress = (controlValue - range[0]) / (range[1] - range[0]);\r\n props.onAnimationChange(progress);\r\n }\r\n };\r\n\r\n // 绑定拖拽事件\r\n controlRef.current.on('drag', triggerUpdate);\r\n\r\n // 存储监听器以便后续清理\r\n sliderListenersRef.current[config.id] = triggerUpdate;\r\n\r\n console.warn(`🔗 Slider listener attached for transform ${config.id} (auto-update mode)`);\r\n } else {\r\n // 使用现有的 getJSXGraphParams 计算参数(无 control)\r\n params = getJSXGraphParams(config, progress);\r\n console.warn(`🔧 Creating transform ${config.id} (with progress ${progress}):`, {\r\n type: config.type,\r\n params,\r\n targetShapes: config.targetShapes\r\n });\r\n\r\n // 创建 Transform 对象(无需监听)\r\n transform = board.create('transform', params, {\r\n type: config.type,\r\n id: `transform_${config.id}`\r\n });\r\n }\r\n\r\n newTransforms[config.id] = transform;\r\n console.warn(`📝 Transform ${config.id} created:`, {\r\n type: config.type,\r\n paramsTypes: params.map(p => typeof p),\r\n transformMethods: Object.keys(transform).filter(k => typeof transform[k] === 'function')\r\n });\r\n } catch (error) {\r\n console.error(`Failed to create transform ${config.id}:`, error);\r\n }\r\n });\r\n\r\n transformsRef.current = newTransforms;\r\n\r\n } catch (error) {\r\n console.error('Transform setup failed:', error);\r\n }\r\n }, [board, props.animation]);\r\n\r\n // 绑定 Transform 到目标图形(依赖 shapesReady)\r\n useEffect(() => {\r\n if (!shapesReady || !board || !props.animation) {\r\n console.warn(`⏳ Transform binding waiting: shapesReady=${shapesReady}, board=${!!board}, animation=${!!props.animation}`);\r\n return;\r\n }\r\n\r\n console.warn('✅ Attempting to bind transforms to shapes...');\r\n console.warn(` Available shapes: ${Object.keys(shapeElementsRef.current).length}`);\r\n console.warn(` Available transforms: ${Object.keys(transformsRef.current).length}`);\r\n\r\n if (Object.keys(shapeElementsRef.current).length === 0) {\r\n console.warn('❌ No shapes available, skipping transform binding');\r\n return;\r\n }\r\n\r\n if (Object.keys(transformsRef.current).length === 0) {\r\n console.warn('❌ No transforms available, skipping binding');\r\n return;\r\n }\r\n\r\n Object.entries(transformsRef.current).forEach(([transformId, transform]) => {\r\n const config = props.animation?.transforms.find(t => t.id === transformId);\r\n if (!config) return;\r\n\r\n console.warn(`🔍 Binding transform ${transformId} (type: ${config.type}) to shapes:`, config.targetShapes);\r\n console.warn(`🔍 Available shapes in shapeElementsRef:`, Object.keys(shapeElementsRef.current));\r\n\r\n const targetElements = config.targetShapes\r\n .map(shapeId => {\r\n const element = shapeElementsRef.current[shapeId];\r\n if (!element) {\r\n console.warn(`❌ Shape not found for transform binding: ${shapeId}`);\r\n console.warn(` Available IDs:`, Object.keys(shapeElementsRef.current));\r\n } else {\r\n console.warn(`✅ Found shape ${shapeId}:`, element);\r\n }\r\n return element;\r\n })\r\n .filter(Boolean);\r\n\r\n console.warn(`🔍 Target elements after filtering:`, targetElements.length);\r\n\r\n if (targetElements.length > 0) {\r\n try {\r\n console.warn(`🔗 Attempting to bind transform ${transformId} to ${targetElements.length} shapes`);\r\n transform.bindTo(targetElements);\r\n console.warn(`✅ Successfully bound transform ${transformId} to ${targetElements.length} shapes`);\r\n // 验证绑定\r\n console.warn(` Transform object:`, transform);\r\n console.warn(` Target elements:`, targetElements.map(el => ({\r\n id: el.id,\r\n name: el.name,\r\n type: el.elementClass\r\n })));\r\n } catch (error) {\r\n console.error(`❌ Failed to bind transform ${transformId}:`, error);\r\n console.error(` Transform:`, transform);\r\n console.error(` TargetElements:`, targetElements);\r\n }\r\n } else {\r\n console.warn(`⚠️ No valid target elements for transform ${transformId}`);\r\n }\r\n });\r\n\r\n // 触发更新\r\n board.update();\r\n console.warn('✅ All transforms bound and board updated');\r\n }, [shapesReady, board, props.animation]);\r\n\r\n // 更新 Transform 参数(当 animationProgress 变化时)\r\n useEffect(() => {\r\n if (!board || Object.keys(transformsRef.current).length === 0) return;\r\n\r\n const progress = props.animationProgress ?? 0;\r\n console.warn(`🔄 Updating transforms for progress: ${progress}`);\r\n\r\n try {\r\n // 更新每个 Transform 的参数\r\n Object.entries(transformsRef.current).forEach(([transformId, transform]) => {\r\n const config = props.animation?.transforms.find(t => t.id === transformId);\r\n if (!config) return;\r\n\r\n const params = getJSXGraphParams(config, progress);\r\n\r\n // JSXGraph Transform 的矩阵更新方法\r\n // @ts-ignore - JSXGraph API 可能没有正确类型的声明\r\n console.warn(`🔄 Attempting to update transform ${transformId} with params:`, params);\r\n\r\n // 尝试不同的更新方法\r\n if (transform.update) {\r\n console.warn(` Using transform.update(params)`);\r\n transform.update(params);\r\n } else if (transform.setMatrix) {\r\n console.warn(` Using transform.setMatrix(board, config.type, params)`);\r\n transform.setMatrix(board, config.type, params);\r\n } else {\r\n console.warn(` Transform has no update or setMatrix method`);\r\n console.warn(` Available methods:`, Object.keys(transform).filter(k => typeof transform[k] === 'function'));\r\n }\r\n });\r\n\r\n // 触发重新渲染\r\n board.update();\r\n } catch (error) {\r\n console.error('Transform update failed:', error);\r\n }\r\n }, [board, props.animationProgress]);\r\n\r\n // 渲染图形\r\n useEffect(() => {\r\n if (!board) return;\r\n\r\n try {\r\n // 调试:打印所有形状数据\r\n console.warn('🎯 GraphContainer rendering shapes:', {\r\n totalShapes: props.shapes.length,\r\n shapes: props.shapes.map(shape => ({\r\n id: shape.id,\r\n type: shape.type,\r\n hasVertices: 'vertices' in shape,\r\n verticesCount: ('vertices' in shape && shape.vertices) ? shape.vertices.length : 'undefined',\r\n hasPosition: 'position' in shape,\r\n hasGeometryRef: 'geometryRef' in shape,\r\n geometryRef: 'geometryRef' in shape ? shape.geometryRef : undefined\r\n }))\r\n });\r\n\r\n // 清除旧图形\r\n board.suspendUpdate();\r\n // JSXGraph 的正确清除方法 - 移除所有对象\r\n // 注意:JSXGraph 没有 removeObjects 方法,需要逐个移除\r\n const objectsToRemove: JSXGraph.GeometryElement[] = [...board.objectsList] as JSXGraph.GeometryElement[];\r\n objectsToRemove.forEach(obj => {\r\n board.removeObject(obj);\r\n });\r\n\r\n // 创建新的图形元素\r\n const newShapeElements: Record<string, any> = {};\r\n shapeElementsRef.current = {};\r\n\r\n // 第一阶段:渲染所有点(确保被引用的点先存在)\r\n props.shapes.forEach(shape => {\r\n if (shape.type === 'point') {\r\n try {\r\n const element = createShapeWithEvents(\r\n board,\r\n shape,\r\n props.mode,\r\n handleShapeChange,\r\n handleSelectionChange\r\n );\r\n if (element) {\r\n newShapeElements[shape.id] = element;\r\n }\r\n } catch (error) {\r\n console.warn(`Failed to create point shape ${shape.id}:`, error);\r\n }\r\n }\r\n });\r\n\r\n // 第二阶段:渲染线、圆和多边形(它们可以引用已存在的点)\r\n console.warn('📐 Starting phase 2: creating lines, circles and polygons');\r\n console.warn('📊 Current board.objectsList:', board.objectsList.map((obj: any) => ({\r\n id: obj.id,\r\n name: obj.name,\r\n type: obj.elementClass\r\n })));\r\n\r\n props.shapes.forEach(shape => {\r\n if (shape.type === 'line' || shape.type === 'circle' || shape.type === 'polygon') {\r\n try {\r\n const element = createShapeWithEvents(\r\n board,\r\n shape,\r\n props.mode,\r\n handleShapeChange,\r\n handleSelectionChange\r\n );\r\n if (element) {\r\n newShapeElements[shape.id] = element;\r\n }\r\n } catch (error) {\r\n console.warn(`Failed to create shape ${shape.id}:`, error);\r\n }\r\n }\r\n });\r\n\r\n // 第三阶段:渲染文本(文本不依赖其他图形)\r\n console.warn('📝 Starting phase 3: creating text labels');\r\n props.shapes.forEach(shape => {\r\n if (shape.type === 'text') {\r\n try {\r\n const element = createShapeWithEvents(\r\n board,\r\n shape,\r\n props.mode,\r\n handleShapeChange,\r\n handleSelectionChange\r\n );\r\n if (element) {\r\n newShapeElements[shape.id] = element;\r\n }\r\n } catch (error) {\r\n console.warn(`Failed to create text ${shape.id}:`, error);\r\n }\r\n }\r\n });\r\n\r\n setShapeElements(newShapeElements);\r\n // 更新 shapeElementsRef 供 Transform 绑定使用\r\n shapeElementsRef.current = newShapeElements;\r\n setShapesReady(true); // ← 标记 shapes 已就绪\r\n console.warn(`✅ Shapes rendering completed: ${Object.keys(newShapeElements).length} shapes created`);\r\n board.unsuspendUpdate();\r\n } catch (error) {\r\n console.error('Shape rendering failed:', error);\r\n }\r\n }, [board, props.shapes, props.mode, handleShapeChange, handleSelectionChange]);\r\n\r\n // 组件卸载时清理 Transform\r\n useEffect(() => {\r\n return () => {\r\n console.warn('🧹 Component unmounting, cleaning up...');\r\n\r\n // 清理 Slider 监听器\r\n if (controlRef.current) {\r\n Object.entries(sliderListenersRef.current).forEach(([transformId, listener]) => {\r\n try {\r\n controlRef.current.off('drag', listener);\r\n console.warn(` Removed drag listener for transform ${transformId}`);\r\n } catch (error) {\r\n console.warn(`Failed to remove drag listener for ${transformId}:`, error);\r\n }\r\n });\r\n }\r\n sliderListenersRef.current = {};\r\n\r\n // 清理 Transform(避免内存泄漏)\r\n Object.values(transformsRef.current).forEach((transform: any) => {\r\n try {\r\n if (transform && transform.remove) {\r\n transform.remove();\r\n }\r\n } catch (error) {\r\n console.warn('Failed to remove transform during cleanup:', error);\r\n }\r\n });\r\n transformsRef.current = {};\r\n shapeElementsRef.current = {};\r\n setShapesReady(false);\r\n\r\n console.warn('✅ Cleanup complete');\r\n };\r\n }, []);\r\n\r\n return <div ref={containerRef} className=\"w-full h-full\" />;\r\n};\r\n\r\n/**\r\n * 创建带事件处理的图形元素\r\n */\r\nfunction createShapeWithEvents(\r\n board: JSXGraph.Board,\r\n shape: Shape,\r\n mode: 'view' | 'edit',\r\n onShapeChange: (shapeId: string, newPosition: Point) => void,\r\n onSelectionChange: (shapeId: string | null) => void\r\n): any | null {\r\n const isEditMode = mode === 'edit';\r\n\r\n switch (shape.type) {\r\n case 'point':\r\n try {\r\n // 调试:检查点数据\r\n console.warn(`🔍 Creating point ${shape.id}:`, {\r\n id: shape.id,\r\n type: shape.type,\r\n position: shape.position,\r\n hasPosition: 'position' in shape,\r\n positionType: typeof shape.position,\r\n positionIsArray: Array.isArray(shape.position),\r\n positionX: shape.position?.x,\r\n positionY: shape.position?.y,\r\n position0: Array.isArray(shape.position) ? shape.position[0] : undefined,\r\n position1: Array.isArray(shape.position) ? shape.position[1] : undefined\r\n });\r\n\r\n if (!shape.position) {\r\n console.error(`❌ Point ${shape.id} has no position field`);\r\n return null;\r\n }\r\n\r\n // 处理坐标格式:支持对象 {x, y} 和数组 [x, y]\r\n let x: number, y: number;\r\n if (shape.position.x !== undefined && shape.position.y !== undefined) {\r\n x = shape.position.x;\r\n y = shape.position.y;\r\n } else if (Array.isArray(shape.position) && shape.position.length >= 2) {\r\n x = shape.position[0];\r\n y = shape.position[1];\r\n } else {\r\n console.error(`❌ Point ${shape.id} has invalid position format:`, shape.position);\r\n return null;\r\n }\r\n\r\n const point: JSXGraph.GeometryElement = board.create('point', [x, y], {\r\n id: shape.id, // 设置ID以便后续引用\r\n name: shape.name || '',\r\n withLabel: shape.withLabel ?? (!!shape.name), // 如果有 name 默认显示标签\r\n fixed: !isEditMode,\r\n size: shape.size ?? 3,\r\n strokeColor: shape.strokeColor || shape.color || 'black',\r\n visible: shape.visible ?? true,\r\n // 添加标签配置\r\n label: shape.label ? {\r\n offset: shape.label.offset || [10, 10],\r\n fontSize: shape.label.fontSize || 14,\r\n color: shape.label.color,\r\n anchorX: shape.label.anchorX || 'middle',\r\n anchorY: shape.label.anchorY || 'bottom',\r\n cssClass: shape.label.cssClass,\r\n position: shape.label.position || 'urt',\r\n autoPosition: shape.label.autoPosition || false,\r\n distance: shape.label.distance || 1.5\r\n } : undefined\r\n });\r\n\r\n // 调试:打印创建的点信息\r\n console.warn(`🔵 Created point:`, {\r\n shapeId: shape.id,\r\n pointId: (point as any).id,\r\n pointName: (point as any).name,\r\n hasIdProperty: 'id' in point\r\n });\r\n\r\n // 添加拖拽事件处理\r\n if (isEditMode) {\r\n // 使用 JSXGraph 事件系统\r\n board.on('drag', () => {\r\n onShapeChange(shape.id, { x: (point as any).X(), y: (point as any).Y() });\r\n });\r\n\r\n // 添加点击选择事件\r\n board.on('down', () => {\r\n onSelectionChange(shape.id);\r\n });\r\n }\r\n\r\n return point;\r\n } catch (error) {\r\n console.error(`Failed to create point ${shape.id}:`, error);\r\n return null;\r\n }\r\n\r\n case 'line':\r\n const startPoint = resolvePointRef(shape.start, board);\r\n const endPoint = resolvePointRef(shape.end, board);\r\n\r\n if (startPoint && endPoint) {\r\n try {\r\n const line = board.create('line', [startPoint, endPoint], {\r\n strokeWidth: shape.strokeWidth ?? 2,\r\n strokeColor: shape.strokeColor || shape.color || 'black',\r\n dash: shape.dash ?? 0,\r\n fixed: !isEditMode,\r\n visible: shape.visible ?? true,\r\n // JSXGraph 推荐设置:不自动延伸线段\r\n straightFirst: false,\r\n straightLast: false\r\n });\r\n\r\n // 添加点击选择事件\r\n if (isEditMode) {\r\n board.on('down', () => {\r\n onSelectionChange(shape.id);\r\n });\r\n }\r\n\r\n return line;\r\n } catch (error) {\r\n console.error(`Failed to create line ${shape.id}:`, error);\r\n return null;\r\n }\r\n } else {\r\n console.warn(`Cannot create line ${shape.id}: missing start or end point`, {\r\n startPoint: !!startPoint,\r\n endPoint: !!endPoint,\r\n startRef: shape.start,\r\n endRef: shape.end\r\n });\r\n }\r\n break;\r\n\r\n case 'circle':\r\n const centerPoint = resolvePointRef(shape.center, board);\r\n\r\n if (centerPoint) {\r\n let circle;\r\n\r\n if (shape.through) {\r\n const throughPoint = resolvePointRef(shape.through, board);\r\n if (throughPoint) {\r\n circle = board.create('circle', [centerPoint, throughPoint], {\r\n strokeWidth: shape.strokeWidth ?? 2,\r\n strokeColor: shape.strokeColor || shape.color || 'black',\r\n fillColor: shape.fillColor || 'none',\r\n fillOpacity: shape.fillOpacity ?? 0.3,\r\n dash: shape.dash ?? 0,\r\n fixed: !isEditMode,\r\n visible: shape.visible ?? true\r\n });\r\n }\r\n } else if (shape.radius !== undefined) {\r\n circle = board.create('circle', [centerPoint, shape.radius], {\r\n strokeWidth: shape.strokeWidth ?? 2,\r\n strokeColor: shape.strokeColor || shape.color || 'black',\r\n fillColor: shape.fillColor || 'none',\r\n fillOpacity: shape.fillOpacity ?? 0.3,\r\n dash: shape.dash ?? 0,\r\n fixed: !isEditMode,\r\n visible: shape.visible ?? true\r\n });\r\n }\r\n\r\n // 添加点击选择事件\r\n if (circle && isEditMode) {\r\n board.on('down', () => {\r\n onSelectionChange(shape.id);\r\n });\r\n }\r\n\r\n return circle;\r\n }\r\n break;\r\n\r\n case 'polygon':\r\n try {\r\n console.error(`🔍 Creating polygon ${shape.id}:`, {\r\n id: shape.id,\r\n type: shape.type,\r\n hasVertices: 'vertices' in shape,\r\n vertices: shape.vertices,\r\n verticesIsArray: Array.isArray(shape.vertices),\r\n verticesLength: shape.vertices ? shape.vertices.length : 'undefined',\r\n shapeKeys: Object.keys(shape),\r\n geometryRef: 'geometryRef' in shape ? shape.geometryRef : undefined,\r\n styleRef: 'styleRef' in shape ? shape.styleRef : undefined,\r\n fullShapeData: JSON.stringify(shape, null, 2)\r\n });\r\n\r\n // 检查 vertices 是否存在\r\n if (!shape.vertices) {\r\n console.error(`❌ FATAL: Polygon ${shape.id} has no vertices! Full shape data:`, JSON.stringify(shape, null, 2));\r\n return null;\r\n }\r\n\r\n if (!Array.isArray(shape.vertices)) {\r\n console.error(`❌ FATAL: Polygon ${shape.id} vertices is not an array:`, shape.vertices);\r\n return null;\r\n }\r\n\r\n // 解析所有顶点,考虑顶点配置\r\n const vertices = shape.vertices.map((vertex, index) => {\r\n const vertexConfig = shape.verticesConfig ? shape.verticesConfig[index] : null;\r\n return resolvePointRefWithConfig(vertex, board, vertexConfig);\r\n });\r\n\r\n // 检查所有顶点是否都解析成功\r\n console.warn(`🔧 Polygon ${shape.id} resolved vertices:`, vertices);\r\n console.warn(`🔧 Polygon ${shape.id} vertices types:`, vertices.map(v => ({\r\n type: typeof v,\r\n isArray: Array.isArray(v),\r\n value: v\r\n })));\r\n if (vertices.every(vertex => vertex !== null)) {\r\n // 构建多边形配置\r\n const polygonConfig: any = {\r\n strokeWidth: shape.strokeWidth ?? 2,\r\n strokeColor: shape.strokeColor || shape.color || 'black',\r\n fillColor: shape.fillColor || 'lightblue',\r\n fillOpacity: shape.fillOpacity ?? 0.3,\r\n dash: shape.dash ?? 0,\r\n fixed: !isEditMode,\r\n visible: shape.visible ?? true\r\n };\r\n\r\n // 处理顶点配置\r\n if (shape.verticesConfig) {\r\n console.warn(`🔧 GraphContainer processing verticesConfig for polygon ${shape.id}:`, {\r\n verticesConfig: shape.verticesConfig,\r\n verticesConfigKeys: Object.keys(shape.verticesConfig),\r\n verticesConfigType: typeof shape.verticesConfig\r\n });\r\n\r\n // JSXGraph 多边形顶点配置\r\n // 支持:vertices: { withLabel: true, label: { offset: [x,y], fontSize: N, color: '...' } }\r\n const jsxgraphVerticesConfig: any = {};\r\n\r\n // 检查是否有顶层的 withLabel\r\n if (shape.verticesConfig.withLabel !== undefined) {\r\n jsxgraphVerticesConfig.withLabel = shape.verticesConfig.withLabel;\r\n } else {\r\n // 默认开启标签显示\r\n jsxgraphVerticesConfig.withLabel = true;\r\n }\r\n\r\n // 复制标签样式配置(如果存在)\r\n const labelConfig: any = {};\r\n let hasLabelConfig = false;\r\n\r\n if (shape.verticesConfig.offset) {\r\n labelConfig.offset = shape.verticesConfig.offset;\r\n hasLabelConfig = true;\r\n }\r\n if (shape.verticesConfig.fontSize) {\r\n labelConfig.fontSize = shape.verticesConfig.fontSize;\r\n hasLabelConfig = true;\r\n }\r\n if (shape.verticesConfig.color) {\r\n labelConfig.color = shape.verticesConfig.color;\r\n hasLabelConfig = true;\r\n }\r\n if (shape.verticesConfig.anchorX) {\r\n labelConfig.anchorX = shape.verticesConfig.anchorX;\r\n hasLabelConfig = true;\r\n }\r\n if (shape.verticesConfig.anchorY) {\r\n labelConfig.anchorY = shape.verticesConfig.anchorY;\r\n hasLabelConfig = true;\r\n }\r\n\r\n if (hasLabelConfig) {\r\n jsxgraphVerticesConfig.label = labelConfig;\r\n }\r\n\r\n polygonConfig.vertices = jsxgraphVerticesConfig;\r\n console.warn(`🔧 Using JSXGraph vertices config:`, jsxgraphVerticesConfig);\r\n } else {\r\n // 如果没有 verticesConfig,默认开启标签显示\r\n polygonConfig.vertices = { withLabel: true };\r\n }\r\n\r\n console.warn(`🔧 Creating polygon with config:`, polygonConfig);\r\n const polygon = board.create('polygon', vertices, polygonConfig);\r\n console.warn(`🔧 Polygon created:`, polygon);\r\n console.warn(`🔧 Polygon vertices:`, polygon.vertices);\r\n console.warn(`🔧 Polygon vertices names:`, polygon.vertices ? polygon.vertices.map((v: any) => v.name) : 'no vertices');\r\n console.warn(`🔧 Polygon vertices labels:`, polygon.vertices ? polygon.vertices.map((v: any) => v.hasLabel ? v.label : 'no label') : 'no vertices');\r\n\r\n // 添加点击选择事件\r\n if (isEditMode) {\r\n board.on('down', () => {\r\n onSelectionChange(shape.id);\r\n });\r\n }\r\n\r\n return polygon;\r\n } else {\r\n console.warn(`Cannot create polygon ${shape.id}: some vertices are missing`, {\r\n vertices: shape.vertices,\r\n resolvedVertices: vertices\r\n });\r\n }\r\n } catch (error) {\r\n console.error(`Failed to create polygon ${shape.id}:`, error);\r\n }\r\n break;\r\n\r\n case 'text':\r\n try {\r\n console.warn(`🔍 Creating text ${shape.id}:`, {\r\n id: shape.id,\r\n type: shape.type,\r\n hasPosition: 'position' in shape,\r\n position: shape.position,\r\n positionX: shape.position?.x,\r\n positionY: shape.position?.y,\r\n hasContent: 'content' in shape,\r\n content: shape.content,\r\n shapeKeys: Object.keys(shape)\r\n });\r\n const text = board.create('text', [shape.position.x, shape.position.y, shape.content], {\r\n color: shape.color || 'black',\r\n fontSize: shape.fontSize ?? 14,\r\n fixed: true,\r\n visible: shape.visible ?? true\r\n });\r\n\r\n return text;\r\n } catch (error) {\r\n console.error(`Failed to create text ${shape.id}:`, error);\r\n }\r\n break;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * 点引用解析函数 - 符合 JSXGraph API 要求\r\n * 支持直接坐标和引用其他点\r\n */\r\nfunction resolvePointRef(ref: any, board: JSXGraph.Board): any | null {\r\n // 处理数组格式坐标 [x, y]\r\n if (Array.isArray(ref) && ref.length >= 2) {\r\n return ref;\r\n }\r\n\r\n if (typeof ref === 'object' && ref !== null) {\r\n // 直接坐标 - 返回数组格式 [x, y]\r\n if ('x' in ref && 'y' in ref) {\r\n return [ref.x, ref.y];\r\n }\r\n\r\n // 引用其他点 - 使用 JSXGraph API\r\n if ('$ref' in ref) {\r\n try {\r\n // 方法 1: 通过 board.objects 访问(如果存在)\r\n if ((board as any).objects && (board as any).objects[ref.$ref]) {\r\n const referencedPoint = (board as any).objects[ref.$ref];\r\n if (referencedPoint) {\r\n return referencedPoint;\r\n }\r\n }\r\n\r\n // 方法 2: 遍历 board.objectsList 查找匹配的 ID\r\n const referencedPoint = board.objectsList.find((obj: any) => obj.id === ref.$ref);\r\n\r\n if (referencedPoint) {\r\n console.warn(`✅ Found referenced point ${ref.$ref}:`, referencedPoint);\r\n return referencedPoint;\r\n } else {\r\n console.warn(`⚠️ Point reference ${ref.$ref} not found in board.objectsList`);\r\n }\r\n } catch (error) {\r\n console.warn(`Failed to resolve point reference ${ref.$ref}:`, error);\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * 点引用解析函数(带配置)- 符合 JSXGraph API 要求\r\n * 支持直接坐标和引用其他点,并可应用顶点配置(如 name)\r\n */\r\nfunction resolvePointRefWithConfig(ref: any, board: JSXGraph.Board, vertexConfig: any): any | null {\r\n // 处理数组格式坐标 [x, y]\r\n if (Array.isArray(ref) && ref.length >= 2) {\r\n // 如果有顶点配置且包含 name,创建带标签的点对象\r\n if (vertexConfig && vertexConfig.name) {\r\n const point = board.create('point', ref, { name: vertexConfig.name });\r\n console.warn(`🔧 Created point with name ${vertexConfig.name} at`, ref);\r\n return point;\r\n }\r\n return ref;\r\n }\r\n\r\n if (typeof ref === 'object' && ref !== null) {\r\n // 直接坐标 - 返回数组格式 [x, y] 或创建点对象\r\n if ('x' in ref && 'y' in ref) {\r\n const coords = [ref.x, ref.y];\r\n // 如果有顶点配置且包含 name,创建带标签的点对象\r\n if (vertexConfig && vertexConfig.name) {\r\n const point = board.create('point', coords, { name: vertexConfig.name });\r\n console.warn(`🔧 Created point with name ${vertexConfig.name} at`, coords);\r\n return point;\r\n }\r\n return coords;\r\n }\r\n\r\n // 引用其他点 - 使用 JSXGraph API\r\n if ('$ref' in ref) {\r\n try {\r\n // 方法 1: 通过 board.objects 访问(如果存在)\r\n if ((board as any).objects && (board as any).objects[ref.$ref]) {\r\n const referencedPoint = (board as any).objects[ref.$ref];\r\n if (referencedPoint) {\r\n // 如果有顶点配置且包含 name,更新点对象的名称\r\n if (vertexConfig && vertexConfig.name && referencedPoint.setName) {\r\n referencedPoint.setName(vertexConfig.name);\r\n console.warn(`🔧 Updated point ${ref.$ref} name to ${vertexConfig.name}`);\r\n }\r\n return referencedPoint;\r\n }\r\n }\r\n\r\n // 方法 2: 遍历 board.objectsList 查找匹配的 ID\r\n const referencedPoint = board.objectsList.find((obj: any) => obj.id === ref.$ref);\r\n\r\n if (referencedPoint) {\r\n console.warn(`✅ Found referenced point ${ref.$ref}:`, referencedPoint);\r\n // 如果有顶点配置且包含 name,更新点对象的名称\r\n if (vertexConfig && vertexConfig.name && (referencedPoint as any).setName) {\r\n (referencedPoint as any).setName(vertexConfig.name);\r\n console.warn(`🔧 Updated point ${ref.$ref} name to ${vertexConfig.name}`);\r\n }\r\n return referencedPoint;\r\n } else {\r\n console.warn(`⚠️ Point reference ${ref.$ref} not found in board.objectsList`);\r\n }\r\n } catch (error) {\r\n console.warn(`Failed to resolve point reference ${ref.$ref}:`, error);\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}","/**\r\n * 自动边界框计算工具\r\n * 根据几何图形数据自动计算合适的边界框\r\n */\r\n\r\nimport type { Shape, Point, PointShape } from '../types';\r\n\r\nexport interface BoundingBoxOptions {\r\n padding?: number; // 边距比例 (0-1),默认 0.2\r\n margin?: number; // 固定边距,默认 1\r\n aspectRatio?: number; // 宽高比,默认 null(自动计算)\r\n minSize?: number; // 最小尺寸,默认 4\r\n}\r\n\r\nexport interface CalculatedBoundingBox {\r\n boundingBox: [number, number, number, number]; // [left, top, right, bottom]\r\n center: Point;\r\n width: number;\r\n height: number;\r\n}\r\n\r\n/**\r\n * 计算几何图形的边界框\r\n */\r\nexport function calculateBoundingBox(\r\n shapes: Shape[],\r\n options: BoundingBoxOptions = {}\r\n): CalculatedBoundingBox {\r\n const {\r\n padding = 0.2, // 20% 边距\r\n margin = 1, // 固定边距\r\n // aspectRatio,\r\n minSize = 4\r\n } = options;\r\n\r\n // 收集所有坐标点\r\n const allPoints: Point[] = [];\r\n\r\n shapes.forEach(shape => {\r\n switch (shape.type) {\r\n case 'point':\r\n allPoints.push(shape.position);\r\n break;\r\n\r\n case 'line':\r\n // 解析线段端点\r\n const startPoint = resolvePoint(shape.start, shapes);\r\n const endPoint = resolvePoint(shape.end, shapes);\r\n if (startPoint) allPoints.push(startPoint);\r\n if (endPoint) allPoints.push(endPoint);\r\n break;\r\n\r\n case 'circle':\r\n // 解析圆心\r\n const centerPoint = resolvePoint(shape.center, shapes);\r\n if (centerPoint) {\r\n allPoints.push(centerPoint);\r\n // 如果指定了半径,添加圆的边界点\r\n if (shape.radius !== undefined) {\r\n allPoints.push(\r\n { x: centerPoint.x + shape.radius, y: centerPoint.y },\r\n { x: centerPoint.x - shape.radius, y: centerPoint.y },\r\n { x: centerPoint.x, y: centerPoint.y + shape.radius },\r\n { x: centerPoint.x, y: centerPoint.y - shape.radius }\r\n );\r\n }\r\n }\r\n // 如果指定了经过点,添加经过点\r\n if (shape.through) {\r\n const throughPoint = resolvePoint(shape.through, shapes);\r\n if (throughPoint) allPoints.push(throughPoint);\r\n }\r\n break;\r\n\r\n case 'polygon':\r\n // 解析多边形所有顶点\r\n shape.vertices.forEach(vertex => {\r\n const point = resolvePoint(vertex, shapes);\r\n if (point) allPoints.push(point);\r\n });\r\n break;\r\n\r\n case 'text':\r\n // 文本位置\r\n allPoints.push(shape.position);\r\n // 估算文本占用空间(基于字体大小)\r\n const textWidth = (shape.content.length * (shape.fontSize || 14)) / 20;\r\n const textHeight = (shape.fontSize || 14) / 10;\r\n allPoints.push(\r\n { x: shape.position.x + textWidth, y: shape.position.y },\r\n { x: shape.position.x - textWidth, y: shape.position.y },\r\n { x: shape.position.x, y: shape.position.y + textHeight },\r\n { x: shape.position.x, y: shape.position.y - textHeight }\r\n );\r\n break;\r\n }\r\n });\r\n\r\n // 如果没有点,返回默认边界框\r\n if (allPoints.length === 0) {\r\n return {\r\n boundingBox: [-minSize, minSize, minSize, -minSize],\r\n center: { x: 0, y: 0 },\r\n width: minSize * 2,\r\n height: minSize * 2\r\n };\r\n }\r\n\r\n // 计算最小包围盒\r\n const minX = Math.min(...allPoints.map(p => p.x));\r\n const maxX = Math.max(...allPoints.map(p => p.x));\r\n const minY = Math.min(...allPoints.map(p => p.y));\r\n const maxY = Math.max(...allPoints.map(p => p.y));\r\n\r\n // 计算中心点\r\n const centerX = (minX + maxX) / 2;\r\n const centerY = (minY + maxY) / 2;\r\n\r\n // 计算原始宽度和高度\r\n let width = Math.max(maxX - minX, minSize);\r\n let height = Math.max(maxY - minY, minSize);\r\n\r\n // 应用宽高比约束 - 考虑画布宽高比\r\n const canvasAspectRatio = 800 / 500; // 默认画布宽高比\r\n const currentRatio = width / height;\r\n\r\n if (Math.abs(currentRatio - canvasAspectRatio) > 0.1) {\r\n if (currentRatio > canvasAspectRatio) {\r\n // 图形太宽,需要增加高度\r\n height = width / canvasAspectRatio;\r\n } else {\r\n // 图形太高,需要增加宽度\r\n width = height * canvasAspectRatio;\r\n }\r\n }\r\n\r\n // 应用边距\r\n const paddedWidth = width * (1 + padding) + margin * 2;\r\n const paddedHeight = height * (1 + padding) + margin * 2;\r\n\r\n // 计算最终的边界框\r\n const left = centerX - paddedWidth / 2;\r\n const top = centerY + paddedHeight / 2;\r\n const right = centerX + paddedWidth / 2;\r\n const bottom = centerY - paddedHeight / 2;\r\n\r\n // 验证边界框是否包含所有图形\r\n const finalBoundingBox: [number, number, number, number] = [left, top, right, bottom];\r\n\r\n // 开发环境下的验证\r\n if (process.env.NODE_ENV === 'development') {\r\n const validationPoints = allPoints.map(p => ({\r\n x: p.x,\r\n y: p.y,\r\n insideX: p.x >= left && p.x <= right,\r\n insideY: p.y <= top && p.y >= bottom,\r\n inside: p.x >= left && p.x <= right && p.y <= top && p.y >= bottom\r\n }));\r\n\r\n const outsidePoints = validationPoints.filter(p => !p.inside);\r\n if (outsidePoints.length > 0) {\r\n console.warn('⚠️ 边界框验证警告: 有图形元素超出边界框', {\r\n boundingBox: finalBoundingBox,\r\n outsidePoints: outsidePoints.slice(0, 5), // 只显示前5个\r\n totalOutside: outsidePoints.length\r\n });\r\n }\r\n }\r\n\r\n return {\r\n boundingBox: finalBoundingBox,\r\n center: { x: centerX, y: centerY },\r\n width: paddedWidth,\r\n height: paddedHeight\r\n };\r\n}\r\n\r\n/**\r\n * 解析点引用 - 增强版,支持 $ref 引用解析\r\n */\r\nexport function resolvePoint(ref: any, shapes: Shape[] = []): Point | null {\r\n if (typeof ref === 'object' && ref !== null) {\r\n // 直接坐标\r\n if ('x' in ref && 'y' in ref) {\r\n return { x: ref.x, y: ref.y };\r\n }\r\n\r\n // 引用其他点 (如 { $ref: 'pointA' })\r\n if ('$ref' in ref) {\r\n const referencedPoint = shapes.find(s => s.id === ref.$ref && s.type === 'point') as PointShape;\r\n if (referencedPoint) {\r\n return referencedPoint.position;\r\n }\r\n }\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * 快速边界框计算(仅考虑直接坐标,不解析引用)\r\n * 适用于性能敏感场景\r\n */\r\nexport function calculateSimpleBoundingBox(shapes: Shape[]): CalculatedBoundingBox {\r\n const points: Point[] = [];\r\n\r\n shapes.forEach(shape => {\r\n if (shape.type === 'point') {\r\n points.push(shape.position);\r\n } else if (shape.type === 'text') {\r\n points.push(shape.position);\r\n }\r\n // 其他类型需要解析引用,这里简化处理\r\n });\r\n\r\n if (points.length === 0) {\r\n return {\r\n boundingBox: [-5, 5, 5, -5],\r\n center: { x: 0, y: 0 },\r\n width: 10,\r\n height: 10\r\n };\r\n }\r\n\r\n const minX = Math.min(...points.map(p => p.x));\r\n const maxX = Math.max(...points.map(p => p.x));\r\n const minY = Math.min(...points.map(p => p.y));\r\n const maxY = Math.max(...points.map(p => p.y));\r\n\r\n const centerX = (minX + maxX) / 2;\r\n const centerY = (minY + maxY) / 2;\r\n const width = Math.max(maxX - minX, 4);\r\n const height = Math.max(maxY - minY, 4);\r\n\r\n const padding = 0.3;\r\n const paddedWidth = width * (1 + padding);\r\n const paddedHeight = height * (1 + padding);\r\n\r\n return {\r\n boundingBox: [\r\n centerX - paddedWidth / 2,\r\n centerY + paddedHeight / 2,\r\n centerX + paddedWidth / 2,\r\n centerY - paddedHeight / 2\r\n ],\r\n center: { x: centerX, y: centerY },\r\n width: paddedWidth,\r\n height: paddedHeight\r\n };\r\n}","/**\r\n * 边界框计算调试工具\r\n */\r\n\r\nimport type { Shape } from '../types';\r\nimport { calculateBoundingBox } from './boundingBoxCalculator';\r\nimport { resolvePoint } from './boundingBoxCalculator';\r\n\r\n/**\r\n * 调试边界框计算\r\n */\r\nexport function debugBoundingBox(shapes: Shape[], label: string = 'Debug') {\r\n console.group(`🔍 ${label} - 边界框计算调试`);\r\n\r\n // 收集所有坐标点\r\n const allPoints: {x: number, y: number, source: string}[] = [];\r\n\r\n shapes.forEach(shape => {\r\n switch (shape.type) {\r\n case 'point':\r\n allPoints.push({\r\n x: shape.position.x,\r\n y: shape.position.y,\r\n source: `point:${shape.id}`\r\n });\r\n break;\r\n\r\n case 'text':\r\n allPoints.push({\r\n x: shape.position.x,\r\n y: shape.position.y,\r\n source: `text:${shape.id}`\r\n });\r\n // 估算文本占用空间\r\n const textWidth = (shape.content.length * (shape.fontSize || 14)) / 20;\r\n const textHeight = (shape.fontSize || 14) / 10;\r\n allPoints.push(\r\n { x: shape.position.x + textWidth, y: shape.position.y, source: `text:${shape.id}:right` },\r\n { x: shape.position.x - textWidth, y: shape.position.y, source: `text:${shape.id}:left` },\r\n { x: shape.position.x, y: shape.position.y + textHeight, source: `text:${shape.id}:top` },\r\n { x: shape.position.x, y: shape.position.y - textHeight, source: `text:${shape.id}:bottom` }\r\n );\r\n break;\r\n\r\n case 'polygon':\r\n // 多边形顶点(解析引用)\r\n shape.vertices.forEach((vertex, index) => {\r\n const point = resolvePoint(vertex, shapes);\r\n if (point) {\r\n allPoints.push({\r\n x: point.x,\r\n y: point.y,\r\n source: `polygon:${shape.id}:vertex${index}`\r\n });\r\n }\r\n });\r\n break;\r\n }\r\n });\r\n\r\n console.log('📊 收集到的坐标点:', allPoints);\r\n\r\n // 计算最小包围盒\r\n if (allPoints.length > 0) {\r\n const minX = Math.min(...allPoints.map(p => p.x));\r\n const maxX = Math.max(...allPoints.map(p => p.x));\r\n const minY = Math.min(...allPoints.map(p => p.y));\r\n const maxY = Math.max(...allPoints.map(p => p.y));\r\n\r\n console.log('📐 原始包围盒:', {\r\n minX, maxX, minY, maxY,\r\n width: maxX - minX,\r\n height: maxY - minY\r\n });\r\n }\r\n\r\n // 计算自动边界框\r\n const result = calculateBoundingBox(shapes, {\r\n padding: 0.3,\r\n margin: 1,\r\n minSize: 4\r\n });\r\n\r\n console.log('🎯 自动边界框计算结果:', result);\r\n\r\n console.groupEnd();\r\n\r\n return result;\r\n}","/**\r\n * MathGraph 组件\r\n * 面向数学教育场景的交互式绘图功能组件\r\n */\r\n\r\nimport React, { useMemo } from 'react';\r\nimport { MathGraphErrorBoundary } from './MathGraphErrorBoundary';\r\nimport { GraphContainer } from './GraphContainer';\r\nimport { calculateBoundingBox } from './utils/boundingBoxCalculator';\r\nimport { debugBoundingBox } from './utils/debugBoundingBox';\r\nimport type { MathGraphProps } from './types';\r\nimport type { AnimationConfig } from './animation.types';\r\n\r\nexport const MathGraph: React.FC<MathGraphProps> = (props) => {\r\n const {\r\n shapes,\r\n mode,\r\n onShapeChange,\r\n onSelectionChange,\r\n width = 600,\r\n height = 400,\r\n showGrid = true,\r\n showAxis = true,\r\n className = '',\r\n boundingBox,\r\n autoBoundingBox = true,\r\n boundingBoxOptions,\r\n animation,\r\n animationProgress,\r\n onAnimationChange,\r\n showAnimationControls: _showAnimationControls\r\n } = props;\r\n\r\n // 自动计算边界框\r\n const calculatedBoundingBox = useMemo(() => {\r\n if (boundingBox) {\r\n return boundingBox;\r\n }\r\n\r\n if (autoBoundingBox && shapes.length > 0) {\r\n try {\r\n // 调试模式:在开发环境中输出详细计算信息\r\n if (process.env.NODE_ENV === 'development') {\r\n debugBoundingBox(shapes, 'MathGraph Auto BoundingBox');\r\n }\r\n\r\n const result = calculateBoundingBox(shapes, boundingBoxOptions);\r\n console.log('📐 Auto-calculated bounding box:');\r\n console.log(' - BoundingBox:', result.boundingBox);\r\n console.log(' - Center:', result.center);\r\n console.log(' - Width:', result.width);\r\n console.log(' - Height:', result.height);\r\n console.log(' - Options used:', boundingBoxOptions);\r\n return result.boundingBox as [number, number, number, number];\r\n } catch (error) {\r\n console.warn('Failed to calculate auto bounding box, using default:', error);\r\n return [-10, 10, 10, -10];\r\n }\r\n }\r\n\r\n return [-10, 10, 10, -10];\r\n }, [boundingBox, autoBoundingBox, shapes, boundingBoxOptions]);\r\n\r\n const containerStyle = useMemo(() => ({\r\n width: typeof width === 'number' ? `${width}px` : width,\r\n height: typeof height === 'number' ? `${height}px` : height\r\n }), [width, height]);\r\n\r\n return (\r\n <MathGraphErrorBoundary>\r\n <div\r\n className={`border border-gray-200 rounded-lg bg-white shadow-sm overflow-hidden ${className}`}\r\n style={containerStyle}\r\n data-testid=\"mathgraph\"\r\n role=\"application\"\r\n aria-label=\"数学绘图区域\"\r\n >\r\n <GraphContainer\r\n shapes={shapes}\r\n mode={mode}\r\n onShapeChange={onShapeChange}\r\n onSelectionChange={onSelectionChange}\r\n boundingBox={calculatedBoundingBox as [number, number, number, number]}\r\n showGrid={showGrid}\r\n showAxis={showAxis}\r\n animation={animation as AnimationConfig | undefined}\r\n animationProgress={animationProgress}\r\n onAnimationChange={onAnimationChange}\r\n />\r\n </div>\r\n </MathGraphErrorBoundary>\r\n );\r\n};","import React, { useRef, useEffect, useState } from 'react';\r\nimport { MathGraph } from '../../../MathGraph/MathGraph';\r\nimport type { GraphContentProps } from '../../MathCardV2.types';\r\n\r\nexport const GraphContent: React.FC<GraphContentProps> = ({\r\n shapes,\r\n width,\r\n height,\r\n showGrid = true,\r\n showAxis = true,\r\n boundingBox,\r\n autoBoundingBox,\r\n onShapeChange,\r\n className = '',\r\n // 动画相关属性\r\n animation,\r\n animationProgress,\r\n showAnimationControls,\r\n onAnimationChange\r\n}) => {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const [containerSize, setContainerSize] = useState({ width: 600, height: 400 });\r\n\r\n // 监听容器尺寸变化\r\n useEffect(() => {\r\n const updateSize = () => {\r\n if (containerRef.current) {\r\n const { clientWidth, clientHeight } = containerRef.current;\r\n if (clientWidth > 0 && clientHeight > 0) {\r\n setContainerSize({ width: clientWidth, height: clientHeight });\r\n }\r\n }\r\n };\r\n\r\n updateSize();\r\n\r\n // 监听窗口大小变化\r\n window.addEventListener('resize', updateSize);\r\n\r\n // 使用 ResizeObserver 监听容器尺寸变化\r\n const resizeObserver = new ResizeObserver(updateSize);\r\n if (containerRef.current) {\r\n resizeObserver.observe(containerRef.current);\r\n }\r\n\r\n return () => {\r\n window.removeEventListener('resize', updateSize);\r\n resizeObserver.disconnect();\r\n };\r\n }, []);\r\n\r\n // 如果提供了width/height,则使用;否则使用100%填充容器\r\n const containerStyle = {\r\n width: width ? (typeof width === 'string' ? width : `${width}px`) : '100%',\r\n height: height ? (typeof height === 'string' ? height : `${height}px`) : '100%'\r\n };\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={`mathcard-v2-graph ${className}`}\r\n style={containerStyle}\r\n >\r\n <MathGraph\r\n shapes={shapes}\r\n width={containerSize.width}\r\n height={containerSize.height}\r\n showGrid={showGrid}\r\n showAxis={showAxis}\r\n boundingBox={boundingBox}\r\n autoBoundingBox={autoBoundingBox}\r\n onShapeChange={onShapeChange}\r\n mode=\"view\"\r\n data-testid=\"mathgraph\"\r\n // 传递动画相关属性\r\n animation={animation}\r\n animationProgress={animationProgress}\r\n showAnimationControls={showAnimationControls}\r\n onAnimationChange={onAnimationChange}\r\n />\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport GeometryTransform from '../../../GeometryTransform/GeometryTransform';\r\nimport type { GeometryTransformContentProps } from '../../MathCardV2.types';\r\n\r\nexport const GeometryTransformContent: React.FC<GeometryTransformContentProps> = ({\r\n config,\r\n onTransformChange,\r\n onTransformComplete,\r\n onError,\r\n layoutDensity,\r\n boardHeight,\r\n boardWidth,\r\n className = ''\r\n}) => {\r\n const effectiveLayoutDensity = layoutDensity ?? config.ui?.layoutDensity ?? 'default';\r\n const effectiveBoardHeight = boardHeight ?? config.ui?.boardHeight ?? 300;\r\n const effectiveBoardWidth = boardWidth ?? config.ui?.boardWidth ?? 400;\r\n\r\n // 处理变换进度变化\r\n const handleTransformChange = (progress: number) => {\r\n onTransformChange?.(progress);\r\n };\r\n\r\n // 处理变换完成\r\n const handleTransformComplete = () => {\r\n onTransformComplete?.();\r\n };\r\n\r\n // 处理错误\r\n const handleError = (error: any) => {\r\n onError?.(error);\r\n };\r\n {\r\n console.error('🔍 GeometryTransformContent: config =', {\r\n base: config.base,\r\n height: config.height,\r\n unit: config.unit,\r\n shapes: config.shapes,\r\n shapesAnimatedLength: config.shapes?.animated?.length,\r\n shapesStaticLength: config.shapes?.static?.length,\r\n transform: config.transform,\r\n animation: config.animation,\r\n boardConfig: config.boardConfig,\r\n boardConfigKeys: config.boardConfig ? Object.keys(config.boardConfig) : [],\r\n boardConfigBoundingBox: config.boardConfig?.boundingBox,\r\n boardConfigOriginX: config.boardConfig?.originX,\r\n boardConfigOriginY: config.boardConfig?.originY,\r\n configKeys: Object.keys(config)\r\n })\r\n }\r\n return (\r\n <div\r\n className={`mathcard-v2-geometry-transform ${className}`}\r\n style={{\r\n width: '100%',\r\n display: 'flex',\r\n justifyContent: 'center',\r\n alignItems: 'center'\r\n }}\r\n data-testid=\"geometry-transform\"\r\n >\r\n <GeometryTransform\r\n base={config.base}\r\n height={config.height}\r\n unit={config.unit}\r\n shapes={config.shapes}\r\n transform={config.transform}\r\n animation={config.animation}\r\n boardConfig={config.boardConfig}\r\n onTransformChange={handleTransformChange}\r\n onTransformComplete={handleTransformComplete}\r\n onError={handleError}\r\n layoutDensity={effectiveLayoutDensity}\r\n boardHeight={effectiveBoardHeight}\r\n boardWidth={effectiveBoardWidth}\r\n enableKeyboardNavigation={true}\r\n enableRigidityVerification={true}\r\n autoCompleteThreshold={0.95}\r\n theme=\"light\"\r\n />\r\n </div>\r\n );\r\n};","import React from 'react';\r\n\r\ninterface PlaceValueChartProps {\r\n headers: string[];\r\n values: string[];\r\n colors?: {\r\n headerBg?: string;\r\n valueBg?: string;\r\n borderColor?: string;\r\n };\r\n}\r\n\r\n/**\r\n * 数位表组件\r\n * 用于展示小数的数位结构\r\n */\r\nconst PlaceValueChart: React.FC<PlaceValueChartProps> = ({\r\n headers,\r\n values,\r\n colors = {}\r\n}) => {\r\n const {\r\n headerBg = '#f1f5f9',\r\n valueBg = '#ffffff',\r\n borderColor = '#e2e8f0'\r\n } = colors;\r\n\r\n // 验证数据长度匹配\r\n if (headers.length !== values.length) {\r\n console.warn('PlaceValueChart: headers and values length mismatch');\r\n return null;\r\n }\r\n\r\n return (\r\n <div\r\n className=\"place-value-chart\"\r\n style={{\r\n display: 'inline-block',\r\n border: `1px solid ${borderColor}`,\r\n borderRadius: '8px',\r\n overflow: 'hidden',\r\n fontFamily: 'system-ui, sans-serif',\r\n fontSize: '14px',\r\n lineHeight: '1.4'\r\n }}\r\n >\r\n <div\r\n style={{\r\n display: 'flex',\r\n borderBottom: `1px solid ${borderColor}`\r\n }}\r\n >\r\n {headers.map((header, index) => (\r\n <div\r\n key={index}\r\n style={{\r\n flex: 1,\r\n padding: '8px 12px',\r\n backgroundColor: headerBg,\r\n fontWeight: '600',\r\n textAlign: 'center',\r\n borderRight: index < headers.length - 1 ? `1px solid ${borderColor}` : 'none',\r\n color: '#1e293b'\r\n }}\r\n >\r\n {header}\r\n </div>\r\n ))}\r\n </div>\r\n <div\r\n style={{\r\n display: 'flex'\r\n }}\r\n >\r\n {values.map((value, index) => (\r\n <div\r\n key={index}\r\n style={{\r\n flex: 1,\r\n padding: '12px',\r\n backgroundColor: valueBg,\r\n textAlign: 'center',\r\n borderRight: index < values.length - 1 ? `1px solid ${borderColor}` : 'none',\r\n color: '#0f172a',\r\n fontSize: '16px',\r\n fontWeight: '500'\r\n }}\r\n >\r\n {value}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default PlaceValueChart;","import React from 'react';\r\nimport { TextContent } from '../content/TextContent';\r\nimport { FormulaContent } from '../content/FormulaContent';\r\nimport { GraphContent } from '../content/GraphContent';\r\nimport { GeometryTransformContent } from '../content/GeometryTransformContent';\r\nimport HundredChart from '../../../HundredChart/HundredChart';\r\nimport PlaceValueChart from '../content/PlaceValueChart';\r\nimport type { ContentRendererProps, ContentBlock, HundredGridContentBlock, PlaceValueChartContentBlock, GeometryTransformContentBlock } from '../../MathCardV2.types';\r\n\r\nexport const ContentRenderer: React.FC<ContentRendererProps> = ({\r\n content,\r\n onInteraction\r\n}) => {\r\n const renderContentBlock = (block: ContentBlock, index: number) => {\r\n // 统一检查 enabled 字段(默认为 true)\r\n if (block.enabled === false) {\r\n return null; // 不渲染此内容块\r\n }\r\n\r\n const contentId = `${block.type}-${index}`;\r\n\r\n const handleInteraction = (interaction: any) => {\r\n onInteraction?.(contentId, interaction);\r\n };\r\n\r\n switch (block.type) {\r\n case 'text':\r\n return (\r\n <TextContent\r\n key={contentId}\r\n content={block.content}\r\n style={block.style}\r\n onInteraction={handleInteraction}\r\n />\r\n );\r\n case 'formula':\r\n // Type guard for formula content\r\n const formulaBlock = block as any;\r\n return (\r\n <FormulaContent\r\n key={contentId}\r\n parts={formulaBlock.parts || []}\r\n displayMode={formulaBlock.displayMode}\r\n style={block.style}\r\n />\r\n );\r\n case 'graph':\r\n // Type guard for graph content\r\n const graphBlock = block as any;\r\n return (\r\n <GraphContent\r\n key={contentId}\r\n shapes={graphBlock.shapes || []}\r\n width={graphBlock.width}\r\n height={graphBlock.height}\r\n showGrid={graphBlock.showGrid}\r\n showAxis={graphBlock.showAxis}\r\n boundingBox={graphBlock.boardConfig?.boundingBox}\r\n autoBoundingBox={!graphBlock.boardConfig?.boundingBox}\r\n // 传递动画相关属性\r\n animation={graphBlock.animation}\r\n animationProgress={graphBlock.animationProgress}\r\n showAnimationControls={graphBlock.showAnimationControls}\r\n onAnimationChange={graphBlock.onAnimationChange}\r\n />\r\n );\r\n case 'hundredGrid':\r\n // Type guard for hundred grid content\r\n const hundredGridBlock = block as HundredGridContentBlock;\r\n return (\r\n <HundredChart\r\n key={contentId}\r\n {...hundredGridBlock.props}\r\n />\r\n );\r\n case 'placeValueChart':\r\n // Type guard for place value chart content\r\n const placeValueChartBlock = block as PlaceValueChartContentBlock;\r\n return (\r\n <PlaceValueChart\r\n key={contentId}\r\n {...placeValueChartBlock.props}\r\n />\r\n );\r\n case 'geometryTransform':\r\n // Type guard for geometry transform content\r\n const geometryTransformBlock = block as GeometryTransformContentBlock;\r\n console.log('🔍 ContentRenderer: geometryTransformBlock =', {\r\n metadata: geometryTransformBlock.metadata,\r\n config: geometryTransformBlock.metadata?.config,\r\n hasConfig: !!geometryTransformBlock.metadata?.config,\r\n configKeys: geometryTransformBlock.metadata?.config ? Object.keys(geometryTransformBlock.metadata.config) : [],\r\n configShapes: geometryTransformBlock.metadata?.config?.shapes,\r\n configShapesAnimatedLength: geometryTransformBlock.metadata?.config?.shapes?.animated?.length,\r\n configShapesStaticLength: geometryTransformBlock.metadata?.config?.shapes?.static?.length,\r\n configBase: geometryTransformBlock.metadata?.config?.base,\r\n configHeight: geometryTransformBlock.metadata?.config?.height,\r\n configUnit: geometryTransformBlock.metadata?.config?.unit,\r\n configTransform: geometryTransformBlock.metadata?.config?.transform\r\n });\r\n return (\r\n <GeometryTransformContent\r\n key={contentId}\r\n config={geometryTransformBlock.metadata.config}\r\n onTransformChange={(progress) => handleInteraction({ type: 'transformChange', progress })}\r\n onTransformComplete={() => handleInteraction({ type: 'transformComplete' })}\r\n onError={(error) => handleInteraction({ type: 'error', error })}\r\n />\r\n );\r\n default:\r\n return (\r\n <div key={contentId} onClick={() => handleInteraction({ type: 'click' })}>\r\n {block.content}\r\n </div>\r\n );\r\n }\r\n };\r\n\r\n return <>{content.map(renderContentBlock)}</>;\r\n};","import React from 'react';\r\nimport { MathCardV2Context } from './context';\r\nimport { useDataAdapter } from './hooks/useDataAdapter';\r\nimport { CardLayout } from './components/layouts/CardLayout';\r\nimport { GridLayout } from './components/layouts/GridLayout';\r\nimport { FlowLayout } from './components/layouts/FlowLayout';\r\nimport { TextContent } from './components/content/TextContent';\r\nimport { FormulaContent } from './components/content/FormulaContent';\r\nimport { GraphContent } from './components/content/GraphContent';\r\nimport { GeometryTransformContent } from './components/content/GeometryTransformContent';\r\nimport { ContentRenderer } from './components/renderers/ContentRenderer';\r\nimport type { MathCardV2Props } from './MathCardV2.types';\r\n\r\n// 主容器组件\r\nexport const MathCardV2: React.FC<MathCardV2Props> & {\r\n // 布局组件\r\n CardLayout: React.FC<any>;\r\n GridLayout: React.FC<any>;\r\n FlowLayout: React.FC<any>;\r\n\r\n // 内容组件\r\n TextContent: React.FC<any>;\r\n FormulaContent: React.FC<any>;\r\n GraphContent: React.FC<any>;\r\n GeometryTransformContent: React.FC<any>;\r\n\r\n // 渲染器组件\r\n ContentRenderer: React.FC<any>;\r\n} = ({\r\n data,\r\n scene = 'question',\r\n layout = { type: 'card' },\r\n renderer = { mode: 'default' },\r\n theme = 'light',\r\n onContentInteraction,\r\n className = '',\r\n children\r\n}) => {\r\n // 数据适配\r\n const adaptedData = useDataAdapter(data, scene);\r\n\r\n // 上下文值\r\n const contextValue = {\r\n data: adaptedData,\r\n scene,\r\n layout: adaptedData.layout || layout,\r\n renderer: adaptedData.renderer || renderer,\r\n theme,\r\n onContentInteraction\r\n };\r\n\r\n // 根据布局类型选择布局组件和对应的props\r\n const currentLayout = adaptedData.layout || layout;\r\n const LayoutComponent = (() => {\r\n switch (currentLayout.type) {\r\n case 'grid':\r\n return GridLayout;\r\n case 'flow':\r\n return FlowLayout;\r\n case 'card':\r\n default:\r\n return CardLayout;\r\n }\r\n })();\r\n\r\n // 根据布局类型构建对应的props\r\n const layoutProps = (() => {\r\n const baseProps = {\r\n className,\r\n theme,\r\n 'data-testid': 'mathcard-v2-container'\r\n };\r\n\r\n switch (currentLayout.type) {\r\n case 'grid':\r\n return {\r\n ...baseProps,\r\n columns: currentLayout.columns || 2,\r\n gap: currentLayout.gap || '16px',\r\n responsive: currentLayout.responsive !== false\r\n } as any;\r\n case 'flow':\r\n return {\r\n ...baseProps,\r\n direction: currentLayout.direction || 'vertical',\r\n gap: currentLayout.gap || '16px',\r\n wrap: currentLayout.wrap !== false\r\n } as any;\r\n case 'card':\r\n default:\r\n return {\r\n ...baseProps,\r\n padding: currentLayout.padding || '24px',\r\n shadow: currentLayout.shadow !== false,\r\n border: currentLayout.border !== false\r\n } as any;\r\n }\r\n })();\r\n\r\n return (\r\n <MathCardV2Context.Provider value={contextValue}>\r\n <LayoutComponent {...layoutProps}>\r\n {children || (\r\n <ContentRenderer\r\n content={adaptedData.content}\r\n layout={adaptedData.layout || layout}\r\n onInteraction={onContentInteraction}\r\n />\r\n )}\r\n </LayoutComponent>\r\n </MathCardV2Context.Provider>\r\n );\r\n};\r\n\r\n// 挂载子组件\r\nMathCardV2.CardLayout = CardLayout;\r\nMathCardV2.GridLayout = GridLayout;\r\nMathCardV2.FlowLayout = FlowLayout;\r\nMathCardV2.TextContent = TextContent;\r\nMathCardV2.FormulaContent = FormulaContent;\r\nMathCardV2.GraphContent = GraphContent;\r\nMathCardV2.GeometryTransformContent = GeometryTransformContent;\r\nMathCardV2.ContentRenderer = ContentRenderer;","import { useMemo } from 'react';\r\nimport type {\r\n IXLCardConfig,\r\n IXLStyleHookReturn,\r\n IXLColorMap,\r\n IXL_LABELS\r\n} from '../IXLStyleCard.types';\r\n\r\n/**\r\n * IXL样式Hook配置\r\n */\r\nexport interface UseIXLStyleConfig {\r\n /**\r\n * IXL卡片配置\r\n */\r\n ixlConfig: IXLCardConfig;\r\n\r\n /**\r\n * 是否启用IXL样式\r\n */\r\n enableIXLStyle: boolean;\r\n\r\n /**\r\n * 是否移动端\r\n */\r\n isMobile: boolean;\r\n}\r\n\r\n/**\r\n * 获取IXL样式信息的自定义Hook\r\n *\r\n * @param config - IXL样式配置\r\n * @returns IXL样式信息对象\r\n */\r\nexport const useIXLStyle = (config: UseIXLStyleConfig): IXLStyleHookReturn => {\r\n const { ixlConfig, enableIXLStyle, isMobile } = config;\r\n\r\n // 获取标签文本\r\n const tagText = useMemo(() => {\r\n if (ixlConfig.label) {\r\n return ixlConfig.label;\r\n }\r\n\r\n // 使用默认标签映射\r\n const defaultLabels: Record<keyof typeof IXL_LABELS, string> = {\r\n remember: '速记',\r\n review: '回顾',\r\n solve: '解答'\r\n };\r\n\r\n return defaultLabels[ixlConfig.type] || ixlConfig.type;\r\n }, [ixlConfig.label, ixlConfig.type]);\r\n\r\n // 获取标签颜色\r\n const tagColor = useMemo(() => {\r\n if (ixlConfig.tagColor) {\r\n return ixlConfig.tagColor;\r\n }\r\n\r\n // 使用默认颜色映射\r\n const defaultColors: IXLColorMap = {\r\n remember: 'var(--ixl-color-remember, #5bc0de)',\r\n review: 'var(--ixl-color-review, #a5c63b)',\r\n solve: 'var(--ixl-color-solve, #f0ad4e)'\r\n };\r\n\r\n return defaultColors[ixlConfig.type] || defaultColors.remember;\r\n }, [ixlConfig.tagColor, ixlConfig.type]);\r\n\r\n // 获取标签文本颜色\r\n const tagTextColor = useMemo(() => {\r\n if (ixlConfig.tagTextColor) {\r\n return ixlConfig.tagTextColor;\r\n }\r\n\r\n return 'var(--ixl-tag-text-color, #ffffff)';\r\n }, [ixlConfig.tagTextColor]);\r\n\r\n // 构建标签样式\r\n const tagStyle = useMemo(() => {\r\n if (!enableIXLStyle) {\r\n return {};\r\n }\r\n\r\n const baseStyle: React.CSSProperties = {\r\n backgroundColor: tagColor,\r\n color: tagTextColor,\r\n fontSize: 'var(--ixl-tag-font-size, 14px)',\r\n fontWeight: 'var(--ixl-tag-font-weight, 600)'\r\n };\r\n\r\n if (isMobile) {\r\n // 移动端样式\r\n Object.assign(baseStyle, {\r\n height: 'var(--ixl-mobile-tag-height, 32px)',\r\n borderRadius: 'var(--ixl-mobile-tag-border-radius, 8px 8px 0 0)',\r\n width: '100%',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n position: 'relative',\r\n zIndex: 1\r\n });\r\n } else {\r\n // 桌面端样式\r\n Object.assign(baseStyle, {\r\n width: 'var(--ixl-tag-width, 40px)',\r\n borderRadius: 'var(--ixl-tag-border-radius, 8px 0 0 8px)',\r\n height: '100%',\r\n position: 'absolute',\r\n left: 0,\r\n top: 0,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n writingMode: 'vertical-rl',\r\n textOrientation: 'mixed',\r\n transform: 'rotate(0deg)'\r\n });\r\n }\r\n\r\n return baseStyle;\r\n }, [enableIXLStyle, tagColor, tagTextColor, isMobile]);\r\n\r\n // 构建内容样式\r\n const contentStyle = useMemo(() => {\r\n if (!enableIXLStyle || isMobile) {\r\n return {};\r\n }\r\n\r\n // 桌面端需要为左侧标签留出空间\r\n return {\r\n paddingLeft: 'calc(var(--ixl-tag-width, 40px) + var(--ixl-card-gap, 16px))'\r\n };\r\n }, [enableIXLStyle, isMobile]);\r\n\r\n // 构建IXL类名\r\n const ixlClassName = useMemo(() => {\r\n if (!enableIXLStyle) {\r\n return '';\r\n }\r\n\r\n const classes = ['ixl-styled'];\r\n\r\n // 添加类型类名\r\n classes.push(`ixl-type-${ixlConfig.type}`);\r\n\r\n // 添加响应式类名\r\n if (isMobile) {\r\n classes.push('ixl-mobile-layout');\r\n } else {\r\n classes.push('ixl-desktop-layout');\r\n }\r\n\r\n return classes.join(' ');\r\n }, [enableIXLStyle, ixlConfig.type, isMobile]);\r\n\r\n return {\r\n ixlClassName,\r\n tagStyle,\r\n contentStyle,\r\n tagText,\r\n tagColor,\r\n tagTextColor\r\n };\r\n};","import { useState, useEffect, useCallback, useRef } from 'react';\r\nimport type { ResponsiveHookReturn } from '../IXLStyleCard.types';\r\n\r\n/**\r\n * 响应式Hook配置\r\n */\r\nexport interface UseResponsiveConfig {\r\n /**\r\n * 移动端断点(像素)\r\n * @default 768\r\n */\r\n breakpoint?: number;\r\n\r\n /**\r\n * 是否启用响应式监听\r\n * @default true\r\n */\r\n enabled?: boolean;\r\n}\r\n\r\n/**\r\n * 防抖函数\r\n */\r\nconst debounce = <T extends (...args: any[]) => any>(\r\n func: T,\r\n wait: number\r\n): ((...args: Parameters<T>) => void) => {\r\n let timeout: NodeJS.Timeout | null = null;\r\n\r\n return (...args: Parameters<T>) => {\r\n if (timeout) {\r\n clearTimeout(timeout);\r\n }\r\n\r\n timeout = setTimeout(() => {\r\n func(...args);\r\n }, wait);\r\n };\r\n};\r\n\r\n/**\r\n * 响应式布局自定义Hook\r\n *\r\n * 监听窗口大小变化,提供移动端/桌面端状态判断。\r\n * 使用防抖优化性能,避免频繁触发重渲染。\r\n *\r\n * @param config - 响应式配置\r\n * @returns 响应式信息对象\r\n */\r\nexport const useResponsive = (\r\n config: UseResponsiveConfig | number = {}\r\n): ResponsiveHookReturn => {\r\n // 解析配置\r\n const breakpoint = typeof config === 'number' ? config : config.breakpoint || 768;\r\n const enabled = typeof config === 'number' ? true : config.enabled !== false;\r\n\r\n // 状态\r\n const [viewportWidth, setViewportWidth] = useState<number>(() => {\r\n if (typeof window !== 'undefined') {\r\n return window.innerWidth;\r\n }\r\n return 1024; // 默认桌面端宽度\r\n });\r\n\r\n const [isMobile, setIsMobile] = useState<boolean>(() => {\r\n if (typeof window !== 'undefined') {\r\n return window.innerWidth < breakpoint;\r\n }\r\n return false;\r\n });\r\n\r\n // 监听器引用\r\n const listenersRef = useRef<Set<() => void>>(new Set());\r\n\r\n // 更新视口宽度和移动端状态\r\n const updateViewport = useCallback(() => {\r\n if (typeof window === 'undefined') {\r\n return;\r\n }\r\n\r\n const newWidth = window.innerWidth;\r\n const newIsMobile = newWidth < breakpoint;\r\n\r\n setViewportWidth(newWidth);\r\n setIsMobile(newIsMobile);\r\n\r\n // 通知所有监听器\r\n listenersRef.current.forEach(listener => {\r\n try {\r\n listener();\r\n } catch (error) {\r\n console.error('Error in resize listener:', error);\r\n }\r\n });\r\n }, [breakpoint]);\r\n\r\n // 防抖的更新函数\r\n const debouncedUpdateViewport = useCallback(\r\n debounce(updateViewport, 150),\r\n [updateViewport]\r\n );\r\n\r\n // 添加resize监听器\r\n useEffect(() => {\r\n if (!enabled || typeof window === 'undefined') {\r\n return;\r\n }\r\n\r\n // 初始更新\r\n updateViewport();\r\n\r\n // 添加resize监听器\r\n window.addEventListener('resize', debouncedUpdateViewport);\r\n\r\n // 清理函数\r\n return () => {\r\n window.removeEventListener('resize', debouncedUpdateViewport);\r\n };\r\n }, [enabled, debouncedUpdateViewport, updateViewport]);\r\n\r\n // 添加监听器\r\n const addResizeListener = useCallback((listener: () => void) => {\r\n listenersRef.current.add(listener);\r\n\r\n // 返回清理函数\r\n return () => {\r\n listenersRef.current.delete(listener);\r\n };\r\n }, []);\r\n\r\n // 移除监听器\r\n const removeResizeListener = useCallback((listener: () => void) => {\r\n listenersRef.current.delete(listener);\r\n }, []);\r\n\r\n return {\r\n isMobile,\r\n viewportWidth,\r\n addResizeListener,\r\n removeResizeListener\r\n };\r\n};","import React, { useMemo, useEffect } from 'react';\r\nimport { MathCardV2 } from '../MathCardV2/MathCardV2';\r\nimport { useIXLStyle } from './hooks/useIXLStyle';\r\nimport { useResponsive } from './hooks/useResponsive';\r\nimport type { IXLStyleCardProps } from './IXLStyleCard.types';\r\nimport './IXLStyleCard.css';\r\n\r\n/**\r\n * IXL风格卡片包装器组件\r\n *\r\n * 这是一个非侵入式包装器,用于为MathCardV2组件或任意组件添加IXL风格的视觉样式。\r\n * 支持三种IXL卡片类型:remember(速记)、review(回顾)、solve(解答)。\r\n * 提供响应式布局,桌面端为左侧垂直标签,移动端为顶部水平标签。\r\n * 支持两种包装模式:mathcard(包装MathCardV2)和generic(包装任意子组件)。\r\n *\r\n * @example\r\n * ```tsx\r\n * // 包装MathCardV2(默认模式)\r\n * <IXLStyleCard\r\n * cardProps={mathCardProps}\r\n * ixlConfig={{ type: 'remember', label: '速记' }}\r\n * enableIXLStyle={true}\r\n * />\r\n *\r\n * // 包装任意组件\r\n * <IXLStyleCard\r\n * ixlConfig={{ type: 'review', label: '回顾' }}\r\n * wrapperMode=\"generic\"\r\n * >\r\n * <div>自定义内容</div>\r\n * </IXLStyleCard>\r\n * ```\r\n */\r\nexport const IXLStyleCard: React.FC<IXLStyleCardProps> = ({\r\n cardProps,\r\n ixlConfig,\r\n enableIXLStyle = true,\r\n wrapperMode = 'mathcard',\r\n mobileBreakpoint = 768,\r\n className = '',\r\n style,\r\n children,\r\n onResponsiveChange\r\n}) => {\r\n // 使用响应式Hook\r\n const responsive = useResponsive(mobileBreakpoint);\r\n\r\n // 使用IXL样式Hook\r\n const ixlStyle = useIXLStyle({\r\n ixlConfig,\r\n enableIXLStyle,\r\n isMobile: responsive.isMobile\r\n });\r\n\r\n // 触发响应式变化回调\r\n useEffect(() => {\r\n onResponsiveChange?.(responsive.isMobile);\r\n }, [responsive.isMobile, onResponsiveChange]);\r\n\r\n // 构建容器类名\r\n const containerClassName = useMemo(() => {\r\n const classes = ['ixl-style-card-container'];\r\n\r\n if (enableIXLStyle) {\r\n classes.push(ixlStyle.ixlClassName);\r\n }\r\n\r\n if (className) {\r\n classes.push(className);\r\n }\r\n\r\n if (responsive.isMobile) {\r\n classes.push('ixl-mobile');\r\n } else {\r\n classes.push('ixl-desktop');\r\n }\r\n\r\n return classes.join(' ');\r\n }, [enableIXLStyle, ixlStyle.ixlClassName, className, responsive.isMobile]);\r\n\r\n // 构建容器样式\r\n const containerStyle = useMemo(() => {\r\n const baseStyle = { ...style };\r\n\r\n if (enableIXLStyle && !responsive.isMobile) {\r\n // 桌面端添加左侧padding为标签留出空间\r\n return {\r\n ...baseStyle,\r\n paddingLeft: ixlStyle.contentStyle.paddingLeft\r\n };\r\n }\r\n\r\n return baseStyle;\r\n }, [enableIXLStyle, responsive.isMobile, ixlStyle.contentStyle, style]);\r\n\r\n // 构建MathCardV2的类名(仅当包装MathCardV2时)\r\n const mathCardClassName = useMemo(() => {\r\n if (wrapperMode !== 'mathcard' || !cardProps) {\r\n return '';\r\n }\r\n\r\n const classes = [cardProps.className || ''];\r\n\r\n if (enableIXLStyle) {\r\n // 移除MathCardV2中的border-l-8 pl-6类名\r\n classes.push('ixl-adjusted');\r\n }\r\n\r\n return classes.filter(Boolean).join(' ');\r\n }, [wrapperMode, cardProps?.className, enableIXLStyle]);\r\n\r\n return (\r\n <div\r\n className={containerClassName}\r\n style={containerStyle}\r\n data-testid=\"ixl-style-card-container\"\r\n data-ixl-type={ixlConfig.type}\r\n data-ixl-enabled={enableIXLStyle}\r\n data-responsive-mode={responsive.isMobile ? 'mobile' : 'desktop'}\r\n >\r\n {/* IXL标签 */}\r\n {enableIXLStyle && ixlConfig.showTag !== false && (\r\n <div\r\n className=\"ixl-tag\"\r\n style={ixlStyle.tagStyle}\r\n data-testid=\"ixl-tag\"\r\n >\r\n <span className=\"ixl-tag-text\">\r\n {ixlStyle.tagText}\r\n </span>\r\n </div>\r\n )}\r\n\r\n {/* 内容渲染 */}\r\n {wrapperMode === 'mathcard' && cardProps ? (\r\n <MathCardV2\r\n {...cardProps}\r\n className={mathCardClassName}\r\n />\r\n ) : (\r\n /* 通用包装模式,渲染子内容 */\r\n children\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// 为组件添加displayName\r\nIXLStyleCard.displayName = 'IXLStyleCard';\r\n\r\n// 导出类型\r\nexport type { IXLStyleCardProps } from './IXLStyleCard.types';","// ========== IXLStyleCard 类型定义 ==========\r\n\r\nimport type { ReactNode } from 'react';\r\nimport type { MathCardV2Props } from '../MathCardV2/MathCardV2.types';\r\n\r\n/**\r\n * IXL卡片类型\r\n */\r\nexport type IXLCardType = 'remember' | 'review' | 'solve';\r\n\r\n/**\r\n * IXL卡片配置接口\r\n */\r\nexport interface IXLCardConfig {\r\n /**\r\n * 卡片类型\r\n */\r\n type: IXLCardType;\r\n\r\n /**\r\n * 标签文本\r\n */\r\n label?: string;\r\n\r\n /**\r\n * 自定义标签颜色\r\n */\r\n tagColor?: string;\r\n\r\n /**\r\n * 自定义标签文本颜色\r\n */\r\n tagTextColor?: string;\r\n\r\n /**\r\n * 是否显示标签\r\n */\r\n showTag?: boolean;\r\n}\r\n\r\n/**\r\n * IXLStyleCard 包装模式\r\n */\r\nexport type IXLWrapperMode = 'mathcard' | 'generic';\r\n\r\n/**\r\n * IXLStyleCard 核心 Props 接口\r\n */\r\nexport interface IXLStyleCardProps {\r\n /**\r\n * MathCardV2 组件的 props\r\n * 当 wrapperMode=\"mathcard\" 时必需\r\n */\r\n cardProps?: MathCardV2Props;\r\n\r\n /**\r\n * IXL 卡片配置\r\n */\r\n ixlConfig: IXLCardConfig;\r\n\r\n /**\r\n * 是否启用 IXL 样式\r\n * @default true\r\n */\r\n enableIXLStyle?: boolean;\r\n\r\n /**\r\n * 包装模式\r\n * - 'mathcard': 包装MathCardV2组件(默认)\r\n * - 'generic': 包装任意子组件\r\n * @default 'mathcard'\r\n */\r\n wrapperMode?: IXLWrapperMode;\r\n\r\n /**\r\n * 移动端断点(像素)\r\n * @default 768\r\n */\r\n mobileBreakpoint?: number;\r\n\r\n /**\r\n * 自定义类名\r\n */\r\n className?: string;\r\n\r\n /**\r\n * 自定义样式\r\n */\r\n style?: React.CSSProperties;\r\n\r\n /**\r\n * 子组件(用于自定义渲染)\r\n * 当 wrapperMode=\"generic\" 时必需\r\n */\r\n children?: ReactNode;\r\n\r\n /**\r\n * 响应式变化回调\r\n */\r\n onResponsiveChange?: (isMobile: boolean) => void;\r\n}\r\n\r\n/**\r\n * IXL 标签颜色映射\r\n */\r\nexport interface IXLColorMap {\r\n remember: string;\r\n review: string;\r\n solve: string;\r\n}\r\n\r\n/**\r\n * 响应式配置接口\r\n */\r\nexport interface ResponsiveConfig {\r\n /**\r\n * 是否移动端\r\n */\r\n isMobile: boolean;\r\n\r\n /**\r\n * 当前视口宽度\r\n */\r\n viewportWidth: number;\r\n\r\n /**\r\n * 移动端断点\r\n */\r\n breakpoint: number;\r\n}\r\n\r\n/**\r\n * IXL 样式 Hook 返回值\r\n */\r\nexport interface IXLStyleHookReturn {\r\n /**\r\n * IXL 样式类名\r\n */\r\n ixlClassName: string;\r\n\r\n /**\r\n * 标签样式\r\n */\r\n tagStyle: React.CSSProperties;\r\n\r\n /**\r\n * 内容样式\r\n */\r\n contentStyle: React.CSSProperties;\r\n\r\n /**\r\n * 标签文本\r\n */\r\n tagText: string;\r\n\r\n /**\r\n * 标签颜色\r\n */\r\n tagColor: string;\r\n\r\n /**\r\n * 标签文本颜色\r\n */\r\n tagTextColor: string;\r\n}\r\n\r\n/**\r\n * 响应式 Hook 返回值\r\n */\r\nexport interface ResponsiveHookReturn {\r\n /**\r\n * 是否移动端\r\n */\r\n isMobile: boolean;\r\n\r\n /**\r\n * 当前视口宽度\r\n */\r\n viewportWidth: number;\r\n\r\n /**\r\n * 添加 resize 监听器\r\n */\r\n addResizeListener: (listener: () => void) => () => void;\r\n\r\n /**\r\n * 移除 resize 监听器\r\n */\r\n removeResizeListener: (listener: () => void) => void;\r\n}\r\n\r\n/**\r\n * IXL 卡片默认配置\r\n */\r\nexport const DEFAULT_IXL_CONFIG: Record<IXLCardType, IXLCardConfig> = {\r\n remember: {\r\n type: 'remember',\r\n label: '速记',\r\n showTag: true\r\n },\r\n review: {\r\n type: 'review',\r\n label: '回顾',\r\n showTag: true\r\n },\r\n solve: {\r\n type: 'solve',\r\n label: '解答',\r\n showTag: true\r\n }\r\n};\r\n\r\n/**\r\n * IXL 颜色映射\r\n */\r\nexport const IXL_COLORS: IXLColorMap = {\r\n remember: 'var(--ixl-color-remember, #5bc0de)',\r\n review: 'var(--ixl-color-review, #a5c63b)',\r\n solve: 'var(--ixl-color-solve, #f0ad4e)'\r\n};\r\n\r\n/**\r\n * IXL 标签文本映射\r\n */\r\nexport const IXL_LABELS: Record<IXLCardType, string> = {\r\n remember: '速记',\r\n review: '回顾',\r\n solve: '解答'\r\n};","import React from 'react';\r\nimport './components.css';\r\n\r\nexport interface GradeNavigationProps {\r\n grades: Array<{\r\n id: string;\r\n name: string;\r\n level: string;\r\n description: string;\r\n color: string;\r\n }>;\r\n onGradeSelect?: (gradeId: string) => void;\r\n selectedGrade?: string;\r\n}\r\n\r\nexport const GradeNavigation: React.FC<GradeNavigationProps> = ({\r\n grades,\r\n onGradeSelect,\r\n selectedGrade,\r\n}) => {\r\n return (\r\n <div className=\"grade-navigation\">\r\n <h2 className=\"grade-navigation__title\">选择年级</h2>\r\n <div className=\"grade-navigation__grid\">\r\n {grades.map((grade) => (\r\n <div\r\n key={grade.id}\r\n className={`grade-card ${selectedGrade === grade.id ? 'grade-card--selected' : ''}`}\r\n style={{ borderLeftColor: grade.color }}\r\n onClick={() => onGradeSelect?.(grade.id)}\r\n >\r\n <div className=\"grade-card__level\">{grade.level}</div>\r\n <div className=\"grade-card__name\">{grade.name}</div>\r\n <div className=\"grade-card__description\">{grade.description}</div>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport type { RadarChartProps } from '../../../types/radarAbility';\r\n\r\nconst RadarChart: React.FC<RadarChartProps> = ({ \r\n abilities, \r\n width = 400, \r\n height = 400 \r\n}) => {\r\n // 计算雷达图的数据点\r\n const calculateRadarPoints = () => {\r\n if (abilities.length === 0) return '';\r\n \r\n return abilities\r\n .map(ability => {\r\n // 使用预定义的SVG坐标点,如果没有则动态计算\r\n if (ability.svgPoint) {\r\n return `${ability.svgPoint.x},${ability.svgPoint.y}`;\r\n }\r\n \r\n // 动态计算坐标(基于能力和分数)\r\n const angle = (Math.PI * 2 * abilities.indexOf(ability)) / abilities.length;\r\n const radius = (ability.score / ability.maxScore) * 40 + 10; // 10-50范围\r\n const x = 50 + radius * Math.sin(angle);\r\n const y = 50 - radius * Math.cos(angle);\r\n \r\n return `${x},${y}`;\r\n })\r\n .join(' ');\r\n };\r\n\r\n // 计算轴线端点\r\n const calculateAxisEndPoints = (index: number) => {\r\n const angle = (Math.PI * 2 * index) / Math.max(abilities.length, 1);\r\n const x2 = 50 + 40 * Math.sin(angle);\r\n const y2 = 50 - 40 * Math.cos(angle);\r\n return { x2, y2 };\r\n };\r\n\r\n // 计算标签位置\r\n const calculateLabelPosition = (index: number) => {\r\n const angle = (Math.PI * 2 * index) / Math.max(abilities.length, 1);\r\n const x = 50 + 45 * Math.sin(angle);\r\n const y = 50 - 45 * Math.cos(angle);\r\n \r\n // 根据角度调整文本锚点\r\n let textAnchor = 'middle';\r\n if (angle > Math.PI * 0.25 && angle < Math.PI * 0.75) textAnchor = 'start';\r\n if (angle > Math.PI * 1.25 && angle < Math.PI * 1.75) textAnchor = 'end';\r\n \r\n return { x, y, textAnchor };\r\n };\r\n\r\n return (\r\n <svg \r\n data-testid=\"radar-chart\"\r\n width={width} \r\n height={height} \r\n viewBox=\"0 0 100 100\" \r\n className=\"w-full h-full\"\r\n preserveAspectRatio=\"xMidYMid meet\"\r\n >\r\n {/* 中心点 */}\r\n <circle \r\n data-testid=\"center-point\"\r\n cx=\"50\" \r\n cy=\"50\" \r\n r=\"1\" \r\n fill=\"#4A90E2\" \r\n />\r\n\r\n {/* 轴线 */}\r\n {abilities.map((_, index) => {\r\n const { x2, y2 } = calculateAxisEndPoints(index);\r\n return (\r\n <line\r\n key={`axis-${index}`}\r\n data-testid=\"axis-line\"\r\n x1=\"50\"\r\n y1=\"50\"\r\n x2={x2}\r\n y2={y2}\r\n stroke=\"#E2E8F0\"\r\n strokeWidth=\"0.5\"\r\n />\r\n );\r\n })}\r\n\r\n {/* 雷达多边形 */}\r\n {abilities.length > 2 && (\r\n <polygon\r\n data-testid=\"radar-polygon\"\r\n points={calculateRadarPoints()}\r\n fill=\"rgba(74, 144, 226, 0.2)\"\r\n stroke=\"rgb(74, 144, 226)\"\r\n strokeWidth=\"1\"\r\n fillRule=\"evenodd\"\r\n />\r\n )}\r\n\r\n {/* 数据点 */}\r\n {abilities.map((ability, index) => {\r\n let x, y;\r\n \r\n if (ability.svgPoint) {\r\n x = ability.svgPoint.x;\r\n y = ability.svgPoint.y;\r\n } else {\r\n const angle = (Math.PI * 2 * index) / abilities.length;\r\n const radius = (ability.score / ability.maxScore) * 40 + 10;\r\n x = 50 + radius * Math.sin(angle);\r\n y = 50 - radius * Math.cos(angle);\r\n }\r\n \r\n return (\r\n <circle\r\n key={`point-${ability.name}`}\r\n data-testid=\"data-point\"\r\n cx={x}\r\n cy={y}\r\n r=\"2\"\r\n fill={ability.progressBarColor === 'bg-orange-400' ? '#FBBF24' : '#4A90E2'}\r\n />\r\n );\r\n })}\r\n\r\n {/* 能力标签 */}\r\n {abilities.map((ability, index) => {\r\n const { x, y, textAnchor } = calculateLabelPosition(index);\r\n \r\n return (\r\n <text\r\n key={`label-${ability.name}`}\r\n x={x}\r\n y={y}\r\n textAnchor={textAnchor as any}\r\n fontSize=\"5\"\r\n fill=\"#334155\"\r\n className=\"text-xs\"\r\n >\r\n {ability.name}\r\n </text>\r\n );\r\n })}\r\n </svg>\r\n );\r\n};\r\n\r\nexport default RadarChart;","import axios from 'axios';\r\nimport type { RadarAbilityData } from '../types/radarAbility';\r\n\r\n// 模拟数据 - 在实际应用中会从API获取\r\nexport const mockRadarAbilityData: RadarAbilityData = {\r\n overallRating: '优秀',\r\n generalRecommendation: '你的空间想象力和逻辑推理能力非常出色!若能进一步提升在复杂图形下的专注力,你将所向披靡。建议尝试我们‘专注力挑战’系列游戏。',\r\n abilities: [\r\n {\r\n name: '空间想象力',\r\n score: 7.5,\r\n maxScore: 10,\r\n progressBarColor: 'bg-blue-500',\r\n svgPoint: { x: 50, y: 17.5 },\r\n recommendation: '通过观察三维物体在不同角度的投影,或尝试构建复杂结构的游戏,能有效提升空间想象力。',\r\n recommendationLink: '#spatial-challenges'\r\n },\r\n {\r\n name: '逻辑推理',\r\n score: 8.0,\r\n maxScore: 10,\r\n progressBarColor: 'bg-blue-500',\r\n svgPoint: { x: 82, y: 35 },\r\n recommendation: '解决数独、迷宫或逻辑谜题,能够持续锻炼你的逻辑思维,尝试挑战更高难度的推理游戏。',\r\n recommendationLink: '#logic-puzzles'\r\n },\r\n {\r\n name: '图形辨识',\r\n score: 9.0,\r\n maxScore: 10,\r\n progressBarColor: 'bg-blue-500',\r\n svgPoint: { x: 85, y: 65 },\r\n recommendation: '你在这方面表现出色!可以尝试在更复杂、干扰因素更多的图形中进行辨识训练,保持敏锐。',\r\n recommendationLink: '#graphic-training'\r\n },\r\n {\r\n name: '专注力',\r\n score: 7.0,\r\n maxScore: 10,\r\n progressBarColor: 'bg-orange-400',\r\n svgPoint: { x: 50, y: 80 },\r\n recommendation: '在长时间的游戏中保持专注对你来说是一个挑战,建议尝试我们‘专注力挑战’系列游戏,逐渐延长专注时间。',\r\n recommendationLink: '#focus-challenges'\r\n },\r\n {\r\n name: '观察力',\r\n score: 8.5,\r\n maxScore: 10,\r\n progressBarColor: 'bg-blue-500',\r\n svgPoint: { x: 15, y: 65 },\r\n recommendation: '你的观察力非常敏锐,在细节发现上尤为突出。尝试在限时模式下进行观察力训练,提高反应速度。',\r\n recommendationLink: '#observation-drills'\r\n },\r\n {\r\n name: '抗压性',\r\n score: 7.8,\r\n maxScore: 10,\r\n progressBarColor: 'bg-blue-500',\r\n svgPoint: { x: 18, y: 35 },\r\n recommendation: '面对高压挑战时,保持冷静是关键。通过模拟竞赛或限时任务来提升抗压能力,逐步适应压力。',\r\n recommendationLink: '#stress-games'\r\n }\r\n ]\r\n};\r\n\r\nexport class RadarAbilityService {\r\n private static readonly API_BASE_URL = '/api/radar-ability';\r\n\r\n static async fetchRadarAbilityData(): Promise<RadarAbilityData> {\r\n try {\r\n // 在测试环境中使用mock数据,避免真实API调用\r\n if (process.env.NODE_ENV === 'test') {\r\n // 测试环境使用mock数据\r\n await new Promise(resolve => setTimeout(resolve, 100));\r\n return mockRadarAbilityData;\r\n } else {\r\n // 开发和生产环境调用真实API\r\n const response = await axios.get<RadarAbilityData>(`${this.API_BASE_URL}/assessment`);\r\n return response.data;\r\n }\r\n } catch (error) {\r\n console.error('Failed to fetch radar ability data:', error);\r\n // 在测试环境中抛出错误以便测试错误处理\r\n if (process.env.NODE_ENV === 'test') {\r\n throw new Error('获取能力评估数据失败');\r\n }\r\n // 开发和生产环境返回mock数据作为fallback\r\n return mockRadarAbilityData;\r\n }\r\n }\r\n\r\n static async submitFeedback(feedback: {\r\n abilityName: string;\r\n rating: number;\r\n comment: string;\r\n }): Promise<void> {\r\n try {\r\n // 模拟API调用\r\n await axios.post(`${this.API_BASE_URL}/feedback`, feedback);\r\n } catch (error) {\r\n console.error('Failed to submit feedback:', error);\r\n throw new Error('提交反馈失败');\r\n }\r\n }\r\n}","import { create } from 'zustand';\r\nimport type { RadarAbilityData } from '../types/radarAbility';\r\nimport { RadarAbilityService } from '../services/radarAbilityService';\r\n\r\ninterface RadarAbilityState {\r\n data: RadarAbilityData | null;\r\n loading: boolean;\r\n error: string | null;\r\n fetchData: () => Promise<void>;\r\n setData: (data: RadarAbilityData) => void;\r\n setError: (error: string) => void;\r\n reset: () => void;\r\n}\r\n\r\nexport const useRadarAbilityStore = create<RadarAbilityState>((set, get) => ({\r\n data: null,\r\n loading: false,\r\n error: null,\r\n\r\n fetchData: async () => {\r\n // Don't fetch if already loading\r\n if (get().loading) return;\r\n\r\n set({ loading: true, error: null });\r\n\r\n try {\r\n const radarData = await RadarAbilityService.fetchRadarAbilityData();\r\n set({ data: radarData, loading: false });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : '获取数据失败';\r\n set({ error: errorMessage, loading: false });\r\n }\r\n },\r\n\r\n setData: (data: RadarAbilityData) => {\r\n set({ data, error: null, loading: false });\r\n },\r\n\r\n setError: (error: string) => {\r\n set({ error, loading: false });\r\n },\r\n\r\n reset: () => {\r\n set({ data: null, loading: false, error: null });\r\n }\r\n}));","import React from 'react';\r\nimport type { AbilityProgressBarProps } from '../../../types/radarAbility';\r\n\r\nconst AbilityProgressBar: React.FC<AbilityProgressBarProps> = ({ ability }) => {\r\n const percentage = (ability.score / ability.maxScore) * 100;\r\n \r\n return (\r\n <div \r\n className=\"ability-progress-bar-item\" \r\n data-ability={ability.name}\r\n data-testid=\"progress-bar-container\"\r\n >\r\n <div className=\"flex justify-between text-sm mb-1\">\r\n <span className=\"text-gray-700 font-medium\">{ability.name}</span>\r\n <span className=\"text-gray-600\">\r\n {ability.score}/{ability.maxScore}\r\n </span>\r\n </div>\r\n \r\n <div \r\n className=\"w-full bg-gray-200 rounded-full h-2.5\"\r\n data-testid=\"progress-bar-outer\"\r\n >\r\n <div \r\n className={`${ability.progressBarColor} h-2.5 rounded-full transition-all duration-300`}\r\n style={{ width: `${percentage}%` }}\r\n data-testid=\"progress-bar-inner\"\r\n role=\"progressbar\"\r\n aria-valuenow={ability.score}\r\n aria-valuemin={0}\r\n aria-valuemax={ability.maxScore}\r\n aria-label={`${ability.name} progress: ${ability.score} out of ${ability.maxScore}`}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default AbilityProgressBar;","import React from 'react';\r\nimport type { PersonalizedAdvicePanelProps } from '../../../types/radarAbility';\r\n\r\nconst PersonalizedAdvicePanel: React.FC<PersonalizedAdvicePanelProps> = ({ \r\n generalRecommendation \r\n}) => {\r\n return (\r\n <div \r\n className=\"bg-blue-50 border border-blue-200 rounded-lg p-4\"\r\n data-testid=\"advice-panel\"\r\n role=\"region\"\r\n aria-label=\"个性化建议\"\r\n >\r\n <div className=\"flex items-start\">\r\n <div className=\"flex-shrink-0\">\r\n <i \r\n className=\"material-icons text-blue-500\"\r\n data-testid=\"lightbulb-icon\"\r\n aria-hidden=\"true\"\r\n >\r\n lightbulb\r\n </i>\r\n </div>\r\n \r\n <div className=\"ml-3\">\r\n <h3 \r\n className=\"text-md font-semibold text-blue-800\"\r\n aria-level={3}\r\n >\r\n 个性化建议\r\n </h3>\r\n \r\n <p \r\n className=\"text-sm text-blue-700 mt-1\"\r\n data-testid=\"recommendation-text\"\r\n >\r\n {generalRecommendation}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default PersonalizedAdvicePanel;","import React from 'react';\r\nimport { Card, CardBody, Button } from '@heroui/react';\r\nimport { ArrowRight } from 'lucide-react';\r\nimport type { RecommendationCardProps } from '../../../types/radarAbility';\r\n\r\nconst RecommendationCard: React.FC<RecommendationCardProps> = ({ ability, customLinkTexts = {} }) => {\r\n // 根据能力名称生成对应的链接文本,支持自定义映射\r\n const getLinkText = (abilityName: string) => {\r\n const defaultLinkTexts: Record<string, string> = {\r\n '空间想象力': '探索空间挑战',\r\n '逻辑推理': '深入逻辑谜题',\r\n '图形辨识': '精进图形训练',\r\n '专注力': '挑战专注极限',\r\n '观察力': '提升观察速度',\r\n '抗压性': '磨砺抗压意志'\r\n };\r\n \r\n // 优先使用自定义链接文本,如果没有则使用默认值\r\n return customLinkTexts[abilityName] || defaultLinkTexts[abilityName] || '开始挑战';\r\n };\r\n\r\n return (\r\n <Card \r\n className=\"recommendation-card w-full max-w-sm hover:shadow-lg transition-all duration-300\"\r\n data-ability={ability.name}\r\n data-testid=\"recommendation-card\"\r\n isHoverable\r\n isPressable\r\n >\r\n <CardBody className=\"p-5\">\r\n <div className=\"flex flex-col gap-3\">\r\n <h4 \r\n className=\"text-lg font-semibold text-foreground\"\r\n aria-level={4}\r\n >\r\n {ability.name}: 专项提高\r\n </h4>\r\n \r\n <p \r\n className=\"text-sm text-default-600 leading-relaxed\"\r\n data-testid=\"recommendation-description\"\r\n >\r\n {ability.recommendation}\r\n </p>\r\n \r\n <Button\r\n as=\"a\"\r\n href={ability.recommendationLink}\r\n className=\"mt-2 w-fit\"\r\n size=\"sm\"\r\n variant=\"flat\"\r\n color=\"primary\"\r\n endContent={<ArrowRight className=\"w-4 h-4\" />}\r\n data-testid=\"recommendation-link\"\r\n aria-label={`前往${ability.name}专项提高页面`}\r\n >\r\n {getLinkText(ability.name)}\r\n </Button>\r\n </div>\r\n </CardBody>\r\n </Card>\r\n );\r\n};\r\n\r\nexport default RecommendationCard;","import React, { useEffect } from 'react';\r\nimport { useRadarAbilityStore } from '../../../store/radarAbilityStore';\r\nimport RadarChart from '../RadarChart/RadarChart';\r\nimport AbilityProgressBar from '../AbilityProgressBar/AbilityProgressBar';\r\nimport PersonalizedAdvicePanel from '../PersonalizedAdvicePanel/PersonalizedAdvicePanel';\r\nimport RecommendationCard from '../RecommendationCard/RecommendationCard';\r\nimport styles from './AbilityAssessmentDashboard.module.css';\r\n\r\nconst AbilityAssessmentDashboard: React.FC = () => {\r\n const { data, loading, error, fetchData } = useRadarAbilityStore();\r\n\r\n useEffect(() => {\r\n fetchData();\r\n }, [fetchData]);\r\n\r\n if (loading) {\r\n return (\r\n <div \r\n className=\"card max-w-4xl mx-auto p-6 md:p-8 flex items-center justify-center\"\r\n data-testid=\"loading-spinner\"\r\n >\r\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500\"></div>\r\n <span className=\"ml-3 text-gray-600\">加载中...</span>\r\n </div>\r\n );\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div \r\n className=\"card max-w-4xl mx-auto p-6 md:p-8 text-center\"\r\n role=\"alert\"\r\n aria-live=\"assertive\"\r\n >\r\n <div className=\"text-red-500 mb-4\">\r\n <i \r\n className=\"material-icons text-4xl\"\r\n aria-hidden=\"true\"\r\n >\r\n error_outline\r\n </i>\r\n </div>\r\n <h3 className=\"text-lg font-semibold text-gray-800 mb-2\">加载失败</h3>\r\n <p className=\"text-gray-600 mb-4\">{error}</p>\r\n <button\r\n onClick={fetchData}\r\n className=\"bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\r\n aria-label=\"重试加载数据\"\r\n >\r\n 重试\r\n </button>\r\n </div>\r\n );\r\n }\r\n\r\n if (!data) {\r\n return (\r\n <div \r\n className=\"card max-w-4xl mx-auto p-6 md:p-8 text-center\"\r\n role=\"status\"\r\n aria-live=\"polite\"\r\n >\r\n <p className=\"text-gray-600\">暂无数据</p>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div \r\n className=\"card max-w-4xl mx-auto p-6 md:p-8 animate-fade-in\"\r\n data-component=\"AbilityAssessmentDashboard\"\r\n role=\"main\"\r\n aria-label=\"能力评估雷达图展示\"\r\n >\r\n {/* 头部标题和评级 */}\r\n <div className=\"flex justify-between items-center mb-6\">\r\n <h2 className=\"text-xl font-bold text-gray-800\">能力评估雷达图</h2>\r\n <span \r\n className=\"bg-blue-100 text-blue-800 text-sm font-semibold px-2.5 py-0.5 rounded-full\"\r\n aria-label={`综合评级: ${data.overallRating}`}\r\n >\r\n 综合评级: {data.overallRating}\r\n </span>\r\n </div>\r\n\r\n {/* 主要内容区域 - 上下布局 3:2 */}\r\n <div className={styles.dashboardLayout}>\r\n {/* 上部容器: 能力雷达展示视图 (3/5 高度) */}\r\n <div className={styles.upperSection}>\r\n {/* 左边: 雷达图 */}\r\n <div className={styles.radarChartArea}>\r\n <RadarChart abilities={data.abilities} />\r\n </div>\r\n\r\n {/* 右边: 进度条列表 */}\r\n <div className=\"space-y-4 flex flex-col justify-around py-2\">\r\n {data.abilities.map(ability => (\r\n <AbilityProgressBar \r\n key={ability.name} \r\n ability={ability} \r\n />\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* 下部容器: 个性化推荐视图 (2/5 高度) */}\r\n <div className={styles.lowerSection}>\r\n {/* 通用个性化建议面板 */}\r\n <PersonalizedAdvicePanel \r\n generalRecommendation={data.generalRecommendation} \r\n />\r\n\r\n {/* 专项提升建议 */}\r\n <h3 className=\"text-lg font-bold text-gray-800 mb-4 mt-6\">\r\n 专项提升建议\r\n </h3>\r\n\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n {data.abilities.map(ability => (\r\n <RecommendationCard \r\n key={ability.name} \r\n ability={ability} \r\n />\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default AbilityAssessmentDashboard;","// 课程数据类型定义\r\nexport interface KnowledgeItem {\r\n id: string;\r\n title: string;\r\n description: string;\r\n progress: number;\r\n contentUrl: string;\r\n status?: 'mastered' | 'proficient' | 'familiar' | 'attempted' | 'not-started';\r\n}\r\n\r\nexport interface Lesson {\r\n id: string;\r\n title: string;\r\n duration: number;\r\n knowledgeItems: KnowledgeItem[];\r\n}\r\n\r\nexport interface Unit {\r\n id: string;\r\n title: string;\r\n description: string;\r\n estimatedDuration: string;\r\n totalLessons: number;\r\n moduleCategory: string;\r\n lessons: Lesson[];\r\n}\r\n\r\nexport interface CourseData {\r\n id: string;\r\n title: string;\r\n level: number;\r\n subject: string;\r\n units: Unit[];\r\n}\r\n\r\n// 用户数据类型\r\nexport interface UserData {\r\n id: string;\r\n name: string;\r\n level: number;\r\n avatar: string;\r\n badges: string[];\r\n}\r\n\r\n// 探索菜单项\r\nexport interface ExploreItem {\r\n id: string;\r\n label: string;\r\n status: string;\r\n}\r\n\r\n// 单元进度类型\r\nexport interface UnitProgress {\r\n unitId: string;\r\n title: string;\r\n progressPercentage: number;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n totalLessons: number;\r\n completedLessons: number;\r\n lastAccessed?: string;\r\n}\r\n\r\n// 状态管理类型\r\nexport interface AppState {\r\n currentUnitId: string | null;\r\n currentLessonId: string | null;\r\n currentKnowledgeId: string | null;\r\n sidebarCollapsed: boolean;\r\n exploreMenuOpen: boolean;\r\n activeLessonIds: string[];\r\n \r\n // Actions\r\n setCurrentUnit: (unitId: string) => void;\r\n setCurrentLesson: (lessonId: string) => void;\r\n setCurrentKnowledge: (knowledgeId: string) => void;\r\n toggleSidebar: () => void;\r\n toggleExploreMenu: (open?: boolean) => void;\r\n toggleLessonActive: (lessonId: string) => void;\r\n}\r\n\r\n// 图标映射\r\nexport const categoryIcons: Record<string, string> = {\r\n \"Arithmetic and Algebra\": \"🔢\",\r\n \"Graphics and Geometry\": \"📐\",\r\n \"Probability and Statistics\": \"📊\",\r\n \"Default\": \"📚\"\r\n};\r\n\r\n// 状态映射\r\nexport const statusMapping: Record<string, string> = {\r\n 'mastered': '已掌握',\r\n 'proficient': '熟练',\r\n 'familiar': '熟悉',\r\n 'attempted': '已尝试',\r\n 'not-started': '未开始'\r\n};\r\n\r\nexport const statusColors: Record<string, string> = {\r\n 'mastered': '#10b981',\r\n 'proficient': '#3b82f6',\r\n 'familiar': '#f59e0b',\r\n 'attempted': '#8b5cf6',\r\n 'not-started': '#6b7280'\r\n};","// 单一数据源 - 所有模拟数据集中管理\r\n// 这是整个应用的唯一mock数据来源,确保数据一致性\r\n\r\nexport const MOCK_USER_DATA = {\r\n id: 'user-001',\r\n name: '小明',\r\n level: 5,\r\n avatar: 'https://i.pravatar.cc/40?u=student1',\r\n logIn: true,\r\n badges: ['🏆', '🏅', '🌟']\r\n};\r\n\r\nexport const MOCK_EXPLORE_ITEMS = [\r\n { id: 'g3', label: '三年级', status: 'new', onClick: () => console.log('三年级 clicked') },\r\n { id: 'g4', label: '四年级', status: '2%', onClick: () => console.log('四年级 clicked') },\r\n { id: 'g5', label: '五年级', status: '进行中', onClick: () => console.log('五年级 clicked') },\r\n { id: 'g6', label: '六年级', status: 'new', onClick: () => console.log('六年级 clicked') },\r\n { id: 'g7', label: '七年级', status: 'new', onClick: () => console.log('七年级 clicked') },\r\n { id: 'g8', label: '八年级', status: 'new', onClick: () => console.log('八年级 clicked') },\r\n { id: 'alg_topic', label: '代数专题', status: 'new', onClick: () => console.log('代数专题 clicked') },\r\n { id: 'calc_topic', label: '计算专题', status: 'new', onClick: () => console.log('计算专题 clicked') },\r\n { id: 'geo_topic', label: '几何专题', status: 'new', onClick: () => console.log('几何专题 clicked') },\r\n { id: 'olym_topic', label: '奥数专题', status: 'new', onClick: () => console.log('奥数专题 clicked') }\r\n];\r\n\r\n// JWT token (API专用)\r\nexport const MOCK_JWT_TOKEN = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c2VyLTAwMSIsIm5hbWUiOiLlsI_mmI4iLCJsZXZlbCI6NSwiYXZhdGFyIjoiaHR0cHM6Ly9pLnByYXZhdGFyLmNjLzQwP3U9c3R1ZGVudDEiLCJiYWRnZXMiOlsi8J-SoiIsIvCfjZUiLCLwn5KbIl0sImlhdCI6MTY5MTYwMDAwMCwiZXhwIjoxNzIzMTM2MDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c\";","import type { CourseData } from '../types';\r\n\r\nexport const courseData: CourseData = {\r\n \"id\": \"g5\",\r\n \"title\": \"小学数学五年级\",\r\n \"level\": 5,\r\n \"subject\": \"数学\",\r\n \"units\": [\r\n {\r\n \"id\": \"unit_1\",\r\n \"title\": \"小数乘法\",\r\n \"description\": \"学习小数乘法的计算方法及应用\",\r\n \"estimatedDuration\": \"3周\",\r\n \"totalLessons\": 10,\r\n \"moduleCategory\": \"Arithmetic and Algebra\",\r\n \"lessons\": [\r\n { \"id\": \"unit1_lesson1\", \"title\": \"小数乘整数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit1_lesson1_k1\", \"title\": \"小数乘整数的意义\", \"description\": \"理解小数乘整数的意义与整数乘法相同\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit1_lesson1_k2\", \"title\": \"小数乘整数的计算方法\", \"description\": \"掌握小数乘整数的计算方法:先按整数乘法计算,再看因数中有几位小数,就从积的右边起数出几位点上小数点\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit1_lesson2\", \"title\": \"小数乘小数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit1_lesson2_k1\", \"title\": \"小数乘小数的计算方法\", \"description\": \"掌握小数乘小数的计算方法:先按整数乘法算出积,再给积点上小数点\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit1_lesson2_k2\", \"title\": \"积的小数位数确定\", \"description\": \"理解积的小数位数等于两个因数的小数位数之和\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit1_lesson3\", \"title\": \"积的近似数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit1_lesson3_k1\", \"title\": \"用\\\"四舍五入\\\"法求积的近似数\", \"description\": \"掌握用\\\"四舍五入\\\"法求积的近似数的方法\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit1_lesson4\", \"title\": \"整数乘法运算定律推广到小数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit1_lesson4_k1\", \"title\": \"乘法运算定律在小数中的适用性\", \"description\": \"理解整数乘法运算定律对于小数乘法同样适用\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit1_lesson4_k2\", \"title\": \"运用运算定律进行简便计算\", \"description\": \"能运用乘法运算定律进行小数乘法的简便计算\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit1_lesson5\", \"title\": \"解决问题\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit1_lesson5_k1\", \"title\": \"用小数乘法解决实际问题\", \"description\": \"能运用小数乘法解决购物、面积计算等实际问题\", \"progress\": 0, \"contentUrl\": \"\" } ] }\r\n ]\r\n },\r\n {\r\n \"id\": \"unit_2\", \"title\": \"小数除法\", \"description\": \"学习小数除法的计算方法及应用\", \"estimatedDuration\": \"3周\", \"totalLessons\": 12, \"moduleCategory\": \"Arithmetic and Algebra\",\r\n \"lessons\": [\r\n { \"id\": \"unit2_lesson1\", \"title\": \"小数除以整数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit2_lesson1_k1\", \"title\": \"小数除以整数的计算方法\", \"description\": \"掌握小数除以整数的计算方法:按照整数除法的方法计算,商的小数点要与被除数的小数点对齐\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit2_lesson2\", \"title\": \"一个数除以小数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit2_lesson2_k1\", \"title\": \"除数是小数的除法计算方法\", \"description\": \"掌握除数是小数的除法计算方法:利用商不变的性质,将除数转化为整数\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit2_lesson3\", \"title\": \"商的近似数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit2_lesson3_k1\", \"title\": \"用\\\"四舍五入\\\"法求商的近似数\", \"description\": \"掌握用\\\"四舍五入\\\"法求商的近似数的方法\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit2_lesson4\", \"title\": \"循环小数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit2_lesson4_k1\", \"title\": \"循环小数的概念\", \"description\": \"理解循环小数的概念,认识循环节\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit2_lesson4_k2\", \"title\": \"循环小数的表示方法\", \"description\": \"掌握循环小数的简便表示方法\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit2_lesson5\", \"title\": \"用计算器探索规律\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit2_lesson5_k1\", \"title\": \"用计算器计算小数除法\", \"description\": \"会用计算器计算较复杂的小数除法\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit2_lesson5_k2\", \"title\": \"发现商的变化规律\", \"description\": \"能借助计算器发现商的变化规律\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit2_lesson6\", \"title\": \"解决问题\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit2_lesson6_k1\", \"title\": \"用小数除法解决实际问题\", \"description\": \"能运用小数除法解决购物、分配等实际问题\", \"progress\": 0, \"contentUrl\": \"\" } ] }\r\n ]\r\n },\r\n {\r\n \"id\": \"unit_3\", \"title\": \"简易方程\", \"description\": \"学习用字母表示数和解简易方程\", \"estimatedDuration\": \"4周\", \"totalLessons\": 14, \"moduleCategory\": \"Arithmetic and Algebra\",\r\n \"lessons\": [\r\n { \"id\": \"unit3_lesson1\", \"title\": \"用字母表示数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit3_lesson1_k1\", \"title\": \"用字母表示数\", \"description\": \"初步理解用字母表示数的意义和作用\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit3_lesson1_k2\", \"title\": \"用字母表示运算定律和计算公式\", \"description\": \"会用字母表示运算定律和计算公式\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit3_lesson2\", \"title\": \"方程的意义\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit3_lesson2_k1\", \"title\": \"方程的概念\", \"description\": \"理解方程的意义,知道方程与等式的区别和联系\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit3_lesson3\", \"title\": \"等式的性质\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit3_lesson3_k1\", \"title\": \"等式的性质1\", \"description\": \"理解等式的性质1:等式两边加上或减去同一个数,左右两边仍然相等\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit3_lesson3_k2\", \"title\": \"等式的性质2\", \"description\": \"理解等式的性质2:等式两边乘同一个数,或除以同一个不为0的数,左右两边仍然相等\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit3_lesson4\", \"title\": \"解简易方程\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit3_lesson4_k1\", \"title\": \"利用等式的性质解方程\", \"description\": \"会利用等式的性质解形如x±a=b、ax=b、x÷a=b、a-x=b、a÷x=b的方程\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit3_lesson5\", \"title\": \"实际问题与方程\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit3_lesson5_k1\", \"title\": \"列方程解决实际问题\", \"description\": \"初步学会列方程解决一些简单的实际问题\", \"progress\": 0, \"contentUrl\": \"\" } ] }\r\n ]\r\n },\r\n {\r\n \"id\": \"unit_4\", \"title\": \"多边形的面积\", \"description\": \"学习平行四边形、三角形、梯形和组合图形的面积计算\", \"estimatedDuration\": \"3周\", \"totalLessons\": 12, \"moduleCategory\": \"Graphics and Geometry\",\r\n \"lessons\": [\r\n { \"id\": \"unit4_lesson1\", \"title\": \"平行四边形的面积\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit4_lesson1_k1\", \"title\": \"平行四边形面积公式的推导\", \"description\": \"通过割补法理解平行四边形面积公式的推导过程\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit4_lesson1_k2\", \"title\": \"平行四边形面积的计算\", \"description\": \"掌握平行四边形面积计算公式:S=ah,并能正确运用\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit4_lesson2\", \"title\": \"三角形的面积\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit4_lesson2_k1\", \"title\": \"三角形面积公式的推导\", \"description\": \"通过拼摆法理解三角形面积公式的推导过程\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit4_lesson2_k2\", \"title\": \"三角形面积的计算\", \"description\": \"掌握三角形面积计算公式:S=ah÷2,并能正确运用\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit4_lesson3\", \"title\": \"梯形的面积\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit4_lesson3_k1\", \"title\": \"梯形面积公式的推导\", \"description\": \"通过拼摆法理解梯形面积公式的推导过程\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit4_lesson3_k2\", \"title\": \"梯形面积的计算\", \"description\": \"掌握梯形面积计算公式:S=(a+b)h÷2,并能正确运用\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit4_lesson4\", \"title\": \"组合图形的面积\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit4_lesson4_k1\", \"title\": \"认识组合图形\", \"description\": \"认识组合图形,会把组合图形分解成已学过的平面图形\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit4_lesson4_k2\", \"title\": \"计算组合图形的面积\", \"description\": \"掌握计算组合图形面积的多种方法\", \"progress\": 0, \"contentUrl\": \"\" } ] }\r\n ]\r\n },\r\n {\r\n \"id\": \"unit_5\", \"title\": \"因数与倍数\", \"description\": \"学习因数、倍数、质数、合数等概念\", \"estimatedDuration\": \"3周\", \"totalLessons\": 10, \"moduleCategory\": \"Arithmetic and Algebra\",\r\n \"lessons\": [\r\n { \"id\": \"unit5_lesson1\", \"title\": \"因数和倍数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit5_lesson1_k1\", \"title\": \"因数和倍数的意义\", \"description\": \"理解因数和倍数的意义,掌握找一个数的因数和倍数的方法\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit5_lesson1_k2\", \"title\": \"因数和倍数的特征\", \"description\": \"了解一个数的因数的个数是有限的,倍数的个数是无限的\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit5_lesson2\", \"title\": \"2、5、3的倍数的特征\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit5_lesson2_k1\", \"title\": \"2、5的倍数的特征\", \"description\": \"掌握2、5的倍数的特征,理解奇数和偶数的意义\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit5_lesson2_k2\", \"title\": \"3的倍数的特征\", \"description\": \"掌握3的倍数的特征,能判断一个数是不是3的倍数\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit5_lesson3\", \"title\": \"质数和合数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit5_lesson3_k1\", \"title\": \"质数和合数的意义\", \"description\": \"理解质数和合数的意义,能判断一个数是质数还是合数\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit5_lesson3_k2\", \"title\": \"制作100以内的质数表\", \"description\": \"会制作100以内的质数表,熟记20以内的质数\", \"progress\": 0, \"contentUrl\": \"\" } ] }\r\n ]\r\n },\r\n {\r\n \"id\": \"unit_6\", \"title\": \"长方体和正方体\", \"description\": \"学习长方体和正方体的特征、表面积和体积计算\", \"estimatedDuration\": \"4周\", \"totalLessons\": 14, \"moduleCategory\": \"Graphics and Geometry\",\r\n \"lessons\": [\r\n { \"id\": \"unit6_lesson1\", \"title\": \"长方体和正方体的认识\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit6_lesson1_k1\", \"title\": \"长方体的特征\", \"description\": \"认识长方体的特征,了解长方体的长、宽、高\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit6_lesson1_k2\", \"title\": \"正方体的特征\", \"description\": \"认识正方体的特征,理解正方体是特殊的长方体\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit6_lesson2\", \"title\": \"长方体和正方体的表面积\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit6_lesson2_k1\", \"title\": \"表面积的意义\", \"description\": \"理解表面积的意义,掌握长方体和正方体表面积的计算方法\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit6_lesson2_k2\", \"title\": \"表面积的实际应用\", \"description\": \"能运用表面积知识解决一些实际问题\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit6_lesson3\", \"title\": \"长方体和正方体的体积\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit6_lesson3_k1\", \"title\": \"体积和体积单位\", \"description\": \"理解体积的意义,认识常用的体积单位\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit6_lesson3_k2\", \"title\": \"长方体和正方体体积的计算\", \"description\": \"掌握长方体和正方体体积的计算公式\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit6_lesson3_k3\", \"title\": \"体积单位间的进率\", \"description\": \"掌握体积单位之间的进率和换算\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit6_lesson4\", \"title\": \"容积和容积单位\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit6_lesson4_k1\", \"title\": \"容积和容积单位\", \"description\": \"理解容积的意义,认识常用的容积单位\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit6_lesson4_k2\", \"title\": \"容积和体积的关系\", \"description\": \"掌握容积和体积之间的关系\", \"progress\": 0, \"contentUrl\": \"\" } ] }\r\n ]\r\n },\r\n {\r\n \"id\": \"unit_7\", \"title\": \"分数的意义和性质\", \"description\": \"学习分数的意义、性质和约分、通分等方法\", \"estimatedDuration\": \"4周\", \"totalLessons\": 16, \"moduleCategory\": \"Arithmetic and Algebra\",\r\n \"lessons\": [\r\n { \"id\": \"unit7_lesson1\", \"title\": \"分数的意义\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit7_lesson1_k1\", \"title\": \"分数的产生和意义\", \"description\": \"理解分数的产生和意义,明确分数与除法的关系\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit7_lesson1_k2\", \"title\": \"分数单位\", \"description\": \"认识分数单位,能说出一个分数中有几个这样的分数单位\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit7_lesson2\", \"title\": \"分数与除法\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit7_lesson2_k1\", \"title\": \"分数与除法的关系\", \"description\": \"理解分数与除法的关系,会用分数表示两个数相除的商\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit7_lesson3\", \"title\": \"真分数和假分数\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit7_lesson3_k1\", \"title\": \"真分数和假分数的意义\", \"description\": \"理解真分数和假分数的意义和特征\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit7_lesson3_k2\", \"title\": \"带分数\", \"description\": \"认识带分数,会进行假分数与整数、带分数的互化\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit7_lesson4\", \"title\": \"分数的基本性质\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit7_lesson4_k1\", \"title\": \"分数的基本性质\", \"description\": \"理解分数的基本性质,能运用分数的基本性质进行分数的变形\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit7_lesson5\", \"title\": \"约分\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit7_lesson5_k1\", \"title\": \"最大公因数\", \"description\": \"理解公因数和最大公因数的意义,掌握求两个数的最大公因数的方法\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit7_lesson5_k2\", \"title\": \"约分的方法\", \"description\": \"掌握约分的方法,能正确地进行约分\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit7_lesson6\", \"title\": \"通分\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit7_lesson6_k1\", \"title\": \"最小公倍数\", \"description\": \"理解公倍数和最小公倍数的意义,掌握求两个数的最小公倍数的方法\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit7_lesson6_k2\", \"title\": \"通分的方法\", \"description\": \"掌握通分的方法,能正确地进行通分\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit7_lesson7\", \"title\": \"分数和小数的互化\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit7_lesson7_k1\", \"title\": \"分数化成小数\", \"description\": \"掌握分数化成小数的方法\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit7_lesson7_k2\", \"title\": \"小数化成分数\", \"description\": \"掌握小数化成分数的方法\", \"progress\": 0, \"contentUrl\": \"\" } ] }\r\n ]\r\n },\r\n {\r\n \"id\": \"unit_8\", \"title\": \"分数的加法和减法\", \"description\": \"学习同分母分数、异分母分数的加法和减法\", \"estimatedDuration\": \"3周\", \"totalLessons\": 12, \"moduleCategory\": \"Arithmetic and Algebra\",\r\n \"lessons\": [\r\n { \"id\": \"unit8_lesson1\", \"title\": \"同分母分数加、减法\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit8_lesson1_k1\", \"title\": \"同分母分数加法的计算方法\", \"description\": \"掌握同分母分数加法的计算方法\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit8_lesson1_k2\", \"title\": \"同分母分数减法的计算方法\", \"description\": \"掌握同分母分数减法的计算方法\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit8_lesson2\", \"title\": \"异分母分数加、减法\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit8_lesson2_k1\", \"title\": \"异分母分数加法的计算方法\", \"description\": \"掌握异分母分数加法的计算方法:先通分,然后按照同分母分数加法进行计算\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit8_lesson2_k2\", \"title\": \"异分母分数减法的计算方法\", \"description\": \"掌握异分母分数减法的计算方法:先通分,然后按照同分母分数减法进行计算\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit8_lesson3\", \"title\": \"分数加减混合运算\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit8_lesson3_k1\", \"title\": \"分数加减混合运算的顺序\", \"description\": \"掌握分数加减混合运算的运算顺序\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit8_lesson3_k2\", \"title\": \"整数加法运算定律推广到分数加法\", \"description\": \"理解整数加法运算定律对于分数加法同样适用,能运用运算定律进行简便计算\", \"progress\": 0, \"contentUrl\": \"\" } ] }\r\n ]\r\n },\r\n {\r\n \"id\": \"unit_9\", \"title\": \"折线统计图\", \"description\": \"学习单式折线统计图和复式折线统计图的认识和制作\", \"estimatedDuration\": \"2周\", \"totalLessons\": 6, \"moduleCategory\": \"Probability and Statistics\",\r\n \"lessons\": [\r\n { \"id\": \"unit9_lesson1\", \"title\": \"单式折线统计图\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit9_lesson1_k1\", \"title\": \"单式折线统计图的特点\", \"description\": \"认识单式折线统计图,了解其特点和作用\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit9_lesson1_k2\", \"title\": \"绘制单式折线统计图\", \"description\": \"能根据数据绘制单式折线统计图\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit9_lesson2\", \"title\": \"复式折线统计图\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit9_lesson2_k1\", \"title\": \"复式折线统计图的特点\", \"description\": \"认识复式折线统计图,了解其特点和作用\", \"progress\": 0, \"contentUrl\": \"\" }, { \"id\": \"unit9_lesson2_k2\", \"title\": \"绘制复式折线统计图\", \"description\": \"能根据数据绘制复式折线统计图\", \"progress\": 0, \"contentUrl\": \"\" } ] },\r\n { \"id\": \"unit9_lesson3\", \"title\": \"数据分析\", \"duration\": 40, \"knowledgeItems\": [ { \"id\": \"unit9_lesson3_k1\", \"title\": \"根据统计图进行数据分析\", \"description\": \"能根据折线统计图进行简单的数据分析,作出合理的判断和预测\", \"progress\": 0, \"contentUrl\": \"\" } ] }\r\n ]\r\n }\r\n ]\r\n};\r\n\r\nimport { MOCK_USER_DATA, MOCK_EXPLORE_ITEMS } from './mockData';\r\n\r\n// 从单一数据源导入,确保数据一致性\r\nexport const exploreItems = MOCK_EXPLORE_ITEMS;\r\nexport const userData = MOCK_USER_DATA;","import type { CourseData, UnitProgress } from '../types';\r\nimport { MOCK_JWT_TOKEN } from '../data/mockData';\r\n\r\nexport interface UserGradeUnitsNav {\r\n userId: string;\r\n courseId: string;\r\n courseTitle: string;\r\n courseLevel: number;\r\n totalUnits: number;\r\n completedUnits: number;\r\n overallProgress: number;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n lastAccessed?: string;\r\n units: Array<{\r\n unitId: string;\r\n title: string;\r\n description: string;\r\n moduleCategory: string;\r\n estimatedDuration: string;\r\n totalLessons: number;\r\n completedLessons: number;\r\n progressPercentage: number;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n lastAccessed?: string;\r\n isActive: boolean;\r\n route: string;\r\n }>;\r\n}\r\n\r\nexport interface BatchLessonProgressUpdate {\r\n lessonId: string;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n progress?: number;\r\n}\r\n\r\nclass CourseService {\r\n private baseURL: string;\r\n private token: string;\r\n\r\n constructor(baseURL: string = '/api/v1', token: string = MOCK_JWT_TOKEN) {\r\n this.baseURL = baseURL;\r\n this.token = token;\r\n }\r\n\r\n private getAuthHeaders(): HeadersInit {\r\n return {\r\n 'Authorization': `Bearer ${this.token}`,\r\n 'Content-Type': 'application/json'\r\n };\r\n }\r\n\r\n private async fetchWithAuth(url: string, options: RequestInit = {}): Promise<Response> {\r\n const response = await fetch(url, {\r\n ...options,\r\n headers: {\r\n ...this.getAuthHeaders(),\r\n ...options.headers\r\n }\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n // 获取课程数据\r\n async getCourseData(courseId: string): Promise<CourseData> {\r\n const response = await this.fetchWithAuth(`${this.baseURL}/content/courses/${courseId}`);\r\n return response.json();\r\n }\r\n\r\n // 获取用户年级单元导航数据(包含所有单元进度)\r\n async getUserGradeUnitsNav(gradeId?: string): Promise<UserGradeUnitsNav> {\r\n const url = gradeId\r\n ? `${this.baseURL}/content/grades/${encodeURIComponent(gradeId)}/units/nav`\r\n : `${this.baseURL}/content/grades/current/units/nav`;\r\n\r\n const response = await this.fetchWithAuth(url);\r\n return response.json();\r\n }\r\n\r\n // 获取单元进度\r\n async getUnitProgress(courseId: string, unitId?: string): Promise<Record<string, UnitProgress>> {\r\n const url = unitId\r\n ? `${this.baseURL}/content/courses/${courseId}/units/${unitId}/progress`\r\n : `${this.baseURL}/content/courses/${courseId}/progress`;\r\n\r\n const response = await this.fetchWithAuth(url);\r\n return response.json();\r\n }\r\n\r\n // 批量更新单元课时进度\r\n async batchUpdateLessonProgress(\r\n unitId: string,\r\n progressUpdates: BatchLessonProgressUpdate[]\r\n ): Promise<{ success: boolean; results: Array<{ lessonId: string; success: boolean; status: string }> }> {\r\n const response = await this.fetchWithAuth(\r\n `${this.baseURL}/content/units/${unitId}/progress/batch`,\r\n {\r\n method: 'POST',\r\n body: JSON.stringify(progressUpdates)\r\n }\r\n );\r\n\r\n return response.json();\r\n }\r\n\r\n // 更新学习进度(单个课时)\r\n async updateLessonProgress(\r\n courseId: string,\r\n unitId: string,\r\n lessonId: string,\r\n status: 'completed' | 'in-progress' | 'not-started'\r\n ): Promise<void> {\r\n await this.fetchWithAuth(\r\n `${this.baseURL}/content/courses/${courseId}/units/${unitId}/lessons/${lessonId}/progress`,\r\n {\r\n method: 'POST',\r\n body: JSON.stringify({ status })\r\n }\r\n );\r\n }\r\n\r\n // 设置认证token\r\n setToken(token: string): void {\r\n this.token = token;\r\n }\r\n\r\n // 获取当前token\r\n getToken(): string {\r\n return this.token;\r\n }\r\n}\r\n\r\n// 单例模式导出\r\nexport const courseService = new CourseService();","// 数据源抽象层类型定义\r\nimport type { UserData } from '../types';\r\nimport type { ExploreItem } from '../components/MathWizHeader/MathWizHeader.types';\r\nimport type { UserGradeUnitsProgressData } from '../components/Sidebar/types';\r\n\r\n/**\r\n * 数据源接口定义\r\n * 所有数据源实现都必须遵循此接口\r\n */\r\nexport interface IDataSource {\r\n /**\r\n * 获取用户年级单元导航数据\r\n * @param gradeId 年级ID\r\n * @param userId 用户ID\r\n * @returns 用户年级单元进度数据\r\n */\r\n getUserGradeUnitsNav(gradeId: string, userId: string): Promise<UserGradeUnitsProgressData>;\r\n\r\n /**\r\n * 获取用户个人信息\r\n * @param userId 用户ID\r\n * @returns 用户数据\r\n */\r\n getUserProfile(userId: string): Promise<UserData>;\r\n\r\n /**\r\n * 获取探索菜单数据\r\n * @returns 探索菜单项列表\r\n */\r\n getExploreMenu(): Promise<ExploreItem[]>;\r\n\r\n /**\r\n * 更新课时进度\r\n * @param params 进度更新参数\r\n */\r\n updateLessonProgress(params: UpdateProgressParams): Promise<void>;\r\n\r\n /**\r\n * 批量更新课时进度\r\n * @param unitId 单元ID\r\n * @param progressUpdates 进度更新列表\r\n */\r\n batchUpdateLessonProgress(\r\n unitId: string,\r\n progressUpdates: BatchLessonProgressUpdate[]\r\n ): Promise<{ success: boolean; results: Array<{ lessonId: string; success: boolean; status: string }> }>;\r\n}\r\n\r\n/**\r\n * 进度更新参数\r\n */\r\nexport interface UpdateProgressParams {\r\n courseId: string;\r\n unitId: string;\r\n lessonId: string;\r\n status: 'completed' | 'in-progress' | 'not-started';\r\n}\r\n\r\n/**\r\n * 批量课时进度更新\r\n */\r\nexport interface BatchLessonProgressUpdate {\r\n lessonId: string;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n progress?: number;\r\n}\r\n\r\n/**\r\n * 数据源配置基类\r\n */\r\nexport interface DataSourceConfig {\r\n /** 数据源名称,用于调试和日志 */\r\n name: string;\r\n /** 是否启用缓存 */\r\n enableCaching?: boolean;\r\n /** 缓存过期时间(毫秒) */\r\n cacheTTL?: number;\r\n /** 请求超时时间(毫秒) */\r\n timeout?: number;\r\n}\r\n\r\n/**\r\n * API数据源配置\r\n */\r\nexport interface ApiDataSourceConfig extends DataSourceConfig {\r\n /** API基础URL */\r\n baseURL: string;\r\n /** 认证token */\r\n token: string;\r\n /** 重试次数 */\r\n retryCount?: number;\r\n /** 重试延迟(毫秒) */\r\n retryDelay?: number;\r\n}\r\n\r\n/**\r\n * 模拟数据源配置\r\n */\r\nexport interface MockDataSourceConfig extends DataSourceConfig {\r\n /** 模拟数据延迟(毫秒) */\r\n delay?: number;\r\n /** 是否模拟错误 */\r\n simulateError?: boolean;\r\n /** 错误概率(0-1) */\r\n errorProbability?: number;\r\n}\r\n\r\n/**\r\n * 数据源错误类型\r\n */\r\nexport class DataSourceError extends Error {\r\n constructor(\r\n message: string,\r\n public code: string,\r\n public originalError?: Error\r\n ) {\r\n super(message);\r\n this.name = 'DataSourceError';\r\n }\r\n}\r\n\r\n/**\r\n * 数据源工厂选项\r\n */\r\nexport interface DataSourceFactoryOptions {\r\n /** 数据源类型 */\r\n type: 'api' | 'mock' | 'custom';\r\n /** 配置参数 */\r\n config: DataSourceConfig;\r\n /** 自定义数据源类(当type为custom时使用) */\r\n customDataSourceClass?: new (config: DataSourceConfig) => IDataSource;\r\n}","// API数据源实现\r\nimport { courseService } from '../services/courseService';\r\nimport type {\r\n IDataSource,\r\n ApiDataSourceConfig,\r\n UpdateProgressParams,\r\n BatchLessonProgressUpdate\r\n} from './types';\r\nimport { DataSourceError } from './types';\r\nimport type { UserData } from '../types';\r\nimport type { ExploreItem } from '../components/MathWizHeader/MathWizHeader.types';\r\nimport type { UserGradeUnitsProgressData } from '../components/Sidebar/types';\r\n/**\r\n * API数据源 - 基于现有courseService的实现\r\n */\r\nexport class ApiDataSource implements IDataSource {\r\n private config: ApiDataSourceConfig;\r\n\r\n constructor(config: ApiDataSourceConfig) {\r\n this.config = {\r\n enableCaching: false,\r\n cacheTTL: 300000, // 5分钟\r\n timeout: 15000, // 15秒\r\n retryCount: 3,\r\n retryDelay: 1000,\r\n ...config\r\n };\r\n\r\n // 配置courseService\r\n courseService.setToken(this.config.token);\r\n }\r\n\r\n async getUserGradeUnitsNav(gradeId: string, userId: string): Promise<UserGradeUnitsProgressData> {\r\n try {\r\n console.log(`[ApiDataSource] 获取年级单元导航数据: gradeId=${gradeId}, userId=${userId}`);\r\n\r\n const data = await this.withRetry(() =>\r\n courseService.getUserGradeUnitsNav(gradeId)\r\n );\r\n\r\n return data;\r\n } catch (error) {\r\n console.error('[ApiDataSource] 获取年级单元导航数据失败:', error);\r\n throw new DataSourceError(\r\n `获取年级单元导航数据失败: ${error instanceof Error ? error.message : '未知错误'}`,\r\n 'GET_USER_GRADE_UNITS_NAV_FAILED',\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n async getUserProfile(userId: string): Promise<UserData> {\r\n try {\r\n console.log(`[ApiDataSource] 获取用户个人信息: userId=${userId}`);\r\n\r\n // 这里应该调用实际的用户API\r\n // 目前使用模拟数据,实际项目中需要替换为真实的API调用\r\n const mockUserData: UserData = {\r\n id: userId,\r\n name: '学生用户',\r\n level: 5,\r\n avatar: 'https://i.pravatar.cc/40',\r\n badges: ['🏆']\r\n };\r\n\r\n return mockUserData;\r\n } catch (error) {\r\n console.error('[ApiDataSource] 获取用户个人信息失败:', error);\r\n throw new DataSourceError(\r\n `获取用户个人信息失败: ${error instanceof Error ? error.message : '未知错误'}`,\r\n 'GET_USER_PROFILE_FAILED',\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n async getExploreMenu(): Promise<ExploreItem[]> {\r\n try {\r\n console.log('[ApiDataSource] 获取探索菜单数据');\r\n\r\n // 这里应该调用实际的探索菜单API\r\n // 目前使用模拟数据,实际项目中需要替换为真实的API调用\r\n const mockExploreMenu: ExploreItem[] = [\r\n { id: 'g5', label: '五年级', status: '进行中' },\r\n { id: 'g6', label: '六年级', status: 'new' }\r\n ];\r\n\r\n return mockExploreMenu;\r\n } catch (error) {\r\n console.error('[ApiDataSource] 获取探索菜单数据失败:', error);\r\n throw new DataSourceError(\r\n `获取探索菜单数据失败: ${error instanceof Error ? error.message : '未知错误'}`,\r\n 'GET_EXPLORE_MENU_FAILED',\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n async updateLessonProgress(params: UpdateProgressParams): Promise<void> {\r\n try {\r\n console.log(`[ApiDataSource] 更新课时进度:`, params);\r\n\r\n await this.withRetry(() =>\r\n courseService.updateLessonProgress(\r\n params.courseId,\r\n params.unitId,\r\n params.lessonId,\r\n params.status\r\n )\r\n );\r\n } catch (error) {\r\n console.error('[ApiDataSource] 更新课时进度失败:', error);\r\n throw new DataSourceError(\r\n `更新课时进度失败: ${error instanceof Error ? error.message : '未知错误'}`,\r\n 'UPDATE_LESSON_PROGRESS_FAILED',\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n async batchUpdateLessonProgress(\r\n unitId: string,\r\n progressUpdates: BatchLessonProgressUpdate[]\r\n ): Promise<{ success: boolean; results: Array<{ lessonId: string; success: boolean; status: string }> }> {\r\n try {\r\n console.log(`[ApiDataSource] 批量更新课时进度: unitId=${unitId}`, progressUpdates);\r\n\r\n const result = await this.withRetry(() =>\r\n courseService.batchUpdateLessonProgress(unitId, progressUpdates)\r\n );\r\n\r\n return result;\r\n } catch (error) {\r\n console.error('[ApiDataSource] 批量更新课时进度失败:', error);\r\n throw new DataSourceError(\r\n `批量更新课时进度失败: ${error instanceof Error ? error.message : '未知错误'}`,\r\n 'BATCH_UPDATE_LESSON_PROGRESS_FAILED',\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * 带重试机制的请求执行\r\n */\r\n private async withRetry<T>(operation: () => Promise<T>): Promise<T> {\r\n let lastError: Error;\r\n\r\n for (let attempt = 1; attempt <= this.config.retryCount!; attempt++) {\r\n try {\r\n return await operation();\r\n } catch (error) {\r\n lastError = error instanceof Error ? error : new Error(String(error));\r\n\r\n if (attempt < this.config.retryCount!) {\r\n console.warn(`[ApiDataSource] 请求失败,第${attempt}次重试...`, lastError.message);\r\n await this.delay(this.config.retryDelay!);\r\n }\r\n }\r\n }\r\n\r\n throw lastError!;\r\n }\r\n\r\n /**\r\n * 延迟函数\r\n */\r\n private delay(ms: number): Promise<void> {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n }\r\n\r\n /**\r\n * 获取配置信息\r\n */\r\n getConfig(): ApiDataSourceConfig {\r\n return { ...this.config };\r\n }\r\n}\r\n\r\n/**\r\n * 创建API数据源实例的工厂函数\r\n */\r\nexport function createApiDataSource(config: ApiDataSourceConfig): ApiDataSource {\r\n return new ApiDataSource(config);\r\n}","// 模拟数据源实现\r\nimport { courseData } from '../data/courseData';\r\nimport { categoryIcons } from '../types';\r\nimport type {\r\n IDataSource,\r\n MockDataSourceConfig,\r\n UpdateProgressParams,\r\n BatchLessonProgressUpdate\r\n} from './types';\r\nimport { DataSourceError } from './types';\r\nimport type { UserData, Lesson } from '../types';\r\nimport type { UserGradeUnitsProgressData } from '../components/Sidebar/types';\r\nimport type { ExploreItem } from '../components/MathWizHeader/MathWizHeader.types';\r\n\r\n/**\r\n * 模拟数据源 - 基于courseData.ts的实现\r\n */\r\nexport class MockDataSource implements IDataSource {\r\n private config: MockDataSourceConfig;\r\n\r\n constructor(config: MockDataSourceConfig) {\r\n this.config = {\r\n delay: 500,\r\n simulateError: false,\r\n errorProbability: 0.1,\r\n ...config\r\n };\r\n }\r\n\r\n async getUserGradeUnitsNav(gradeId: string, userId: string): Promise<UserGradeUnitsProgressData> {\r\n console.log(`[MockDataSource] 开始获取年级单元导航数据: gradeId=${gradeId}, userId=${userId}`);\r\n await this.simulateDelay();\r\n\r\n if (this.shouldSimulateError()) {\r\n console.log(`[MockDataSource] 模拟错误: gradeId=${gradeId}, userId=${userId}`);\r\n throw new DataSourceError(\r\n '模拟数据源:获取年级单元导航数据失败',\r\n 'MOCK_GET_USER_GRADE_UNITS_NAV_FAILED'\r\n );\r\n }\r\n\r\n console.log(`[MockDataSource] 成功获取年级单元导航数据: gradeId=${gradeId}, userId=${userId}`);\r\n\r\n // 基于courseData.ts生成模拟进度数据\r\n const mockUnitsData: UserGradeUnitsProgressData = {\r\n userId: userId,\r\n courseId: gradeId,\r\n courseTitle: '小学数学五年级',\r\n courseLevel: 5,\r\n totalUnits: courseData.units.length,\r\n completedUnits: 2,\r\n overallProgress: 22,\r\n status: 'in-progress',\r\n lastAccessed: new Date().toISOString(),\r\n units: courseData.units.map((unit, index) => ({\r\n unitId: unit.id,\r\n title: unit.title,\r\n description: unit.description,\r\n moduleCategory: unit.moduleCategory,\r\n estimatedDuration: unit.estimatedDuration,\r\n totalLessons: unit.lessons.length,\r\n completedLessons: index < 2 ? Math.floor(unit.lessons.length * 0.5) : 0,\r\n progressPercentage: index < 2 ? 50 : 0,\r\n status: index < 2 ? 'in-progress' : 'not-started',\r\n lastAccessed: index < 2 ? new Date().toISOString() : undefined,\r\n isActive: index === 0,\r\n route: `/math/grade-5/unit/${unit.id}`,\r\n icon: categoryIcons[unit.moduleCategory] || categoryIcons.Default\r\n }))\r\n };\r\n\r\n return mockUnitsData;\r\n }\r\n\r\n async getUserProfile(userId: string): Promise<UserData> {\r\n await this.simulateDelay();\r\n\r\n if (this.shouldSimulateError()) {\r\n throw new DataSourceError(\r\n '模拟数据源:获取用户个人信息失败',\r\n 'MOCK_GET_USER_PROFILE_FAILED'\r\n );\r\n }\r\n\r\n console.log(`[MockDataSource] 获取用户个人信息: userId=${userId}`);\r\n\r\n const mockUserData: UserData = {\r\n id: userId,\r\n name: '学生用户',\r\n level: 5,\r\n avatar: 'https://i.pravatar.cc/40',\r\n badges: ['🏆']\r\n };\r\n\r\n return mockUserData;\r\n }\r\n\r\n async getExploreMenu(): Promise<ExploreItem[]> {\r\n await this.simulateDelay();\r\n\r\n if (this.shouldSimulateError()) {\r\n throw new DataSourceError(\r\n '模拟数据源:获取探索菜单数据失败',\r\n 'MOCK_GET_EXPLORE_MENU_FAILED'\r\n );\r\n }\r\n\r\n console.log('[MockDataSource] 获取探索菜单数据');\r\n\r\n const mockExploreMenu: ExploreItem[] = [\r\n { id: 'g5', label: '五年级', status: '进行中' },\r\n { id: 'g6', label: '六年级', status: 'new' }\r\n ];\r\n\r\n return mockExploreMenu;\r\n }\r\n\r\n async updateLessonProgress(params: UpdateProgressParams): Promise<void> {\r\n await this.simulateDelay();\r\n\r\n if (this.shouldSimulateError()) {\r\n throw new DataSourceError(\r\n '模拟数据源:更新课时进度失败',\r\n 'MOCK_UPDATE_LESSON_PROGRESS_FAILED'\r\n );\r\n }\r\n\r\n console.log(`[MockDataSource] 更新课时进度:`, params);\r\n\r\n // 模拟数据源中,进度更新只是记录日志\r\n console.log(`课时 ${params.lessonId} 状态更新为: ${params.status}`);\r\n }\r\n\r\n async batchUpdateLessonProgress(\r\n unitId: string,\r\n progressUpdates: BatchLessonProgressUpdate[]\r\n ): Promise<{ success: boolean; results: Array<{ lessonId: string; success: boolean; status: string }> }> {\r\n await this.simulateDelay();\r\n\r\n if (this.shouldSimulateError()) {\r\n throw new DataSourceError(\r\n '模拟数据源:批量更新课时进度失败',\r\n 'MOCK_BATCH_UPDATE_LESSON_PROGRESS_FAILED'\r\n );\r\n }\r\n\r\n console.log(`[MockDataSource] 批量更新课时进度: unitId=${unitId}`, progressUpdates);\r\n\r\n const results = progressUpdates.map(update => ({\r\n lessonId: update.lessonId,\r\n success: true,\r\n status: update.status\r\n }));\r\n\r\n return {\r\n success: true,\r\n results\r\n };\r\n }\r\n\r\n /**\r\n * 模拟网络延迟\r\n */\r\n private async simulateDelay(): Promise<void> {\r\n if (this.config.delay && this.config.delay > 0) {\r\n await new Promise(resolve => setTimeout(resolve, this.config.delay));\r\n }\r\n }\r\n\r\n /**\r\n * 判断是否应该模拟错误\r\n */\r\n private shouldSimulateError(): boolean {\r\n if (!this.config.simulateError) {\r\n return false;\r\n }\r\n\r\n return Math.random() < (this.config.errorProbability || 0.1);\r\n }\r\n\r\n /**\r\n * 获取配置信息\r\n */\r\n getConfig(): MockDataSourceConfig {\r\n return { ...this.config };\r\n }\r\n\r\n /**\r\n * 生成课程数据\r\n */\r\n getCourseData(): typeof courseData {\r\n return courseData;\r\n }\r\n\r\n /**\r\n * 生成课时数据\r\n */\r\n getLessonsData(): Record<string, Lesson[]> {\r\n const lessonsData: Record<string, Lesson[]> = {};\r\n courseData.units.forEach(unit => {\r\n lessonsData[unit.id] = unit.lessons.map(lesson => ({\r\n id: lesson.id,\r\n title: lesson.title,\r\n duration: lesson.duration,\r\n knowledgeItems: lesson.knowledgeItems.map(item => ({\r\n ...item,\r\n progress: 0 // 添加默认进度值\r\n }))\r\n }));\r\n });\r\n return lessonsData;\r\n }\r\n}\r\n\r\n/**\r\n * 创建模拟数据源实例的工厂函数\r\n */\r\nexport function createMockDataSource(config: MockDataSourceConfig): MockDataSource {\r\n return new MockDataSource(config);\r\n}","// 数据源工厂\r\nimport { ApiDataSource } from './api-data-source';\r\nimport { MockDataSource } from './mock-data-source';\r\nimport type {\r\n IDataSource,\r\n DataSourceFactoryOptions,\r\n DataSourceConfig,\r\n ApiDataSourceConfig,\r\n MockDataSourceConfig\r\n} from './types';\r\n\r\n/**\r\n * 数据源工厂 - 用于创建和管理数据源实例\r\n */\r\nexport class DataSourceFactory {\r\n private static instances: Map<string, IDataSource> = new Map();\r\n\r\n /**\r\n * 创建数据源实例\r\n * @param options 数据源选项\r\n * @returns 数据源实例\r\n */\r\n static createDataSource(options: DataSourceFactoryOptions): IDataSource {\r\n const { type, config, customDataSourceClass } = options;\r\n\r\n // 生成实例标识符\r\n const instanceKey = this.getInstanceKey(type, config);\r\n\r\n // 如果已存在相同配置的实例,则返回现有实例\r\n if (this.instances.has(instanceKey)) {\r\n return this.instances.get(instanceKey)!;\r\n }\r\n\r\n let dataSource: IDataSource;\r\n\r\n switch (type) {\r\n case 'api':\r\n dataSource = new ApiDataSource(config as ApiDataSourceConfig);\r\n break;\r\n\r\n case 'mock':\r\n dataSource = new MockDataSource(config as MockDataSourceConfig);\r\n break;\r\n\r\n case 'custom':\r\n if (!customDataSourceClass) {\r\n throw new Error('自定义数据源类型需要提供 customDataSourceClass 参数');\r\n }\r\n dataSource = new customDataSourceClass(config);\r\n break;\r\n\r\n default:\r\n throw new Error(`不支持的数据源类型: ${type}`);\r\n }\r\n\r\n // 缓存实例\r\n this.instances.set(instanceKey, dataSource);\r\n\r\n console.log(`[DataSourceFactory] 创建数据源: type=${type}, name=${config.name}`);\r\n\r\n return dataSource;\r\n }\r\n\r\n /**\r\n * 获取API数据源实例\r\n * @param config API数据源配置\r\n * @returns API数据源实例\r\n */\r\n static createApiDataSource(config: ApiDataSourceConfig): ApiDataSource {\r\n return this.createDataSource({\r\n type: 'api',\r\n config\r\n }) as ApiDataSource;\r\n }\r\n\r\n /**\r\n * 获取模拟数据源实例\r\n * @param config 模拟数据源配置\r\n * @returns 模拟数据源实例\r\n */\r\n static createMockDataSource(config: Partial<MockDataSourceConfig> = {}): MockDataSource {\r\n return this.createDataSource({\r\n type: 'mock',\r\n config: {\r\n name: 'MockDataSource',\r\n ...config\r\n }\r\n }) as MockDataSource;\r\n }\r\n\r\n /**\r\n * 获取默认数据源实例\r\n * 根据环境自动选择合适的数据源\r\n */\r\n static createDefaultDataSource(): IDataSource {\r\n // 浏览器环境检测\r\n const isBrowser = typeof window !== 'undefined';\r\n\r\n // 安全的环境检测,避免 process is not defined 错误\r\n let isDevelopment = false;\r\n let isTest = false;\r\n let useMock = false;\r\n\r\n try {\r\n // 尝试访问 process.env,如果不存在则使用默认值\r\n if (typeof process !== 'undefined' && process.env) {\r\n isDevelopment = process.env.NODE_ENV === 'development';\r\n isTest = process.env.NODE_ENV === 'test';\r\n useMock = process.env.REACT_APP_USE_MOCK === 'true';\r\n } else {\r\n // 在浏览器环境中,默认使用 mock 数据源\r\n isDevelopment = true;\r\n useMock = true;\r\n }\r\n } catch (error) {\r\n // 如果访问 process.env 失败,使用默认配置\r\n console.warn('无法检测环境变量,使用默认配置:', error);\r\n isDevelopment = true;\r\n useMock = true;\r\n }\r\n\r\n // 开发环境、测试环境或明确配置使用 mock 时使用模拟数据源\r\n if (isDevelopment || isTest || useMock) {\r\n return this.createMockDataSource({\r\n name: 'DefaultMockDataSource',\r\n delay: 300\r\n });\r\n }\r\n\r\n // 生产环境使用API数据源\r\n return this.createApiDataSource({\r\n name: 'DefaultApiDataSource',\r\n baseURL: '/api/v1',\r\n token: isBrowser ? localStorage.getItem('authToken') || '' : ''\r\n });\r\n }\r\n\r\n /**\r\n * 清除所有数据源实例缓存\r\n */\r\n static clearCache(): void {\r\n this.instances.clear();\r\n console.log('[DataSourceFactory] 已清除所有数据源实例缓存');\r\n }\r\n\r\n /**\r\n * 获取缓存的实例数量\r\n */\r\n static getCachedInstanceCount(): number {\r\n return this.instances.size;\r\n }\r\n\r\n /**\r\n * 生成实例标识符\r\n */\r\n private static getInstanceKey(type: string, config: DataSourceConfig): string {\r\n return `${type}:${config.name}:${JSON.stringify(config)}`;\r\n }\r\n}\r\n\r\n/**\r\n * 创建数据源的快捷函数\r\n */\r\nexport function createDataSource(options: DataSourceFactoryOptions): IDataSource {\r\n return DataSourceFactory.createDataSource(options);\r\n}\r\n\r\n/**\r\n * 创建API数据源的快捷函数\r\n */\r\nexport function createApiDataSource(config: ApiDataSourceConfig): ApiDataSource {\r\n return DataSourceFactory.createApiDataSource(config);\r\n}\r\n\r\n/**\r\n * 创建模拟数据源的快捷函数\r\n */\r\nexport function createMockDataSource(config: Partial<MockDataSourceConfig> = {}): MockDataSource {\r\n return DataSourceFactory.createMockDataSource(config);\r\n}\r\n\r\n/**\r\n * 创建默认数据源的快捷函数\r\n */\r\nexport function createDefaultDataSource(): IDataSource {\r\n return DataSourceFactory.createDefaultDataSource();\r\n}","// 配置系统工具函数\r\nimport type {\r\n GradeUnitBrowserConfig,\r\n CreateConfigOptions,\r\n ConfigValidationResult,\r\n ConfigPreset,\r\n ConfigChangeEvent\r\n} from './types';\r\nimport { createDefaultDataSource } from '../data-sources/factory';\r\n\r\n/**\r\n * 创建 GradeUnitBrowser 配置\r\n * @param options 配置选项\r\n * @returns 完整的配置对象\r\n */\r\nexport function createGradeUnitBrowserConfig(\r\n options: CreateConfigOptions = {}\r\n): GradeUnitBrowserConfig {\r\n const {\r\n dataSource = createDefaultDataSource(),\r\n fallbackStrategy = 'mock',\r\n errorHandling = {},\r\n performance = {},\r\n theme = {},\r\n debug = false,\r\n enableDevTools = false\r\n } = options;\r\n\r\n const config: GradeUnitBrowserConfig = {\r\n dataSource,\r\n fallbackStrategy,\r\n errorHandling: {\r\n showUserFriendlyErrors: true,\r\n logErrors: true,\r\n autoRetry: true,\r\n maxRetries: 3,\r\n retryDelay: 1000,\r\n ...errorHandling\r\n },\r\n performance: {\r\n enableVirtualization: true,\r\n lazyLoadImages: true,\r\n debounceSearch: 300,\r\n enableCaching: true,\r\n cacheTTL: 300000, // 5分钟\r\n ...performance\r\n },\r\n theme: {\r\n primaryColor: '#1865f2',\r\n borderRadius: '8px',\r\n spacing: '16px',\r\n fontSize: '14px',\r\n enableDarkMode: false,\r\n ...theme\r\n },\r\n debug,\r\n enableDevTools\r\n };\r\n\r\n return config;\r\n}\r\n\r\n/**\r\n * 验证配置的有效性\r\n * @param config 要验证的配置\r\n * @returns 验证结果\r\n */\r\nexport function validateConfig(config: GradeUnitBrowserConfig): ConfigValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // 验证数据源\r\n if (!config.dataSource) {\r\n errors.push('数据源配置不能为空');\r\n } else {\r\n // 验证数据源接口方法\r\n const requiredMethods = [\r\n 'getUserGradeUnitsNav',\r\n 'getUserProfile',\r\n 'getExploreMenu',\r\n 'updateLessonProgress',\r\n 'batchUpdateLessonProgress'\r\n ];\r\n\r\n for (const method of requiredMethods) {\r\n if (typeof (config.dataSource as any)[method] !== 'function') {\r\n errors.push(`数据源缺少必需的方法: ${method}`);\r\n }\r\n }\r\n }\r\n\r\n // 验证fallback策略\r\n const validFallbackStrategies = ['error', 'mock', 'cached', 'none'];\r\n if (!validFallbackStrategies.includes(config.fallbackStrategy)) {\r\n errors.push(`无效的fallback策略: ${config.fallbackStrategy}`);\r\n }\r\n\r\n // 验证错误处理配置\r\n if (config.errorHandling.maxRetries < 0) {\r\n errors.push('最大重试次数不能为负数');\r\n }\r\n\r\n if (config.errorHandling.retryDelay < 0) {\r\n errors.push('重试延迟不能为负数');\r\n }\r\n\r\n // 验证性能配置\r\n if (config.performance.debounceSearch < 0) {\r\n errors.push('防抖时间不能为负数');\r\n }\r\n\r\n if (config.performance.cacheTTL < 0) {\r\n errors.push('缓存过期时间不能为负数');\r\n }\r\n\r\n // 验证主题配置\r\n if (!isValidColor(config.theme.primaryColor)) {\r\n warnings.push('主色调可能不是有效的颜色值');\r\n }\r\n\r\n // 开发环境警告\r\n if (config.debug && !config.enableDevTools) {\r\n warnings.push('调试模式已启用但开发工具未启用');\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n warnings\r\n };\r\n}\r\n\r\n/**\r\n * 合并配置\r\n * @param baseConfig 基础配置\r\n * @param overrideConfig 覆盖配置\r\n * @returns 合并后的配置\r\n */\r\nexport function mergeConfigs(\r\n baseConfig: GradeUnitBrowserConfig,\r\n overrideConfig: Partial<GradeUnitBrowserConfig>\r\n): GradeUnitBrowserConfig {\r\n return {\r\n ...baseConfig,\r\n ...overrideConfig,\r\n errorHandling: {\r\n ...baseConfig.errorHandling,\r\n ...overrideConfig.errorHandling\r\n },\r\n performance: {\r\n ...baseConfig.performance,\r\n ...overrideConfig.performance\r\n },\r\n theme: {\r\n ...baseConfig.theme,\r\n ...overrideConfig.theme\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * 获取预设配置\r\n * @param preset 预设类型\r\n * @returns 预设配置\r\n */\r\nexport function getPresetConfig(preset: ConfigPreset): GradeUnitBrowserConfig {\r\n switch (preset) {\r\n case 'development':\r\n return createGradeUnitBrowserConfig({\r\n debug: true,\r\n enableDevTools: true,\r\n fallbackStrategy: 'mock',\r\n errorHandling: {\r\n logErrors: true,\r\n autoRetry: true\r\n }\r\n });\r\n\r\n case 'production':\r\n return createGradeUnitBrowserConfig({\r\n debug: false,\r\n enableDevTools: false,\r\n fallbackStrategy: 'error',\r\n errorHandling: {\r\n showUserFriendlyErrors: true,\r\n logErrors: false,\r\n autoRetry: true,\r\n maxRetries: 2\r\n },\r\n performance: {\r\n enableVirtualization: true,\r\n lazyLoadImages: true,\r\n enableCaching: true\r\n }\r\n });\r\n\r\n case 'testing':\r\n return createGradeUnitBrowserConfig({\r\n debug: true,\r\n enableDevTools: false,\r\n fallbackStrategy: 'mock',\r\n errorHandling: {\r\n showUserFriendlyErrors: false,\r\n logErrors: true,\r\n autoRetry: false\r\n },\r\n performance: {\r\n enableVirtualization: false,\r\n lazyLoadImages: false,\r\n enableCaching: false\r\n }\r\n });\r\n\r\n case 'minimal':\r\n return createGradeUnitBrowserConfig({\r\n debug: false,\r\n enableDevTools: false,\r\n fallbackStrategy: 'none',\r\n errorHandling: {\r\n showUserFriendlyErrors: false,\r\n logErrors: false,\r\n autoRetry: false\r\n },\r\n performance: {\r\n enableVirtualization: false,\r\n lazyLoadImages: false,\r\n enableCaching: false\r\n },\r\n theme: {\r\n primaryColor: '#1865f2',\r\n borderRadius: '4px',\r\n spacing: '8px'\r\n }\r\n });\r\n\r\n default:\r\n return createGradeUnitBrowserConfig();\r\n }\r\n}\r\n\r\n/**\r\n * 克隆配置\r\n * @param config 要克隆的配置\r\n * @returns 克隆的配置\r\n */\r\nexport function cloneConfig(config: GradeUnitBrowserConfig): GradeUnitBrowserConfig {\r\n return JSON.parse(JSON.stringify(config));\r\n}\r\n\r\n/**\r\n * 检查颜色值是否有效\r\n * @param color 颜色值\r\n * @returns 是否有效\r\n */\r\nfunction isValidColor(color: string): boolean {\r\n const s = new Option().style;\r\n s.color = color;\r\n return s.color !== '';\r\n}\r\n\r\n/**\r\n * 配置变更监听器类型\r\n */\r\nexport type ConfigChangeListener = (event: ConfigChangeEvent) => void;\r\n\r\n/**\r\n * 配置管理器\r\n */\r\nexport class ConfigManager {\r\n private config: GradeUnitBrowserConfig;\r\n private listeners: ConfigChangeListener[] = [];\r\n\r\n constructor(initialConfig: GradeUnitBrowserConfig) {\r\n this.config = initialConfig;\r\n }\r\n\r\n /**\r\n * 获取当前配置\r\n */\r\n getConfig(): GradeUnitBrowserConfig {\r\n return { ...this.config };\r\n }\r\n\r\n /**\r\n * 更新配置\r\n * @param updates 配置更新\r\n */\r\n updateConfig(updates: Partial<GradeUnitBrowserConfig>): void {\r\n const oldConfig = { ...this.config };\r\n this.config = mergeConfigs(this.config, updates);\r\n\r\n // 触发变更事件\r\n this.triggerChangeEvents(oldConfig, this.config);\r\n }\r\n\r\n /**\r\n * 添加配置变更监听器\r\n * @param listener 监听器函数\r\n */\r\n addChangeListener(listener: ConfigChangeListener): void {\r\n this.listeners.push(listener);\r\n }\r\n\r\n /**\r\n * 移除配置变更监听器\r\n * @param listener 监听器函数\r\n */\r\n removeChangeListener(listener: ConfigChangeListener): void {\r\n const index = this.listeners.indexOf(listener);\r\n if (index > -1) {\r\n this.listeners.splice(index, 1);\r\n }\r\n }\r\n\r\n /**\r\n * 触发配置变更事件\r\n */\r\n private triggerChangeEvents(oldConfig: GradeUnitBrowserConfig, newConfig: GradeUnitBrowserConfig): void {\r\n const changedKeys = this.getChangedKeys(oldConfig, newConfig);\r\n\r\n for (const key of changedKeys) {\r\n const event: ConfigChangeEvent = {\r\n key,\r\n oldValue: (oldConfig as any)[key],\r\n newValue: (newConfig as any)[key],\r\n timestamp: Date.now()\r\n };\r\n\r\n this.listeners.forEach(listener => listener(event));\r\n }\r\n }\r\n\r\n /**\r\n * 获取变更的配置键\r\n */\r\n private getChangedKeys(oldConfig: any, newConfig: any): string[] {\r\n const keys = new Set([...Object.keys(oldConfig), ...Object.keys(newConfig)]);\r\n const changedKeys: string[] = [];\r\n\r\n for (const key of keys) {\r\n if (JSON.stringify(oldConfig[key]) !== JSON.stringify(newConfig[key])) {\r\n changedKeys.push(key);\r\n }\r\n }\r\n\r\n return changedKeys;\r\n }\r\n}","import React, { createContext, useContext, useState, useCallback, useEffect } from 'react';\r\nimport type { UserData, Lesson } from '../../types';\r\nimport { categoryIcons } from '../../types';\r\nimport type { ExploreItem } from '../../components/MathWizHeader/MathWizHeader.types';\r\nimport type { UserGradeUnitsProgressData } from '../../components/Sidebar/types';\r\nimport type { GradeUnitBrowserContextType, GradeUnitBrowserProviderProps } from './types';\r\nimport { courseData } from '../../data/courseData';\r\nimport { createGradeUnitBrowserConfig, mergeConfigs } from '../../config/utils';\r\nimport type { GradeUnitBrowserConfig } from '../../config/types';\r\n\r\n// 创建 Context\r\nexport const GradeUnitBrowserContext = createContext<GradeUnitBrowserContextType | null>(null);\r\n\r\nexport const useGradeUnitBrowser = () => {\r\n const context = useContext(GradeUnitBrowserContext);\r\n if (!context) {\r\n throw new Error('useGradeUnitBrowser must be used within GradeUnitBrowserProvider');\r\n }\r\n return context;\r\n};\r\n\r\n// Context Provider 组件\r\nexport const GradeUnitBrowserProvider: React.FC<GradeUnitBrowserProviderProps> = ({ children, config: providedConfig }) => {\r\n const [config, setConfig] = useState(() => createGradeUnitBrowserConfig(providedConfig));\r\n const [userInfo, setUserInfo] = useState<UserData | null>(null);\r\n const [exploreMenu, setExploreMenu] = useState<ExploreItem[]>([]);\r\n const [unitsData, setUnitsData] = useState<UserGradeUnitsProgressData | null>(null);\r\n const [lessons, setLessons] = useState<Record<string, Lesson[]>>({});\r\n const [loading, setLoading] = useState<boolean>(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [activeUnitId, setActiveUnitId] = useState<string | null>(null);\r\n const [activeLessonIds, setActiveLessonIds] = useState<string[]>([]);\r\n\r\n const loadPageData = useCallback(async (gradeId: string, userId: string) => {\r\n setLoading(true);\r\n setError(null);\r\n\r\n try {\r\n // 添加短暂延迟确保MSW已初始化\r\n // 在测试环境中移除延迟,避免异步问题\r\n if (process.env.NODE_ENV !== 'test') {\r\n await new Promise(resolve => setTimeout(resolve, 100));\r\n }\r\n\r\n // 使用配置的数据源获取数据\r\n const unitsData = await config.dataSource.getUserGradeUnitsNav(gradeId, userId);\r\n setUnitsData(unitsData);\r\n\r\n // 设置课程数据(从本地课程数据中获取)\r\n const lessonsData: Record<string, Lesson[]> = {};\r\n courseData.units.forEach(unit => {\r\n lessonsData[unit.id] = unit.lessons.map(lesson => ({\r\n id: lesson.id,\r\n title: lesson.title,\r\n duration: lesson.duration,\r\n knowledgeItems: lesson.knowledgeItems.map(item => ({\r\n ...item,\r\n progress: 0 // 添加默认进度值\r\n }))\r\n }));\r\n });\r\n console.log('Lessons data loaded:', lessonsData);\r\n setLessons(lessonsData);\r\n\r\n // 设置用户信息\r\n try {\r\n const userProfile = await config.dataSource.getUserProfile(userId);\r\n setUserInfo(userProfile);\r\n } catch (error) {\r\n console.warn('获取用户信息失败,使用默认数据:', error);\r\n setUserInfo({\r\n id: userId,\r\n name: '学生用户',\r\n level: 5,\r\n avatar: 'https://i.pravatar.cc/40',\r\n badges: ['🏆']\r\n });\r\n }\r\n\r\n // 设置探索菜单\r\n try {\r\n const exploreMenuData = await config.dataSource.getExploreMenu();\r\n setExploreMenu(exploreMenuData);\r\n } catch (error) {\r\n console.warn('获取探索菜单失败,使用默认数据:', error);\r\n setExploreMenu([\r\n { id: 'g5', label: '五年级', status: '进行中' },\r\n { id: 'g6', label: '六年级', status: 'new' }\r\n ]);\r\n }\r\n\r\n } catch (err) {\r\n console.error('数据加载错误:', err);\r\n\r\n // 根据fallback策略处理错误\r\n if (config.fallbackStrategy === 'mock') {\r\n console.log('使用mock数据作为fallback');\r\n // 使用courseData生成mock数据作为fallback\r\n const mockUnitsData = {\r\n userId: userId,\r\n courseId: gradeId,\r\n courseTitle: '小学数学五年级',\r\n courseLevel: 5,\r\n totalUnits: courseData.units.length,\r\n completedUnits: 2,\r\n overallProgress: 22,\r\n status: 'in-progress' as const,\r\n lastAccessed: new Date().toISOString(),\r\n units: courseData.units.map((unit, index) => ({\r\n unitId: unit.id,\r\n title: unit.title,\r\n description: unit.description,\r\n moduleCategory: unit.moduleCategory,\r\n estimatedDuration: unit.estimatedDuration,\r\n totalLessons: unit.lessons.length,\r\n completedLessons: index < 2 ? Math.floor(unit.lessons.length * 0.5) : 0,\r\n progressPercentage: index < 2 ? 50 : 0,\r\n status: index < 2 ? 'in-progress' as const : 'not-started' as const,\r\n lastAccessed: index < 2 ? new Date().toISOString() : undefined,\r\n isActive: index === 0,\r\n route: `/math/grade-5/unit/${unit.id}`,\r\n icon: categoryIcons[unit.moduleCategory] || categoryIcons.Default\r\n }))\r\n };\r\n setUnitsData(mockUnitsData);\r\n\r\n // 设置课程数据\r\n const lessonsData: Record<string, Lesson[]> = {};\r\n courseData.units.forEach(unit => {\r\n lessonsData[unit.id] = unit.lessons.map(lesson => ({\r\n id: lesson.id,\r\n title: lesson.title,\r\n duration: lesson.duration,\r\n knowledgeItems: lesson.knowledgeItems.map(item => ({\r\n ...item,\r\n progress: 0\r\n }))\r\n }));\r\n });\r\n setLessons(lessonsData);\r\n\r\n // 设置默认用户信息和探索菜单\r\n setUserInfo({\r\n id: userId,\r\n name: '学生用户',\r\n level: 5,\r\n avatar: 'https://i.pravatar.cc/40',\r\n badges: ['🏆']\r\n });\r\n setExploreMenu([\r\n { id: 'g5', label: '五年级', status: '进行中' },\r\n { id: 'g6', label: '六年级', status: 'new' }\r\n ]);\r\n } else {\r\n // 其他fallback策略:显示错误\r\n setError(err instanceof Error ? err.message : '数据加载失败');\r\n setUnitsData(null);\r\n }\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [config]);\r\n\r\n const toggleLesson = useCallback((lessonId: string) => {\r\n setActiveLessonIds(prev =>\r\n prev.includes(lessonId)\r\n ? prev.filter(id => id !== lessonId)\r\n : [...prev, lessonId]\r\n );\r\n }, []);\r\n\r\n // 包装setActiveUnit函数,接受unitId参数(可为null)\r\n const setActiveUnit = useCallback((unitId: string | null) => {\r\n setActiveUnitId(unitId);\r\n }, []);\r\n\r\n // 更新配置\r\n const updateConfig = useCallback((updates: Partial<GradeUnitBrowserConfig>) => {\r\n setConfig(prevConfig => mergeConfigs(prevConfig, updates));\r\n }, []);\r\n\r\n // 状态更新后执行默认单元选择\r\n useEffect(() => {\r\n console.log('unitsData state updated:', unitsData);\r\n console.log('unitsData?.units:', unitsData?.units);\r\n console.log('unitsData?.units?.length:', unitsData?.units?.length);\r\n\r\n if (unitsData && unitsData.units.length > 0) {\r\n console.log('Looking for active unit...');\r\n const activeUnit = unitsData.units.find(unit => unit.isActive);\r\n console.log('Found active unit:', activeUnit);\r\n const defaultActiveUnit = activeUnit?.unitId || unitsData.units[0].unitId;\r\n console.log('Setting default active unit:', defaultActiveUnit);\r\n setActiveUnitId(defaultActiveUnit);\r\n console.log('Default active unit set after state update:', defaultActiveUnit);\r\n } else {\r\n console.log('No units data available for setting default active unit');\r\n }\r\n }, [unitsData]);\r\n\r\n const contextValue: GradeUnitBrowserContextType = {\r\n // 数据状态\r\n userInfo,\r\n exploreMenu,\r\n unitsData,\r\n lessons,\r\n\r\n // UI状态\r\n loading,\r\n error,\r\n activeUnitId,\r\n activeLessonIds,\r\n\r\n // 配置状态\r\n config,\r\n theme: config.theme,\r\n enableVirtualization: config.performance?.enableVirtualization,\r\n\r\n // Actions\r\n setLoading,\r\n setError,\r\n setActiveUnit,\r\n toggleLesson,\r\n loadPageData,\r\n updateConfig\r\n };\r\n\r\n return (\r\n <GradeUnitBrowserContext.Provider value={contextValue}>\r\n {children}\r\n </GradeUnitBrowserContext.Provider>\r\n );\r\n};","import React, { useEffect } from 'react';\r\nimport MathWizHeader from '../../components/MathWizHeader/MathWizHeader';\r\nimport { Sidebar } from '../../components/Sidebar/Sidebar';\r\nimport { ContentAccordion } from '../../components/ContentAccordion/ContentAccordion';\r\nimport { GradeUnitBrowserProvider, useGradeUnitBrowser } from './GradeUnitBrowserContext';\r\nimport type { GradeUnitBrowserPageProps } from './types';\r\nimport './GradeUnitBrowserPage.css';\r\n\r\n// 内部页面组件(使用Context)\r\nconst GradeUnitBrowserPageContent: React.FC<GradeUnitBrowserPageProps> = ({\r\n gradeId,\r\n userId,\r\n onLearnAction,\r\n className,\r\n userInfo: propUserInfo,\r\n exploreMenu: propExploreMenu\r\n}) => {\r\n const {\r\n userInfo: contextUserInfo,\r\n exploreMenu: contextExploreMenu,\r\n unitsData,\r\n lessons,\r\n loading,\r\n error,\r\n activeUnitId,\r\n activeLessonIds,\r\n setActiveUnit,\r\n toggleLesson,\r\n loadPageData\r\n } = useGradeUnitBrowser();\r\n\r\n // 使用props中的值或context中的值\r\n const userInfo = propUserInfo ?? contextUserInfo;\r\n const exploreMenu = propExploreMenu ?? contextExploreMenu;\r\n\r\n useEffect(() => {\r\n console.log('GradeUnitBrowserPageContent: useEffect triggered, calling loadPageData');\r\n console.log('gradeId:', gradeId, 'userId:', userId);\r\n loadPageData(gradeId, userId);\r\n }, [gradeId, userId, loadPageData]);\r\n\r\n // 调试日志\r\n useEffect(() => {\r\n console.log('activeUnitId from context:', activeUnitId);\r\n console.log('lessons from context:', lessons);\r\n\r\n // 重新计算 activeUnit 用于调试\r\n const activeUnitNav = unitsData?.units?.find(unit => unit.unitId === activeUnitId) || null;\r\n const debugActiveUnit = activeUnitNav && activeUnitId && lessons[activeUnitId] ? {\r\n id: activeUnitNav.unitId,\r\n title: activeUnitNav.title,\r\n description: activeUnitNav.description,\r\n estimatedDuration: activeUnitNav.estimatedDuration,\r\n totalLessons: activeUnitNav.totalLessons,\r\n moduleCategory: activeUnitNav.moduleCategory,\r\n lessons: lessons[activeUnitId]\r\n } : null;\r\n\r\n console.log('activeUnit computed:', debugActiveUnit);\r\n }, [activeUnitId, lessons, unitsData]);\r\n\r\n // 获取当前激活的单元\r\n const activeUnitNav = unitsData?.units?.find(unit => unit.unitId === activeUnitId) || null;\r\n\r\n // 获取完整的单元数据(包含课程和知识点)\r\n const activeUnit = activeUnitNav && activeUnitId && lessons[activeUnitId] ? {\r\n id: activeUnitNav.unitId,\r\n title: activeUnitNav.title,\r\n description: activeUnitNav.description,\r\n estimatedDuration: activeUnitNav.estimatedDuration,\r\n totalLessons: activeUnitNav.totalLessons,\r\n moduleCategory: activeUnitNav.moduleCategory,\r\n lessons: lessons[activeUnitId]\r\n } : null;\r\n\r\n if (loading) {\r\n return (\r\n <div className={`grade-unit-browser-page loading ${className || ''}`} data-testid=\"grade-unit-browser-page\">\r\n <div className=\"loading-spinner\" data-testid=\"loading-spinner\">\r\n 加载中...\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div className={`grade-unit-browser-page error ${className || ''}`} data-testid=\"grade-unit-browser-page\">\r\n <div className=\"error-message\" data-testid=\"error-message\">\r\n {error}\r\n </div>\r\n <button\r\n onClick={() => loadPageData(gradeId, userId)}\r\n className=\"retry-button\"\r\n >\r\n 重试\r\n </button>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n className={`grade-unit-browser-page ${className || ''}`}\r\n data-testid=\"grade-unit-browser-page\"\r\n >\r\n {/* Header 区域 */}\r\n <div className=\"header-area\">\r\n <MathWizHeader\r\n userData={userInfo || undefined}\r\n exploreItems={exploreMenu}\r\n />\r\n </div>\r\n\r\n {/* Sidebar 区域 */}\r\n <div className=\"sidebar-area\">\r\n <Sidebar\r\n data={unitsData}\r\n activeUnitId={activeUnitId}\r\n onUnitSelect={setActiveUnit}\r\n loading={loading}\r\n />\r\n </div>\r\n\r\n {/* 主内容区域 */}\r\n <div className=\"content-area\">\r\n <ContentAccordion\r\n unit={activeUnit}\r\n activeLessonIds={activeLessonIds}\r\n onToggleLesson={toggleLesson}\r\n onLearnAction={onLearnAction || (() => { })}\r\n loading={loading}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n// 主页面组件(包装Provider)\r\nexport const GradeUnitBrowserPage: React.FC<GradeUnitBrowserPageProps> = (props) => {\r\n return (\r\n <GradeUnitBrowserProvider config={props.config}>\r\n <GradeUnitBrowserPageContent {...props} />\r\n </GradeUnitBrowserProvider>\r\n );\r\n};","import { create } from 'zustand';\r\nimport { useShallow } from 'zustand/react/shallow';\r\nimport type { MathPracticeSessionStore, MathPracticeProblemData, AnswerValidationResult } from './MathPracticeSessionTypes';\r\n\r\n/**\r\n * 答案验证工具函数\r\n */\r\nconst validateAnswer = (\r\n userAnswer: string,\r\n correctAnswer: number,\r\n tolerance: number = 0.1\r\n): AnswerValidationResult => {\r\n // 1. 检查是否为空\r\n if (!userAnswer.trim()) {\r\n return {\r\n isValid: false,\r\n isCorrect: false,\r\n errorMessage: '请输入答案'\r\n };\r\n }\r\n\r\n // 2. 检查是否为有效数字\r\n const userAnswerNum = parseFloat(userAnswer);\r\n if (isNaN(userAnswerNum)) {\r\n return {\r\n isValid: false,\r\n isCorrect: false,\r\n errorMessage: '请输入有效的数字'\r\n };\r\n }\r\n\r\n // 3. 检查是否为负数(如果问题不允许负数)\r\n if (userAnswerNum < 0) {\r\n return {\r\n isValid: false,\r\n isCorrect: false,\r\n errorMessage: '答案不能为负数'\r\n };\r\n }\r\n\r\n // 4. 数值比较(考虑容差)\r\n const difference = Math.abs(userAnswerNum - correctAnswer);\r\n const isCorrect = difference <= tolerance;\r\n\r\n return {\r\n isValid: true,\r\n isCorrect,\r\n errorMessage: isCorrect ? undefined : `答案不正确,请再试一次`\r\n };\r\n};\r\n\r\n/**\r\n * 创建数学练习会话状态管理 Store 的工厂函数\r\n * 管理三场景流程:问题场景 → 解释场景/成功场景 → 重置\r\n * 每个调用返回独立的 store 实例,支持 Storybook 多故事状态隔离\r\n */\r\nexport const createMathPracticeStore = () => {\r\n return create<MathPracticeSessionStore>((set, get) => ({\r\n // 初始状态\r\n currentScene: 'question',\r\n userAnswer: '',\r\n isCorrect: null,\r\n showAnswerForm: true,\r\n problemData: null,\r\n validationError: null,\r\n\r\n // 设置问题数据\r\n setProblemData: (problemData: MathPracticeProblemData) => {\r\n set({\r\n problemData,\r\n currentScene: 'question',\r\n userAnswer: '',\r\n isCorrect: null,\r\n showAnswerForm: true,\r\n validationError: null\r\n });\r\n },\r\n\r\n // 更新用户答案(输入时)\r\n updateUserAnswer: (answer: string) => {\r\n set({\r\n userAnswer: answer,\r\n validationError: null // 清除之前的错误信息\r\n });\r\n },\r\n\r\n // 提交答案\r\n submitAnswer: (answer: string) => {\r\n const state = get(); // 使用 get() 获取当前 store 实例状态\r\n\r\n // 检查是否有问题数据\r\n if (!state.problemData) {\r\n set({\r\n validationError: '问题数据未加载,请刷新页面重试'\r\n });\r\n return;\r\n }\r\n\r\n // 获取正确答案 - 优先使用answer_info.value,回退到answer.value\r\n const correctAnswer = state.problemData.answer_info?.value ?? state.problemData.answer.value;\r\n\r\n // 确保是数字类型\r\n const correctAnswerNum = Number(correctAnswer);\r\n\r\n // 验证答案 - 使用数据中的容差或默认值0.1\r\n const tolerance = state.problemData.answer_info?.tolerance ?? 0.1;\r\n const validationResult = validateAnswer(answer, correctAnswerNum, tolerance);\r\n\r\n if (!validationResult.isValid) {\r\n // 验证失败,显示错误信息\r\n set({\r\n userAnswer: answer,\r\n validationError: validationResult.errorMessage || '答案格式错误'\r\n });\r\n return;\r\n }\r\n\r\n // 验证成功,更新状态\r\n set({\r\n userAnswer: answer,\r\n isCorrect: validationResult.isCorrect,\r\n showAnswerForm: false,\r\n validationError: null,\r\n currentScene: validationResult.isCorrect ? 'success' : 'explanation'\r\n });\r\n },\r\n\r\n // 下一题\r\n nextQuestion: () => {\r\n set({\r\n currentScene: 'question',\r\n userAnswer: '',\r\n isCorrect: null,\r\n showAnswerForm: true,\r\n validationError: null\r\n });\r\n },\r\n\r\n // 重置会话\r\n resetSession: () => {\r\n set({\r\n currentScene: 'question',\r\n userAnswer: '',\r\n isCorrect: null,\r\n showAnswerForm: true,\r\n validationError: null\r\n });\r\n }\r\n }));\r\n};\r\n\r\n/**\r\n * 全局数学练习会话状态管理 Store\r\n * 向后兼容的全局单例 store,用于现有组件\r\n * 注意:在 Storybook 环境中,所有故事共享此全局 store 实例\r\n */\r\nexport const useMathPracticeSessionStore = createMathPracticeStore();\r\n\r\n/**\r\n * 自定义 Hook - 获取当前场景的状态\r\n */\r\nexport const useCurrentScene = () => {\r\n return useMathPracticeSessionStore((state) => state.currentScene);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取用户答案\r\n */\r\nexport const useUserAnswer = () => {\r\n return useMathPracticeSessionStore((state) => state.userAnswer);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取答案正确性\r\n */\r\nexport const useAnswerCorrectness = () => {\r\n return useMathPracticeSessionStore((state) => state.isCorrect);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取答案表单显示状态\r\n */\r\nexport const useAnswerFormVisibility = () => {\r\n return useMathPracticeSessionStore((state) => state.showAnswerForm);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取验证错误信息\r\n */\r\nexport const useValidationError = () => {\r\n return useMathPracticeSessionStore((state) => state.validationError);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取问题数据\r\n */\r\nexport const useProblemData = () => {\r\n return useMathPracticeSessionStore((state) => state.problemData);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取会话操作方法\r\n * 在 Zustand 中,action 函数是稳定引用,直接选择它们不会导致重渲染\r\n */\r\nexport const useSessionActions = () =>\r\n useMathPracticeSessionStore(\r\n useShallow<MathPracticeSessionStore, Pick<\r\n MathPracticeSessionStore,\r\n 'updateUserAnswer' | 'submitAnswer' | 'nextQuestion' | 'resetSession' | 'setProblemData'\r\n >>((state) => ({\r\n updateUserAnswer: state.updateUserAnswer,\r\n submitAnswer: state.submitAnswer,\r\n nextQuestion: state.nextQuestion,\r\n resetSession: state.resetSession,\r\n setProblemData: state.setProblemData\r\n }))\r\n );","import React, { createContext, useContext, useMemo } from 'react';\r\nimport { useShallow } from 'zustand/react/shallow';\r\nimport type { MathPracticeSessionStore } from './MathPracticeSessionTypes';\r\nimport { createMathPracticeStore } from './MathPracticeSessionStore';\r\n\r\n// Store hook 类型:既能作为 selector 函数调用,又能直接访问 store 方法\r\ntype StoreHook = {\r\n // 作为函数调用:接受 selector 函数并返回选中的状态\r\n <T>(selector: (state: MathPracticeSessionStore) => T): T;\r\n // 直接访问 store 方法\r\n setState: (partial: Partial<MathPracticeSessionStore> | ((state: MathPracticeSessionStore) => Partial<MathPracticeSessionStore>)) => void;\r\n getState: () => MathPracticeSessionStore;\r\n};\r\n\r\n/**\r\n * Store Context 用于提供独立的 store 实例\r\n * 每个 Provider 层提供独立的 store,支持 Storybook 多故事状态隔离\r\n */\r\nconst MathPracticeStoreContext = createContext<StoreHook | null>(null);\r\n\r\n/**\r\n * Store Provider 组件\r\n * 为子组件提供独立的数学练习会话 store 实例\r\n *\r\n * @param children - 子组件\r\n * @param createStore - 可选的 store 创建函数,用于自定义 store 配置\r\n */\r\nexport const MathPracticeStoreProvider: React.FC<{\r\n children: React.ReactNode;\r\n createStore?: () => StoreHook;\r\n}> = ({ children, createStore }) => {\r\n // 创建独立的 store 实例并包装为 StoreHook 类型\r\n const store = useMemo((): StoreHook => {\r\n const rawStore = createStore ? createStore() : createMathPracticeStore();\r\n\r\n // 包装为 StoreHook 类型\r\n const storeHook = ((selector: any) => rawStore(selector)) as StoreHook;\r\n\r\n // 添加 setState 和 getState 方法\r\n storeHook.setState = (partial: any) => {\r\n if (typeof rawStore.setState === 'function') {\r\n rawStore.setState(partial);\r\n }\r\n };\r\n\r\n storeHook.getState = () => {\r\n if (typeof rawStore.getState === 'function') {\r\n return rawStore.getState();\r\n }\r\n // 如果没有 getState 方法,尝试通过 selector 获取\r\n return rawStore((state: any) => state);\r\n };\r\n\r\n return storeHook;\r\n }, [createStore]);\r\n\r\n return (\r\n <MathPracticeStoreContext.Provider value={store}>\r\n {children}\r\n </MathPracticeStoreContext.Provider>\r\n );\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 使用独立 store 实例\r\n * 必须用在 MathPracticeStoreProvider 内部\r\n *\r\n * @returns 独立的 store 实例\r\n */\r\nexport const useMathPracticeStore = () => {\r\n const store = useContext(MathPracticeStoreContext);\r\n if (!store) {\r\n throw new Error('useMathPracticeStore 必须在 MathPracticeStoreProvider 内部使用');\r\n }\r\n return store;\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取当前场景的状态(使用独立 store)\r\n */\r\nexport const useCurrentSceneFromStore = () => {\r\n const store = useMathPracticeStore();\r\n const selector = React.useCallback((state: MathPracticeSessionStore) => state.currentScene, []);\r\n return store(selector);\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取用户答案(使用独立 store)\r\n */\r\nexport const useUserAnswerFromStore = () => {\r\n const store = useMathPracticeStore();\r\n const selector = React.useCallback((state: MathPracticeSessionStore) => state.userAnswer, []);\r\n return store(selector);\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取答案正确性(使用独立 store)\r\n */\r\nexport const useAnswerCorrectnessFromStore = () => {\r\n const store = useMathPracticeStore();\r\n const selector = React.useCallback((state: MathPracticeSessionStore) => state.isCorrect, []);\r\n return store(selector);\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取答案表单显示状态(使用独立 store)\r\n */\r\nexport const useAnswerFormVisibilityFromStore = () => {\r\n const store = useMathPracticeStore();\r\n const selector = React.useCallback((state: MathPracticeSessionStore) => state.showAnswerForm, []);\r\n return store(selector);\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取验证错误信息(使用独立 store)\r\n */\r\nexport const useValidationErrorFromStore = () => {\r\n const store = useMathPracticeStore();\r\n const selector = React.useCallback((state: MathPracticeSessionStore) => state.validationError, []);\r\n return store(selector);\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取问题数据(使用独立 store)\r\n */\r\nexport const useProblemDataFromStore = () => {\r\n const store = useMathPracticeStore();\r\n const selector = React.useCallback((state: MathPracticeSessionStore) => state.problemData, []);\r\n return store(selector);\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取会话操作方法(使用独立 store)\r\n * 使用 useShallow 避免不必要的重渲染\r\n */\r\nexport const useSessionActionsFromStore = () => {\r\n const store = useMathPracticeStore();\r\n return store(\r\n useShallow((state: MathPracticeSessionStore) => ({\r\n updateUserAnswer: state.updateUserAnswer,\r\n submitAnswer: state.submitAnswer,\r\n nextQuestion: state.nextQuestion,\r\n resetSession: state.resetSession,\r\n setProblemData: state.setProblemData\r\n }))\r\n );\r\n};","import {\r\n useCurrentScene as useGlobalCurrentScene,\r\n useUserAnswer as useGlobalUserAnswer,\r\n useAnswerCorrectness as useGlobalAnswerCorrectness,\r\n useAnswerFormVisibility as useGlobalAnswerFormVisibility,\r\n useValidationError as useGlobalValidationError,\r\n useProblemData as useGlobalProblemData,\r\n useSessionActions as useGlobalSessionActions,\r\n useMathPracticeSessionStore as useGlobalStore\r\n} from './MathPracticeSessionStore';\r\n\r\nimport {\r\n useCurrentSceneFromStore,\r\n useUserAnswerFromStore,\r\n useAnswerCorrectnessFromStore,\r\n useAnswerFormVisibilityFromStore,\r\n useValidationErrorFromStore,\r\n useProblemDataFromStore,\r\n useSessionActionsFromStore,\r\n useMathPracticeStore\r\n} from './MathPracticeStoreContext';\r\n\r\n/**\r\n * 兼容性 Hook - 获取当前场景的状态\r\n * 优先使用独立 store(如果在 Provider 内部),否则回退到全局 store\r\n */\r\nexport const useCurrentScene = () => {\r\n try {\r\n // 尝试使用独立 store\r\n return useCurrentSceneFromStore();\r\n } catch (error) {\r\n // 回退到全局 store\r\n return useGlobalCurrentScene();\r\n }\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取用户答案\r\n * 优先使用独立 store(如果在 Provider 内部),否则回退到全局 store\r\n */\r\nexport const useUserAnswer = () => {\r\n try {\r\n return useUserAnswerFromStore();\r\n } catch (error) {\r\n return useGlobalUserAnswer();\r\n }\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取答案正确性\r\n * 优先使用独立 store(如果在 Provider 内部),否则回退到全局 store\r\n */\r\nexport const useAnswerCorrectness = () => {\r\n try {\r\n return useAnswerCorrectnessFromStore();\r\n } catch (error) {\r\n return useGlobalAnswerCorrectness();\r\n }\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取答案表单显示状态\r\n * 优先使用独立 store(如果在 Provider 内部),否则回退到全局 store\r\n */\r\nexport const useAnswerFormVisibility = () => {\r\n try {\r\n return useAnswerFormVisibilityFromStore();\r\n } catch (error) {\r\n return useGlobalAnswerFormVisibility();\r\n }\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取验证错误信息\r\n * 优先使用独立 store(如果在 Provider 内部),否则回退到全局 store\r\n */\r\nexport const useValidationError = () => {\r\n try {\r\n return useValidationErrorFromStore();\r\n } catch (error) {\r\n return useGlobalValidationError();\r\n }\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取问题数据\r\n * 优先使用独立 store(如果在 Provider 内部),否则回退到全局 store\r\n */\r\nexport const useProblemData = () => {\r\n try {\r\n return useProblemDataFromStore();\r\n } catch (error) {\r\n return useGlobalProblemData();\r\n }\r\n};\r\n\r\n/**\r\n * 兼容性 Hook - 获取会话操作方法\r\n * 优先使用独立 store(如果在 Provider 内部),否则回退到全局 store\r\n * 使用 useShallow 避免不必要的重渲染\r\n */\r\nexport const useSessionActions = () => {\r\n try {\r\n return useSessionActionsFromStore();\r\n } catch (error) {\r\n return useGlobalSessionActions();\r\n }\r\n};\r\n\r\n/**\r\n * 辅助 Hook - 检查是否在 MathPracticeStoreProvider 内部\r\n */\r\nexport const useIsInStoreProvider = () => {\r\n try {\r\n useMathPracticeStore();\r\n return true;\r\n } catch (error) {\r\n return false;\r\n }\r\n};\r\n\r\n/**\r\n * 辅助 Hook - 安全地获取 store 实例\r\n * 优先返回独立 store,如果不在 Provider 内部则返回全局 store\r\n */\r\nexport const useStoreInstance = () => {\r\n try {\r\n return useMathPracticeStore();\r\n } catch (error) {\r\n return useGlobalStore();\r\n }\r\n};","import React from 'react';\r\nimport { MathCardV2 } from '../../MathCardV2';\r\nimport { Button } from '../../../Button/Button';\r\nimport type { QuestionSceneProps } from '../../MathPracticeSessionTypes';\r\nimport './QuestionScene.css';\r\n\r\n/**\r\n * 问题场景组件\r\n * 展示数学问题和答案输入表单\r\n */\r\nexport const QuestionScene: React.FC<QuestionSceneProps> = ({\r\n problemData,\r\n userAnswer,\r\n showAnswerForm,\r\n onAnswerSubmit,\r\n onAnswerChange,\r\n validationError\r\n}) => {\r\n const handleSubmit = (e: React.FormEvent) => {\r\n e.preventDefault();\r\n onAnswerSubmit(userAnswer);\r\n };\r\n\r\n const handleAnswerChange = (value: string) => {\r\n onAnswerChange(value);\r\n };\r\n\r\n return (\r\n <div className=\"question-scene-container\">\r\n <div className=\"question-scene-card\">\r\n {/* 问题展示 */}\r\n <div className=\"question-display-area\">\r\n <MathCardV2\r\n data={{\r\n id: problemData.id,\r\n grade: problemData.grade,\r\n unit: problemData.unit,\r\n content: problemData.scenes?.question?.items || // 新标准优先\r\n problemData.scenes?.question?.content || // 旧标准回退\r\n []\r\n }}\r\n scene=\"question\"\r\n layout={{ type: 'card', padding: '0px', shadow: false, border: false }}\r\n />\r\n </div>\r\n\r\n {/* 答案输入表单 */}\r\n {showAnswerForm && (\r\n <div className=\"answer-form-container\">\r\n <form\r\n onSubmit={handleSubmit}\r\n className=\"answer-form\"\r\n >\r\n <label className=\"answer-label\">\r\n 答案\r\n </label>\r\n <input\r\n type=\"number\"\r\n value={userAnswer}\r\n onChange={(e) => handleAnswerChange(e.target.value)}\r\n className={`answer-input ${validationError ? 'error' : 'normal'}`}\r\n placeholder=\"?\"\r\n required\r\n />\r\n <span className=\"answer-unit\">\r\n {problemData.basicInfo.answerUnit || problemData.basicInfo.areaUnit}\r\n </span>\r\n <Button\r\n type=\"submit\"\r\n size=\"lg\"\r\n className=\"submit-button\"\r\n >\r\n 提交答案\r\n </Button>\r\n </form>\r\n {validationError && (\r\n <div className=\"validation-error\">\r\n <span>⚠️</span>\r\n <span>{validationError}</span>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport { MathCardV2 } from '../../MathCardV2';\r\nimport { IXLStyleCard } from '../../../IXLStyleCard/IXLStyleCard';\r\nimport type { RememberModuleProps } from '../../MathPracticeSessionTypes';\r\nimport type { FormulaContentBlock } from '../../MathCardV2.types';\r\nimport './RememberModule.css';\r\n\r\n/**\r\n * 记忆模块组件\r\n * 蓝色主题,强化核心概念和公式记忆\r\n * 通用组件,适配不同数据源中的review内容\r\n */\r\nexport const RememberModule: React.FC<RememberModuleProps> = ({\r\n problemData,\r\n enableIXLStyle = true\r\n}) => {\r\n console.log('🔍 RememberModule problemData:', problemData);\r\n console.log('🔍 RememberModule scenes.remember:', problemData?.scenes?.remember);\r\n console.log('🔍 RememberModule scenes.remember.items:', problemData?.scenes?.remember?.items);\r\n console.log('🔍 RememberModule scenes.remember.content:', problemData?.scenes?.remember?.content);\r\n // 从数据中获取review内容,兼容remember和review两种场景\r\n // 修复:只有当review有实际内容时才优先使用review,否则使用remember\r\n const getContentWithFallback = () => {\r\n // 检查review.items是否有内容\r\n const reviewItems = problemData.scenes?.review?.items;\r\n if (reviewItems && Array.isArray(reviewItems) && reviewItems.length > 0) {\r\n console.log('🔍 RememberModule 使用 review.items');\r\n return reviewItems;\r\n }\r\n\r\n // 检查review.content是否有内容\r\n const reviewContent = problemData.scenes?.review?.content;\r\n if (reviewContent && Array.isArray(reviewContent) && reviewContent.length > 0) {\r\n console.log('🔍 RememberModule 使用 review.content');\r\n return reviewContent;\r\n }\r\n\r\n // 检查remember.items是否有内容\r\n const rememberItems = problemData.scenes?.remember?.items;\r\n if (rememberItems && Array.isArray(rememberItems) && rememberItems.length > 0) {\r\n console.log('🔍 RememberModule 使用 remember.items');\r\n return rememberItems;\r\n }\r\n\r\n // 检查remember.content是否有内容\r\n const rememberContent = problemData.scenes?.remember?.content;\r\n if (rememberContent && Array.isArray(rememberContent) && rememberContent.length > 0) {\r\n console.log('🔍 RememberModule 使用 remember.content');\r\n return rememberContent;\r\n }\r\n\r\n console.log('🔍 RememberModule 未找到任何内容');\r\n return [];\r\n };\r\n\r\n const reviewContent = getContentWithFallback();\r\n\r\n // 如果没有review内容,显示默认提示\r\n if (reviewContent.length === 0) {\r\n const emptyContent = (\r\n <div className=\"remember-module-content\">\r\n <p className=\"remember-module-empty\">暂无记忆内容</p>\r\n </div>\r\n );\r\n\r\n if (enableIXLStyle) {\r\n return (\r\n <IXLStyleCard\r\n wrapperMode=\"generic\"\r\n ixlConfig={{ type: 'remember', label: '速记', showTag: true }}\r\n enableIXLStyle={true}\r\n >\r\n {emptyContent}\r\n </IXLStyleCard>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"remember-module-container\">\r\n <h4 className=\"remember-module-title\">\r\n 记忆\r\n </h4>\r\n {emptyContent}\r\n </div>\r\n );\r\n }\r\n\r\n // 渲染内容区域\r\n const contentArea = (\r\n <div className=\"remember-module-content\">\r\n {/* 动态渲染review内容 */}\r\n {reviewContent.map((contentBlock, index) => {\r\n const { type, content, style, parts } = contentBlock as any;\r\n\r\n switch (type) {\r\n case 'text':\r\n return (\r\n <p\r\n key={index}\r\n className=\"remember-module-text-block\"\r\n style={style}\r\n >\r\n {content}\r\n </p>\r\n );\r\n\r\n case 'formula':\r\n return (\r\n <div key={index} className=\"remember-module-formula-block\">\r\n <MathCardV2\r\n data={{\r\n id: `formula-${index}`,\r\n grade: problemData.grade,\r\n unit: problemData.unit,\r\n content: [\r\n {\r\n type: 'formula',\r\n content,\r\n parts: parts || [content]\r\n } as FormulaContentBlock\r\n ]\r\n }}\r\n layout={{ type: 'card' }}\r\n className={enableIXLStyle ? 'ixl-adjusted' : ''}\r\n />\r\n </div>\r\n );\r\n\r\n default:\r\n return (\r\n <p key={index} className=\"remember-module-unsupported\">\r\n 不支持的内容类型: {type}\r\n </p>\r\n );\r\n }\r\n })}\r\n </div>\r\n );\r\n\r\n if (enableIXLStyle) {\r\n return (\r\n <IXLStyleCard\r\n wrapperMode=\"generic\"\r\n ixlConfig={{ type: 'remember', label: '速记', showTag: true }}\r\n enableIXLStyle={true}\r\n >\r\n {contentArea}\r\n </IXLStyleCard>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"remember-module-container\">\r\n {/* 模块标题 */}\r\n <h4 className=\"remember-module-title\">\r\n 记忆\r\n </h4>\r\n {contentArea}\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport { MathCardV2 } from '../../MathCardV2';\r\nimport { IXLStyleCard } from '../../../IXLStyleCard/IXLStyleCard';\r\nimport type { ReviewModuleProps } from '../../MathPracticeSessionTypes';\r\nimport './ReviewModule.css';\r\n\r\n/**\r\n * 复习模块组件\r\n * 黄色主题,显示原始问题和用户错误答案\r\n */\r\nexport const ReviewModule: React.FC<ReviewModuleProps> = ({\r\n problemData,\r\n userAnswer,\r\n enableIXLStyle = true\r\n}) => {\r\n // 渲染内容区域\r\n const contentArea = (\r\n <div className=\"review-module-content\">\r\n {/* 原始问题 */}\r\n <p className=\"review-module-question\">\r\n {problemData.basicInfo.question}\r\n </p>\r\n\r\n {/* 问题图形 */}\r\n <div className=\"review-module-graph\">\r\n <MathCardV2\r\n data={{\r\n id: 'review-problem',\r\n grade: problemData.grade,\r\n unit: problemData.unit,\r\n content: problemData.scenes?.question?.items || // 新标准优先\r\n problemData.scenes?.question?.content || // 旧标准回退\r\n []\r\n }}\r\n scene=\"question\"\r\n layout={{ type: 'card' }}\r\n className={enableIXLStyle ? 'ixl-adjusted' : ''}\r\n />\r\n </div>\r\n\r\n {/* 用户答案显示 */}\r\n <p className=\"review-module-user-answer\">\r\n 你的答案: <span className=\"review-module-user-answer-value\">\r\n {userAnswer}\r\n </span>\r\n </p>\r\n </div>\r\n );\r\n\r\n if (enableIXLStyle) {\r\n return (\r\n <IXLStyleCard\r\n wrapperMode=\"generic\"\r\n ixlConfig={{ type: 'review', label: '回顾', showTag: true }}\r\n enableIXLStyle={true}\r\n >\r\n {contentArea}\r\n </IXLStyleCard>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"review-module-container\">\r\n {/* 模块标题 */}\r\n <h4 className=\"review-module-title\">\r\n 复习\r\n </h4>\r\n {contentArea}\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport { MathCardV2 } from './MathCardV2';\r\nimport { MathGraph } from '../MathGraph/MathGraph';\r\nimport { GeometryTransformContent } from './components/content/GeometryTransformContent';\r\nimport type { MathPracticeProblemData } from './MathPracticeSessionTypes';\r\nimport './ExplanationStep.css';\r\n\r\ninterface ExplanationStepProps {\r\n step: {\r\n id: string;\r\n type: string;\r\n content: {\r\n title: string;\r\n description: string;\r\n chartConfig?: {\r\n type: string;\r\n boundingBox?: [number, number, number, number];\r\n showGrid?: boolean;\r\n showAxis?: boolean;\r\n shapes?: any[];\r\n config?: any; // For geometryTransform type\r\n metadata?: {\r\n config?: any;\r\n [key: string]: any;\r\n };\r\n };\r\n };\r\n };\r\n problemData: MathPracticeProblemData;\r\n stepNumber: number;\r\n}\r\n\r\n/**\r\n * 根据步骤序号获取样式配置\r\n * 简单的循环逻辑:1->Blue(识别), 2->Orange(计算), 3->Green(结果)\r\n */\r\nconst getStepStyle = (index: number) => {\r\n const styles = [\r\n { color: 'var(--mc-step-color-ident)', bg: 'var(--mc-step-bg-ident)' },\r\n { color: 'var(--mc-step-color-calc)', bg: 'var(--mc-step-bg-calc)' },\r\n { color: 'var(--mc-step-color-res)', bg: 'var(--mc-step-bg-res)' }\r\n ];\r\n return styles[index % 3];\r\n};\r\n\r\n/**\r\n * 解释步骤组件\r\n * 使用MathCardV2渲染步骤内容,支持图形和文本的组合\r\n */\r\nexport const ExplanationStep: React.FC<ExplanationStepProps> = ({\r\n step,\r\n problemData,\r\n stepNumber\r\n}) => {\r\n const { title, description, chartConfig } = step.content;\r\n const hasChartConfig = !!chartConfig;\r\n\r\n // 获取当前步骤的样式配置\r\n const styleVars = getStepStyle(stepNumber - 1);\r\n\r\n // 将描述文本转换为MathCardV2可渲染的内容块 - 使用Design Token而不是硬编码样式\r\n const descriptionContent = [\r\n {\r\n type: 'text' as const,\r\n content: description.replace(/<br>/g, '\\n').replace(/<[^>]*>/g, ''),\r\n style: {\r\n fontSize: 'var(--mc-text-base)',\r\n color: 'var(--mc-text-secondary)',\r\n lineHeight: 'var(--mc-leading-relaxed)'\r\n }\r\n }\r\n ];\r\n\r\n return (\r\n <div\r\n className=\"explanation-step-container\"\r\n style={{\r\n '--current-step-color': styleVars.color,\r\n '--current-step-bg': styleVars.bg\r\n } as React.CSSProperties}\r\n >\r\n {/* 步骤标题 - 使用新的CSS类 */}\r\n <h3 className=\"explanation-step-title\">\r\n <span className=\"explanation-step-number\">{stepNumber}</span>\r\n <span>{title}</span>\r\n </h3>\r\n\r\n {/* 步骤描述 - 使用MathCardV2渲染,但移除边框和背景,由容器提供样式 */}\r\n <div className=\"explanation-step-content\">\r\n <MathCardV2\r\n data={{\r\n id: `${step.id}-description`,\r\n grade: problemData.grade,\r\n unit: problemData.unit,\r\n content: descriptionContent\r\n }}\r\n layout={{\r\n type: 'card',\r\n padding: '16px',\r\n border: false, // 禁用边框,由容器提供左侧色条\r\n shadow: false // 禁用阴影,由容器提供渐变背景\r\n }}\r\n className=\"explanation-step-mathcard\" // 使用自定义类而不是硬编码样式\r\n />\r\n\r\n {/* 图形解释 - 直接展示,去除外层边框和标签 */}\r\n {hasChartConfig && (\r\n <div className=\"explanation-step-chart-container\">\r\n {chartConfig.type === 'geometryTransform' && (chartConfig.config || chartConfig.metadata?.config) ? (\r\n <GeometryTransformContent\r\n config={chartConfig.config || chartConfig.metadata?.config}\r\n onTransformChange={(progress) => console.log('Transform progress:', progress)}\r\n onTransformComplete={() => console.log('Transform complete')}\r\n onError={(error) => console.error('Geometry transform error:', error)}\r\n />\r\n ) : (\r\n <MathGraph\r\n shapes={chartConfig.shapes || []}\r\n width={400}\r\n height={300}\r\n boundingBox={chartConfig.boundingBox || [-10, 10, 10, -10]}\r\n showGrid={chartConfig.showGrid || false}\r\n showAxis={chartConfig.showAxis || false}\r\n mode=\"view\"\r\n className=\"mx-auto\"\r\n />\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};","/**\r\n * 数学练习会话类型定义\r\n * 用于多场景数学练习会话的状态管理和组件通信\r\n */\r\n\r\nimport type {\r\n ContentBlock,\r\n FormulaContentBlock,\r\n GraphContentBlock,\r\n HundredGridContentBlock,\r\n GeometryTransformContentBlock,\r\n PlaceValueChartContentBlock\r\n} from './MathCardV2.types';\r\n\r\nexport type MathPracticeScene = 'question' | 'explanation' | 'success';\r\n\r\nexport interface MathPracticeSessionState {\r\n // 当前场景\r\n currentScene: MathPracticeScene;\r\n\r\n // 用户答案\r\n userAnswer: string;\r\n\r\n // 答案正确性\r\n isCorrect: boolean | null;\r\n\r\n // 是否显示答案表单\r\n showAnswerForm: boolean;\r\n\r\n // 当前问题数据\r\n problemData: MathPracticeProblemData | null;\r\n\r\n // 验证错误信息\r\n validationError: string | null;\r\n}\r\n\r\nexport interface MathPracticeSessionActions {\r\n // 更新用户答案(输入时)\r\n updateUserAnswer: (answer: string) => void;\r\n\r\n // 提交答案\r\n submitAnswer: (answer: string) => void;\r\n\r\n // 下一题\r\n nextQuestion: () => void;\r\n\r\n // 重置会话\r\n resetSession: () => void;\r\n\r\n // 设置问题数据\r\n setProblemData: (problemData: MathPracticeProblemData) => void;\r\n}\r\n\r\nexport type MathPracticeSessionStore = MathPracticeSessionState & MathPracticeSessionActions;\r\n\r\n// 基础内容块类型 - 兼容JSON数据格式\r\ntype BaseContentBlock = {\r\n type: ContentBlock['type']; // 使用 ContentBlock 的 type 类型\r\n content: string;\r\n style?: Record<string, any>;\r\n};\r\n\r\n// 会话场景内容块(覆盖 MathCardV2 支持的主要内容类型 + 兼容 BaseContentBlock)\r\ntype SessionContentBlock =\r\n | ContentBlock\r\n | FormulaContentBlock\r\n | GraphContentBlock\r\n | GeometryTransformContentBlock\r\n | HundredGridContentBlock\r\n | PlaceValueChartContentBlock\r\n | BaseContentBlock;\r\n\r\n// 问题元数据接口\r\nexport interface ProblemMetadata {\r\n topic: string;\r\n skill: string;\r\n tags: string[];\r\n}\r\n\r\n// 新数据格式类型定义\r\n// 解释步骤接口 - 扁平化结构(新格式)\r\nexport interface ExplanationStep {\r\n id: string;\r\n type: string;\r\n title: string; // 直接属性,无content包装\r\n description: string; // 直接属性,无content包装\r\n chartConfig?:\r\n | {\r\n type: 'graph';\r\n shapes: any[];\r\n boundingBox?: [number, number, number, number];\r\n showGrid?: boolean;\r\n showAxis?: boolean;\r\n }\r\n | {\r\n type: 'geometryTransform';\r\n config: any;\r\n };\r\n // 可选扩展字段\r\n videoUrl?: string;\r\n commonErrors?: string[];\r\n difficulty?: number;\r\n}\r\n\r\n// 提示接口\r\nexport interface Hint {\r\n step: number;\r\n text: string;\r\n condition?: string;\r\n}\r\n\r\n// 解释对象接口 - 包含steps数组和元数据(新格式)\r\nexport interface Explanation {\r\n steps: ExplanationStep[];\r\n strategy?: string;\r\n total_steps?: number;\r\n estimated_time?: number; // 秒\r\n hints?: Hint[];\r\n // 扩展字段\r\n videos?: Array<{\r\n url: string;\r\n title: string;\r\n duration: number;\r\n }>;\r\n common_errors?: Array<{\r\n description: string;\r\n frequency: number;\r\n prevention: string;\r\n }>;\r\n prerequisites?: string[];\r\n learning_objectives?: string[];\r\n}\r\n\r\n// 答案信息接口 - 扩展结构(新格式)\r\nexport interface AnswerInfo {\r\n value: number;\r\n unit: string;\r\n type?: string;\r\n tolerance?: number;\r\n format?: {\r\n decimal_places?: number;\r\n allow_fraction?: boolean;\r\n allow_negative?: boolean;\r\n };\r\n validation_rules?: {\r\n required?: boolean;\r\n min_value?: number;\r\n max_value?: number;\r\n exact_match?: boolean;\r\n };\r\n explanation_text?: string;\r\n solution_steps?: Array<{\r\n step: number;\r\n action: string;\r\n description: string;\r\n }>;\r\n}\r\n\r\n// 练习问题数据接口 - 兼容面积问题与年龄问题\r\nexport interface MathPracticeProblemData {\r\n id: string;\r\n title: string;\r\n grade: number;\r\n unit: string;\r\n lesson: string; // 新增:课时名称(必需)\r\n skill: string; // 新增:技能描述(必需)\r\n objective: string; // 新增:学习目标(必需)\r\n knowledgePoints: string[]; // 新增:知识点列表(必需)\r\n difficulty: number; // 新增:难度等级1-5(必需)\r\n metadata: ProblemMetadata; // 新增:元数据(必需)\r\n description?: string;\r\n basicInfo: {\r\n question: string;\r\n answerUnit?: string;\r\n areaUnit?: string;\r\n shape?: string;\r\n // 新字段(新格式)\r\n base?: number;\r\n height?: number;\r\n baseUnit?: string;\r\n heightUnit?: string;\r\n score?: number;\r\n variables?: Record<string, any>;\r\n context?: {\r\n learning_objective?: string;\r\n prerequisite_skills?: string[];\r\n time_estimate?: number;\r\n };\r\n // 向后兼容字段(旧格式)\r\n length?: number;\r\n width?: number;\r\n lengthUnit?: string;\r\n widthUnit?: string;\r\n };\r\n content?: Array<BaseContentBlock>;\r\n scenes: {\r\n question: {\r\n content?: Array<SessionContentBlock>; // 旧字段,可选\r\n items: Array<SessionContentBlock>; // 新字段,必需\r\n layout?: {\r\n type?: string;\r\n spacing?: string;\r\n alignment?: string;\r\n };\r\n };\r\n solve: {\r\n content?: Array<SessionContentBlock>; // 旧字段,可选\r\n items: Array<SessionContentBlock>; // 新字段,必需\r\n layout?: {\r\n type?: string;\r\n spacing?: string;\r\n alignment?: string;\r\n cardStyle?: {\r\n backgroundColor?: string;\r\n borderColor?: string;\r\n borderWidth?: string;\r\n };\r\n };\r\n };\r\n review: {\r\n content?: Array<SessionContentBlock>; // 旧字段,可选\r\n items: Array<SessionContentBlock>; // 新字段,必需\r\n layout?: {\r\n type?: string;\r\n spacing?: string;\r\n alignment?: string;\r\n };\r\n };\r\n remember?: {\r\n content?: Array<SessionContentBlock>; // 旧字段,可选\r\n items: Array<SessionContentBlock>; // 新字段,必需\r\n layout?: {\r\n type?: string;\r\n spacing?: string;\r\n alignment?: string;\r\n cardStyle?: {\r\n backgroundColor?: string;\r\n borderColor?: string;\r\n borderWidth?: string;\r\n };\r\n };\r\n };\r\n };\r\n explanation: Explanation | ExplanationStep[]; // 联合类型:支持新旧格式\r\n answer: {\r\n value: number;\r\n unit: string;\r\n explanation: string;\r\n };\r\n answer_info?: AnswerInfo; // 新字段:扩展的答案信息\r\n // 新增可选字段(新格式)\r\n math_prob_id?: string;\r\n grade_id?: string;\r\n unit_id?: number;\r\n lesson_id?: number;\r\n module_id?: number;\r\n skill_item_id?: string;\r\n skill_id?: string;\r\n created_at?: string;\r\n updated_at?: string;\r\n layout?: {\r\n type?: string;\r\n padding?: string;\r\n theme?: string;\r\n renderer?: Record<string, any>;\r\n };\r\n}\r\n\r\n// 模块组件 Props\r\nexport interface ReviewModuleProps {\r\n problemData: MathPracticeProblemData;\r\n userAnswer: string;\r\n enableIXLStyle?: boolean;\r\n}\r\n\r\nexport interface RememberModuleProps {\r\n problemData: MathPracticeProblemData;\r\n enableIXLStyle?: boolean;\r\n}\r\n\r\nexport interface SolveModuleProps {\r\n problemData: MathPracticeProblemData;\r\n enableIXLStyle?: boolean;\r\n}\r\n\r\n// 场景组件 Props\r\nexport interface QuestionSceneProps {\r\n problemData: MathPracticeProblemData;\r\n userAnswer: string;\r\n showAnswerForm: boolean;\r\n onAnswerSubmit: (answer: string) => void;\r\n onAnswerChange: (answer: string) => void;\r\n validationError?: string | null;\r\n}\r\n\r\nexport interface ExplanationSceneProps {\r\n problemData: MathPracticeProblemData;\r\n userAnswer: string;\r\n onNextQuestion: () => void;\r\n}\r\n\r\nexport interface SuccessSceneProps {\r\n problemData: MathPracticeProblemData;\r\n onNextQuestion: () => void;\r\n}\r\n\r\n// 主页面 Props\r\nexport interface MathPracticeSessionPageProps {\r\n className?: string;\r\n problemData?: MathPracticeProblemData;\r\n}\r\n\r\n// 答案验证结果\r\nexport interface AnswerValidationResult {\r\n isValid: boolean;\r\n isCorrect: boolean;\r\n errorMessage?: string;\r\n}\r\n\r\n// 工具函数\r\n/**\r\n * 类型守卫:检查解释是否为对象格式\r\n */\r\nexport function isExplanationObject(\r\n explanation: Explanation | ExplanationStep[]\r\n): explanation is Explanation {\r\n return (explanation as Explanation).steps !== undefined;\r\n}\r\n\r\n/**\r\n * 标准化解释数据:将任何格式转换为标准Explanation对象\r\n */\r\nexport function normalizeExplanation(\r\n explanation: Explanation | ExplanationStep[] | any[]\r\n): Explanation {\r\n if (isExplanationObject(explanation)) {\r\n return explanation;\r\n }\r\n\r\n // 检查是否为数组\r\n if (Array.isArray(explanation)) {\r\n // 如果数组为空,直接返回空steps\r\n if (explanation.length === 0) {\r\n return {\r\n steps: [],\r\n total_steps: 0,\r\n strategy: 'step_by_step',\r\n estimated_time: 0,\r\n };\r\n }\r\n\r\n // 检查第一个元素是否为旧格式(有content字段)\r\n const firstStep = explanation[0];\r\n const isLegacyFormat = firstStep && firstStep.content &&\r\n (firstStep.content.title !== undefined || firstStep.content.description !== undefined);\r\n\r\n if (isLegacyFormat) {\r\n // 将旧格式转换为新格式(扁平化)\r\n const steps: ExplanationStep[] = explanation.map((step: any) => ({\r\n id: step.id,\r\n type: step.type,\r\n title: step.content.title || '',\r\n description: step.content.description || '',\r\n chartConfig: step.content.chartConfig,\r\n videoUrl: step.content.videoUrl,\r\n commonErrors: step.content.commonErrors,\r\n difficulty: step.content.difficulty,\r\n }));\r\n\r\n return {\r\n steps,\r\n total_steps: steps.length,\r\n strategy: 'step_by_step',\r\n estimated_time: steps.length * 30, // 默认每步30秒\r\n };\r\n } else {\r\n // 已经是新格式(扁平化)或兼容格式\r\n return {\r\n steps: explanation as ExplanationStep[],\r\n total_steps: explanation.length,\r\n strategy: 'step_by_step',\r\n estimated_time: explanation.length * 30, // 默认每步30秒\r\n };\r\n }\r\n }\r\n\r\n // 默认返回空Explanation对象\r\n return {\r\n steps: [],\r\n total_steps: 0,\r\n strategy: 'step_by_step',\r\n estimated_time: 0,\r\n };\r\n}\r\n\r\n/**\r\n * 智能获取基础尺寸:优先使用新字段(base/height),回退到旧字段(length/width)\r\n */\r\nexport function getBasicInfoDimensions(basicInfo: MathPracticeProblemData['basicInfo']) {\r\n return {\r\n base: basicInfo.base ?? basicInfo.length,\r\n height: basicInfo.height ?? basicInfo.width,\r\n baseUnit: basicInfo.baseUnit ?? basicInfo.lengthUnit,\r\n heightUnit: basicInfo.heightUnit ?? basicInfo.widthUnit,\r\n };\r\n}\r\n\r\n/**\r\n * 获取答案信息:优先使用answer_info,回退到answer\r\n */\r\nexport function getAnswerInfo(problemData: MathPracticeProblemData) {\r\n if (problemData.answer_info) {\r\n return problemData.answer_info;\r\n }\r\n\r\n // 从旧格式answer转换为AnswerInfo\r\n return {\r\n value: problemData.answer.value,\r\n unit: problemData.answer.unit,\r\n explanation_text: problemData.answer.explanation,\r\n } as AnswerInfo;\r\n}","import React, { useMemo, useState } from 'react';\r\nimport { MathCardV2 } from '../../MathCardV2';\r\nimport { ExplanationStep } from '../../ExplanationStep';\r\nimport { IXLStyleCard } from '../../../IXLStyleCard/IXLStyleCard';\r\nimport type { SolveModuleProps } from '../../MathPracticeSessionTypes';\r\nimport { normalizeExplanation } from '../../MathPracticeSessionTypes';\r\nimport './SolveModule.css';\r\n\r\n/**\r\n * 解题模块组件\r\n * 橙色主题,展示详细的解题步骤和图形解释\r\n * 使用MathCardV2组件渲染所有解释步骤,支持多步骤显示\r\n */\r\nexport const SolveModule: React.FC<SolveModuleProps> = ({\r\n problemData,\r\n enableIXLStyle = true\r\n}) => {\r\n const [showDetailedSteps, setShowDetailedSteps] = useState(false);\r\n\r\n const solveContent = (problemData?.scenes?.solve?.items || problemData?.scenes?.solve?.content) as any[] | undefined;\r\n const hasSolve = Array.isArray(solveContent) && solveContent.length > 0;\r\n\r\n // 检查是否有解释步骤 - 支持新旧格式\r\n const normalizedExplanation = useMemo(() =>\r\n normalizeExplanation(problemData.explanation),\r\n [problemData.explanation]\r\n );\r\n const hasExplanations = normalizedExplanation.steps.length > 0;\r\n\r\n const adaptedExplanationSteps = useMemo(() => {\r\n if (!hasExplanations) return [];\r\n\r\n return normalizedExplanation.steps.map((step) => ({\r\n ...step,\r\n content: {\r\n title: step.title,\r\n description: step.description,\r\n chartConfig: step.chartConfig ? {\r\n ...step.chartConfig,\r\n boundingBox: (step.chartConfig.type === 'graph' && Array.isArray(step.chartConfig.boundingBox) &&\r\n step.chartConfig.boundingBox.length === 4\r\n ? [\r\n step.chartConfig.boundingBox[0],\r\n step.chartConfig.boundingBox[1],\r\n step.chartConfig.boundingBox[2],\r\n step.chartConfig.boundingBox[3]\r\n ]\r\n : [-10, 10, 10, -10]) as [number, number, number, number]\r\n } : undefined\r\n }\r\n }));\r\n }, [hasExplanations, normalizedExplanation.steps]);\r\n\r\n // 渲染内容区域\r\n const contentArea = (\r\n <div className=\"solve-module-content\">\r\n {/* 基础解题步骤 */}\r\n {hasSolve ? (\r\n <>\r\n {/* 调试日志:检查solveContent中的geometryTransform配置 */}\r\n {console.log('🔍 SolveModule: solveContent =', solveContent)}\r\n {solveContent?.forEach?.((block, index) => {\r\n if (block.type === 'geometryTransform') {\r\n console.log(`🔍 SolveModule: geometryTransform block [${index}] =`, {\r\n type: block.type,\r\n hasMetadata: !!block.metadata,\r\n metadata: block.metadata,\r\n hasConfig: !!block.config,\r\n config: block.config,\r\n hasShapes: !!block.shapes,\r\n shapes: block.shapes,\r\n hasTransform: !!block.transform,\r\n transform: block.transform\r\n });\r\n }\r\n })}\r\n <MathCardV2\r\n data={{\r\n id: 'solve-steps',\r\n grade: problemData.grade,\r\n unit: problemData.unit,\r\n content: solveContent\r\n }}\r\n scene=\"solve\"\r\n layout={{ type: 'flow', direction: 'vertical', gap: '12px' }}\r\n className={enableIXLStyle ? 'ixl-adjusted' : ''}\r\n />\r\n </>\r\n ) : (\r\n <div className=\"solve-module-empty\">\r\n 空白(暂无简化解题步骤)\r\n </div>\r\n )}\r\n\r\n {/* 展开/收起详细解题步骤 */}\r\n <div className=\"solve-module-button-container\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowDetailedSteps((v) => !v)}\r\n className=\"solve-module-button\"\r\n >\r\n {showDetailedSteps ? '收起详细解题步骤' : '查看详细解题步骤'}\r\n </button>\r\n </div>\r\n\r\n {/* 详细解释步骤 - 仅在存在解释步骤时显示 */}\r\n {showDetailedSteps && (\r\n <div className=\"solve-module-detailed-container\">\r\n <h5 className=\"solve-module-detailed-title\">\r\n 详细解题步骤\r\n </h5>\r\n {hasExplanations ? (\r\n <div className=\"solve-module-detailed-list\">\r\n {adaptedExplanationSteps.map((step, index) => (\r\n <ExplanationStep\r\n key={step.id}\r\n step={step as any}\r\n problemData={problemData}\r\n stepNumber={index + 1}\r\n />\r\n ))}\r\n </div>\r\n ) : (\r\n <div className=\"solve-module-empty\">\r\n 暂无详细解题步骤\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n\r\n if (enableIXLStyle) {\r\n return (\r\n <IXLStyleCard\r\n wrapperMode=\"generic\"\r\n ixlConfig={{ type: 'solve', label: '解答', showTag: true }}\r\n enableIXLStyle={true}\r\n >\r\n {contentArea}\r\n </IXLStyleCard>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"solve-module-container\">\r\n {/* 模块标题 */}\r\n <h4 className=\"solve-module-title\">\r\n 解题\r\n </h4>\r\n {contentArea}\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport { Button } from '../../../Button/Button';\r\nimport { ReviewModule, RememberModule, SolveModule } from '../../modules';\r\nimport type { ExplanationSceneProps } from '../../MathPracticeSessionTypes';\r\nimport './ExplanationScene.css';\r\n\r\n/**\r\n * 解释场景组件\r\n * 错误答案的详细解释,包含三个学习模块\r\n */\r\nexport const ExplanationScene: React.FC<ExplanationSceneProps> = ({\r\n problemData,\r\n userAnswer,\r\n onNextQuestion\r\n}) => {\r\n console.log('🔍 ExplanationScene problemData:', problemData);\r\n console.log('🔍 ExplanationScene scenes.remember:', problemData?.scenes?.remember);\r\n console.log('🔍 ExplanationScene scenes.remember.items:', problemData?.scenes?.remember?.items);\r\n console.log('🔍 ExplanationScene scenes.remember.content:', problemData?.scenes?.remember?.content);\r\n return (\r\n <div>\r\n {/* 顶部错误提示栏 */}\r\n <div className=\"explanation-error-banner\">\r\n <div className=\"explanation-inner-container\">\r\n <div className=\"explanation-icon\" aria-hidden>\r\n 💡\r\n </div>\r\n\r\n <div className=\"explanation-content explanation-content-spacing\">\r\n <h3 className=\"explanation-title\">\r\n 让我们再看一遍...\r\n </h3>\r\n\r\n <div className=\"explanation-description explanation-description-spacing\">\r\n <div className=\"correct-answer-label\">正确答案是:</div>\r\n <div className=\"correct-answer-value-container\">\r\n <span className=\"correct-answer-value\">\r\n <span style={{ fontFamily: 'var(--mc-font-serif)' }}>\r\n {problemData.answer?.value ?? '--'}\r\n </span>\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"explanation-button-container\">\r\n <Button\r\n onClick={onNextQuestion}\r\n size=\"lg\"\r\n className=\"explanation-next-button\"\r\n >\r\n 明白了\r\n </Button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* 解释内容 - 三个学习模块 */}\r\n <div className=\"explanation-content-area\">\r\n <h4 className=\"explanation-subtitle\">\r\n 详细解释\r\n </h4>\r\n {/* 复习模块 */}\r\n <ReviewModule\r\n problemData={problemData}\r\n userAnswer={userAnswer}\r\n />\r\n\r\n {/* 记忆模块 */}\r\n <RememberModule\r\n problemData={problemData}\r\n />\r\n\r\n {/* 解题模块 */}\r\n <SolveModule\r\n problemData={problemData}\r\n />\r\n </div>\r\n\r\n {/* 底部按钮 */}\r\n <div className=\"explanation-bottom-area\">\r\n <Button\r\n onClick={onNextQuestion}\r\n size=\"md\"\r\n >\r\n 明白了\r\n </Button>\r\n </div>\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport { MathCardV2 } from '../../MathCardV2';\r\nimport { Button } from '../../../Button/Button';\r\nimport type { SuccessSceneProps } from '../../MathPracticeSessionTypes';\r\nimport './SuccessScene.css';\r\n\r\n/**\r\n * 成功场景组件\r\n * 正确答案的积极反馈和核心概念回顾\r\n */\r\nexport const SuccessScene: React.FC<SuccessSceneProps> = ({\r\n problemData,\r\n onNextQuestion\r\n}) => {\r\n return (\r\n <div className=\"success-scene-container\">\r\n {/* 成功消息 */}\r\n <h3 className=\"success-message-title\">正确!</h3>\r\n <p className=\"success-message-description\">你做得很好!</p>\r\n\r\n {/* 核心概念回顾 - 兼容remember和review两种场景 */}\r\n <div className=\"concept-review-container\">\r\n <MathCardV2\r\n data={{\r\n id: 'review-concepts',\r\n grade: problemData.grade,\r\n unit: problemData.unit,\r\n // 优先使用review,如果没有则使用remember作为备用\r\n content: problemData.scenes?.review?.items || // 新标准优先\r\n problemData.scenes?.review?.content || // 旧标准回退\r\n problemData.scenes?.remember?.items || // remember场景新标准\r\n problemData.scenes?.remember?.content || // remember场景旧标准\r\n [\r\n {\r\n type: 'text',\r\n content: '核心概念回顾:本次练习中你掌握了重要的数学概念!'\r\n }\r\n ]\r\n }}\r\n scene=\"review\"\r\n layout={{ type: 'card' }}\r\n />\r\n </div>\r\n\r\n {/* 下一题按钮 */}\r\n <Button\r\n onClick={onNextQuestion}\r\n size=\"lg\"\r\n className=\"next-button\"\r\n >\r\n 下一题\r\n </Button>\r\n </div>\r\n );\r\n};","/**\r\n * 数学几何问题V4数据格式类型定义 - 完整版\r\n *\r\n * 基于实际JSON数据结构、组件类型和适配器实现整合的完整类型定义。\r\n * 提供完整的V4数据格式类型安全支持,支持设计令牌、几何引用、样式引用等。\r\n * 整合来源:\r\n * 1. GeometryTransform组件类型定义\r\n * 2. MathPracticeSessionTypes类型定义\r\n * 3. GeometryProblemAdapterV4适配器类型\r\n * 4. 实际V4 JSON数据结构(triangle-v4-final.json)\r\n *\r\n * @generatedBy math-geometry-problem-generator\r\n * @version 2.0.0\r\n * @schemaVersion 4.0.0\r\n */\r\n\r\n// ============================================================================\r\n// 基础类型\r\n// ============================================================================\r\n\r\n/**\r\n * V4数据格式版本\r\n */\r\nexport type V4SchemaVersion = '4.0.0';\r\n\r\n/**\r\n * 数学问题唯一标识符格式\r\n * 格式:mp-{年级}-{单元}-{课程}-{类型}-{序号}\r\n * 示例:mp-10506-0002-0002-G01-0001\r\n */\r\nexport type MathProblemId = `mp-${string}-${string}-${string}-${string}-${string}`;\r\n\r\n/**\r\n * 几何形状类型 - 基于实际JSON和组件定义\r\n */\r\nexport type GeometryShapeType =\r\n | 'acute_triangle'\r\n | 'right_triangle'\r\n | 'obtuse_triangle'\r\n | 'parallelogram'\r\n | 'rectangle'\r\n | 'square'\r\n | 'trapezoid'\r\n | 'circle'\r\n | 'polygon'\r\n | 'segment'\r\n | 'point'\r\n | 'text';\r\n\r\n/**\r\n * 单位类型\r\n */\r\nexport type LengthUnit = 'cm' | 'm' | 'mm' | 'in' | 'ft';\r\nexport type AreaUnit = 'cm²' | 'm²' | 'mm²' | 'in²' | 'ft²';\r\n\r\n/**\r\n * 难度等级(1-5)\r\n */\r\nexport type DifficultyLevel = 1 | 2 | 3 | 4 | 5;\r\n\r\n/**\r\n * 场景类型 - 基于实际JSON和MathPracticeSessionTypes\r\n */\r\nexport type SceneType = 'question' | 'solve' | 'review' | 'remember' | 'explanation' | 'success';\r\n\r\n/**\r\n * 内容块类型 - 基于实际JSON scenes.items\r\n */\r\nexport type ContentType = 'text' | 'formula' | 'graph' | 'geometryTransform' | 'interactive';\r\n\r\n/**\r\n * 布局类型\r\n */\r\nexport type LayoutType = 'vertical' | 'horizontal' | 'centered' | 'grid' | 'flow' | 'card';\r\n\r\n/**\r\n * 方向类型 - 基于GeometryTransform组件\r\n */\r\nexport type DirectionType = 'clockwise' | 'counterclockwise' | 'horizontal' | 'vertical';\r\n\r\n/**\r\n * 缓动函数类型\r\n */\r\nexport type EasingType = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'step';\r\n\r\n/**\r\n * 变换类型 - 基于GeometryTransform组件和JSON\r\n */\r\nexport type TransformType = 'rotation' | 'translation' | 'scale' | 'composite' | 'matrix' | 'fillcolor_set';\r\n\r\n/**\r\n * 变换策略类型\r\n */\r\nexport type TransformStrategy =\r\n | 'double_rotation'\r\n | 'single_rotation'\r\n | 'translation'\r\n | 'composite';\r\n\r\n// ============================================================================\r\n// 引用系统类型\r\n// ============================================================================\r\n\r\n/**\r\n * 引用类型常量对象(替代枚举,兼容 erasableSyntaxOnly)\r\n */\r\nexport const ReferenceType = {\r\n DESIGN_TOKEN: 'design_token',\r\n STYLE_REF: 'style_ref',\r\n GEOMETRY_REF: 'geometry_ref',\r\n TRANSFORM_REF: 'transform_ref',\r\n LAYOUT_REF: 'layout_ref',\r\n ANIMATION_REF: 'animation_ref',\r\n BOARD_REF: 'board_ref',\r\n GEOMETRY_TRANSFORM_REF: 'geometry_transform_ref',\r\n SLIDER_REF: 'slider_ref',\r\n APPEARANCE_REF: 'appearance_ref',\r\n} as const;\r\n\r\nexport type ReferenceType = typeof ReferenceType[keyof typeof ReferenceType];\r\n\r\n/**\r\n * 设计令牌引用\r\n * 格式:$category.property\r\n * 示例:$colors.primary, $fonts.heading_large\r\n */\r\nexport type DesignTokenRef = `$${string}.${string}`;\r\n\r\n/**\r\n * 几何引用\r\n * 格式:geometryRef:shape_id\r\n * 示例:geometryRef:acute_triangle\r\n */\r\nexport type GeometryRef = `geometryRef:${string}`;\r\n\r\n/**\r\n * 样式引用\r\n * 格式:styleRef:style_id\r\n * 示例:styleRef:primary\r\n */\r\nexport type StyleRef = `styleRef:${string}`;\r\n\r\n/**\r\n * 变换引用\r\n * 格式:transformRef:transform_id\r\n * 示例:transformRef:left_rotation\r\n */\r\nexport type TransformRef = `transformRef:${string}`;\r\n\r\n/**\r\n * 几何变换引用\r\n * 格式:geometryTransformRef:config_id\r\n * 示例:geometryTransformRef:double_rotation_proof\r\n */\r\nexport type GeometryTransformRef = `geometryTransformRef:${string}`;\r\n\r\n/**\r\n * 滑块引用\r\n * 格式:sliderRef:slider_id\r\n * 示例:sliderRef:slider_horizontal\r\n */\r\nexport type SliderRef = `sliderRef:${string}`;\r\n\r\n/**\r\n * 画板引用\r\n * 格式:boardRef:board_id\r\n * 示例:boardRef:default\r\n */\r\nexport type BoardRef = `boardRef:${string}`;\r\n\r\n/**\r\n * 外观引用\r\n * 格式:appearanceRef:appearance_id\r\n * 示例:appearanceRef:always_visible\r\n */\r\nexport type AppearanceRef = `appearanceRef:${string}`;\r\n\r\n/**\r\n * 顶点引用格式 - 基于实际JSON中的$ref引用\r\n */\r\nexport interface VertexRef {\r\n $ref: string;\r\n}\r\n\r\n/**\r\n * 引用值类型 - 所有可能的引用格式\r\n */\r\nexport type ReferenceValue =\r\n | DesignTokenRef\r\n | GeometryRef\r\n | StyleRef\r\n | TransformRef\r\n | GeometryTransformRef\r\n | SliderRef\r\n | BoardRef\r\n | AppearanceRef\r\n | VertexRef\r\n | string;\r\n\r\n/**\r\n * 引用对象\r\n */\r\nexport interface ReferenceObject {\r\n type: ReferenceType;\r\n value: string;\r\n combined?: string;\r\n}\r\n\r\n// ============================================================================\r\n// 几何形状和图形类型\r\n// ============================================================================\r\n\r\n/**\r\n * 顶点格式 - 支持数组或对象格式\r\n */\r\nexport type VertexFormat = [number, number] | readonly [number, number] | { x: number; y: number };\r\n\r\n/**\r\n * 标签配置\r\n */\r\nexport interface LabelConfig {\r\n /** 偏移量 */\r\n offset?: [number, number];\r\n /** 字体大小 */\r\n fontSize?: number;\r\n /** 颜色 */\r\n color?: string;\r\n /** 水平锚点 */\r\n anchorX?: 'left' | 'middle' | 'right';\r\n /** 垂直锚点 */\r\n anchorY?: 'top' | 'middle' | 'bottom';\r\n /** 标签内容(对于text类型) */\r\n content?: string;\r\n}\r\n\r\n/**\r\n * 几何形状定义 - 基于实际JSON结构和组件类型\r\n * 用于geometry_shapes字段中的形状定义\r\n */\r\nexport interface GeometryShapeDefinition {\r\n /** 形状ID(必需) */\r\n id: string;\r\n /** 形状类型(必需) */\r\n type: 'point' | 'segment' | 'line' | 'polygon' | 'circle' | 'text';\r\n /** 名称(可选,用于标签) */\r\n name?: string;\r\n\r\n /** 顶点数组(多边形必需,支持顶点引用) */\r\n vertices?: Array<VertexRef | VertexFormat> | ReadonlyArray<VertexRef | VertexFormat> | ReadonlyArray<readonly [number, number]> | any[];\r\n\r\n /** 端点数组(线段必需,支持顶点引用) */\r\n endpoints?: Array<VertexRef | VertexFormat> | ReadonlyArray<VertexRef | VertexFormat> | ReadonlyArray<readonly [number, number]> | any[];\r\n\r\n /** 位置(点必需) */\r\n position?: VertexFormat;\r\n\r\n /** 半径(圆必需) */\r\n radius?: number;\r\n\r\n /** 是否显示标签 */\r\n withLabel?: boolean;\r\n\r\n /** 标签配置 */\r\n label?: LabelConfig;\r\n\r\n /** 描述信息 */\r\n description?: string;\r\n\r\n /** 样式引用(可以是完整引用或普通字符串) */\r\n styleRef?: string;\r\n\r\n /** 外观引用(可以是完整引用或普通字符串) */\r\n appearanceRef?: string;\r\n\r\n /** 扩展字段 */\r\n [key: string]: any;\r\n}\r\n\r\n/**\r\n * 图形样式配置\r\n */\r\nexport interface ShapeStyle {\r\n /** 填充颜色 */\r\n fillColor?: string;\r\n /** 填充透明度(0.0-1.0) */\r\n fillOpacity?: number;\r\n /** 描边颜色 */\r\n strokeColor?: string;\r\n /** 描边宽度 */\r\n strokeWidth?: number;\r\n /** 虚线样式 */\r\n dashStyle?: number[];\r\n /** 是否显示标签 */\r\n labelVisible?: boolean;\r\n /** 是否可见 */\r\n visible?: boolean;\r\n /** 大小(点类型) */\r\n size?: number;\r\n}\r\n\r\n/**\r\n * 动态外观配置 - 基于GeometryTransform组件\r\n */\r\nexport interface DynamicAppearanceConfig {\r\n /** 可见性控制 */\r\n visibility?: {\r\n type?: 'step' | 'fade';\r\n threshold?: number;\r\n startValue?: number;\r\n endValue?: number;\r\n easing?: EasingType;\r\n };\r\n /** 透明度控制 */\r\n opacity?: {\r\n type?: 'linear' | 'custom';\r\n startAt?: number;\r\n endAt?: number;\r\n from?: number;\r\n to?: number;\r\n easing?: EasingType;\r\n };\r\n /** 颜色控制 */\r\n color?: {\r\n type?: 'gradient' | 'step';\r\n startAt?: number;\r\n endAt?: number;\r\n from?: string;\r\n to?: string;\r\n easing?: EasingType;\r\n };\r\n /** 标签可见性控制 */\r\n labelVisibility?: {\r\n type?: 'step' | 'fade';\r\n threshold?: number;\r\n startValue?: number;\r\n endValue?: number;\r\n easing?: EasingType;\r\n };\r\n}\r\n\r\n/**\r\n * 图形元数据 - 基于GeometryTransform组件\r\n */\r\nexport interface ShapeMetadata {\r\n /** 图形ID(必需) */\r\n id: string;\r\n /** 标签 */\r\n label?: string;\r\n /** 是否可移动 */\r\n isMovable?: boolean;\r\n /** 是否静态 */\r\n isStatic?: boolean;\r\n /** 旋转组标识 */\r\n rotationGroup?: string;\r\n /** 变换配置来源 */\r\n transformSource?: 'shape' | 'global';\r\n /** 动态外观配置 */\r\n dynamicAppearance?: DynamicAppearanceConfig;\r\n}\r\n\r\n/**\r\n * 几何图形(用于变换配置) - 基于GeometryTransform组件\r\n */\r\nexport interface GeometryShape {\r\n /** 图形类型 */\r\n type: GeometryShapeType;\r\n /** 顶点数组 */\r\n vertices: Array<[number, number]>;\r\n /** 形状专属变换配置(优先于全局transform) */\r\n transform?: TransformConfig;\r\n /** 样式配置 */\r\n style?: ShapeStyle;\r\n /** 元数据 */\r\n metadata?: ShapeMetadata;\r\n /** 几何引用(可选,用于解析实际形状) */\r\n geometryRef?: GeometryRef;\r\n /** 样式引用(可选,覆盖style) */\r\n styleRef?: StyleRef;\r\n /** 外观引用(可选,用于动态外观) */\r\n appearanceRef?: AppearanceRef;\r\n}\r\n\r\n// ============================================================================\r\n// 变换配置类型\r\n// ============================================================================\r\n\r\n/**\r\n * 旋转变换配置 - 基于GeometryTransform组件和JSON\r\n */\r\nexport interface RotationConfig {\r\n center: [number, number] | 'auto';\r\n startAngle: number; // 弧度\r\n endAngle: number; // 弧度\r\n direction: DirectionType;\r\n}\r\n\r\n/**\r\n * 平移变换配置\r\n */\r\nexport interface TranslationConfig {\r\n direction: [number, number] | 'horizontal' | 'vertical';\r\n distance: number;\r\n startOffset?: number;\r\n}\r\n\r\n/**\r\n * 缩放变换配置\r\n */\r\nexport interface ScaleConfig {\r\n center: [number, number] | 'centroid';\r\n startScale: number;\r\n endScale: number;\r\n uniform: boolean;\r\n}\r\n\r\n/**\r\n * 填充颜色设置配置\r\n */\r\nexport interface FillColorSetConfig {\r\n color: string;\r\n opacity?: number;\r\n}\r\n\r\n/**\r\n * 变换配置 - 基于GeometryTransform组件\r\n */\r\nexport interface TransformConfig {\r\n type: TransformType;\r\n rotation?: RotationConfig;\r\n translation?: TranslationConfig;\r\n scale?: ScaleConfig;\r\n composite?: TransformConfig[];\r\n fillColorSet?: FillColorSetConfig;\r\n targetGroup?: string; // 目标组标识,用于多图形独立变换\r\n}\r\n\r\n/**\r\n * 变换定义 - 基于JSON中的transform_definitions\r\n */\r\nexport interface TransformDefinition {\r\n id: string;\r\n type: TransformType;\r\n config: {\r\n center?: { x: number; y: number } | [number, number] | 'auto' | 'centroid';\r\n startAngle?: number;\r\n endAngle?: number;\r\n direction?: DirectionType;\r\n distance?: number;\r\n startScale?: number;\r\n endScale?: number;\r\n uniform?: boolean;\r\n color?: string;\r\n opacity?: number;\r\n };\r\n targetGroup?: string;\r\n description?: string;\r\n}\r\n\r\n/**\r\n * 变换配置或引用(支持transformRef引用或完整配置)\r\n */\r\nexport type TransformConfigOrRef =\r\n | { transformRef: string }\r\n | TransformConfig;\r\n\r\n// ============================================================================\r\n// 动画和画板配置\r\n// ============================================================================\r\n\r\n/**\r\n * 动画配置 - 基于GeometryTransform组件\r\n */\r\nexport interface AnimationConfig {\r\n /** 动画配置ID */\r\n id: string;\r\n /** 滑块配置 */\r\n slider?: {\r\n position: [number, number];\r\n length: number;\r\n orientation?: 'horizontal' | 'vertical';\r\n min?: number;\r\n max?: number;\r\n step?: number;\r\n };\r\n /** 进度指示器配置 */\r\n progressIndicator?: {\r\n enabled: boolean;\r\n stages?: number;\r\n labels?: string[];\r\n showPercentage?: boolean;\r\n };\r\n /** 动画持续时间(毫秒) */\r\n duration?: number; // 毫秒\r\n /** 缓动函数类型 */\r\n easing?: EasingType;\r\n /** 描述信息 */\r\n description?: string;\r\n}\r\n\r\n/**\r\n * 动画配置集合类型\r\n * 用于animation_configs字段\r\n */\r\nexport type AnimationConfigs = Record<string, AnimationConfig>;\r\n\r\n/**\r\n * 画板配置 - 基于GeometryTransform组件和JSON\r\n */\r\nexport interface BoardConfig {\r\n originX?: number;\r\n originY?: number;\r\n boundingBox?: [number, number, number, number];\r\n keepAspectRatio?: boolean;\r\n showGrid?: boolean;\r\n showAxis?: boolean;\r\n gridSize?: number;\r\n axisColor?: string;\r\n gridColor?: string;\r\n}\r\n\r\n// ============================================================================\r\n// 几何变换配置类型\r\n// ============================================================================\r\n\r\n/**\r\n * 几何变换配置 - 基于JSON中的geometry_transform_configs\r\n */\r\nexport interface GeometryTransformConfig {\r\n /** 配置ID(必需) */\r\n id: string;\r\n /** 描述 */\r\n description?: string;\r\n /** 底边长度(必需) */\r\n base: number;\r\n /** 高度(必需) */\r\n height: number;\r\n /** 单位(必需) */\r\n unit: LengthUnit;\r\n /** 变换策略 */\r\n strategy: TransformStrategy;\r\n /** 图形定义(必需) */\r\n shapes: {\r\n /** 静态图形(保持不变) */\r\n static: Array<{\r\n id: string;\r\n type: GeometryShapeType;\r\n geometryRef: GeometryRef;\r\n styleRef?: StyleRef;\r\n appearanceRef?: AppearanceRef;\r\n }>;\r\n /** 动画图形(应用变换) */\r\n animated: Array<{\r\n id: string;\r\n type: GeometryShapeType;\r\n geometryRef: GeometryRef;\r\n styleRef?: StyleRef;\r\n appearanceRef?: AppearanceRef;\r\n }>;\r\n };\r\n /** 变换配置(必需,支持transformRef引用或完整配置) */\r\n transform: {\r\n type: string;\r\n transforms: any[];\r\n executionMode?: string;\r\n };\r\n /** 滑块引用(必需) */\r\n sliderRef: SliderRef;\r\n /** 画板引用(必需) */\r\n boardRef: BoardRef;\r\n}\r\n\r\n// ============================================================================\r\n// 场景和内容类型\r\n// ============================================================================\r\n\r\n/**\r\n * 场景定义 - 基于实际JSON scenes字段\r\n */\r\nexport interface SceneDefinition {\r\n /** 内容项数组 */\r\n items?: ContentBlock[];\r\n /** 向后兼容字段 */\r\n content?: ContentBlock[];\r\n /** 布局类型 */\r\n layout?: {\r\n type?: LayoutType;\r\n spacing?: string;\r\n alignment?: string;\r\n cardStyle?: {\r\n backgroundColor?: string;\r\n borderColor?: string;\r\n borderWidth?: string;\r\n borderRadius?: string;\r\n padding?: string;\r\n margin?: string;\r\n };\r\n layoutRef?: string;\r\n };\r\n}\r\n\r\n/**\r\n * 内容块类型 - 基于实际JSON scenes.items\r\n */\r\nexport type ContentBlock =\r\n | TextContent\r\n | FormulaContent\r\n | GraphContent\r\n | GeometryTransformContent\r\n | InteractiveContent;\r\n\r\n/**\r\n * 文本内容\r\n */\r\nexport interface TextContent {\r\n type: 'text';\r\n content: string;\r\n styleRef?: StyleRef;\r\n style?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * 公式内容\r\n */\r\nexport interface FormulaContent {\r\n type: 'formula';\r\n content: string;\r\n parts?: string[];\r\n displayMode?: boolean;\r\n styleRef?: StyleRef;\r\n style?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * 图形形状(用于GraphContent)\r\n */\r\nexport interface GraphShape {\r\n id: string;\r\n type: 'point' | 'segment' | 'polygon' | 'circle' | 'text';\r\n geometryRef?: GeometryRef;\r\n styleRef?: StyleRef;\r\n position?: VertexFormat;\r\n content?: string;\r\n /** 点的大小(仅适用于type: 'point') */\r\n size?: number;\r\n style?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * 图形内容\r\n */\r\nexport interface GraphContent {\r\n type: 'graph';\r\n shapes: GraphShape[];\r\n boardRef?: BoardRef;\r\n boundingBox?: [number, number, number, number];\r\n showGrid?: boolean;\r\n showAxis?: boolean;\r\n autoBoundingBox?: boolean;\r\n keepAspectRatio?: boolean;\r\n}\r\n\r\n/**\r\n * 几何变换内容\r\n */\r\nexport interface GeometryTransformContent {\r\n type: 'geometryTransform';\r\n geometryTransformRef: GeometryTransformRef;\r\n metadata?: {\r\n componentType: 'geometry-transform';\r\n config?: Partial<GeometryTransformConfig>;\r\n };\r\n}\r\n\r\n/**\r\n * 交互内容\r\n */\r\nexport interface InteractiveContent {\r\n type: 'interactive';\r\n component: string;\r\n config: Record<string, any>;\r\n}\r\n\r\n// ============================================================================\r\n// 解释和答案类型\r\n// ============================================================================\r\n\r\n/**\r\n * 解释步骤 - 基于MathPracticeSessionTypes和实际JSON\r\n */\r\nexport interface ExplanationStep {\r\n id: string;\r\n type: string;\r\n title: string;\r\n description: string;\r\n chartConfig?: {\r\n type: 'graph' | 'geometryTransform';\r\n boardRef?: string;\r\n shapes?: GraphShape[];\r\n geometryTransformRef?: GeometryTransformRef;\r\n config?: any;\r\n boundingBox?: [number, number, number, number];\r\n showGrid?: boolean;\r\n showAxis?: boolean;\r\n };\r\n videoUrl?: string;\r\n commonErrors?: string[];\r\n difficulty?: number;\r\n}\r\n\r\n/**\r\n * 解释数据 - 基于MathPracticeSessionTypes\r\n */\r\nexport interface ExplanationData {\r\n steps?: ExplanationStep[];\r\n strategy?: string;\r\n total_steps?: number;\r\n estimated_time?: number;\r\n hints?: Array<{\r\n step: number;\r\n text: string;\r\n condition?: string;\r\n }>;\r\n videos?: Array<{\r\n url: string;\r\n title: string;\r\n duration: number;\r\n }>;\r\n common_errors?: Array<{\r\n description: string;\r\n frequency: number;\r\n prevention: string;\r\n }>;\r\n prerequisites?: string[];\r\n learning_objectives?: string[];\r\n}\r\n\r\n/**\r\n * 答案信息 - 基于实际JSON answer_info\r\n */\r\nexport interface AnswerInfo {\r\n value: number;\r\n unit: string;\r\n type?: string;\r\n tolerance?: number;\r\n validation?: {\r\n type: string;\r\n allowPartial?: boolean;\r\n };\r\n explanation_text: string;\r\n solution_steps?: string[];\r\n format?: {\r\n decimal_places?: number;\r\n allow_fraction?: boolean;\r\n allow_negative?: boolean;\r\n };\r\n validation_rules?: {\r\n required?: boolean;\r\n min_value?: number;\r\n max_value?: number;\r\n exact_match?: boolean;\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// 数据接口类型\r\n// ============================================================================\r\n\r\n/**\r\n * 问题元数据\r\n */\r\nexport interface ProblemMetadata {\r\n topic: string;\r\n skill: string;\r\n tags: string[];\r\n version?: string;\r\n author?: string;\r\n strategy?: string;\r\n estimatedTime?: number;\r\n prerequisites?: string[];\r\n learningObjectives?: string[];\r\n [key: string]: any;\r\n}\r\n\r\n/**\r\n * 基础信息 - 基于适配器类型和实际JSON\r\n */\r\nexport interface BasicInfo {\r\n question: string;\r\n answerUnit?: string;\r\n areaUnit?: string;\r\n shape?: GeometryShapeType | string;\r\n base?: number;\r\n height?: number;\r\n baseUnit?: string;\r\n heightUnit?: string;\r\n topBase?: number;\r\n topBaseUnit?: string;\r\n length?: number;\r\n width?: number;\r\n lengthUnit?: string;\r\n widthUnit?: string;\r\n side?: number;\r\n sideUnit?: string;\r\n diagonal1?: number;\r\n diagonal2?: number;\r\n diagonalUnit?: string;\r\n score?: number;\r\n variables?: Record<string, any>;\r\n context?: {\r\n learning_objective?: string;\r\n prerequisite_skills?: string[];\r\n time_estimate?: number;\r\n };\r\n originX?: number;\r\n originY?: number;\r\n unit?: string;\r\n}\r\n\r\n/**\r\n * 布局配置\r\n */\r\nexport interface LayoutConfig {\r\n type?: string;\r\n padding?: string;\r\n theme?: string;\r\n renderer?: {\r\n showFormulaSteps?: boolean;\r\n interactiveAnimations?: boolean;\r\n validateAnswers?: boolean;\r\n keepAspectRatio?: boolean;\r\n };\r\n}\r\n\r\n/**\r\n * V4数学几何问题数据接口 - 完整类型定义\r\n */\r\nexport interface V4MathGeometryProblemData {\r\n /** 数据格式版本,必须为\"4.0.0\" */\r\n schema_version: V4SchemaVersion;\r\n /** 配置版本 */\r\n config_version?: string;\r\n /** 数学问题唯一标识符 */\r\n math_prob_id: MathProblemId;\r\n /** 问题标题 */\r\n title: string;\r\n /** 问题描述 */\r\n description?: string;\r\n /** 学习目标 */\r\n objective: string;\r\n /** 难度等级(1-5) */\r\n difficulty: DifficultyLevel;\r\n /** 年级标识,如\"g5\"表示五年级 */\r\n grade_id: string;\r\n /** 单元名称 */\r\n unit_name: string;\r\n /** 课程名称 */\r\n lesson_name: string;\r\n /** 技能描述 */\r\n skill_description: string;\r\n /** 知识点列表 */\r\n knowledge_points: string[];\r\n /** 分数 */\r\n score?: number;\r\n /** 元数据 */\r\n metadata?: ProblemMetadata;\r\n /** 基础信息 */\r\n basic_info: BasicInfo;\r\n /** 几何形状定义 */\r\n geometry_shapes: Record<string, GeometryShapeDefinition>;\r\n /** 几何变换配置 */\r\n geometry_transform_configs?: Record<string, GeometryTransformConfig>;\r\n /** 变换定义 */\r\n transform_definitions?: Record<string, TransformDefinition>;\r\n /** 动画配置 */\r\n animation_configs?: AnimationConfigs;\r\n /** 场景定义 */\r\n scenes: Record<SceneType, SceneDefinition>;\r\n /** 解释说明 */\r\n explanation: ExplanationData | ExplanationStep[];\r\n /** 答案信息 */\r\n answer_info: AnswerInfo;\r\n /** 布局配置 */\r\n layout?: LayoutConfig;\r\n /** 可选字段 */\r\n unit_id?: number;\r\n lesson_id?: number;\r\n module_id?: number;\r\n skill_item_id?: string;\r\n skill_id?: number;\r\n created_at?: string;\r\n updated_at?: string;\r\n}\r\n\r\n// ============================================================================\r\n// 适配器和转换相关类型\r\n// ============================================================================\r\n\r\n/**\r\n * 适配器错误代码\r\n */\r\nexport const AdapterErrorCode = {\r\n INVALID_INPUT: 'INVALID_INPUT',\r\n MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',\r\n DESIGN_TOKEN_NOT_FOUND: 'DESIGN_TOKEN_NOT_FOUND',\r\n GEOMETRY_REF_NOT_FOUND: 'GEOMETRY_REF_NOT_FOUND',\r\n TRANSFORM_REF_NOT_FOUND: 'TRANSFORM_REF_NOT_FOUND',\r\n GEOMETRY_TRANSFORM_REF_NOT_FOUND: 'GEOMETRY_TRANSFORM_REF_NOT_FOUND',\r\n STYLE_REF_NOT_FOUND: 'STYLE_REF_NOT_FOUND',\r\n ANIMATION_REF_NOT_FOUND: 'ANIMATION_REF_NOT_FOUND',\r\n BOARD_REF_NOT_FOUND: 'BOARD_REF_NOT_FOUND',\r\n SLIDER_REF_NOT_FOUND: 'SLIDER_REF_NOT_FOUND',\r\n TRANSFORMATION_FAILED: 'TRANSFORMATION_FAILED',\r\n OUTPUT_VALIDATION_FAILED: 'OUTPUT_VALIDATION_FAILED',\r\n} as const;\r\n\r\nexport type AdapterErrorCode = typeof AdapterErrorCode[keyof typeof AdapterErrorCode];\r\n\r\n/**\r\n * 适配器错误\r\n */\r\nexport class AdapterError extends Error {\r\n code: AdapterErrorCode;\r\n details?: Record<string, any>;\r\n\r\n constructor(\r\n code: AdapterErrorCode,\r\n message: string,\r\n details?: Record<string, any>\r\n ) {\r\n super(message);\r\n this.name = 'AdapterError';\r\n this.code = code;\r\n this.details = details;\r\n }\r\n}\r\n\r\n/**\r\n * 适配器警告\r\n */\r\nexport interface AdapterWarning {\r\n code: AdapterErrorCode;\r\n message: string;\r\n path?: string;\r\n suggestion?: string;\r\n}\r\n\r\n/**\r\n * 性能统计\r\n */\r\nexport interface PerformanceStats {\r\n totalTime: number;\r\n referenceResolutionTime: number;\r\n transformationTime: number;\r\n validationTime: number;\r\n memoryUsage: number;\r\n referenceCount: number;\r\n}\r\n\r\n/**\r\n * 适配器结果\r\n */\r\nexport interface AdapterResult {\r\n /** 解析后的标准数据 */\r\n data: any; // 实际应为MathPracticeProblemData,但保持灵活性\r\n /** 警告信息列表 */\r\n warnings: AdapterWarning[];\r\n /** 性能统计 */\r\n performance?: PerformanceStats;\r\n /** 引用解析统计 */\r\n referenceStats: {\r\n total: number;\r\n resolved: number;\r\n failed: number;\r\n byType: { [key: string]: { total: number; resolved: number; failed: number } };\r\n };\r\n}\r\n\r\n/**\r\n * 同步适配器配置\r\n */\r\nexport interface SyncAdapterConfig {\r\n /** 是否启用严格模式(错误时抛出异常) */\r\n strictMode?: boolean;\r\n /** 是否启用详细日志 */\r\n enableLogging?: boolean;\r\n /** 验证级别 */\r\n validationLevel?: 'none' | 'basic' | 'strict';\r\n /** 错误时是否回退到默认数据 */\r\n fallbackOnError?: boolean;\r\n /** 是否启用引用解析 */\r\n enableReferenceResolution?: boolean;\r\n /** 是否启用组件契约验证 */\r\n enableComponentContractValidation?: boolean;\r\n /** 最大引用解析深度 */\r\n maxReferenceDepth?: number;\r\n /** 是否启用性能监控 */\r\n enablePerformanceMonitoring?: boolean;\r\n}\r\n\r\n// ============================================================================\r\n// 组件集成类型\r\n// ============================================================================\r\n\r\n/**\r\n * MathCardV2 数学练习问题数据 - 基于MathPracticeSessionTypes\r\n */\r\nexport interface MathPracticeProblemData {\r\n id: string;\r\n title: string;\r\n grade: number;\r\n unit: string;\r\n lesson: string;\r\n skill: string;\r\n objective: string;\r\n knowledgePoints: string[];\r\n difficulty: number;\r\n metadata: ProblemMetadata;\r\n description?: string;\r\n basicInfo: {\r\n question: string;\r\n answerUnit?: string;\r\n areaUnit?: string;\r\n shape?: string;\r\n base?: number;\r\n height?: number;\r\n baseUnit?: string;\r\n heightUnit?: string;\r\n score?: number;\r\n variables?: Record<string, any>;\r\n context?: {\r\n learning_objective?: string;\r\n prerequisite_skills?: string[];\r\n time_estimate?: number;\r\n };\r\n length?: number;\r\n width?: number;\r\n lengthUnit?: string;\r\n widthUnit?: string;\r\n };\r\n scenes: {\r\n question: {\r\n items: ContentBlock[];\r\n layout?: {\r\n type?: string;\r\n spacing?: string;\r\n alignment?: string;\r\n };\r\n };\r\n solve: {\r\n items: ContentBlock[];\r\n layout?: {\r\n type?: string;\r\n spacing?: string;\r\n alignment?: string;\r\n cardStyle?: {\r\n backgroundColor?: string;\r\n borderColor?: string;\r\n borderWidth?: string;\r\n };\r\n };\r\n };\r\n review: {\r\n items: ContentBlock[];\r\n layout?: {\r\n type?: string;\r\n spacing?: string;\r\n alignment?: string;\r\n };\r\n };\r\n remember?: {\r\n items: ContentBlock[];\r\n layout?: {\r\n type?: string;\r\n spacing?: string;\r\n alignment?: string;\r\n cardStyle?: {\r\n backgroundColor?: string;\r\n borderColor?: string;\r\n borderWidth?: string;\r\n };\r\n };\r\n };\r\n };\r\n explanation: ExplanationData | ExplanationStep[];\r\n answer: {\r\n value: number;\r\n unit: string;\r\n explanation: string;\r\n };\r\n answer_info?: AnswerInfo;\r\n math_prob_id?: string;\r\n grade_id?: string;\r\n unit_id?: number;\r\n lesson_id?: number;\r\n module_id?: number;\r\n skill_item_id?: string;\r\n skill_id?: number;\r\n created_at?: string;\r\n updated_at?: string;\r\n layout?: {\r\n type?: string;\r\n padding?: string;\r\n theme?: string;\r\n renderer?: Record<string, any>;\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// 类型守卫和工具函数类型\r\n// ============================================================================\r\n\r\n/**\r\n * 类型守卫:检查是否为V4数据\r\n */\r\nexport function isV4Data(data: any): data is V4MathGeometryProblemData {\r\n return data?.schema_version === '4.0.0';\r\n}\r\n\r\n/**\r\n * 类型守卫:检查是否为几何变换内容\r\n */\r\nexport function isGeometryTransformContent(\r\n content: ContentBlock\r\n): content is GeometryTransformContent {\r\n return content.type === 'geometryTransform';\r\n}\r\n\r\n/**\r\n * 类型守卫:检查是否为设计令牌引用\r\n */\r\nexport function isDesignTokenRef(ref: string): ref is DesignTokenRef {\r\n return ref.startsWith('$') && ref.includes('.');\r\n}\r\n\r\n/**\r\n * 类型守卫:检查是否为几何引用\r\n */\r\nexport function isGeometryRef(ref: string): ref is GeometryRef {\r\n return ref.startsWith('geometryRef:');\r\n}\r\n\r\n/**\r\n * 类型守卫:检查是否为变换引用\r\n */\r\nexport function isTransformRef(ref: string): ref is TransformRef {\r\n return ref.startsWith('transformRef:');\r\n}\r\n\r\n/**\r\n * 类型守卫:检查是否为几何变换引用\r\n */\r\nexport function isGeometryTransformRef(ref: string): ref is GeometryTransformRef {\r\n return ref.startsWith('geometryTransformRef:');\r\n}\r\n\r\n/**\r\n * 提取引用类型\r\n */\r\nexport function extractReferenceType(ref: string): ReferenceType | null {\r\n if (isDesignTokenRef(ref)) return ReferenceType.DESIGN_TOKEN;\r\n if (isGeometryRef(ref)) return ReferenceType.GEOMETRY_REF;\r\n if (ref.startsWith('styleRef:')) return ReferenceType.STYLE_REF;\r\n if (isTransformRef(ref)) return ReferenceType.TRANSFORM_REF;\r\n if (isGeometryTransformRef(ref)) return ReferenceType.GEOMETRY_TRANSFORM_REF;\r\n if (ref.startsWith('sliderRef:')) return ReferenceType.SLIDER_REF;\r\n if (ref.startsWith('boardRef:')) return ReferenceType.BOARD_REF;\r\n if (ref.startsWith('appearanceRef:')) return ReferenceType.APPEARANCE_REF;\r\n return null;\r\n}\r\n\r\n/**\r\n * 创建引用对象\r\n */\r\nexport function createReferenceObject(ref: string): ReferenceObject | null {\r\n const type = extractReferenceType(ref);\r\n if (!type) return null;\r\n\r\n return {\r\n type,\r\n value: ref.split(':').slice(1).join(':') || ref,\r\n combined: ref\r\n };\r\n}\r\n\r\n/**\r\n * 标准化解释数据:将任何格式转换为标准ExplanationData对象\r\n */\r\nexport function normalizeExplanation(\r\n explanation: ExplanationData | ExplanationStep[] | any[]\r\n): ExplanationData {\r\n if (explanation && typeof explanation === 'object' && 'steps' in explanation) {\r\n return explanation as ExplanationData;\r\n }\r\n\r\n if (Array.isArray(explanation)) {\r\n return {\r\n steps: explanation as ExplanationStep[],\r\n total_steps: explanation.length,\r\n strategy: 'step_by_step',\r\n estimated_time: explanation.length * 30,\r\n };\r\n }\r\n\r\n return {\r\n steps: [],\r\n total_steps: 0,\r\n strategy: 'step_by_step',\r\n estimated_time: 0,\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// 导出所有类型\r\n// ============================================================================\r\n\r\n\r\n\r\n// ============================================================================\r\n// 兼容性类型(向后兼容)\r\n// ============================================================================\r\n\r\n/**\r\n * 原始几何问题数据接口 (V4 格式) - 适配器使用的原始类型\r\n * @deprecated 使用V4MathGeometryProblemData替代\r\n */\r\nexport interface LegacyGeometryProblemDataV4 extends Omit<V4MathGeometryProblemData, 'geometry_shapes' | 'transform_definitions' | 'scenes' | 'explanation'> {\r\n /** 几何形状定义 */\r\n geometry_shapes: Record<string, any>;\r\n /** 变换定义 */\r\n transform_definitions: Record<string, any>;\r\n /** 场景内容 */\r\n scenes: Record<string, {\r\n content?: any[];\r\n items?: any[];\r\n layout?: any;\r\n }>;\r\n /** 解释内容 */\r\n explanation: any;\r\n}","/**\n * GeometryProblemAdapterV4 类型定义\n *\n * 基于 TriangleAdapterV3 重构的通用几何问题适配器类型定义。\n * 支持三角形、梯形、平行四边形等多种几何形状的 V4 格式数据。\n */\n\nimport type { MathPracticeProblemData } from '../../components/MathCardV2/MathPracticeSessionTypes';\nimport type {\n GeometryShapeDefinition,\n TransformDefinition,\n SceneType,\n SceneDefinition,\n ExplanationData,\n ExplanationStep,\n GeometryTransformConfig,\n AnimationConfigs,\n V4MathGeometryProblemData,\n ProblemMetadata,\n LayoutConfig,\n ReferenceType,\n AdapterErrorCode,\n BasicInfo,\n AnswerInfo\n} from './geometry-types';\n\n// ============================================================================\n// 适配器配置类型\n// ============================================================================\n\n/**\n * 同步适配器配置\n */\nexport interface SyncAdapterConfig {\n /** 是否启用严格模式(错误时抛出异常) */\n strictMode?: boolean;\n /** 是否启用详细日志 */\n enableLogging?: boolean;\n /** 验证级别 */\n validationLevel?: 'none' | 'basic' | 'strict';\n /** 错误时是否回退到默认数据 */\n fallbackOnError?: boolean;\n /** 是否启用引用解析 */\n enableReferenceResolution?: boolean;\n /** 是否启用组件契约验证 */\n enableComponentContractValidation?: boolean;\n /** 最大引用解析深度 */\n maxReferenceDepth?: number;\n /** 是否启用性能监控 */\n enablePerformanceMonitoring?: boolean;\n}\n\n/**\n * 默认适配器配置\n */\nexport const DEFAULT_SYNC_ADAPTER_CONFIG: SyncAdapterConfig = {\n strictMode: false,\n enableLogging: false,\n validationLevel: 'basic',\n fallbackOnError: true,\n enableReferenceResolution: true,\n enableComponentContractValidation: false,\n maxReferenceDepth: 10,\n enablePerformanceMonitoring: false,\n};\n\n// ============================================================================\n// 数据接口类型\n// ============================================================================\n\n/**\n * 支持的几何形状类型(常量对象)\n */\nexport const GEOMETRY_SHAPE_TYPE = {\n TRIANGLE: 'triangle',\n ACUTE_TRIANGLE: 'acute_triangle',\n RIGHT_TRIANGLE: 'right_triangle',\n OBTUSE_TRIANGLE: 'obtuse_triangle',\n TRAPEZOID: 'trapezoid',\n PARALLELOGRAM: 'parallelogram',\n RECTANGLE: 'rectangle',\n SQUARE: 'square',\n RHOMBUS: 'rhombus',\n} as const;\n\nexport type GeometryShapeType = typeof GEOMETRY_SHAPE_TYPE[keyof typeof GEOMETRY_SHAPE_TYPE];\n\n/**\n * 原始几何问题数据接口 (V4 格式)\n * 对应外部JSON数据格式,支持多种几何形状\n */\nexport interface GeometryProblemDataV4 {\n /** Schema版本,用于检测数据格式 */\n schema_version?: string;\n math_prob_id: string;\n title: string;\n grade_id: string;\n unit_name: string;\n lesson_name: string;\n skill_description: string;\n objective: string;\n knowledge_points: string[];\n difficulty: number;\n description?: string;\n metadata?: ProblemMetadata;\n\n /** 基础信息,包含几何参数 */\n basic_info: BasicInfo;\n\n /** 几何形状定义 */\n geometry_shapes: Record<string, GeometryShapeDefinition>;\n\n /** 变换定义 */\n transform_definitions: Record<string, TransformDefinition>;\n\n /** 几何变换配置 */\n geometry_transform_configs?: Record<string, GeometryTransformConfig>;\n\n /** 动画配置 */\n animation_configs?: AnimationConfigs;\n\n /** 场景内容 */\n scenes: Record<SceneType, SceneDefinition>;\n\n /** 解释内容 */\n explanation: ExplanationData | ExplanationStep[];\n\n /** 答案信息 */\n answer_info: AnswerInfo;\n\n // 可选字段\n unit_id?: number;\n lesson_id?: number;\n module_id?: number;\n skill_item_id?: string;\n skill_id?: number;\n created_at?: string;\n updated_at?: string;\n layout?: LayoutConfig;\n}\n\n// ============================================================================\n// 引用解析类型\n// ============================================================================\n\n\n\n/**\n * 几何变换引用接口\n */\nexport interface GeometryTransformRef {\n geometryTransformRef: string;\n override?: Partial<GeometryTransformConfig>;\n}\n\n/**\n * 引用解析上下文\n */\nexport interface ReferenceContext {\n designTokens: Record<string, any>;\n stylePresets: Record<string, any>;\n geometryPresets: Record<string, any>; // 使用 any 以兼容嵌入式配置\n transformDefinitions?: Record<string, any>; // 使用 any 以兼容嵌入式配置\n layoutPresets?: Record<string, any>;\n animationConfigs?: Record<string, any>; // 兼容嵌入式滑块配置\n boardDefinitions?: Record<string, any>;\n geometryTransformConfigs?: Record<string, any>; // 使用 any 以兼容\n basicInfo?: any; // 使用 any 以兼容\n // 兼容旧字段\n animationDefinitions?: Record<string, any>;\n}\n\n/**\n * 引用解析结果\n */\nexport interface ReferenceResolution {\n type: ReferenceType;\n path: string;\n value: any;\n depth: number;\n}\n\n// ============================================================================\n// 错误处理类型\n// ============================================================================\n\n\n/**\n * 适配器错误\n */\nexport class AdapterError extends Error {\n code: AdapterErrorCode;\n details?: Record<string, any>;\n\n constructor(\n code: AdapterErrorCode,\n message: string,\n details?: Record<string, any>\n ) {\n super(message);\n this.name = 'AdapterError';\n this.code = code;\n this.details = details;\n }\n}\n\n/**\n * 警告信息\n */\nexport interface AdapterWarning {\n code: AdapterErrorCode;\n message: string;\n path?: string;\n suggestion?: string;\n}\n\n// ============================================================================\n// 性能监控类型\n// ============================================================================\n\n/**\n * 性能测量标记\n */\nexport interface PerformanceMark {\n name: string;\n startTime: number;\n endTime?: number;\n duration?: number;\n}\n\n/**\n * 性能统计\n */\nexport interface PerformanceStats {\n totalTime: number;\n referenceResolutionTime: number;\n transformationTime: number;\n validationTime: number;\n memoryUsage: number;\n referenceCount: number;\n}\n\n// ============================================================================\n// 适配器结果类型\n// ============================================================================\n\n/**\n * 适配器输出结果\n */\nexport interface AdapterResult {\n /** 解析后的标准数据 */\n data: MathPracticeProblemData;\n /** 警告信息列表 */\n warnings: AdapterWarning[];\n /** 性能统计 */\n performance?: PerformanceStats;\n /** 引用解析统计 */\n referenceStats: {\n total: number;\n resolved: number;\n failed: number;\n byType: { [key: string]: { total: number; resolved: number; failed: number } };\n };\n}\n\n// ============================================================================\n// 工具类型\n// ============================================================================\n\n/**\n * 严格模式检查结果\n */\nexport interface StrictCheckResult {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n}\n\n// 重新导出引用类型\nexport { ReferenceType, AdapterErrorCode } from './geometry-types';\n\n// 重新导出目标接口类型\nexport type { MathPracticeProblemData } from '../../components/MathCardV2/MathPracticeSessionTypes';","/**\r\n * TriangleAdapterV3 类型定义\r\n *\r\n * 同步适配器核心类型定义,简化自 triangleDataAdapter/types/adapter.types.ts\r\n * 移除异步相关类型,专注于同步数据转换。\r\n */\r\n\r\nimport type { MathPracticeProblemData } from '../../components/MathCardV2/MathPracticeSessionTypes';\r\n\r\n// ============================================================================\r\n// 适配器配置类型\r\n// ============================================================================\r\n\r\n/**\r\n * 同步适配器配置\r\n */\r\nexport interface SyncAdapterConfig {\r\n /** 是否启用严格模式(错误时抛出异常) */\r\n strictMode?: boolean;\r\n /** 是否启用详细日志 */\r\n enableLogging?: boolean;\r\n /** 验证级别 */\r\n validationLevel?: 'none' | 'basic' | 'strict';\r\n /** 错误时是否回退到默认数据 */\r\n fallbackOnError?: boolean;\r\n /** 是否启用引用解析 */\r\n enableReferenceResolution?: boolean;\r\n /** 是否启用组件契约验证 */\r\n enableComponentContractValidation?: boolean;\r\n /** 最大引用解析深度 */\r\n maxReferenceDepth?: number;\r\n /** 是否启用性能监控 */\r\n enablePerformanceMonitoring?: boolean;\r\n}\r\n\r\n/**\r\n * 默认适配器配置\r\n */\r\nexport const DEFAULT_SYNC_ADAPTER_CONFIG: SyncAdapterConfig = {\r\n strictMode: false,\r\n enableLogging: false,\r\n validationLevel: 'basic',\r\n fallbackOnError: true,\r\n enableReferenceResolution: true,\r\n enableComponentContractValidation: false,\r\n maxReferenceDepth: 10,\r\n enablePerformanceMonitoring: false,\r\n};\r\n\r\n// ============================================================================\r\n// 数据接口类型\r\n// ============================================================================\r\n\r\n/**\r\n * 原始三角形问题数据接口\r\n * 对应外部JSON数据格式(V2外部化配置)\r\n */\r\nexport interface RawTriangleProblemData {\r\n math_prob_id: string;\r\n title: string;\r\n grade_id: string;\r\n unit_name: string;\r\n lesson_name: string;\r\n skill_description: string;\r\n objective: string;\r\n knowledge_points: string[];\r\n difficulty: number;\r\n description?: string;\r\n metadata?: Record<string, any>;\r\n basic_info: {\r\n question: string;\r\n answerUnit?: string;\r\n areaUnit?: string;\r\n shape?: string;\r\n base?: number;\r\n height?: number;\r\n baseUnit?: string;\r\n heightUnit?: string;\r\n score?: number;\r\n variables?: Record<string, any>;\r\n context?: {\r\n learning_objective?: string;\r\n prerequisite_skills?: string[];\r\n time_estimate?: number;\r\n };\r\n length?: number;\r\n width?: number;\r\n lengthUnit?: string;\r\n widthUnit?: string;\r\n };\r\n geometry_shapes: Record<string, any>;\r\n transform_definitions: Record<string, any>;\r\n geometry_transform_configs?: Record<string, GeometryTransformConfig>;\r\n animation_configs?: Record<string, any>;\r\n scenes: Record<string, {\r\n content?: any[]; // 旧字段,可选\r\n items?: any[]; // 新字段,可选\r\n layout?: any;\r\n }>;\r\n explanation: any;\r\n answer_info: {\r\n value: number;\r\n unit: string;\r\n explanation_text: string;\r\n };\r\n // 可选字段\r\n unit_id?: number;\r\n lesson_id?: number;\r\n module_id?: number;\r\n skill_item_id?: string;\r\n skill_id?: number;\r\n created_at?: string;\r\n updated_at?: string;\r\n layout?: any;\r\n}\r\n\r\n// ============================================================================\r\n// 引用解析类型\r\n// ============================================================================\r\n\r\n/**\r\n * 引用类型常量对象(替代枚举,兼容 erasableSyntaxOnly)\r\n */\r\nexport const ReferenceType = {\r\n DESIGN_TOKEN: 'design_token',\r\n STYLE_REF: 'style_ref',\r\n GEOMETRY_REF: 'geometry_ref',\r\n TRANSFORM_REF: 'transform_ref',\r\n LAYOUT_REF: 'layout_ref',\r\n ANIMATION_REF: 'animation_ref',\r\n BOARD_REF: 'board_ref',\r\n GEOMETRY_TRANSFORM_REF: 'geometry_transform_ref',\r\n SLIDER_REF: 'slider_ref',\r\n} as const;\r\n\r\nexport type ReferenceType = typeof ReferenceType[keyof typeof ReferenceType];\r\n\r\n/**\r\n * 几何变换配置接口\r\n */\r\nexport interface GeometryTransformConfig {\r\n id: string;\r\n description?: string;\r\n base: number;\r\n height: number;\r\n unit: string;\r\n strategy: string;\r\n shapes: {\r\n static: any[];\r\n animated: any[];\r\n };\r\n transform: {\r\n type: string;\r\n transforms: any[];\r\n executionMode?: string;\r\n };\r\n sliderRef?: string;\r\n boardRef?: string;\r\n}\r\n\r\n/**\r\n * 几何变换引用接口\r\n */\r\nexport interface GeometryTransformRef {\r\n geometryTransformRef: string;\r\n override?: Partial<GeometryTransformConfig>;\r\n}\r\n\r\n/**\r\n * 引用解析上下文\r\n */\r\nexport interface ReferenceContext {\r\n designTokens: Record<string, any>;\r\n stylePresets: Record<string, any>;\r\n geometryPresets: Record<string, any>;\r\n transformDefinitions?: Record<string, any>;\r\n layoutPresets?: Record<string, any>;\r\n animationConfigs?: Record<string, any>; // 修改为 animationConfigs(与 JSON 字段一致)\r\n animationDefinitions?: Record<string, any>; // 兼容性字段\r\n boardDefinitions?: Record<string, any>;\r\n geometryTransformConfigs?: Record<string, GeometryTransformConfig>;\r\n basicInfo?: any;\r\n}\r\n\r\n/**\r\n * 引用解析结果\r\n */\r\nexport interface ReferenceResolution {\r\n type: ReferenceType;\r\n path: string;\r\n value: any;\r\n depth: number;\r\n}\r\n\r\n// ============================================================================\r\n// 错误处理类型\r\n// ============================================================================\r\n\r\n/**\r\n * 适配器错误代码常量对象(替代枚举,兼容 erasableSyntaxOnly)\r\n */\r\nexport const AdapterErrorCode = {\r\n // 输入错误\r\n INVALID_INPUT: 'INVALID_INPUT',\r\n MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',\r\n\r\n // 引用解析错误\r\n DESIGN_TOKEN_NOT_FOUND: 'DESIGN_TOKEN_NOT_FOUND',\r\n GEOMETRY_REF_NOT_FOUND: 'GEOMETRY_REF_NOT_FOUND',\r\n TRANSFORM_REF_NOT_FOUND: 'TRANSFORM_REF_NOT_FOUND',\r\n GEOMETRY_TRANSFORM_REF_NOT_FOUND: 'GEOMETRY_TRANSFORM_REF_NOT_FOUND',\r\n STYLE_REF_NOT_FOUND: 'STYLE_REF_NOT_FOUND',\r\n ANIMATION_REF_NOT_FOUND: 'ANIMATION_REF_NOT_FOUND',\r\n BOARD_REF_NOT_FOUND: 'BOARD_REF_NOT_FOUND',\r\n SLIDER_REF_NOT_FOUND: 'SLIDER_REF_NOT_FOUND',\r\n\r\n // 转换错误\r\n TRANSFORMATION_FAILED: 'TRANSFORMATION_FAILED',\r\n\r\n // 验证错误\r\n OUTPUT_VALIDATION_FAILED: 'OUTPUT_VALIDATION_FAILED',\r\n} as const;\r\n\r\nexport type AdapterErrorCode = typeof AdapterErrorCode[keyof typeof AdapterErrorCode];\r\n\r\n/**\r\n * 适配器错误\r\n */\r\nexport class AdapterError extends Error {\r\n code: AdapterErrorCode;\r\n details?: Record<string, any>;\r\n\r\n constructor(\r\n code: AdapterErrorCode,\r\n message: string,\r\n details?: Record<string, any>\r\n ) {\r\n super(message);\r\n this.name = 'AdapterError';\r\n this.code = code;\r\n this.details = details;\r\n }\r\n}\r\n\r\n/**\r\n * 警告信息\r\n */\r\nexport interface AdapterWarning {\r\n code: AdapterErrorCode;\r\n message: string;\r\n path?: string;\r\n suggestion?: string;\r\n}\r\n\r\n// ============================================================================\r\n// 性能监控类型\r\n// ============================================================================\r\n\r\n/**\r\n * 性能测量标记\r\n */\r\nexport interface PerformanceMark {\r\n name: string;\r\n startTime: number;\r\n endTime?: number;\r\n duration?: number;\r\n}\r\n\r\n/**\r\n * 性能统计\r\n */\r\nexport interface PerformanceStats {\r\n totalTime: number;\r\n referenceResolutionTime: number;\r\n transformationTime: number;\r\n validationTime: number;\r\n memoryUsage: number;\r\n referenceCount: number;\r\n}\r\n\r\n// ============================================================================\r\n// 适配器结果类型\r\n// ============================================================================\r\n\r\n/**\r\n * 适配器输出结果\r\n */\r\nexport interface AdapterResult {\r\n /** 解析后的标准数据 */\r\n data: MathPracticeProblemData;\r\n /** 警告信息列表 */\r\n warnings: AdapterWarning[];\r\n /** 性能统计 */\r\n performance?: PerformanceStats;\r\n /** 引用解析统计 */\r\n referenceStats: {\r\n total: number;\r\n resolved: number;\r\n failed: number;\r\n byType: { [key: string]: { total: number; resolved: number; failed: number } }; // ✅ Correct\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// 工具类型\r\n// ============================================================================\r\n\r\n/**\r\n * 严格模式检查结果\r\n */\r\nexport interface StrictCheckResult {\r\n isValid: boolean;\r\n errors: string[];\r\n warnings: string[];\r\n}\r\n\r\n// 重新导出目标接口类型\r\nexport type { MathPracticeProblemData } from '../../components/MathCardV2/MathPracticeSessionTypes';","/**\r\n * TriangleAdapterV3 常量定义\r\n *\r\n * 同步适配器使用的常量值,包括默认值、错误消息等。\r\n */\r\n\r\nimport { AdapterErrorCode } from './types';\r\n\r\n// ============================================================================\r\n// 默认值常量\r\n// ============================================================================\r\n\r\n/**\r\n * 默认几何预设(简化版)\r\n */\r\nexport const DEFAULT_GEOMETRY_PRESETS = {\r\n acute_triangle: {\r\n id: 'acute_triangle',\r\n type: 'triangle',\r\n vertices: [[2, 2], [8, 2], [5, 6]],\r\n description: '锐角三角形'\r\n },\r\n right_triangle: {\r\n id: 'right_triangle',\r\n type: 'triangle',\r\n vertices: [[2, 2], [2, 6], [6, 6]],\r\n description: '直角三角形'\r\n },\r\n rectangle: {\r\n id: 'rectangle',\r\n type: 'rectangle',\r\n dimensions: { width: 6, height: 4 },\r\n description: '矩形'\r\n }\r\n} as const;\r\n\r\n/**\r\n * 默认变换定义\r\n */\r\nexport const DEFAULT_TRANSFORM_DEFINITIONS = {\r\n left_rotation: {\r\n id: 'left_rotation',\r\n type: 'rotation',\r\n angle: -90,\r\n origin: [0, 0],\r\n description: '向左旋转90度'\r\n },\r\n right_rotation: {\r\n id: 'right_rotation',\r\n type: 'rotation',\r\n angle: 90,\r\n origin: [0, 0],\r\n description: '向右旋转90度'\r\n },\r\n translation: {\r\n id: 'translation',\r\n type: 'translation',\r\n dx: 0,\r\n dy: 0,\r\n description: '平移变换'\r\n }\r\n} as const;\r\n\r\n/**\r\n * 默认回退数据(当适配失败时使用)\r\n */\r\nexport const DEFAULT_FALLBACK_DATA = {\r\n id: 'fallback-triangle-problem',\r\n title: '三角形面积计算',\r\n grade: 5,\r\n unit: '三角形面积计算',\r\n lesson: '锐角三角形的面积',\r\n skill: '已知锐角三角形的底和高,求三角形面积',\r\n objective: '掌握锐角三角形面积公式 A=½bh',\r\n knowledgePoints: ['三角形面积公式 A=½bh'],\r\n difficulty: 1,\r\n metadata: {\r\n topic: '三角形面积计算',\r\n skill: '三角形面积求解技能',\r\n tags: ['锐角三角形', '三角形面积公式']\r\n },\r\n basicInfo: {\r\n question: '以下三角形面积是多少?',\r\n base: 6,\r\n height: 4,\r\n baseUnit: 'cm',\r\n heightUnit: 'cm',\r\n answerUnit: 'cm²'\r\n },\r\n scenes: {\r\n question: { content: [], layout: { type: 'card' } },\r\n solve: { content: [], layout: { type: 'card' } },\r\n review: { content: [], layout: { type: 'card' } }\r\n },\r\n explanation: { steps: [] },\r\n answer: {\r\n value: 12,\r\n unit: 'cm²',\r\n explanation: '三角形面积公式为 A = ½ × 底 × 高 = ½ × 6 × 4 = 12'\r\n }\r\n} as const;\r\n\r\n// ============================================================================\r\n// 错误消息常量\r\n// ============================================================================\r\n\r\n/**\r\n * 错误消息映射\r\n */\r\nexport const ERROR_MESSAGES: { [key: string]: string } = {\r\n [AdapterErrorCode.INVALID_INPUT]: '输入数据无效',\r\n [AdapterErrorCode.MISSING_REQUIRED_FIELD]: '缺少必需字段',\r\n [AdapterErrorCode.DESIGN_TOKEN_NOT_FOUND]: '设计令牌未找到',\r\n [AdapterErrorCode.GEOMETRY_REF_NOT_FOUND]: '几何引用未找到',\r\n [AdapterErrorCode.TRANSFORM_REF_NOT_FOUND]: '变换引用未找到',\r\n [AdapterErrorCode.STYLE_REF_NOT_FOUND]: '样式引用未找到',\r\n [AdapterErrorCode.ANIMATION_REF_NOT_FOUND]: '动画引用未找到',\r\n [AdapterErrorCode.BOARD_REF_NOT_FOUND]: '画板引用未找到',\r\n [AdapterErrorCode.GEOMETRY_TRANSFORM_REF_NOT_FOUND]: '几何变换引用未找到',\r\n [AdapterErrorCode.SLIDER_REF_NOT_FOUND]: '滑块引用未找到',\r\n [AdapterErrorCode.TRANSFORMATION_FAILED]: '数据转换失败',\r\n [AdapterErrorCode.OUTPUT_VALIDATION_FAILED]: '输出验证失败'\r\n};\r\n\r\n/**\r\n * 警告消息\r\n */\r\nexport const WARNING_MESSAGES = {\r\n DESIGN_TOKEN_FALLBACK: '设计令牌未找到,使用默认值',\r\n GEOMETRY_REF_FALLBACK: '几何引用未找到,使用默认几何',\r\n TRANSFORM_REF_FALLBACK: '变换引用未找到,跳过变换',\r\n STYLE_REF_FALLBACK: '样式引用未找到,使用默认样式',\r\n ANIMATION_REF_FALLBACK: '动画引用未找到,使用默认动画配置',\r\n BOARD_REF_FALLBACK: '画板引用未找到,使用默认画板配置',\r\n GEOMETRY_TRANSFORM_REF_FALLBACK: '几何变换引用未找到,使用默认配置',\r\n SLIDER_REF_FALLBACK: '滑块引用未找到,使用默认滑块配置',\r\n VALIDATION_WARNING: '验证警告,数据可能不完整',\r\n PERFORMANCE_WARNING: '性能警告,转换时间较长'\r\n} as const;\r\n\r\n// ============================================================================\r\n// 性能常量\r\n// ============================================================================\r\n\r\n/**\r\n * 性能阈值(毫秒)\r\n */\r\nexport const PERFORMANCE_THRESHOLDS = {\r\n MAX_TRANSFORMATION_TIME: 5, // 最大转换时间 5ms\r\n MAX_MEMORY_INCREASE: 50 * 1024, // 最大内存增加 50KB\r\n MAX_REFERENCE_DEPTH: 10, // 最大引用深度\r\n WARNING_TRANSFORMATION_TIME: 10 // 警告转换时间 10ms\r\n} as const;\r\n\r\n// ============================================================================\r\n// 验证常量\r\n// ============================================================================\r\n\r\n/**\r\n * 必需字段列表\r\n */\r\nexport const REQUIRED_FIELDS = {\r\n RAW_DATA: [\r\n 'math_prob_id',\r\n 'title',\r\n 'grade_id',\r\n 'unit_name',\r\n 'lesson_name',\r\n 'skill_description',\r\n 'objective',\r\n 'knowledge_points',\r\n 'difficulty',\r\n 'basic_info',\r\n 'scenes',\r\n 'explanation',\r\n 'answer_info'\r\n ],\r\n BASIC_INFO: ['question'],\r\n ANSWER_INFO: ['value', 'unit', 'explanation_text']\r\n} as const;\r\n\r\n/**\r\n * 场景名称枚举\r\n */\r\nexport const SCENE_NAMES = ['question', 'solve', 'review', 'remember'] as const;\r\n\r\n// ============================================================================\r\n// 引用解析常量\r\n// ============================================================================\r\n\r\n/**\r\n * 引用前缀映射\r\n */\r\nexport const REFERENCE_PREFIXES = {\r\n DESIGN_TOKEN: '$',\r\n STYLE_REF: 'styleRef:',\r\n GEOMETRY_REF: 'geometryRef:',\r\n TRANSFORM_REF: 'transformRef:',\r\n LAYOUT_REF: 'layoutRef:',\r\n ANIMATION_REF: 'animationRef:',\r\n BOARD_REF: 'boardRef:',\r\n GEOMETRY_TRANSFORM_REF: 'geometryTransformRef:',\r\n SLIDER_REF: 'sliderRef:'\r\n} as const;\r\n\r\n/**\r\n * 引用正则表达式\r\n */\r\nexport const REFERENCE_PATTERNS = {\r\n DESIGN_TOKEN: /^\\$([a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*)$/,\r\n STYLE_REF: /^styleRef:([a-zA-Z_][a-zA-Z0-9_]*)$/,\r\n GEOMETRY_REF: /^geometryRef:([a-zA-Z_][a-zA-Z0-9_]*)$/,\r\n TRANSFORM_REF: /^transformRef:([a-zA-Z_][a-zA-Z0-9_]*)$/,\r\n LAYOUT_REF: /^layoutRef:([a-zA-Z_][a-zA-Z0-9_]*)$/,\r\n ANIMATION_REF: /^animationRef:([a-zA-Z_][a-zA-Z0-9_]*)$/,\r\n BOARD_REF: /^boardRef:([a-zA-Z_][a-zA-Z0-9_]*)$/,\r\n GEOMETRY_TRANSFORM_REF: /^geometryTransformRef:([a-zA-Z_][a-zA-Z0-9_]*)$/,\r\n SLIDER_REF: /^sliderRef:([a-zA-Z_][a-zA-Z0-9_]*)$/\r\n} as const;\r\n\r\n// ============================================================================\r\n// 组件类型常量\r\n// ============================================================================\r\n\r\n/**\r\n * 内容块类型\r\n */\r\nexport const CONTENT_BLOCK_TYPES = {\r\n TEXT: 'text',\r\n FORMULA: 'formula',\r\n GRAPH: 'graph',\r\n GEOMETRY_TRANSFORM: 'geometryTransform',\r\n HUNDRED_GRID: 'hundredGrid',\r\n PLACE_VALUE_CHART: 'placeValueChart'\r\n} as const;\r\n\r\n/**\r\n * 布局类型\r\n */\r\nexport const LAYOUT_TYPES = {\r\n CARD: 'card',\r\n VERTICAL: 'vertical',\r\n HORIZONTAL: 'horizontal',\r\n GRID: 'grid',\r\n PANEL: 'panel'\r\n} as const;","/**\r\n * TriangleAdapterV3 嵌入式配置\r\n *\r\n * 同步适配器使用的嵌入式配置,替代网络加载的JSON配置。\r\n * 基于现有嵌入式配置简化,专注于核心功能。\r\n */\r\n\r\n// ============================================================================\r\n// 设计令牌配置(简化版)\r\n// ============================================================================\r\n\r\nexport const EMBEDDED_DESIGN_TOKENS = {\r\n config_version: \"1.0.0\",\r\n design_tokens: {\r\n colors: {\r\n primary: \"#4a90e2\",\r\n primary_light: \"#8ec5fc\",\r\n error: \"#FF5252\",\r\n success: \"#7ED321\",\r\n success_dark: \"#67b510\",\r\n highlight_left: \"#6a5acd\",\r\n highlight_right: \"#FF6B6B\",\r\n highlight_yellow: \"#FFFFE0\",\r\n text_primary: \"#333\",\r\n text_secondary: \"#666\",\r\n background_light: \"#F8FAFC\",\r\n background_lighter: \"#F0F9FF\",\r\n background_gray: \"#f9f9f9\",\r\n border_light: \"#E3F2FD\",\r\n border_lighter: \"#BAE6FD\"\r\n },\r\n fonts: {\r\n heading_large: \"1.8rem\",\r\n heading_normal: \"1.2rem\",\r\n body: \"1rem\",\r\n label: \"16px\",\r\n formula: \"1.1rem\"\r\n },\r\n spacing: {\r\n large: \"20px\",\r\n medium: \"15px\",\r\n small: \"10px\",\r\n tiny: \"5px\"\r\n },\r\n geometry: {\r\n stroke_width_normal: 2,\r\n stroke_width_thick: 3,\r\n stroke_width_thin: 1.5,\r\n opacity_normal: 0.8,\r\n opacity_light: 0.3,\r\n opacity_medium: 0.7,\r\n dash_normal: 2,\r\n dash_long: 4\r\n }\r\n }\r\n} as const;\r\n\r\n// ============================================================================\r\n// 样式预设配置(简化版)\r\n// ============================================================================\r\n\r\nexport const EMBEDDED_STYLE_PRESETS = {\r\n config_version: \"1.0.0\",\r\n style_presets: {\r\n primary: {\r\n id: \"primary\",\r\n fillColor: \"$colors.primary_light\",\r\n fillOpacity: \"$geometry.opacity_normal\",\r\n strokeColor: \"$colors.primary\",\r\n strokeWidth: \"$geometry.stroke_width_normal\"\r\n },\r\n secondary: {\r\n id: \"secondary\",\r\n fillColor: \"$colors.background_light\",\r\n fillOpacity: \"$geometry.opacity_medium\",\r\n strokeColor: \"$colors.text_secondary\",\r\n strokeWidth: \"$geometry.stroke_width_normal\"\r\n },\r\n transparent: {\r\n id: \"transparent\",\r\n fillColor: \"$colors.primary_light\",\r\n fillOpacity: \"$geometry.opacity_light\",\r\n strokeColor: \"$colors.text_secondary\",\r\n strokeWidth: \"$geometry.stroke_width_normal\"\r\n },\r\n highlight: {\r\n id: \"highlight\",\r\n fillColor: \"$colors.highlight_yellow\",\r\n fillOpacity: \"$geometry.opacity_medium\",\r\n strokeColor: \"$colors.primary\",\r\n strokeWidth: \"$geometry.stroke_width_thick\"\r\n },\r\n error: {\r\n id: \"error\",\r\n fillColor: \"transparent\",\r\n strokeColor: \"$colors.error\",\r\n strokeWidth: \"$geometry.stroke_width_thick\"\r\n },\r\n success: {\r\n id: \"success\",\r\n fillColor: \"$colors.success\",\r\n fillOpacity: \"$geometry.opacity_normal\",\r\n strokeColor: \"$colors.success_dark\",\r\n strokeWidth: \"$geometry.stroke_width_normal\"\r\n },\r\n dashed: {\r\n id: \"dashed\",\r\n strokeColor: \"$colors.text_secondary\",\r\n strokeWidth: \"$geometry.stroke_width_normal\",\r\n dash: \"$geometry.dash_normal\"\r\n },\r\n text_primary: {\r\n id: \"text_primary\",\r\n color: \"$colors.text_primary\",\r\n fontSize: \"$fonts.body\"\r\n },\r\n text_heading_large: {\r\n id: \"text_heading_large\",\r\n color: \"$colors.text_primary\",\r\n fontSize: \"$fonts.heading_large\",\r\n fontWeight: \"bold\"\r\n },\r\n // 新增通用样式预设\r\n base_highlight: {\r\n id: \"base_highlight\",\r\n strokeColor: \"$colors.error\",\r\n strokeWidth: \"$geometry.stroke_width_thick\",\r\n fillColor: \"transparent\"\r\n },\r\n label_position: {\r\n id: \"label_position\",\r\n color: \"$colors.text_primary\",\r\n fontSize: \"$fonts.label\",\r\n fontWeight: \"bold\",\r\n textAlign: \"center\"\r\n },\r\n highlight_left: {\r\n id: \"highlight_left\",\r\n fillColor: \"$colors.highlight_left\",\r\n fillOpacity: \"$geometry.opacity_medium\",\r\n strokeColor: \"$colors.primary\",\r\n strokeWidth: \"$geometry.stroke_width_normal\"\r\n },\r\n highlight_right: {\r\n id: \"highlight_right\",\r\n fillColor: \"$colors.highlight_right\",\r\n fillOpacity: \"$geometry.opacity_medium\",\r\n strokeColor: \"$colors.primary\",\r\n strokeWidth: \"$geometry.stroke_width_normal\"\r\n },\r\n label_error: {\r\n id: \"label_error\",\r\n color: \"$colors.error\",\r\n fontSize: \"$fonts.label\",\r\n fontWeight: \"bold\"\r\n }\r\n }\r\n} as const;\r\n\r\n// ============================================================================\r\n// 几何预设配置(简化版)\r\n// ============================================================================\r\n\r\nexport const EMBEDDED_GEOMETRY_PRESETS = {\r\n config_version: \"1.0.0\",\r\n geometry_presets: {\r\n acute_triangle: {\r\n id: \"acute_triangle\",\r\n type: \"polygon\",\r\n vertices: [[100, 300], [300, 100], [500, 300]],\r\n styleRef: \"primary\",\r\n description: \"锐角三角形\"\r\n },\r\n right_triangle: {\r\n id: \"right_triangle\",\r\n type: \"triangle\",\r\n vertices: [[100, 100], [100, 300], [300, 300]],\r\n styleRef: \"secondary\",\r\n description: \"直角三角形\"\r\n },\r\n equilateral_triangle: {\r\n id: \"equilateral_triangle\",\r\n type: \"triangle\",\r\n vertices: [[200, 100], [100, 273], [300, 273]],\r\n styleRef: \"highlight\",\r\n description: \"等边三角形\"\r\n },\r\n rectangle: {\r\n id: \"rectangle\",\r\n type: \"rectangle\",\r\n dimensions: { width: 200, height: 100 },\r\n styleRef: \"primary\",\r\n description: \"矩形\"\r\n },\r\n parallelogram: {\r\n id: \"parallelogram\",\r\n type: \"parallelogram\",\r\n vertices: [[100, 100], [300, 100], [250, 200], [50, 200]],\r\n styleRef: \"secondary\",\r\n description: \"平行四边形\"\r\n },\r\n // 通用线段预设\r\n horizontal_line: {\r\n id: \"horizontal_line\",\r\n type: \"segment\",\r\n endpoints: [[0, 0], [100, 0]], // 标准化水平线\r\n styleRef: \"primary\",\r\n description: \"水平线段模板\"\r\n },\r\n vertical_line: {\r\n id: \"vertical_line\",\r\n type: \"segment\",\r\n endpoints: [[0, 0], [0, 100]], // 标准化垂直线\r\n styleRef: \"primary\",\r\n description: \"垂直线段模板\"\r\n },\r\n arrow_line: {\r\n id: \"arrow_line\",\r\n type: \"segment\",\r\n endpoints: [[0, 0], [100, 0]], // 标准化线段,可添加箭头\r\n styleRef: \"error\",\r\n description: \"箭头线段模板\"\r\n },\r\n // 通用点预设\r\n label_point: {\r\n id: \"label_point\",\r\n type: \"point\",\r\n position: [50, 20], // 标准化标签位置\r\n styleRef: \"text_primary\",\r\n description: \"标签位置点模板\"\r\n },\r\n center_point: {\r\n id: \"center_point\",\r\n type: \"point\",\r\n position: [50, 50], // 标准化中心位置\r\n styleRef: \"primary\",\r\n description: \"中心点模板\"\r\n },\r\n vertex_point: {\r\n id: \"vertex_point\",\r\n type: \"point\",\r\n position: [0, 0], // 标准化顶点位置\r\n styleRef: \"primary\",\r\n description: \"顶点点模板\"\r\n },\r\n marker_point: {\r\n id: \"marker_point\",\r\n type: \"point\",\r\n position: [0, 0], // 标准化标记位置\r\n styleRef: \"highlight\",\r\n description: \"标记点模板\"\r\n },\r\n // 具体三角形预设(保持兼容性)\r\n left_triangle: {\r\n id: \"left_triangle\",\r\n type: \"polygon\",\r\n vertices: [[100, 100], [100, 300], [250, 300]],\r\n styleRef: \"highlight_left\",\r\n description: \"左三角形模板\"\r\n }\r\n }\r\n} as const;\r\n\r\n// ============================================================================\r\n// 布局预设配置(简化版)\r\n// ============================================================================\r\n\r\nexport const EMBEDDED_LAYOUT_PRESETS = {\r\n config_version: \"1.0.0\",\r\n layout_presets: {\r\n card: {\r\n id: \"card\",\r\n type: \"card\",\r\n padding: \"$spacing.large\",\r\n theme: \"light\"\r\n },\r\n vertical_centered: {\r\n id: \"vertical_centered\",\r\n type: \"vertical\",\r\n spacing: \"$spacing.large\",\r\n alignment: \"center\"\r\n },\r\n vertical_spaced: {\r\n id: \"vertical_spaced\",\r\n type: \"vertical\",\r\n spacing: \"$spacing.medium\",\r\n alignment: \"start\"\r\n },\r\n grid_2col: {\r\n id: \"grid_2col\",\r\n type: \"grid\",\r\n columns: 2,\r\n spacing: \"$spacing.medium\"\r\n }\r\n }\r\n} as const;\r\n\r\n// ============================================================================\r\n// 变换定义配置\r\n// ============================================================================\r\n\r\nexport const EMBEDDED_TRANSFORM_DEFINITIONS = {\r\n config_version: \"1.0.0\",\r\n transform_definitions: {\r\n left_rotation: {\r\n id: \"left_rotation\",\r\n type: \"rotation\",\r\n angle: -90,\r\n origin: [0, 0],\r\n description: \"向左旋转90度\"\r\n },\r\n right_rotation: {\r\n id: \"right_rotation\",\r\n type: \"rotation\",\r\n angle: 90,\r\n origin: [0, 0],\r\n description: \"向右旋转90度\"\r\n },\r\n translation: {\r\n id: \"translation\",\r\n type: \"translation\",\r\n dx: 0,\r\n dy: 0,\r\n description: \"平移变换\"\r\n },\r\n scale: {\r\n id: \"scale\",\r\n type: \"scale\",\r\n factor: 1,\r\n origin: [0, 0],\r\n description: \"缩放变换\"\r\n }\r\n }\r\n} as const;\r\n\r\n// ============================================================================\r\n// 动画滑块定义配置\r\n// ============================================================================\r\n\r\nexport const EMBEDDED_ANIMATION_DEFINITIONS = {\r\n config_version: \"1.0.0\",\r\n slider_definitions: {\r\n slider_horizontal: {\r\n id: \"slider_horizontal\",\r\n slider: {\r\n position: [0, -6] as [number, number],\r\n length: 10,\r\n orientation: 'horizontal' as const,\r\n min: 0,\r\n max: 1,\r\n step: 0.01\r\n },\r\n progressIndicator: {\r\n enabled: true,\r\n stages: 4,\r\n labels: ['开始', '25%', '50%', '75%', '完成'],\r\n showPercentage: true\r\n },\r\n duration: 2000,\r\n easing: 'ease-in-out' as const,\r\n description: \"水平滑块动画\"\r\n },\r\n slider_vertical: {\r\n id: \"slider_vertical\",\r\n slider: {\r\n position: [-6, 0] as [number, number],\r\n length: 10,\r\n orientation: 'vertical' as const,\r\n min: 0,\r\n max: 1,\r\n step: 0.01\r\n },\r\n progressIndicator: {\r\n enabled: true,\r\n stages: 4,\r\n labels: ['开始', '25%', '50%', '75%', '完成'],\r\n showPercentage: true\r\n },\r\n duration: 2000,\r\n easing: 'ease-in-out' as const,\r\n description: \"垂直滑块动画\"\r\n }\r\n }\r\n} as const;\r\n\r\n// ============================================================================\r\n// 画板定义配置\r\n// ============================================================================\r\n\r\nexport const EMBEDDED_BOARD_DEFINITIONS = {\r\n config_version: \"1.0.0\",\r\n board_definitions: {\r\n default: {\r\n id: \"default\",\r\n originX: 2,\r\n originY: 2,\r\n boundingBox: [0, 7, 10, 0] as [number, number, number, number],\r\n keepAspectRatio: true,\r\n showGrid: false,\r\n showAxis: false,\r\n description: \"默认画板配置\"\r\n },\r\n extended: {\r\n id: \"extended\",\r\n originX: 0,\r\n originY: 0,\r\n boundingBox: [-5, 12, 15, -5] as [number, number, number, number],\r\n keepAspectRatio: true,\r\n showGrid: true,\r\n showAxis: true,\r\n gridSize: 1,\r\n description: \"扩展画板配置(带网格和坐标轴)\"\r\n }\r\n }\r\n} as const;\r\n\r\n// ============================================================================\r\n// 全局配置上下文\r\n// ============================================================================\r\n\r\n/**\r\n * 全局引用解析上下文\r\n */\r\nexport const GLOBAL_REFERENCE_CONTEXT = {\r\n designTokens: EMBEDDED_DESIGN_TOKENS.design_tokens,\r\n stylePresets: EMBEDDED_STYLE_PRESETS.style_presets,\r\n geometryPresets: EMBEDDED_GEOMETRY_PRESETS.geometry_presets,\r\n layoutPresets: EMBEDDED_LAYOUT_PRESETS.layout_presets,\r\n transformDefinitions: EMBEDDED_TRANSFORM_DEFINITIONS.transform_definitions,\r\n // 同时提供两个字段名,确保兼容性\r\n animationDefinitions: EMBEDDED_ANIMATION_DEFINITIONS.slider_definitions,\r\n animationConfigs: EMBEDDED_ANIMATION_DEFINITIONS.slider_definitions,\r\n boardDefinitions: EMBEDDED_BOARD_DEFINITIONS.board_definitions\r\n} as const;\r\n\r\n// ============================================================================\r\n// 配置文件索引\r\n// ============================================================================\r\n\r\nexport const EMBEDDED_CONFIG_MAP = {\r\n 'design-tokens': EMBEDDED_DESIGN_TOKENS,\r\n 'style-presets': EMBEDDED_STYLE_PRESETS,\r\n 'geometry-presets': EMBEDDED_GEOMETRY_PRESETS,\r\n 'layout-presets': EMBEDDED_LAYOUT_PRESETS,\r\n 'transform-definitions': EMBEDDED_TRANSFORM_DEFINITIONS,\r\n 'animation-definitions': EMBEDDED_ANIMATION_DEFINITIONS,\r\n 'board-definitions': EMBEDDED_BOARD_DEFINITIONS\r\n} as const;","/**\r\n * TriangleAdapterV3 配置模块导出\r\n */\r\n\r\nexport * from './embeddedConfigs';\r\n\r\nimport {\r\n EMBEDDED_DESIGN_TOKENS,\r\n EMBEDDED_STYLE_PRESETS,\r\n EMBEDDED_GEOMETRY_PRESETS,\r\n EMBEDDED_LAYOUT_PRESETS,\r\n EMBEDDED_TRANSFORM_DEFINITIONS,\r\n EMBEDDED_ANIMATION_DEFINITIONS,\r\n EMBEDDED_BOARD_DEFINITIONS,\r\n EMBEDDED_CONFIG_MAP\r\n} from './embeddedConfigs';\r\n\r\n/**\r\n * 获取默认配置上下文\r\n */\r\nexport function getDefaultReferenceContext() {\r\n console.error('🔍 getDefaultReferenceContext called:', {\r\n hasEmbeddedAnimationDefinitions: !!EMBEDDED_ANIMATION_DEFINITIONS,\r\n sliderDefinitionsKeys: EMBEDDED_ANIMATION_DEFINITIONS.slider_definitions ? Object.keys(EMBEDDED_ANIMATION_DEFINITIONS.slider_definitions) : []\r\n });\r\n\r\n // 同时提供 animationDefinitions 和 animationConfigs 两个别名\r\n // 确保 SliderRefResolver 无论查找哪个字段都能找到滑块配置\r\n const sliderDefinitions = EMBEDDED_ANIMATION_DEFINITIONS.slider_definitions;\r\n\r\n return {\r\n designTokens: EMBEDDED_DESIGN_TOKENS.design_tokens,\r\n stylePresets: EMBEDDED_STYLE_PRESETS.style_presets,\r\n geometryPresets: EMBEDDED_GEOMETRY_PRESETS.geometry_presets,\r\n layoutPresets: EMBEDDED_LAYOUT_PRESETS.layout_presets,\r\n transformDefinitions: EMBEDDED_TRANSFORM_DEFINITIONS.transform_definitions,\r\n // 同时提供两个字段名,确保兼容性\r\n animationDefinitions: sliderDefinitions,\r\n animationConfigs: sliderDefinitions,\r\n boardDefinitions: EMBEDDED_BOARD_DEFINITIONS.board_definitions\r\n };\r\n}\r\n\r\n/**\r\n * 获取配置项\r\n */\r\nexport function getConfig(configName: keyof typeof EMBEDDED_CONFIG_MAP) {\r\n return EMBEDDED_CONFIG_MAP[configName];\r\n}\r\n\r\n/**\r\n * 检查配置版本\r\n */\r\nexport function checkConfigVersion(config: any): boolean {\r\n return config?.config_version === '1.0.0';\r\n}","/**\r\n * 设计令牌解析器\r\n *\r\n * 解析 $colors.primary 等设计令牌引用\r\n */\r\n\r\nimport type { ReferenceContext } from '../types';\r\nimport { ReferenceType } from '../types';\r\nimport { REFERENCE_PATTERNS } from '../constants';\r\n\r\n/**\r\n * 设计令牌解析器\r\n */\r\nexport class DesignTokenResolver {\r\n /**\r\n * 检查是否能够解析该引用\r\n */\r\n static canResolve(ref: string): boolean {\r\n return REFERENCE_PATTERNS.DESIGN_TOKEN.test(ref);\r\n }\r\n\r\n /**\r\n * 解析设计令牌引用\r\n */\r\n static resolve(ref: string, context: ReferenceContext): any {\r\n if (!this.canResolve(ref)) {\r\n throw new Error(`无法解析的设计令牌引用: ${ref}`);\r\n }\r\n\r\n // 移除 $ 前缀\r\n const path = ref.substring(1);\r\n return this.resolvePath(path, context.designTokens);\r\n }\r\n\r\n /**\r\n * 根据路径解析令牌值\r\n */\r\n private static resolvePath(path: string, tokens: Record<string, any>): any {\r\n const parts = path.split('.');\r\n let current: any = tokens;\r\n\r\n for (const part of parts) {\r\n if (current === undefined || current === null) {\r\n throw new Error(`设计令牌路径不存在: ${path} (在 ${part} 处中断)`);\r\n }\r\n\r\n if (typeof current !== 'object') {\r\n throw new Error(`设计令牌路径无效: ${path} (${part} 不是对象)`);\r\n }\r\n\r\n current = current[part];\r\n }\r\n\r\n if (current === undefined) {\r\n throw new Error(`设计令牌未找到: ${path}`);\r\n }\r\n\r\n return current;\r\n }\r\n\r\n /**\r\n * 批量解析设计令牌引用\r\n */\r\n static batchResolve(refs: string[], context: ReferenceContext): Record<string, any> {\r\n const results: Record<string, any> = {};\r\n\r\n for (const ref of refs) {\r\n if (this.canResolve(ref)) {\r\n try {\r\n results[ref] = this.resolve(ref, context);\r\n } catch (error) {\r\n // 在严格模式下会抛出异常,这里仅记录\r\n console.warn(`设计令牌解析失败: ${ref}`, error);\r\n }\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * 提取对象中的所有设计令牌引用\r\n */\r\n static extractDesignTokenRefs(obj: any): string[] {\r\n const refs: string[] = [];\r\n\r\n const traverse = (value: any) => {\r\n if (typeof value === 'string') {\r\n if (this.canResolve(value)) {\r\n refs.push(value);\r\n }\r\n } else if (Array.isArray(value)) {\r\n value.forEach(traverse);\r\n } else if (typeof value === 'object' && value !== null) {\r\n Object.values(value).forEach(traverse);\r\n }\r\n };\r\n\r\n traverse(obj);\r\n return refs;\r\n }\r\n\r\n /**\r\n * 替换对象中的设计令牌引用\r\n */\r\n static replaceDesignTokenRefs(\r\n obj: any,\r\n context: ReferenceContext,\r\n onMissing?: (ref: string) => any\r\n ): any {\r\n const replace = (value: any): any => {\r\n if (typeof value === 'string') {\r\n // 检查整个字符串是否是设计令牌引用\r\n if (this.canResolve(value)) {\r\n try {\r\n return this.resolve(value, context);\r\n } catch (error) {\r\n if (onMissing) {\r\n return onMissing(value);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n // 检查字符串中是否包含设计令牌引用\r\n // 使用正则表达式查找所有 $xxx.yyy 模式的子串\r\n const tokenRegex = /\\$([a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*)/g;\r\n let result = value;\r\n let match;\r\n let lastIndex = 0;\r\n const parts: string[] = [];\r\n\r\n while ((match = tokenRegex.exec(value)) !== null) {\r\n // 添加非令牌部分\r\n if (match.index > lastIndex) {\r\n parts.push(value.substring(lastIndex, match.index));\r\n }\r\n\r\n const token = match[0];\r\n try {\r\n const resolved = this.resolve(token, context);\r\n parts.push(String(resolved));\r\n } catch (error) {\r\n if (onMissing) {\r\n parts.push(String(onMissing(token)));\r\n } else {\r\n // 如果无法解析且没有onMissing回调,保留原始令牌\r\n parts.push(token);\r\n }\r\n }\r\n\r\n lastIndex = match.index + token.length;\r\n }\r\n\r\n // 添加剩余部分\r\n if (lastIndex < value.length) {\r\n parts.push(value.substring(lastIndex));\r\n }\r\n\r\n // 如果有替换发生,返回新字符串\r\n if (parts.length > 1) {\r\n return parts.join('');\r\n }\r\n\r\n return value;\r\n } else if (Array.isArray(value)) {\r\n return value.map(replace);\r\n } else if (typeof value === 'object' && value !== null) {\r\n const result: Record<string, any> = {};\r\n for (const [key, val] of Object.entries(value)) {\r\n result[key] = replace(val);\r\n }\r\n return result;\r\n }\r\n return value;\r\n };\r\n\r\n return replace(obj);\r\n }\r\n}\r\n\r\n/**\r\n * 设计令牌解析器工厂函数\r\n */\r\nexport function createDesignTokenResolver() {\r\n return {\r\n type: ReferenceType.DESIGN_TOKEN,\r\n canResolve: DesignTokenResolver.canResolve.bind(DesignTokenResolver),\r\n resolve: DesignTokenResolver.resolve.bind(DesignTokenResolver)\r\n };\r\n}","/**\r\n * 几何引用解析器\r\n *\r\n * 解析 geometryRef:acute_triangle 等几何引用\r\n */\r\n\r\nimport type { ReferenceContext } from '../types';\r\nimport { ReferenceType } from '../types';\r\nimport { REFERENCE_PATTERNS } from '../constants';\r\n\r\n/**\r\n * 几何引用解析器\r\n */\r\nexport class GeometryRefResolver {\r\n /**\r\n * 检查是否能够解析该引用\r\n */\r\n static canResolve(ref: string, context?: ReferenceContext): boolean {\r\n if (typeof ref !== 'string' || ref.length === 0) {\r\n return false;\r\n }\r\n\r\n // 检查是否是 geometryRef:xxx 格式\r\n if (REFERENCE_PATTERNS.GEOMETRY_REF.test(ref)) {\r\n return true;\r\n }\r\n\r\n // 检查是否是通用的几何元素命名模式\r\n // 支持:point_xxx, segment_xxx, line_xxx, triangle_xxx 等\r\n const geometryPatterns = [\r\n /^point_[a-zA-Z0-9_]+$/, // point_a, point_b, point_c1\r\n /^segment_[a-zA-Z0-9_]+$/, // segment_ab, segment_1\r\n /^line_[a-zA-Z0-9_]+$/, // line_1, line_horizontal\r\n /^triangle_[a-zA-Z0-9_]+$/, // triangle_left, triangle_1\r\n /^polygon_[a-zA-Z0-9_]+$/, // polygon_main, polygon_1\r\n /^circle_[a-zA-Z0-9_]+$/, // circle_1, circle_main\r\n /^angle_[a-zA-Z0-9_]+$/, // angle_abc, angle_1\r\n /^vector_[a-zA-Z0-9_]+$/, // vector_v1, vector_2\r\n /^arc_[a-zA-Z0-9_]+$/, // arc_ab, arc_main\r\n /^ray_[a-zA-Z0-9_]+$/, // ray_oa, ray_1\r\n ];\r\n\r\n if (geometryPatterns.some(pattern => pattern.test(ref))) {\r\n return true;\r\n }\r\n\r\n // 如果提供了context,检查引用是否在geometryPresets中\r\n if (context && context.geometryPresets) {\r\n // 提取几何名称\r\n let geometryName: string;\r\n const match = ref.match(REFERENCE_PATTERNS.GEOMETRY_REF);\r\n if (match) {\r\n geometryName = match[1];\r\n } else {\r\n geometryName = ref;\r\n }\r\n return geometryName in context.geometryPresets;\r\n }\r\n\r\n // 检查是否是已知的几何名称(避免将普通文本误判为几何引用)\r\n // 已知的几何名称:从嵌入式配置中提取\r\n const knownGeometryNames = [\r\n 'acute_triangle', 'right_triangle', 'equilateral_triangle',\r\n 'rectangle', 'parallelogram', 'horizontal_line', 'vertical_line',\r\n 'arrow_line', 'label_point', 'center_point', 'vertex_point',\r\n 'marker_point', 'left_triangle', 'right_triangle',\r\n 'base_segment', 'height_segment', 'base_arrow', 'height_arrow',\r\n 'full_rectangle'\r\n ];\r\n return knownGeometryNames.includes(ref);\r\n }\r\n\r\n /**\r\n * 解析顶点引用($ref 格式)\r\n */\r\n private static resolveVertexReference(vertex: any, context: ReferenceContext): any {\r\n console.error('🔍 GeometryRefResolver.resolveVertexReference:', {\r\n input: vertex,\r\n isRef: vertex && typeof vertex === 'object' && '$ref' in vertex,\r\n refName: vertex?.$ref,\r\n hasContext: !!context.geometryPresets,\r\n pointFound: context.geometryPresets?.[vertex?.$ref] ? true : false\r\n });\r\n\r\n // 处理$ref引用\r\n if (vertex && typeof vertex === 'object' && '$ref' in vertex) {\r\n const refName = vertex.$ref;\r\n if (context.geometryPresets && context.geometryPresets[refName]) {\r\n const point = context.geometryPresets[refName];\r\n // 点对象应该包含position属性或x/y坐标\r\n if (point.position) {\r\n console.error(`✅ 解析顶点引用 ${refName}: 使用 position`, point.position);\r\n return [point.position.x, point.position.y];\r\n }\r\n if ('x' in point && 'y' in point) {\r\n console.error(`✅ 解析顶点引用 ${refName}: 使用 x/y`, { x: point.x, y: point.y });\r\n return [point.x, point.y];\r\n }\r\n }\r\n console.warn(`无法解析顶点引用: ${refName}`);\r\n return vertex; // 返回原始引用,让后续验证捕获错误\r\n }\r\n\r\n // 已经是数组格式或对象格式,确保转换为数组格式\r\n if (Array.isArray(vertex) && vertex.length === 2) {\r\n return vertex;\r\n } else if (vertex && typeof vertex === 'object' && 'x' in vertex && 'y' in vertex) {\r\n return [vertex.x, vertex.y];\r\n }\r\n\r\n return vertex;\r\n }\r\n\r\n /**\r\n * 解析几何引用\r\n */\r\n static resolve(ref: string, context: ReferenceContext): any {\r\n if (!this.canResolve(ref, context)) {\r\n throw new Error(`无法解析的几何引用: ${ref}`);\r\n }\r\n\r\n // 提取几何名称\r\n let geometryName: string;\r\n const match = ref.match(REFERENCE_PATTERNS.GEOMETRY_REF);\r\n if (match) {\r\n // 格式: geometryRef:xxx\r\n geometryName = match[1];\r\n } else {\r\n // 格式: xxx (直接名称)\r\n geometryName = ref;\r\n }\r\n\r\n console.error(`🔍 GeometryRefResolver.resolve: ref=\"${ref}\", geometryName=\"${geometryName}\"`);\r\n console.error(` Available geometryPresets:`, Object.keys(context.geometryPresets || {}));\r\n\r\n const geometry = context.geometryPresets[geometryName];\r\n\r\n if (!geometry) {\r\n console.error(`❌ Geometry preset not found: ${geometryName} in`, context.geometryPresets);\r\n throw new Error(`几何预设未找到: ${geometryName}`);\r\n }\r\n\r\n console.error(`✅ Geometry resolved:`, {\r\n name: geometryName,\r\n type: geometry.type,\r\n hasVertices: 'vertices' in geometry,\r\n verticesCount: geometry.vertices ? geometry.vertices.length : 0,\r\n hasEndpoints: 'endpoints' in geometry,\r\n endpoints: geometry.endpoints,\r\n endpointsIsArray: Array.isArray(geometry.endpoints),\r\n endpointsLength: geometry.endpoints ? geometry.endpoints.length : 0,\r\n geometryKeys: Object.keys(geometry)\r\n });\r\n\r\n // 创建几何对象的副本\r\n const geometryCopy = { ...geometry };\r\n\r\n // 转换顶点格式:如果 vertices 是对象数组 [{x, y}, ...],转换为元组数组 [[x, y], ...]\r\n if (geometryCopy.vertices && Array.isArray(geometryCopy.vertices)) {\r\n geometryCopy.vertices = geometryCopy.vertices.map((vertex: any) => {\r\n try {\r\n // 检查是否为 $ref 引用对象,如果是则解析它\r\n if (vertex && typeof vertex === 'object' && '$ref' in vertex) {\r\n return this.resolveVertexReference(vertex, context);\r\n }\r\n if (Array.isArray(vertex) && vertex.length === 2) {\r\n // 已经是数组格式\r\n return vertex;\r\n } else if (vertex && typeof vertex === 'object' && 'x' in vertex && 'y' in vertex) {\r\n // 对象格式 {x, y},转换为数组 [x, y]\r\n return [vertex.x, vertex.y];\r\n }\r\n // 未知格式,返回原值\r\n return vertex;\r\n } catch (error) {\r\n console.warn(`顶点引用解析失败:`, error);\r\n // 返回原始顶点,让后续验证捕获错误\r\n return vertex;\r\n }\r\n });\r\n console.error(`🔍 GeometryRefResolver: 转换顶点格式,数量=${geometryCopy.vertices.length}`, {\r\n sampleVertices: geometryCopy.vertices.slice(0, 3).map((v: any, i: number) => ({ index: i, value: v, isArray: Array.isArray(v), length: Array.isArray(v) ? v.length : 'N/A' }))\r\n });\r\n }\r\n\r\n // 转换端点格式(对于线段等)\r\n if (geometryCopy.endpoints && Array.isArray(geometryCopy.endpoints)) {\r\n geometryCopy.endpoints = geometryCopy.endpoints.map((point: any) => {\r\n try {\r\n if (point && typeof point === 'object' && '$ref' in point) {\r\n return this.resolveVertexReference(point, context);\r\n }\r\n if (Array.isArray(point) && point.length === 2) {\r\n return point;\r\n } else if (point && typeof point === 'object' && 'x' in point && 'y' in point) {\r\n return [point.x, point.y];\r\n }\r\n return point;\r\n } catch (error) {\r\n console.warn(`端点引用解析失败:`, error);\r\n return point;\r\n }\r\n });\r\n }\r\n\r\n // 返回转换后的几何对象\r\n return geometryCopy;\r\n }\r\n\r\n /**\r\n * 验证几何引用是否存在\r\n */\r\n static validate(ref: string, context: ReferenceContext): boolean {\r\n if (!this.canResolve(ref, context)) {\r\n return false;\r\n }\r\n\r\n // 提取几何名称\r\n let geometryName: string;\r\n const match = ref.match(REFERENCE_PATTERNS.GEOMETRY_REF);\r\n if (match) {\r\n // 格式: geometryRef:xxx\r\n geometryName = match[1];\r\n } else {\r\n // 格式: xxx (直接名称)\r\n geometryName = ref;\r\n }\r\n\r\n return geometryName in context.geometryPresets;\r\n }\r\n\r\n /**\r\n * 获取所有可用的几何预设名称\r\n */\r\n static getAvailableGeometryNames(context: ReferenceContext): string[] {\r\n return Object.keys(context.geometryPresets);\r\n }\r\n\r\n /**\r\n * 解析几何引用并应用样式(如果几何中包含styleRef)\r\n */\r\n static resolveWithStyle(ref: string, context: ReferenceContext): any {\r\n const geometry = this.resolve(ref, context);\r\n\r\n // 如果几何中包含styleRef,尝试解析样式\r\n if (geometry.styleRef && context.stylePresets[geometry.styleRef]) {\r\n const style = context.stylePresets[geometry.styleRef];\r\n return {\r\n ...geometry,\r\n style: { ...style }\r\n };\r\n }\r\n\r\n return geometry;\r\n }\r\n\r\n /**\r\n * 批量解析几何引用\r\n */\r\n static batchResolve(refs: string[], context: ReferenceContext): Record<string, any> {\r\n const results: Record<string, any> = {};\r\n\r\n for (const ref of refs) {\r\n if (this.canResolve(ref)) {\r\n try {\r\n results[ref] = this.resolve(ref, context);\r\n } catch (error) {\r\n console.warn(`几何引用解析失败: ${ref}`, error);\r\n }\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * 从内容块中提取几何引用\r\n */\r\n static extractGeometryRefs(content: any[]): string[] {\r\n const refs: string[] = [];\r\n\r\n const traverse = (obj: any) => {\r\n if (!obj || typeof obj !== 'object') {\r\n return;\r\n }\r\n\r\n // 检查 geometryRef 字段\r\n if (obj.geometryRef && typeof obj.geometryRef === 'string') {\r\n refs.push(obj.geometryRef);\r\n }\r\n\r\n // 检查 shapes 数组中的几何引用\r\n if (Array.isArray(obj.shapes)) {\r\n obj.shapes.forEach((shape: any) => {\r\n if (shape.geometryRef && typeof shape.geometryRef === 'string') {\r\n refs.push(shape.geometryRef);\r\n }\r\n });\r\n }\r\n\r\n // 递归遍历所有属性\r\n for (const value of Object.values(obj)) {\r\n if (Array.isArray(value)) {\r\n value.forEach(traverse);\r\n } else if (value && typeof value === 'object') {\r\n traverse(value);\r\n }\r\n }\r\n };\r\n\r\n traverse(content);\r\n return [...new Set(refs)]; // 去重\r\n }\r\n}\r\n\r\n/**\r\n * 几何引用解析器工厂函数\r\n */\r\nexport function createGeometryRefResolver() {\r\n return {\r\n type: ReferenceType.GEOMETRY_REF,\r\n canResolve: GeometryRefResolver.canResolve.bind(GeometryRefResolver),\r\n resolve: GeometryRefResolver.resolve.bind(GeometryRefResolver),\r\n validate: GeometryRefResolver.validate.bind(GeometryRefResolver)\r\n };\r\n}","/**\r\n * 变换引用解析器\r\n *\r\n * 解析 transformRef:left_rotation 等变换引用\r\n */\r\n\r\nimport type { ReferenceContext } from '../types';\r\nimport { ReferenceType } from '../types';\r\nimport { REFERENCE_PATTERNS } from '../constants';\r\n\r\n/**\r\n * 变换引用解析器\r\n */\r\nexport class TransformRefResolver {\r\n /**\r\n * 检查是否能够解析该引用\r\n */\r\n static canResolve(ref: string): boolean {\r\n if (typeof ref !== 'string' || ref.length === 0) {\r\n return false;\r\n }\r\n\r\n // 检查是否是 transformRef:xxx 格式\r\n if (REFERENCE_PATTERNS.TRANSFORM_REF.test(ref)) {\r\n return true;\r\n }\r\n\r\n // 检查是否是已知的变换名称(避免将普通文本误判为变换引用)\r\n // 已知的变换名称:left_rotation, right_rotation, translation\r\n const knownTransformNames = ['left_rotation', 'right_rotation', 'translation'];\r\n return knownTransformNames.includes(ref);\r\n }\r\n\r\n /**\r\n * 解析变换引用\r\n */\r\n static resolve(ref: string, context: ReferenceContext): any {\r\n if (!this.canResolve(ref)) {\r\n throw new Error(`无法解析的变换引用: ${ref}`);\r\n }\r\n\r\n // 提取变换名称\r\n let transformName: string;\r\n const match = ref.match(REFERENCE_PATTERNS.TRANSFORM_REF);\r\n if (match) {\r\n // 格式: transformRef:xxx\r\n transformName = match[1];\r\n } else {\r\n // 格式: xxx (直接名称)\r\n transformName = ref;\r\n }\r\n\r\n // 优先从 transformDefinitions 中获取\r\n if (context.transformDefinitions && context.transformDefinitions[transformName]) {\r\n return { ...context.transformDefinitions[transformName] };\r\n }\r\n\r\n // 回退到默认变换\r\n const defaultTransforms = {\r\n left_rotation: { type: 'rotation', angle: -90, origin: [0, 0] },\r\n right_rotation: { type: 'rotation', angle: 90, origin: [0, 0] },\r\n translation: { type: 'translation', dx: 0, dy: 0 }\r\n };\r\n\r\n if (defaultTransforms[transformName as keyof typeof defaultTransforms]) {\r\n return { ...defaultTransforms[transformName as keyof typeof defaultTransforms] };\r\n }\r\n\r\n throw new Error(`变换定义未找到: ${transformName}`);\r\n }\r\n\r\n /**\r\n * 验证变换引用是否存在\r\n */\r\n static validate(ref: string, context: ReferenceContext): boolean {\r\n if (!this.canResolve(ref)) {\r\n return false;\r\n }\r\n\r\n // 提取变换名称\r\n let transformName: string;\r\n const match = ref.match(REFERENCE_PATTERNS.TRANSFORM_REF);\r\n if (match) {\r\n // 格式: transformRef:xxx\r\n transformName = match[1];\r\n } else {\r\n // 格式: xxx (直接名称)\r\n transformName = ref;\r\n }\r\n\r\n // 检查 transformDefinitions\r\n if (context.transformDefinitions && context.transformDefinitions[transformName]) {\r\n return true;\r\n }\r\n\r\n // 检查默认变换\r\n const defaultTransforms = ['left_rotation', 'right_rotation', 'translation'];\r\n return defaultTransforms.includes(transformName);\r\n }\r\n\r\n /**\r\n * 应用变换到几何对象\r\n */\r\n static applyTransform(geometry: any, transform: any): any {\r\n if (!transform || !geometry) {\r\n return geometry;\r\n }\r\n\r\n const result = { ...geometry };\r\n\r\n switch (transform.type) {\r\n case 'rotation':\r\n result.vertices = this.applyRotation(geometry.vertices, transform.angle, transform.origin);\r\n break;\r\n case 'translation':\r\n result.vertices = this.applyTranslation(geometry.vertices, transform.dx, transform.dy);\r\n break;\r\n case 'scale':\r\n result.vertices = this.applyScale(geometry.vertices, transform.factor, transform.origin);\r\n break;\r\n default:\r\n console.warn(`未知的变换类型: ${transform.type}`);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 应用旋转变换\r\n */\r\n private static applyRotation(vertices: [number, number][], angle: number, origin: [number, number]): [number, number][] {\r\n if (!vertices || !Array.isArray(vertices)) {\r\n return vertices;\r\n }\r\n\r\n const [ox, oy] = origin;\r\n const rad = (angle * Math.PI) / 180;\r\n const cos = Math.cos(rad);\r\n const sin = Math.sin(rad);\r\n\r\n return vertices.map(([x, y]) => {\r\n const dx = x - ox;\r\n const dy = y - oy;\r\n return [\r\n ox + dx * cos - dy * sin,\r\n oy + dx * sin + dy * cos\r\n ];\r\n });\r\n }\r\n\r\n /**\r\n * 应用平移变换\r\n */\r\n private static applyTranslation(vertices: [number, number][], dx: number, dy: number): [number, number][] {\r\n if (!vertices || !Array.isArray(vertices)) {\r\n return vertices;\r\n }\r\n\r\n return vertices.map(([x, y]) => [x + dx, y + dy]);\r\n }\r\n\r\n /**\r\n * 应用缩放变换\r\n */\r\n private static applyScale(vertices: [number, number][], factor: number, origin: [number, number]): [number, number][] {\r\n if (!vertices || !Array.isArray(vertices)) {\r\n return vertices;\r\n }\r\n\r\n const [ox, oy] = origin;\r\n return vertices.map(([x, y]) => {\r\n const dx = x - ox;\r\n const dy = y - oy;\r\n return [\r\n ox + dx * factor,\r\n oy + dy * factor\r\n ];\r\n });\r\n }\r\n\r\n /**\r\n * 批量解析变换引用\r\n */\r\n static batchResolve(refs: string[], context: ReferenceContext): Record<string, any> {\r\n const results: Record<string, any> = {};\r\n\r\n for (const ref of refs) {\r\n if (this.canResolve(ref)) {\r\n try {\r\n results[ref] = this.resolve(ref, context);\r\n } catch (error) {\r\n console.warn(`变换引用解析失败: ${ref}`, error);\r\n }\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * 从内容块中提取变换引用\r\n */\r\n static extractTransformRefs(content: any[]): string[] {\r\n const refs: string[] = [];\r\n\r\n const traverse = (obj: any) => {\r\n if (!obj || typeof obj !== 'object') {\r\n return;\r\n }\r\n\r\n // 检查 transformRef 字段\r\n if (obj.transformRef && typeof obj.transformRef === 'string') {\r\n refs.push(obj.transformRef);\r\n }\r\n\r\n // 检查 transformations 数组\r\n if (Array.isArray(obj.transformations)) {\r\n obj.transformations.forEach((transform: any) => {\r\n if (transform.transformRef && typeof transform.transformRef === 'string') {\r\n refs.push(transform.transformRef);\r\n }\r\n });\r\n }\r\n\r\n // 递归遍历所有属性\r\n for (const value of Object.values(obj)) {\r\n if (Array.isArray(value)) {\r\n value.forEach(traverse);\r\n } else if (value && typeof value === 'object') {\r\n traverse(value);\r\n }\r\n }\r\n };\r\n\r\n traverse(content);\r\n return [...new Set(refs)]; // 去重\r\n }\r\n}\r\n\r\n/**\r\n * 变换引用解析器工厂函数\r\n */\r\nexport function createTransformRefResolver() {\r\n return {\r\n type: ReferenceType.TRANSFORM_REF,\r\n canResolve: TransformRefResolver.canResolve.bind(TransformRefResolver),\r\n resolve: TransformRefResolver.resolve.bind(TransformRefResolver),\r\n validate: TransformRefResolver.validate.bind(TransformRefResolver)\r\n };\r\n}","/**\r\n * 样式引用解析器\r\n *\r\n * 解析 styleRef:primary 等样式引用\r\n */\r\n\r\nimport type { ReferenceContext } from '../types';\r\nimport { ReferenceType } from '../types';\r\nimport { REFERENCE_PATTERNS } from '../constants';\r\nimport { DesignTokenResolver } from './designTokenResolver';\r\n\r\n/**\r\n * 样式引用解析器\r\n */\r\nexport class StyleRefResolver {\r\n /**\r\n * 检查是否能够解析该引用\r\n */\r\n static canResolve(ref: string): boolean {\r\n if (typeof ref !== 'string' || ref.length === 0) {\r\n return false;\r\n }\r\n\r\n // 检查是否是 styleRef:xxx 格式\r\n if (REFERENCE_PATTERNS.STYLE_REF.test(ref)) {\r\n return true;\r\n }\r\n\r\n // 检查是否是已知的样式名称(避免将普通文本误判为样式引用)\r\n // 已知的样式名称:从嵌入式配置中提取\r\n const knownStyleNames = [\r\n 'primary', 'secondary', 'transparent', 'highlight', 'error', 'success',\r\n 'dashed', 'text_primary', 'text_heading_large', 'base_highlight',\r\n 'label_position', 'highlight_left', 'highlight_right', 'label_error'\r\n ];\r\n return knownStyleNames.includes(ref);\r\n }\r\n\r\n /**\r\n * 解析样式引用\r\n */\r\n static resolve(ref: string, context: ReferenceContext): any {\r\n if (!this.canResolve(ref)) {\r\n throw new Error(`无法解析的样式引用: ${ref}`);\r\n }\r\n\r\n // 提取样式名称\r\n let styleName: string;\r\n const match = ref.match(REFERENCE_PATTERNS.STYLE_REF);\r\n if (match) {\r\n // 格式: styleRef:xxx\r\n styleName = match[1];\r\n } else {\r\n // 格式: xxx (直接名称)\r\n styleName = ref;\r\n }\r\n\r\n const stylePreset = context.stylePresets[styleName];\r\n\r\n if (!stylePreset) {\r\n throw new Error(`样式预设未找到: ${styleName}`);\r\n }\r\n\r\n // 深度解析样式预设中的设计令牌引用\r\n return this.resolveStylePreset(stylePreset, context);\r\n }\r\n\r\n /**\r\n * 解析样式预设,处理其中的设计令牌引用\r\n */\r\n private static resolveStylePreset(stylePreset: any, context: ReferenceContext): any {\r\n const resolvedStyle: Record<string, any> = { ...stylePreset };\r\n\r\n // 遍历样式预设的所有属性\r\n for (const [key, value] of Object.entries(stylePreset)) {\r\n if (typeof value === 'string') {\r\n // 如果是设计令牌引用,解析它\r\n if (DesignTokenResolver.canResolve(value)) {\r\n try {\r\n resolvedStyle[key] = DesignTokenResolver.resolve(value, context);\r\n } catch (error) {\r\n console.warn(`样式中的设计令牌解析失败: ${key}=${value}`, error);\r\n // 保留原始值作为回退\r\n resolvedStyle[key] = value;\r\n }\r\n }\r\n } else if (value && typeof value === 'object') {\r\n // 递归处理嵌套对象\r\n resolvedStyle[key] = this.resolveStylePreset(value, context);\r\n }\r\n }\r\n\r\n return resolvedStyle;\r\n }\r\n\r\n /**\r\n * 验证样式引用是否存在\r\n */\r\n static validate(ref: string, context: ReferenceContext): boolean {\r\n if (!this.canResolve(ref)) {\r\n return false;\r\n }\r\n\r\n // 提取样式名称\r\n let styleName: string;\r\n const match = ref.match(REFERENCE_PATTERNS.STYLE_REF);\r\n if (match) {\r\n // 格式: styleRef:xxx\r\n styleName = match[1];\r\n } else {\r\n // 格式: xxx (直接名称)\r\n styleName = ref;\r\n }\r\n\r\n return styleName in context.stylePresets;\r\n }\r\n\r\n /**\r\n * 应用样式到几何对象\r\n */\r\n static applyStyle(geometry: any, style: any): any {\r\n if (!geometry || !style) {\r\n return geometry;\r\n }\r\n\r\n const result = { ...geometry };\r\n\r\n // 合并样式属性\r\n result.style = result.style ? { ...result.style, ...style } : { ...style };\r\n\r\n // 特殊处理:如果样式中有特定的几何属性,直接应用到几何对象\r\n const geometryProps = ['strokeWidth', 'fillOpacity', 'strokeOpacity', 'dash'];\r\n geometryProps.forEach(prop => {\r\n if (style[prop] !== undefined) {\r\n result[prop] = style[prop];\r\n }\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 批量解析样式引用\r\n */\r\n static batchResolve(refs: string[], context: ReferenceContext): Record<string, any> {\r\n const results: Record<string, any> = {};\r\n\r\n for (const ref of refs) {\r\n if (this.canResolve(ref)) {\r\n try {\r\n results[ref] = this.resolve(ref, context);\r\n } catch (error) {\r\n console.warn(`样式引用解析失败: ${ref}`, error);\r\n }\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * 从内容块中提取样式引用\r\n */\r\n static extractStyleRefs(content: any[]): string[] {\r\n const refs: string[] = [];\r\n\r\n const traverse = (obj: any) => {\r\n if (!obj || typeof obj !== 'object') {\r\n return;\r\n }\r\n\r\n // 检查 styleRef 字段\r\n if (obj.styleRef && typeof obj.styleRef === 'string') {\r\n refs.push(obj.styleRef);\r\n }\r\n\r\n // 检查 style 对象中的引用\r\n if (obj.style && typeof obj.style === 'object') {\r\n // 样式对象可能包含 styleRef 属性\r\n if (obj.style.styleRef && typeof obj.style.styleRef === 'string') {\r\n refs.push(obj.style.styleRef);\r\n }\r\n }\r\n\r\n // 检查 shapes 数组中的样式引用\r\n if (Array.isArray(obj.shapes)) {\r\n obj.shapes.forEach((shape: any) => {\r\n if (shape.styleRef && typeof shape.styleRef === 'string') {\r\n refs.push(shape.styleRef);\r\n }\r\n if (shape.style && shape.style.styleRef && typeof shape.style.styleRef === 'string') {\r\n refs.push(shape.style.styleRef);\r\n }\r\n });\r\n }\r\n\r\n // 递归遍历所有属性\r\n for (const value of Object.values(obj)) {\r\n if (Array.isArray(value)) {\r\n value.forEach(traverse);\r\n } else if (value && typeof value === 'object') {\r\n traverse(value);\r\n }\r\n }\r\n };\r\n\r\n traverse(content);\r\n return [...new Set(refs)]; // 去重\r\n }\r\n\r\n /**\r\n * 创建默认样式(当样式引用未找到时使用)\r\n */\r\n static createDefaultStyle(): any {\r\n return {\r\n fillColor: '#8ec5fc',\r\n fillOpacity: 0.3,\r\n strokeColor: '#4a90e2',\r\n strokeWidth: 2\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * 样式引用解析器工厂函数\r\n */\r\nexport function createStyleRefResolver() {\r\n return {\r\n type: ReferenceType.STYLE_REF,\r\n canResolve: StyleRefResolver.canResolve.bind(StyleRefResolver),\r\n resolve: StyleRefResolver.resolve.bind(StyleRefResolver),\r\n validate: StyleRefResolver.validate.bind(StyleRefResolver)\r\n };\r\n}","/**\r\n * 布局引用解析器\r\n *\r\n * 解析 layoutRef:card 等布局引用\r\n */\r\n\r\nimport type { ReferenceContext } from '../types';\r\nimport { ReferenceType } from '../types';\r\nimport { REFERENCE_PATTERNS } from '../constants';\r\nimport { DesignTokenResolver } from './designTokenResolver';\r\n\r\n/**\r\n * 布局引用解析器\r\n */\r\nexport class LayoutRefResolver {\r\n /**\r\n * 检查是否能够解析该引用\r\n */\r\n static canResolve(ref: string): boolean {\r\n if (typeof ref !== 'string' || ref.length === 0) {\r\n return false;\r\n }\r\n\r\n // 检查是否是 layoutRef:xxx 格式\r\n if (REFERENCE_PATTERNS.LAYOUT_REF.test(ref)) {\r\n return true;\r\n }\r\n\r\n // 检查是否是已知的布局名称(避免将普通文本误判为布局引用)\r\n // 已知的布局名称:默认布局和预设布局\r\n const knownLayoutNames = [\r\n 'card', 'vertical', 'horizontal', 'grid', 'panel',\r\n 'vertical_centered', 'horizontal_centered', 'centered'\r\n ];\r\n\r\n // 如果引用匹配已知布局名称,则接受它\r\n return knownLayoutNames.includes(ref);\r\n }\r\n\r\n /**\r\n * 解析布局引用\r\n */\r\n static resolve(ref: string, context: ReferenceContext): any {\r\n if (!this.canResolve(ref)) {\r\n throw new Error(`无法解析的布局引用: ${ref}`);\r\n }\r\n\r\n // 提取布局名称\r\n let layoutName: string;\r\n const match = ref.match(REFERENCE_PATTERNS.LAYOUT_REF);\r\n if (match) {\r\n layoutName = match[1];\r\n } else {\r\n // 如果不是 layoutRef:xxx 格式,则整个字符串就是布局名称\r\n layoutName = ref;\r\n }\r\n\r\n // 优先从 layoutPresets 中获取\r\n if (context.layoutPresets && context.layoutPresets[layoutName]) {\r\n const layoutPreset = context.layoutPresets[layoutName];\r\n return this.resolveLayoutPreset(layoutPreset, context);\r\n }\r\n\r\n // 回退到默认布局\r\n const defaultLayouts = {\r\n card: { type: 'card', padding: '20px', theme: 'light' },\r\n vertical: { type: 'vertical', spacing: '15px', alignment: 'start' },\r\n horizontal: { type: 'horizontal', spacing: '15px', alignment: 'center' }\r\n };\r\n\r\n if (defaultLayouts[layoutName as keyof typeof defaultLayouts]) {\r\n return { ...defaultLayouts[layoutName as keyof typeof defaultLayouts] };\r\n }\r\n\r\n throw new Error(`布局预设未找到: ${layoutName}`);\r\n }\r\n\r\n /**\r\n * 解析布局预设,处理其中的设计令牌引用\r\n */\r\n private static resolveLayoutPreset(layoutPreset: any, context: ReferenceContext): any {\r\n const resolvedLayout: Record<string, any> = { ...layoutPreset };\r\n\r\n // 遍历布局预设的所有属性\r\n for (const [key, value] of Object.entries(layoutPreset)) {\r\n if (typeof value === 'string') {\r\n // 如果是设计令牌引用,解析它\r\n if (DesignTokenResolver.canResolve(value)) {\r\n try {\r\n resolvedLayout[key] = DesignTokenResolver.resolve(value, context);\r\n } catch (error) {\r\n console.warn(`布局中的设计令牌解析失败: ${key}=${value}`, error);\r\n // 保留原始值作为回退\r\n resolvedLayout[key] = value;\r\n }\r\n }\r\n } else if (value && typeof value === 'object') {\r\n // 递归处理嵌套对象\r\n resolvedLayout[key] = this.resolveLayoutPreset(value, context);\r\n }\r\n }\r\n\r\n return resolvedLayout;\r\n }\r\n\r\n /**\r\n * 验证布局引用是否存在\r\n */\r\n static validate(ref: string, context: ReferenceContext): boolean {\r\n if (!this.canResolve(ref)) {\r\n return false;\r\n }\r\n\r\n // 提取布局名称\r\n let layoutName: string;\r\n const match = ref.match(REFERENCE_PATTERNS.LAYOUT_REF);\r\n if (match) {\r\n layoutName = match[1];\r\n } else {\r\n // 如果不是 layoutRef:xxx 格式,则整个字符串就是布局名称\r\n layoutName = ref;\r\n }\r\n\r\n // 检查 layoutPresets\r\n if (context.layoutPresets && context.layoutPresets[layoutName]) {\r\n return true;\r\n }\r\n\r\n // 检查默认布局\r\n const defaultLayouts = ['card', 'vertical', 'horizontal'];\r\n return defaultLayouts.includes(layoutName);\r\n }\r\n\r\n /**\r\n * 应用布局到场景配置\r\n */\r\n static applyLayout(sceneConfig: any, layout: any): any {\r\n if (!sceneConfig || !layout) {\r\n return sceneConfig;\r\n }\r\n\r\n const result = { ...sceneConfig };\r\n\r\n // 如果场景已有布局,合并它们\r\n if (result.layout) {\r\n result.layout = { ...result.layout, ...layout };\r\n } else {\r\n result.layout = { ...layout };\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 批量解析布局引用\r\n */\r\n static batchResolve(refs: string[], context: ReferenceContext): Record<string, any> {\r\n const results: Record<string, any> = {};\r\n\r\n for (const ref of refs) {\r\n if (this.canResolve(ref)) {\r\n try {\r\n results[ref] = this.resolve(ref, context);\r\n } catch (error) {\r\n console.warn(`布局引用解析失败: ${ref}`, error);\r\n }\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * 从场景配置中提取布局引用\r\n */\r\n static extractLayoutRefs(scenes: Record<string, any>): string[] {\r\n const refs: string[] = [];\r\n\r\n for (const scene of Object.values(scenes)) {\r\n if (scene.layout && scene.layout.type && typeof scene.layout.type === 'string') {\r\n // 检查是否为 layoutRef 格式\r\n if (this.isLayoutRef(scene.layout.type)) {\r\n refs.push(scene.layout.type);\r\n }\r\n }\r\n\r\n // 检查 layout 对象中的其他属性\r\n if (scene.layout && typeof scene.layout === 'object') {\r\n for (const value of Object.values(scene.layout)) {\r\n if (typeof value === 'string' && this.isLayoutRef(value)) {\r\n refs.push(value);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return [...new Set(refs)]; // 去重\r\n }\r\n\r\n /**\r\n * 检查字符串是否为布局引用\r\n */\r\n private static isLayoutRef(value: string): boolean {\r\n return REFERENCE_PATTERNS.LAYOUT_REF.test(value);\r\n }\r\n\r\n /**\r\n * 创建默认布局(当布局引用未找到时使用)\r\n */\r\n static createDefaultLayout(): any {\r\n return {\r\n type: 'card',\r\n padding: '20px',\r\n theme: 'light'\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * 布局引用解析器工厂函数\r\n */\r\nexport function createLayoutRefResolver() {\r\n return {\r\n type: ReferenceType.LAYOUT_REF,\r\n canResolve: LayoutRefResolver.canResolve.bind(LayoutRefResolver),\r\n resolve: LayoutRefResolver.resolve.bind(LayoutRefResolver),\r\n validate: LayoutRefResolver.validate.bind(LayoutRefResolver)\r\n };\r\n}","/**\n * 动画引用解析器\n *\n * 解析 animationRef:xxx 等动画配置引用\n * 支持从 animation_configs 中加载和解析动画配置\n */\n\nimport type { ReferenceContext } from '../types';\nimport { ReferenceType } from '../types';\nimport { REFERENCE_PATTERNS } from '../constants';\nimport { AdapterError, AdapterErrorCode } from '../types';\nimport type { AnimationConfig, RawAnimationConfig, JSXTransformConfig } from '../../../components/MathGraph/animation.types';\nimport {\n resolveDynamicParams,\n validateAnimationConfig\n} from '../../../components/MathGraph/utils/transformUtils';\n\n/**\n * 动画引用解析器\n */\nexport class AnimationRefResolver {\n /**\n * 检查是否能够解析该引用\n * 只接受明确的 animationRef:xxx 格式,拒绝简单的标识符\n */\n static canResolve(ref: string): boolean {\n if (typeof ref !== 'string' || ref.length === 0) {\n return false;\n }\n\n // 只接受明确的 animationRef:xxx 格式\n // 拒绝简单的标识符,避免误判为其他类型的引用(如 boardRef)\n return REFERENCE_PATTERNS.ANIMATION_REF.test(ref);\n }\n\n /**\n * 解析动画引用\n *\n * @param ref - 动画引用字符串(如 \"animationRef:double_rotation_proof\")\n * @param context - 引用解析上下文,包含 animation_configs\n * @returns 解析后的 AnimationConfig\n * @throws 当引用格式无效或动画配置未找到时抛出错误\n */\n static resolve(ref: string, context: ReferenceContext): AnimationConfig {\n if (!this.canResolve(ref)) {\n throw new AdapterError(\n AdapterErrorCode.ANIMATION_REF_NOT_FOUND,\n `无法解析的动画引用: ${ref}`\n );\n }\n\n // 提取动画配置 ID(只支持 animationRef:id 格式)\n const match = ref.match(REFERENCE_PATTERNS.ANIMATION_REF);\n\n if (!match) {\n // 不应该发生,因为 canResolve 已经检查过了\n throw new AdapterError(\n AdapterErrorCode.ANIMATION_REF_NOT_FOUND,\n `动画引用格式无效: ${ref}`\n );\n }\n\n // 格式:\"animationRef:double_rotation_proof\"\n const animationConfigId = match[1];\n\n // 从上下文中获取原始动画配置\n const rawConfig = context.animationConfigs?.[animationConfigId];\n\n if (!rawConfig) {\n throw new AdapterError(\n AdapterErrorCode.ANIMATION_REF_NOT_FOUND,\n `动画配置未找到: ${animationConfigId}`\n );\n }\n\n // 解析并转换配置\n return this.resolveAnimationConfig(animationConfigId, rawConfig, context);\n }\n\n /**\n * 解析并转换动画配置\n *\n * 处理原始配置中的函数字符串,将其转换为可执行函数\n *\n * @param animationId - 动画配置 ID\n * @param rawConfig - 原始动画配置(可能包含函数字符串)\n * @param context - 引用解析上下文\n * @returns 解析后的 AnimationConfig\n */\n private static resolveAnimationConfig(\n animationId: string,\n rawConfig: RawAnimationConfig,\n _context: ReferenceContext\n ): AnimationConfig {\n // 基础验证\n if (!rawConfig.transforms || !Array.isArray(rawConfig.transforms)) {\n throw new AdapterError(\n AdapterErrorCode.ANIMATION_REF_NOT_FOUND,\n `动画配置格式错误: ${animationId} 缺少 transforms 数组`\n );\n }\n\n // 转换每个 Transform 配置\n const transforms = rawConfig.transforms.map((transform, index) => {\n // 验证必需字段\n if (!transform.id) {\n throw new AdapterError(\n AdapterErrorCode.ANIMATION_REF_NOT_FOUND,\n `动画配置 ${animationId} 中 transform[${index}] 缺少 id 字段`\n );\n }\n\n if (!transform.type) {\n throw new AdapterError(\n AdapterErrorCode.ANIMATION_REF_NOT_FOUND,\n `动画配置 ${animationId} 中 transform[${index}] 缺少 type 字段`\n );\n }\n\n if (!transform.targetShapes || !Array.isArray(transform.targetShapes)) {\n throw new AdapterError(\n AdapterErrorCode.ANIMATION_REF_NOT_FOUND,\n `动画配置 ${animationId} 中 transform[${index}] 缺少 targetShapes 数组`\n );\n }\n\n // 验证 targetShapes 不为空\n if (transform.targetShapes.length === 0) {\n throw new AdapterError(\n AdapterErrorCode.ANIMATION_REF_NOT_FOUND,\n `动画配置 ${animationId} 中 transform[${index}] targetShapes 不能为空`\n );\n }\n\n // 验证 targetShape ID 格式\n transform.targetShapes.forEach((shapeId, shapeIndex) => {\n if (typeof shapeId !== 'string' || shapeId.trim() === '') {\n throw new AdapterError(\n AdapterErrorCode.ANIMATION_REF_NOT_FOUND,\n `动画配置 ${animationId} 中 transform[${index}].targetShapes[${shapeIndex}] 必须是有效的字符串 ID`\n );\n }\n });\n\n // 解析动态参数(函数字符串转换为函数)\n const resolvedParams = resolveDynamicParams(transform.params);\n\n // 检测是否使用了 control.value(使用原始数据transform.params,不是解析后的resolvedParams)\n const usesControl = JSON.stringify(transform.params).includes('control.value');\n\n return {\n id: transform.id,\n type: transform.type,\n params: resolvedParams,\n targetShapes: transform.targetShapes,\n usesControl\n };\n });\n\n // 组装最终的 AnimationConfig\n const resolvedConfig: AnimationConfig = {\n id: animationId,\n control: rawConfig.control,\n transforms: transforms as unknown as JSXTransformConfig[],\n visualEffects: rawConfig.visualEffects || [],\n progressControl: rawConfig.progressControl\n };\n\n // 验证最终配置\n const validation = validateAnimationConfig(resolvedConfig);\n if (!validation.valid) {\n throw new AdapterError(\n AdapterErrorCode.ANIMATION_REF_NOT_FOUND,\n `动画配置验证失败: ${animationId}\\n${validation.errors?.join('\\n')}`\n );\n }\n\n return resolvedConfig;\n }\n\n /**\n * 验证动画引用是否能够被解析\n *\n * @param ref - 动画引用字符串\n * @param context - 引用解析上下文\n * @returns 是否能够解析\n */\n static validate(ref: string, context: ReferenceContext): boolean {\n if (!this.canResolve(ref)) {\n return false;\n }\n\n // 提取动画配置 ID(支持两种格式:\"animationRef:id\" 或 \"id\")\n let animationConfigId: string;\n const match = ref.match(REFERENCE_PATTERNS.ANIMATION_REF);\n\n if (match) {\n // 格式:\"animationRef:double_rotation_proof\"\n animationConfigId = match[1];\n } else {\n // 格式:\"double_rotation_proof\"(简化格式)\n animationConfigId = ref;\n }\n\n // 对于简单标识符,只有在 animationConfigs 中存在时才验证通过\n // 否则可能是其他类型的引用(如 geometry_ref)\n const configExists = animationConfigId in (context.animationConfigs || {});\n\n return configExists;\n }\n\n /**\n * 批量解析多个动画引用\n *\n * @param refs - 动画引用字符串数组\n * @param context - 引用解析上下文\n * @returns 解析结果映射表\n */\n static batchResolve(refs: string[], context: ReferenceContext): Record<string, AnimationConfig> {\n const results: Record<string, AnimationConfig> = {};\n\n for (const ref of refs) {\n if (this.canResolve(ref)) {\n try {\n results[ref] = this.resolve(ref, context);\n } catch (error) {\n console.warn(`动画引用解析失败: ${ref}`, error);\n // 记录警告,继续处理其他引用\n }\n }\n }\n\n return results;\n }\n\n /**\n * 从内容块中提取动画引用\n *\n * @param content - 内容块数组\n * @returns 提取的动画引用字符串数组\n */\n static extractAnimationRefs(content: any[]): string[] {\n const refs: string[] = [];\n\n const traverse = (obj: any) => {\n if (!obj || typeof obj !== 'object') {\n return;\n }\n\n // 检查 animationRef 字段\n if (obj.animationRef && typeof obj.animationRef === 'string') {\n refs.push(obj.animationRef);\n }\n\n // 检查 chartConfig 中的 animationRef\n if (obj.chartConfig?.animationRef && typeof obj.chartConfig.animationRef === 'string') {\n refs.push(obj.chartConfig.animationRef);\n }\n\n // 递归遍历所有属性\n for (const value of Object.values(obj)) {\n if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (value && typeof value === 'object') {\n traverse(value);\n }\n }\n };\n\n traverse(content);\n\n return [...new Set(refs)]; // 去重\n }\n}\n\n/**\n * 动画引用解析器工厂函数\n */\nexport function createAnimationRefResolver() {\n return {\n type: ReferenceType.ANIMATION_REF,\n canResolve: AnimationRefResolver.canResolve.bind(AnimationRefResolver),\n resolve: AnimationRefResolver.resolve.bind(AnimationRefResolver),\n validate: AnimationRefResolver.validate.bind(AnimationRefResolver)\n };\n}\n","/**\n * 滑块引用解析器\n *\n * 解析 sliderRef:xxx 等滑块配置引用\n * 支持从 animation_definitions/slider_definitions 中加载和解析滑块配置\n */\n\nimport type { ReferenceContext } from '../types';\nimport { ReferenceType } from '../types';\nimport { REFERENCE_PATTERNS } from '../constants';\nimport { AdapterError, AdapterErrorCode } from '../types';\nimport { GLOBAL_REFERENCE_CONTEXT } from '../config/embeddedConfigs';\n\n/**\n * 滑块配置接口(简化版,根据实际需要定义)\n */\nexport interface SliderConfig {\n id: string;\n slider: {\n position: [number, number];\n length: number;\n orientation: 'horizontal' | 'vertical';\n min: number;\n max: number;\n step: number;\n };\n progressIndicator?: {\n enabled: boolean;\n stages?: number;\n labels?: string[];\n showPercentage?: boolean;\n };\n duration?: number;\n easing?: string;\n description?: string;\n}\n\n/**\n * 滑块引用解析器\n */\nexport class SliderRefResolver {\n /**\n * 检查是否能够解析该引用\n * 支持两种格式:\n * 1. sliderRef:xxx (标准引用格式)\n * 2. xxx (简单标识符,向后兼容)\n */\n static canResolve(ref: string): boolean {\n if (typeof ref !== 'string' || ref.length === 0) {\n return false;\n }\n\n // 支持两种格式:\n // 1. sliderRef:xxx (标准引用格式)\n // 2. xxx (简单标识符,向后兼容)\n return REFERENCE_PATTERNS.SLIDER_REF.test(ref) ||\n /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(ref); // 简单标识符\n }\n\n /**\n * 解析滑块引用\n *\n * @param ref - 滑块引用字符串(如 \"sliderRef:slider_horizontal\")\n * @param context - 引用解析上下文,包含 animation_definitions/slider_definitions\n * @returns 解析后的 SliderConfig\n * @throws 当引用格式无效或滑块配置未找到时抛出错误\n */\n static resolve(ref: string, context: ReferenceContext): SliderConfig {\n console.error('🔍 SliderRefResolver.resolve called:', {\n ref,\n hasContext: !!context,\n contextKeys: Object.keys(context || {}),\n animationDefinitionsKeys: context.animationDefinitions ? Object.keys(context.animationDefinitions as any) : [],\n animationConfigsKeys: context.animationConfigs ? Object.keys(context.animationConfigs as any) : []\n });\n\n if (!this.canResolve(ref)) {\n throw new AdapterError(\n AdapterErrorCode.SLIDER_REF_NOT_FOUND,\n `无法解析的滑块引用: ${ref}`\n );\n }\n\n // 提取滑块配置 ID\n // 支持两种格式:\n // 1. sliderRef:slider_horizontal → slider_horizontal\n // 2. slider_horizontal → slider_horizontal\n const match = ref.match(REFERENCE_PATTERNS.SLIDER_REF);\n const sliderConfigId = match ? match[1] : ref;\n\n // 从上下文中获取原始滑块配置\n // 注意:上下文中的字段名是 animationDefinitions(保持向后兼容)\n // 同时检查 animationConfigs 作为回退\n let rawConfig = context.animationDefinitions?.[sliderConfigId as any];\n\n // 如果未找到,尝试 animationConfigs\n if (!rawConfig && context.animationConfigs) {\n rawConfig = (context.animationConfigs as any)[sliderConfigId];\n }\n\n // 如果仍然未找到,尝试全局上下文(GLOBAL_REFERENCE_CONTEXT)\n if (!rawConfig && GLOBAL_REFERENCE_CONTEXT?.animationDefinitions) {\n rawConfig = (GLOBAL_REFERENCE_CONTEXT.animationDefinitions as any)[sliderConfigId];\n }\n\n // 同时检查全局上下文的 animationConfigs\n if (!rawConfig && GLOBAL_REFERENCE_CONTEXT?.animationConfigs) {\n rawConfig = (GLOBAL_REFERENCE_CONTEXT.animationConfigs as any)[sliderConfigId];\n }\n\n console.error('🔍 SliderRefResolver.resolve lookup:', {\n sliderConfigId,\n hasRawConfig: !!rawConfig,\n rawConfig,\n animationDefinitions: context.animationDefinitions as any,\n animationConfigs: context.animationConfigs as any,\n hasGlobalContext: !!GLOBAL_REFERENCE_CONTEXT\n });\n\n if (!rawConfig) {\n console.warn(`⚠️ 滑块配置未找到: ${sliderConfigId},使用默认配置`);\n // 返回默认配置而不是抛出错误,确保适配器可以继续运行\n return {\n ...DEFAULT_SLIDER_CONFIG,\n id: sliderConfigId\n };\n }\n\n // 验证配置结构并返回\n return this.validateAndTransformConfig(sliderConfigId, rawConfig);\n }\n\n /**\n * 验证并转换滑块配置\n *\n * @param sliderId - 滑块配置 ID\n * @param rawConfig - 原始滑块配置\n * @returns 验证后的 SliderConfig\n */\n private static validateAndTransformConfig(\n sliderId: string,\n rawConfig: any\n ): SliderConfig {\n // 基础验证\n if (!rawConfig.slider) {\n throw new AdapterError(\n AdapterErrorCode.SLIDER_REF_NOT_FOUND,\n `滑块配置格式错误: ${sliderId} 缺少 slider 对象`\n );\n }\n\n const { slider } = rawConfig;\n\n // 验证必需字段\n const requiredFields = ['position', 'length', 'orientation', 'min', 'max', 'step'];\n for (const field of requiredFields) {\n if (!(field in slider)) {\n throw new AdapterError(\n AdapterErrorCode.SLIDER_REF_NOT_FOUND,\n `滑块配置 ${sliderId} 中 slider 缺少 ${field} 字段`\n );\n }\n }\n\n // 验证 position 格式\n if (!Array.isArray(slider.position) || slider.position.length !== 2) {\n throw new AdapterError(\n AdapterErrorCode.SLIDER_REF_NOT_FOUND,\n `滑块配置 ${sliderId} 中 slider.position 必须是长度为 2 的数组`\n );\n }\n\n // 验证 orientation\n if (slider.orientation !== 'horizontal' && slider.orientation !== 'vertical') {\n throw new AdapterError(\n AdapterErrorCode.SLIDER_REF_NOT_FOUND,\n `滑块配置 ${sliderId} 中 slider.orientation 必须是 \"horizontal\" 或 \"vertical\"`\n );\n }\n\n // 验证数值范围\n if (slider.min >= slider.max) {\n throw new AdapterError(\n AdapterErrorCode.SLIDER_REF_NOT_FOUND,\n `滑块配置 ${sliderId} 中 slider.min 必须小于 slider.max`\n );\n }\n\n if (slider.step <= 0) {\n throw new AdapterError(\n AdapterErrorCode.SLIDER_REF_NOT_FOUND,\n `滑块配置 ${sliderId} 中 slider.step 必须大于 0`\n );\n }\n\n // 返回验证后的配置\n return {\n id: sliderId,\n slider: {\n position: slider.position,\n length: slider.length,\n orientation: slider.orientation,\n min: slider.min,\n max: slider.max,\n step: slider.step\n },\n progressIndicator: rawConfig.progressIndicator,\n duration: rawConfig.duration,\n easing: rawConfig.easing,\n description: rawConfig.description\n };\n }\n\n /**\n * 验证滑块引用是否能够被解析\n *\n * @param ref - 滑块引用字符串\n * @param context - 引用解析上下文\n * @returns 是否能够解析\n */\n static validate(ref: string, context: ReferenceContext): boolean {\n if (!this.canResolve(ref)) {\n return false;\n }\n\n // 提取滑块配置 ID\n // 支持两种格式:\n // 1. sliderRef:slider_horizontal → slider_horizontal\n // 2. slider_horizontal → slider_horizontal\n const match = ref.match(REFERENCE_PATTERNS.SLIDER_REF);\n const sliderConfigId = match ? match[1] : ref;\n\n // 检查配置是否存在(在 animationDefinitions 或 animationConfigs 中)\n const _configExists =\n sliderConfigId in ((context.animationDefinitions as any) || {}) ||\n sliderConfigId in ((context.animationConfigs as any) || {});\n\n // 如果配置不存在,仍然返回true,因为我们会回退到默认配置\n // 这样可以避免引用统计阶段标记为失败\n return true;\n }\n\n /**\n * 批量解析多个滑块引用\n *\n * @param refs - 滑块引用字符串数组\n * @param context - 引用解析上下文\n * @returns 解析结果映射表\n */\n static batchResolve(refs: string[], context: ReferenceContext): Record<string, SliderConfig> {\n const results: Record<string, SliderConfig> = {};\n\n for (const ref of refs) {\n if (this.canResolve(ref)) {\n try {\n results[ref] = this.resolve(ref, context);\n } catch (error) {\n console.warn(`滑块引用解析失败: ${ref}`, error);\n // 记录警告,继续处理其他引用\n }\n }\n }\n\n return results;\n }\n\n /**\n * 从内容块中提取滑块引用\n *\n * @param content - 内容块数组\n * @returns 提取的滑块引用字符串数组\n */\n static extractSliderRefs(content: any[]): string[] {\n const refs: string[] = [];\n\n const traverse = (obj: any) => {\n if (!obj || typeof obj !== 'object') {\n return;\n }\n\n // 检查 sliderRef 字段\n if (obj.sliderRef && typeof obj.sliderRef === 'string') {\n refs.push(obj.sliderRef);\n }\n\n // 检查 chartConfig 中的 sliderRef\n if (obj.chartConfig?.sliderRef && typeof obj.chartConfig.sliderRef === 'string') {\n refs.push(obj.chartConfig.sliderRef);\n }\n\n // 递归遍历所有属性\n for (const value of Object.values(obj)) {\n if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (value && typeof value === 'object') {\n traverse(value);\n }\n }\n };\n\n traverse(content);\n\n return [...new Set(refs)]; // 去重\n }\n}\n\n/**\n * 默认滑块配置(当引用未找到时使用)\n */\nconst DEFAULT_SLIDER_CONFIG: SliderConfig = {\n id: 'default_slider',\n slider: {\n position: [0, -6] as [number, number],\n length: 10,\n orientation: 'horizontal' as const,\n min: 0,\n max: 1,\n step: 0.01\n },\n progressIndicator: {\n enabled: true,\n stages: 4,\n labels: ['开始', '25%', '50%', '75%', '完成'],\n showPercentage: true\n },\n duration: 2000,\n easing: 'ease-in-out',\n description: '默认滑块配置(引用未找到时使用)'\n};\n\n/**\n * 滑块引用解析器工厂函数\n */\nexport function createSliderRefResolver() {\n return {\n type: ReferenceType.SLIDER_REF,\n canResolve: SliderRefResolver.canResolve.bind(SliderRefResolver),\n resolve: SliderRefResolver.resolve.bind(SliderRefResolver),\n validate: SliderRefResolver.validate.bind(SliderRefResolver)\n };\n}","/**\r\n * 几何变换引用解析器\r\n *\r\n * 解析 geometryTransformRef 引用,从配置定义中加载完整几何变换参数\r\n */\r\n\r\nimport { type ReferenceContext, type GeometryTransformConfig, AdapterErrorCode, AdapterError, ReferenceType } from '../types';\r\nimport { REFERENCE_PATTERNS } from '../constants';\r\n\r\n/**\r\n * 几何变换引用解析器\r\n */\r\nexport class GeometryTransformRefResolver {\r\n /**\r\n * 检查是否能够解析该引用\r\n */\r\n static canResolve(ref: string): boolean {\r\n if (typeof ref !== 'string' || ref.length === 0) {\r\n return false;\r\n }\r\n\r\n // 支持两种格式:\r\n // 1. geometryTransformRef:xxx (标准引用格式)\r\n // 2. xxx (简单标识符,向后兼容)\r\n return REFERENCE_PATTERNS.GEOMETRY_TRANSFORM_REF.test(ref) ||\r\n /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(ref); // 简单标识符\r\n }\r\n\r\n /**\r\n * 解析几何变换引用\r\n */\r\n static resolve(\r\n ref: string,\r\n context: ReferenceContext,\r\n override?: Partial<GeometryTransformConfig>\r\n ): GeometryTransformConfig {\r\n if (!this.canResolve(ref)) {\r\n throw new Error(`无法解析的几何变换引用: ${ref}`);\r\n }\r\n\r\n // 提取配置ID\r\n // 支持两种格式:\r\n // 1. geometryTransformRef:double_rotation_proof → double_rotation_proof\r\n // 2. double_rotation_proof → double_rotation_proof\r\n const match = ref.match(REFERENCE_PATTERNS.GEOMETRY_TRANSFORM_REF);\r\n const configId = match ? match[1] : ref;\r\n\r\n console.error(`🔍 GeometryTransformRefResolver.resolve: 解析引用 ${ref} -> ${configId}`, {\r\n hasGeometryTransformConfigs: !!context.geometryTransformConfigs,\r\n configKeys: context.geometryTransformConfigs ? Object.keys(context.geometryTransformConfigs) : []\r\n });\r\n\r\n // 从 geometryTransformConfigs 中获取配置\r\n const config = context.geometryTransformConfigs?.[configId];\r\n\r\n if (!config) {\r\n throw new AdapterError(\r\n AdapterErrorCode.GEOMETRY_TRANSFORM_REF_NOT_FOUND,\r\n `几何变换配置未找到: ${configId}`,\r\n { reference: ref, configId, availableConfigs: context.geometryTransformConfigs ? Object.keys(context.geometryTransformConfigs) : [] }\r\n );\r\n }\r\n\r\n console.error(`✅ 找到几何变换配置:`, config);\r\n\r\n // 应用覆盖配置\r\n const result = override ? this.applyOverride(config, override) : { ...config };\r\n\r\n console.error(`📋 应用覆盖后的配置:`, result);\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 应用覆盖配置\r\n */\r\n private static applyOverride(\r\n base: GeometryTransformConfig,\r\n override: Partial<GeometryTransformConfig>\r\n ): GeometryTransformConfig {\r\n const result = { ...base };\r\n\r\n // 浅层覆盖简单属性\r\n for (const [key, value] of Object.entries(override)) {\r\n if (value !== undefined) {\r\n (result as any)[key] = value;\r\n }\r\n }\r\n\r\n // 对于嵌套对象(如 shapes, transform),进行深度合并\r\n if (override.shapes) {\r\n result.shapes = {\r\n static: [...(result.shapes?.static || [])],\r\n animated: [...(result.shapes?.animated || [])]\r\n };\r\n\r\n if (override.shapes.static) {\r\n result.shapes.static = override.shapes.static;\r\n }\r\n if (override.shapes.animated) {\r\n result.shapes.animated = override.shapes.animated;\r\n }\r\n }\r\n\r\n if (override.transform) {\r\n result.transform = {\r\n ...result.transform,\r\n ...override.transform\r\n };\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 验证几何变换引用是否存在\r\n */\r\n static validate(ref: string, context: ReferenceContext): boolean {\r\n if (!this.canResolve(ref)) {\r\n return false;\r\n }\r\n\r\n // 提取配置ID\r\n // 支持两种格式:\r\n // 1. geometryTransformRef:double_rotation_proof → double_rotation_proof\r\n // 2. double_rotation_proof → double_rotation_proof\r\n const match = ref.match(REFERENCE_PATTERNS.GEOMETRY_TRANSFORM_REF);\r\n const configId = match ? match[1] : ref;\r\n\r\n return !!context.geometryTransformConfigs?.[configId];\r\n }\r\n\r\n /**\r\n * 批量解析几何变换引用\r\n */\r\n static batchResolve(\r\n refs: string[],\r\n context: ReferenceContext,\r\n overrides?: Record<string, Partial<GeometryTransformConfig>>\r\n ): Record<string, GeometryTransformConfig> {\r\n const results: Record<string, GeometryTransformConfig> = {};\r\n\r\n for (const ref of refs) {\r\n if (this.canResolve(ref) && this.validate(ref, context)) {\r\n try {\r\n const override = overrides?.[ref];\r\n results[ref] = this.resolve(ref, context, override);\r\n } catch (error) {\r\n console.warn(`几何变换引用解析失败: ${ref}`, error);\r\n }\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * 从内容块中提取几何变换引用\r\n */\r\n static extractFromContentBlock(contentBlock: any): string | null {\r\n if (!contentBlock || typeof contentBlock !== 'object') {\r\n return null;\r\n }\r\n\r\n if (contentBlock.geometryTransformRef && typeof contentBlock.geometryTransformRef === 'string') {\r\n return contentBlock.geometryTransformRef;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * 提取多个内容块中的引用\r\n */\r\n static extractFromContentBlocks(blocks: any[]): string[] {\r\n const refs: string[] = [];\r\n\r\n for (const block of blocks) {\r\n const ref = this.extractFromContentBlock(block);\r\n if (ref) {\r\n refs.push(ref);\r\n }\r\n }\r\n\r\n return [...new Set(refs)]; // 去重\r\n }\r\n}\r\n\r\n/**\r\n * 创建几何变换引用解析器实例\r\n */\r\nexport function createGeometryTransformRefResolver() {\r\n return {\r\n type: ReferenceType.GEOMETRY_TRANSFORM_REF,\r\n canResolve: GeometryTransformRefResolver.canResolve.bind(GeometryTransformRefResolver),\r\n resolve: GeometryTransformRefResolver.resolve.bind(GeometryTransformRefResolver),\r\n validate: GeometryTransformRefResolver.validate.bind(GeometryTransformRefResolver)\r\n };\r\n}\r\n","/**\n * 引用提取器\n *\n * 基于显式字段名的引用提取算法\n * 优点:直接、简洁、通用、可维护\n */\n\nimport type { ReferenceContext } from '../types';\nimport { ReferenceType } from '../types';\n\nexport interface ExtractedReference {\n ref: string;\n type: ReferenceType;\n path?: string;\n}\n\n/**\n * 提取的引用(结构化数据)\n *\n * 包含完整的字段上下文信息,避免引用类型误判\n */\nexport interface ExtractedReference {\n /** 引用值(如 \"double_rotation_proof\") */\n value: string;\n /** 字段名(如 \"animationRef\") */\n fieldName: string;\n /** 解析器类型(由 fieldName 映射得到) */\n type: ReferenceType;\n /** 组合字符串(向下兼容,如 \"animationRef:double_rotation_proof\") */\n combined: string;\n}\n\n/**\n * 核心引用字段映射\n *\n * 键:JSON 中的字段名\n * 值:对应的解析器类型\n *\n * 设计原则:\n * 1. 显式优于隐式:字段名就是引用字段,不需要猜测\n * 2. 一一对应:每个字段有且只有一个解析器负责\n * 3. 静态配置:编译时确定,运行时不变\n * 4. 易于扩展:添加新字段只需修改这里\n */\nexport const REFERENCE_FIELD_MAP: Record<string, ReferenceType> = {\n // 几何引用\n geometryRef: ReferenceType.GEOMETRY_REF,\n\n // 样式引用\n styleRef: ReferenceType.STYLE_REF,\n\n // 布局引用\n layoutRef: ReferenceType.LAYOUT_REF,\n\n // 画布引用\n boardRef: ReferenceType.BOARD_REF,\n\n // 动画引用\n animationRef: ReferenceType.ANIMATION_REF,\n\n // 变换引用(保留,向后兼容)\n transformRef: ReferenceType.TRANSFORM_REF,\n\n // 外观引用(保留,向后兼容)\n appearanceRef: ReferenceType.STYLE_REF,\n\n // 几何变换引用(新增)\n geometryTransformRef: ReferenceType.GEOMETRY_TRANSFORM_REF,\n\n // 滑块引用(新增)\n sliderRef: ReferenceType.SLIDER_REF,\n\n // 内联引用($ref, 用于 vertices/endpoints)\n $ref: ReferenceType.GEOMETRY_REF,\n};\n\n/**\n * 引用提取器\n *\n * 专门负责从 JSON 数据中提取引用字段的工具类\n */\nexport class ReferenceExtractor {\n /**\n * 提取对象中的所有引用(结构化数据)\n *\n * 算法:\n * 1. 遍历对象树(深度优先)\n * 2. 检查每个字段名是否在 REFERENCE_FIELD_MAP 中\n * 3. 如果是,创建结构化引用对象\n * 4. 去重后返回\n *\n * 优点:\n * - 保留字段上下文:value + fieldName + type\n * - 避免引用类型误判\n * - 向后兼容:combined 字段可用于现有代码\n *\n * @param obj - 要提取引用的对象\n * @returns 结构化引用数组\n */\n static extractRefs(obj: any): ExtractedReference[] {\n const refs: ExtractedReference[] = [];\n const seen = new Set<string>(); // 用于去重(基于 combined 字符串)\n\n const traverse = (value: any) => {\n if (!value || typeof value !== 'object') {\n return;\n }\n\n // 遍历对象的所有字段\n for (const [key, val] of Object.entries(value)) {\n // 场景 1:字段名是引用字段\n if (key in REFERENCE_FIELD_MAP) {\n // 值必须是字符串才有效\n if (typeof val === 'string') {\n const type = REFERENCE_FIELD_MAP[key];\n const combined = `${key}:${val}`;\n\n // 去重检查\n if (!seen.has(combined)) {\n seen.add(combined);\n refs.push({\n ref: val,\n type,\n path: key,\n value: val,\n fieldName: key,\n combined\n } as ExtractedReference);\n }\n }\n // 引用字段不需要递归遍历(值不是对象)\n continue;\n }\n\n // 场景 2:值是字符串且包含设计令牌($colors.xxx, $fonts.xxx等)\n if (typeof val === 'string') {\n const tokens = this.extractDesignTokens(val);\n tokens.forEach(token => {\n // 设计令牌是特殊的引用,字段名固定为 $ref\n const combined = `$ref:${token}`;\n if (!seen.has(combined)) {\n seen.add(combined);\n refs.push({\n ref: token,\n type: ReferenceType.GEOMETRY_REF,\n path: '$ref',\n value: token,\n fieldName: '$ref',\n combined\n } as ExtractedReference);\n }\n });\n continue; // 如果是字符串,无需递归\n }\n\n // 场景 3:值是数组,遍历每个元素\n if (Array.isArray(val)) {\n val.forEach(item => traverse(item));\n continue;\n }\n\n // 场景 4:值是对象,递归遍历\n if (typeof val === 'object') {\n traverse(val);\n }\n }\n };\n\n traverse(obj);\n\n return refs;\n }\n\n /**\n * 提取字符串中的设计令牌\n *\n * 示例:\n * - \"$colors.success\" → [\"$colors.success\"]\n * - \"prefix-$spacing.large-suffix\" → [\"$spacing.large\"]\n *\n * 模式:$xxx.yyy(如 $colors.primary, $fonts.label, $spacing.large)\n *\n * @param str - 要解析的字符串\n * @returns 设计令牌数组\n */\n private static extractDesignTokens(str: string): string[] {\n const tokens: string[] = [];\n\n // 正则:匹配 $xxx.yyy 模式\n // \\$ - 匹配 $ 符号\n // [a-zA-Z_][a-zA-Z0-9_]* - 匹配主名称(如 colors, fonts)\n // \\. - 匹配点号\n // [a-zA-Z_][a-zA-Z0-9_]* - 匹配子名称(如 primary, label)\n const regex = /\\$[a-zA-Z_][a-zA-Z0-9_]*\\.[a-zA-Z_][a-zA-Z0-9_]*/g;\n\n let match: RegExpExecArray | null;\n while ((match = regex.exec(str)) !== null) {\n tokens.push(match[0]);\n }\n\n return tokens;\n }\n\n /**\n * 计算引用指标(用于调试和监控)\n *\n * @param obj - 要分析的对象\n * @returns 引用统计信息\n */\n static calculateStats(obj: any): {\n totalRefs: number;\n uniqueRefs: number;\n fieldCounts: Record<string, number>;\n } {\n const refs: string[] = this.extractRefs(obj).map(ref => ref.ref);\n const fieldCounts: Record<string, number> = {};\n\n const countFields = (value: any) => {\n if (!value || typeof value !== 'object') {\n return;\n }\n\n for (const [key, val] of Object.entries(value)) {\n if (key in REFERENCE_FIELD_MAP) {\n fieldCounts[key] = (fieldCounts[key] || 0) + 1;\n } else if (typeof val === 'object') {\n countFields(val);\n }\n }\n };\n\n countFields(obj);\n\n return {\n totalRefs: refs.length,\n uniqueRefs: new Set(refs).size,\n fieldCounts,\n };\n }\n}\n\n/**\n * 快速提取助手函数(向后兼容)\n *\n * 返回传统的字符串数组(如 [\"animationRef:value1\", \"geometryRef:value2\"])\n * 用于兼容现有代码\n */\nexport function extractAllReferences(obj: any): string[] {\n const structuredRefs = ReferenceExtractor.extractRefs(obj);\n return structuredRefs.map(ref => ref.combined);\n}\n\n/**\n * 提取结构化引用(新API)\n *\n * 返回完整的结构化数据,包含字段上下文\n * 推荐用于新代码\n */\nexport function extractAllReferencesEnhanced(obj: any): ExtractedReference[] {\n return ReferenceExtractor.extractRefs(obj);\n}\n","/**\r\n * TriangleAdapterV3 解析器模块导出\r\n */\r\n\r\nimport type { ReferenceContext } from '../types';\r\nimport { ReferenceType } from '../types';\r\nimport type { ExtractedReference } from './referenceExtractor';\r\nimport { createDesignTokenResolver } from './designTokenResolver';\r\nimport { createGeometryRefResolver } from './geometryRefResolver';\r\nimport { createTransformRefResolver } from './transformRefResolver';\r\nimport { createStyleRefResolver } from './styleRefResolver';\r\nimport { createLayoutRefResolver } from './layoutRefResolver';\r\nimport { createAnimationRefResolver } from './animationRefResolver';\r\nimport { createSliderRefResolver } from './sliderRefResolver';\r\nimport { createGeometryTransformRefResolver } from './geometryTransformRefResolver';\r\nimport { ReferenceExtractor } from './referenceExtractor';\r\n\r\n// 导出解析器类\r\nexport * from './designTokenResolver';\r\nexport * from './geometryRefResolver';\r\nexport * from './transformRefResolver';\r\nexport * from './styleRefResolver';\r\nexport * from './layoutRefResolver';\r\nexport * from './animationRefResolver';\r\nexport * from './sliderRefResolver';\r\nexport * from './geometryTransformRefResolver';\r\nexport * from './referenceExtractor';\r\n\r\n// 解析器接口\r\nexport interface Resolver {\r\n type: ReferenceType;\r\n canResolve(ref: string): boolean;\r\n resolve(ref: string, context: ReferenceContext): any;\r\n validate?(ref: string, context: ReferenceContext): boolean;\r\n}\r\n\r\n/**\r\n * 可解析的引用类型(支持字符串和结构化数据)\r\n */\r\nexport type ResolvableReference = string | ExtractedReference;\r\n\r\n/**\r\n * 解析器注册表\r\n */\r\nexport class ResolverRegistry {\r\n private resolvers: Resolver[] = [];\r\n\r\n constructor() {\r\n this.registerDefaultResolvers();\r\n }\r\n\r\n /**\r\n * 注册默认解析器\r\n */\r\n private registerDefaultResolvers() {\r\n this.register(createDesignTokenResolver());\r\n this.register(createGeometryRefResolver());\r\n this.register(createTransformRefResolver());\r\n this.register(createStyleRefResolver());\r\n this.register(createLayoutRefResolver());\r\n this.register(createAnimationRefResolver());\r\n this.register(createSliderRefResolver());\r\n this.register(createGeometryTransformRefResolver());\r\n }\r\n\r\n /**\r\n * 注册解析器\r\n */\r\n register(resolver: Resolver): void {\r\n this.resolvers.push(resolver);\r\n }\r\n\r\n /**\r\n * 获取所有解析器\r\n */\r\n getAllResolvers(): Resolver[] {\r\n return [...this.resolvers];\r\n }\r\n\r\n /**\r\n * 根据引用类型获取解析器\r\n */\r\n getResolverByType(type: ReferenceType): Resolver | undefined {\r\n return this.resolvers.find(resolver => resolver.type === type);\r\n }\r\n\r\n /**\r\n * 根据引用字符串获取解析器\r\n */\r\n getResolverForRef(ref: string): Resolver | undefined {\r\n return this.resolvers.find(resolver => resolver.canResolve(ref));\r\n }\r\n\r\n /**\r\n * 解析单个引用(支持字符串和结构化数据)\r\n *\r\n * 策略:\r\n * - 如果是 ExtractedReference:直接使用其类型信息,精确解析\r\n * - 如果是字符串:尝试所有声明可以解析的解析器(向后兼容)\r\n * 如果一个解析器抛出错误,继续尝试下一个\r\n */\r\n resolve(ref: ResolvableReference, context: ReferenceContext): any {\r\n // ===== 方案 1:结构化数据(推荐)=====\r\n if (typeof ref !== 'string') {\r\n // 已经是 ExtractedReference,直接使用类型信息\r\n const resolver = this.getResolverByType(ref.type);\r\n if (!resolver) {\r\n throw new Error(`找不到类型为 ${ref.type} 的解析器`);\r\n }\r\n\r\n try {\r\n // 解析时使用 value 字段(不是 combined)\r\n return resolver.resolve(ref.value, context);\r\n } catch (error) {\r\n throw new Error(\r\n `解析器 ${ref.type} 解析 ${ref.combined} 失败: ${error}`\r\n );\r\n }\r\n }\r\n\r\n // ===== 方案 2:字符串格式(向后兼容)=====\r\n // 获取所有声称可以解析该引用的解析器\r\n const eligibleResolvers = this.resolvers.filter(resolver => resolver.canResolve(ref));\r\n\r\n if (eligibleResolvers.length === 0) {\r\n throw new Error(`没有找到适合的解析器: ${ref}`);\r\n }\r\n\r\n // 尝试每个解析器,直到成功\r\n for (const resolver of eligibleResolvers) {\r\n try {\r\n const result = resolver.resolve(ref, context);\r\n return result;\r\n } catch (error) {\r\n // 解析失败,继续尝试下一个解析器\r\n console.debug(`解析器 ${resolver.type} 解析 ${ref} 失败:`, error);\r\n continue;\r\n }\r\n }\r\n\r\n // 所有解析器都失败了\r\n throw new Error(`所有解析器都无法解析引用: ${ref}`);\r\n }\r\n\r\n /**\r\n * 批量解析引用(支持结构化数据)\r\n */\r\n batchResolve(refs: ResolvableReference[], context: ReferenceContext): Record<string, any> {\r\n const results: Record<string, any> = {};\r\n\r\n for (const ref of refs) {\r\n try {\r\n // 统一使用 resolve 方法(自动处理字符串和结构化数据)\r\n const result = this.resolve(ref, context);\r\n // key 使用 combined(字符串)或 value(结构化数据)\r\n const key = typeof ref === 'string' ? ref : ref.combined;\r\n results[key] = result;\r\n } catch (error) {\r\n const key = typeof ref === 'string' ? ref : ref.combined;\r\n console.warn(`引用解析失败: ${key}`, error);\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * 提取对象中的所有引用(新方法 - 返回结构化数据)\r\n *\r\n * 使用 ReferenceExtractor,基于直接的字段名匹配\r\n * 性能更好,代码更简洁,易于维护\r\n *\r\n * @param obj - 要提取引用的对象\r\n * @returns 结构化引用数组(包含字段上下文)\r\n */\r\n extractAllRefsEnhanced(obj: any): ExtractedReference[] {\r\n try {\r\n // 使用新的 ReferenceExtractor(推荐)\r\n return ReferenceExtractor.extractRefs(obj);\r\n } catch (error) {\r\n console.warn('ReferenceExtractor 提取失败:', error);\r\n // 返回空数组,不再回退到旧实现\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 提取对象中的所有引用(向后兼容)\r\n *\r\n * 返回传统的字符串数组,用于兼容现有代码\r\n *\r\n * @param obj - 要提取引用的对象\r\n * @returns 引用数组(去重,格式如 [\"animationRef:value1\", ...])\r\n */\r\n extractAllRefs(obj: any): string[] {\r\n const structuredRefs = this.extractAllRefsEnhanced(obj);\r\n return structuredRefs.map(ref => ref.combined);\r\n }\r\n\r\n /**\r\n * 提取对象中的所有引用(旧方法 - 仅用于性能测试对比)\r\n *\r\n * @deprecated 此方法仅用于性能测试对比,生产代码应使用 extractAllRefsEnhanced()\r\n * @param obj - 要提取引用的对象\r\n * @returns 引用数组(去重)\r\n */\r\n extractAllRefsLegacy(obj: any): string[] {\r\n const refs: string[] = [];\r\n\r\n // 简化的旧实现,用于性能对比\r\n const traverse = (value: any) => {\r\n if (!value || typeof value !== 'object') {\r\n return;\r\n }\r\n\r\n for (const [key, val] of Object.entries(value)) {\r\n // 检查是否是引用字段\r\n if (key.endsWith('Ref') && typeof val === 'string') {\r\n refs.push(val);\r\n } else if (typeof val === 'string' && val.includes('$')) {\r\n // 设计令牌\r\n const tokens = val.match(/\\$[a-zA-Z_][a-zA-Z0-9_]*\\.[a-zA-Z_][a-zA-Z0-9_]*/g);\r\n if (tokens) refs.push(...tokens);\r\n } else if (Array.isArray(val)) {\r\n val.forEach(item => traverse(item));\r\n } else if (typeof val === 'object') {\r\n traverse(val);\r\n }\r\n }\r\n };\r\n\r\n traverse(obj);\r\n return [...new Set(refs)];\r\n }\r\n\r\n\r\n /**\r\n * 验证引用是否存在\r\n */\r\n validate(ref: string, context: ReferenceContext): boolean {\r\n const resolver = this.getResolverForRef(ref);\r\n if (!resolver) {\r\n return false;\r\n }\r\n\r\n if (resolver.validate) {\r\n return resolver.validate(ref, context);\r\n }\r\n\r\n // 如果没有 validate 方法,尝试解析\r\n try {\r\n resolver.resolve(ref, context);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 创建默认解析器注册表\r\n */\r\nexport function createDefaultResolverRegistry(): ResolverRegistry {\r\n return new ResolverRegistry();\r\n}","/**\r\n * 图形转换器\r\n *\r\n * 处理 graph 类型内容块的转换和引用解析\r\n */\r\n\r\nimport type { ReferenceContext } from '../types';\r\nimport { CONTENT_BLOCK_TYPES } from '../constants';\r\nimport {\r\n GeometryRefResolver,\r\n StyleRefResolver,\r\n TransformRefResolver,\r\n AnimationRefResolver\r\n} from '../resolvers';\r\nimport type { AnimationConfig } from '../../../components/MathGraph/animation.types';\r\n\r\n/**\r\n * 图形转换器\r\n */\r\nexport class GraphTransformer {\r\n /**\r\n * 转换图形内容块\r\n */\r\n static transform(\r\n contentBlock: any,\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): any {\r\n const {\r\n enableReferenceResolution = true,\r\n strictMode = false\r\n } = config;\r\n\r\n console.error(`🔄 GraphTransformer.transform START for content block:`, {\r\n blockType: contentBlock.type,\r\n hasShapes: Array.isArray(contentBlock.shapes),\r\n shapesCount: contentBlock.shapes ? contentBlock.shapes.length : 0,\r\n enableReferenceResolution,\r\n strictMode,\r\n contextGeometryKeys: Object.keys(context.geometryPresets || {})\r\n });\r\n\r\n console.error(`🎯 GraphTransformer.transform called for content block:`, {\r\n blockType: contentBlock.type,\r\n hasShapes: Array.isArray(contentBlock.shapes),\r\n shapesCount: contentBlock.shapes ? contentBlock.shapes.length : 0,\r\n enableReferenceResolution,\r\n strictMode\r\n });\r\n\r\n // 特别记录question场景的graph块\r\n if (contentBlock.shapes && Array.isArray(contentBlock.shapes)) {\r\n console.warn(`📊 GraphTransformer contentBlock shapes (${contentBlock.shapes.length}):`, contentBlock.shapes.map((s: any) => ({\r\n id: s.id,\r\n type: s.type,\r\n geometryRef: s.geometryRef,\r\n styleRef: s.styleRef\r\n })));\r\n }\r\n\r\n // 基础转换\r\n const transformed = {\r\n ...contentBlock,\r\n type: CONTENT_BLOCK_TYPES.GRAPH\r\n };\r\n\r\n // 如果禁用引用解析,直接返回\r\n if (!enableReferenceResolution) {\r\n return transformed;\r\n }\r\n\r\n try {\r\n // 处理 boardRef\r\n if (transformed.boardRef) {\r\n transformed.boardConfig = this.resolveBoardConfig(transformed.boardRef, context);\r\n delete transformed.boardRef;\r\n }\r\n\r\n // 处理 shapes\r\n if (Array.isArray(transformed.shapes)) {\r\n console.error(`🎯 GraphTransformer处理shapes数组,数量: ${transformed.shapes.length}`);\r\n transformed.shapes = transformed.shapes.map((shape: any, index: number) => {\r\n console.error(` 🎯 处理shape[${index}]:`, {\r\n id: shape.id,\r\n geometryRef: shape.geometryRef,\r\n styleRef: shape.styleRef,\r\n keys: Object.keys(shape)\r\n });\r\n return this.transformShape(shape, context, { strictMode });\r\n });\r\n }\r\n\r\n // 处理 styleRef\r\n if (transformed.styleRef) {\r\n try {\r\n const style = StyleRefResolver.resolve(transformed.styleRef, context);\r\n transformed.style = style;\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`图形样式解析失败: ${transformed.styleRef}`, error);\r\n }\r\n delete transformed.styleRef;\r\n }\r\n\r\n // 处理 animationRef 或内联动画配置(✨ 新增)\r\n if (transformed.animationRef) {\r\n console.warn(`🎬 GraphTransformer处理animationRef: ${transformed.animationRef}`);\r\n try {\r\n // 确保使用 animationRef:xxx 格式(支持简单格式自动转换)\r\n const refWithPrefix = transformed.animationRef.startsWith('animationRef:')\r\n ? transformed.animationRef\r\n : `animationRef:${transformed.animationRef}`;\r\n const animationConfig = AnimationRefResolver.resolve(refWithPrefix, context);\r\n console.warn(` 动画配置解析结果:`, {\r\n animationId: animationConfig.id,\r\n transformCount: animationConfig.transforms.length,\r\n hasControl: !!animationConfig.control,\r\n controlConfig: animationConfig.control,\r\n hasVisualEffects: !!animationConfig.visualEffects,\r\n visualEffectsCount: animationConfig.visualEffects?.length || 0\r\n });\r\n\r\n // ✅ 转换为 MathGraph 的 animation prop 格式\r\n transformed.animation = animationConfig;\r\n\r\n // 清理旧的 transform 配置(如果存在)\r\n if (transformed.transformDefinitions) {\r\n console.warn(` 清理旧的 transformDefinitions(被 animation 替代)`);\r\n delete transformed.transformDefinitions;\r\n }\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`❌ 动画配置解析失败: ${transformed.animationRef}`, error);\r\n // 动画解析失败不影响主要功能,继续处理\r\n }\r\n delete transformed.animationRef;\r\n } else if (transformed.animation) {\r\n // 如果已经是内联的 animation 配置,直接使用\r\n console.warn(`🎬 GraphTransformer检测到内联动画配置:`, {\r\n animationId: transformed.animation.id,\r\n transformCount: transformed.animation.transforms?.length || 0\r\n });\r\n\r\n // 验证内联配置的格式\r\n if (transformed.animation.transforms && Array.isArray(transformed.animation.transforms)) {\r\n console.warn(` 内联动画配置有效,transforms 数量: ${transformed.animation.transforms.length}`);\r\n } else {\r\n console.warn(` ⚠️ 内联动画配置格式无效,缺少 transforms 数组`);\r\n // 格式无效,删除该配置\r\n delete transformed.animation;\r\n }\r\n }\r\n\r\n return transformed;\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`图形转换失败:`, error);\r\n return transformed;\r\n }\r\n }\r\n\r\n /**\r\n * 转换单个图形元素\r\n */\r\n private static transformShape(\r\n shape: any,\r\n context: ReferenceContext,\r\n config: { strictMode?: boolean } = {}\r\n ): any {\r\n const { strictMode = false } = config;\r\n console.error(`🔄 GraphTransformer.transformShape START for shape:`, {\r\n shapeId: shape.id,\r\n shapeType: shape.type,\r\n hasGeometryRef: 'geometryRef' in shape,\r\n geometryRef: shape.geometryRef,\r\n hasStyleRef: 'styleRef' in shape,\r\n styleRef: shape.styleRef,\r\n allShapeKeys: Object.keys(shape),\r\n contextGeometryKeys: Object.keys(context.geometryPresets || {})\r\n });\r\n\r\n // 特别检查base_line和height_line形状\r\n if (shape.id === 'base_line' || shape.id === 'height_line') {\r\n console.error(`🔍 特别处理 ${shape.id}:`, {\r\n id: shape.id,\r\n type: shape.type,\r\n geometryRef: shape.geometryRef,\r\n styleRef: shape.styleRef,\r\n endpoints: shape.endpoints,\r\n endpointsIsArray: Array.isArray(shape.endpoints)\r\n });\r\n }\r\n\r\n let transformedShape = { ...shape };\r\n\r\n // 调试:记录点类型图形\r\n if (shape.type === 'point') {\r\n console.warn(`📌 GraphTransformer processing point ${shape.id}:`, {\r\n id: shape.id,\r\n type: shape.type,\r\n position: shape.position,\r\n positionType: typeof shape.position,\r\n positionIsArray: Array.isArray(shape.position),\r\n shapeKeys: Object.keys(shape)\r\n });\r\n }\r\n\r\n try {\r\n // 处理 geometryRef\r\n if (transformedShape.geometryRef) {\r\n console.warn(`🔄 GraphTransformer processing geometryRef: ${transformedShape.geometryRef} for shape ${transformedShape.id}`, {\r\n shapeId: transformedShape.id,\r\n shapeType: transformedShape.type,\r\n geometryRef: transformedShape.geometryRef,\r\n contextHasGeometryPresets: !!context.geometryPresets,\r\n geometryPresetKeys: context.geometryPresets ? Object.keys(context.geometryPresets) : []\r\n });\r\n try {\r\n const geometry = GeometryRefResolver.resolve(transformedShape.geometryRef, context);\r\n console.warn(` Geometry resolved for ${transformedShape.geometryRef}:`, {\r\n type: geometry.type,\r\n hasVertices: 'vertices' in geometry,\r\n vertices: geometry.vertices,\r\n hasPosition: 'position' in geometry,\r\n position: geometry.position,\r\n hasEndpoints: 'endpoints' in geometry,\r\n endpoints: geometry.endpoints,\r\n endpointsIsArray: Array.isArray(geometry.endpoints),\r\n geometryKeys: Object.keys(geometry)\r\n });\r\n // 保存关键属性\r\n const originalType = transformedShape.type;\r\n const originalContent = transformedShape.content;\r\n // 合并几何属性\r\n const beforeMerge = { ...transformedShape };\r\n Object.assign(transformedShape, geometry);\r\n // 恢复原始形状的id,避免被几何预设的id覆盖\r\n transformedShape.id = shape.id;\r\n // 只有在原始形状有type时才覆盖几何预设的type\r\n if (originalType !== undefined) {\r\n transformedShape.type = originalType; // 保持原始type\r\n }\r\n if (originalContent !== undefined) {\r\n transformedShape.content = originalContent; // 保持原始content\r\n }\r\n console.warn(` After merge for ${transformedShape.id}:`, {\r\n type: transformedShape.type,\r\n vertices: transformedShape.vertices,\r\n verticesIsArray: Array.isArray(transformedShape.vertices),\r\n verticesLength: transformedShape.vertices ? transformedShape.vertices.length : 'undefined',\r\n position: transformedShape.position,\r\n endpoints: transformedShape.endpoints,\r\n endpointsIsArray: Array.isArray(transformedShape.endpoints),\r\n transformedShapeKeys: Object.keys(transformedShape)\r\n });\r\n\r\n // 检查合并后是否有必要的几何属性(根据几何类型)\r\n const geometryType = transformedShape.type;\r\n let hasRequiredGeometry = false;\r\n\r\n // 特殊处理:如果原始几何定义有顶点$ref引用,需要提取点名字到verticesConfig\r\n // 获取原始几何定义(未解析$ref的)\r\n const originalGeometry = context.geometryPresets[transformedShape.geometryRef];\r\n console.warn(`🔍 DEBUG: 检查原始几何定义`, {\r\n geometryRef: transformedShape.geometryRef,\r\n originalGeometryExists: !!originalGeometry,\r\n originalGeometryType: originalGeometry?.type,\r\n originalGeometryKeys: originalGeometry ? Object.keys(originalGeometry) : [],\r\n hasVertices: originalGeometry && 'vertices' in originalGeometry,\r\n verticesIsArray: originalGeometry && Array.isArray(originalGeometry.vertices),\r\n verticesLength: originalGeometry?.vertices?.length,\r\n contextGeometryPresetsKeys: Object.keys(context.geometryPresets || {})\r\n });\r\n if (originalGeometry && originalGeometry.vertices && Array.isArray(originalGeometry.vertices)) {\r\n console.warn(`📌 原始几何定义有vertices,检查$ref引用`, {\r\n originalVertices: originalGeometry.vertices,\r\n hasWithLabel: 'withLabel' in originalGeometry,\r\n withLabel: originalGeometry.withLabel,\r\n hasLabel: 'label' in originalGeometry,\r\n label: originalGeometry.label\r\n });\r\n\r\n // 初始化verticesConfig(如果不存在)\r\n if (!transformedShape.verticesConfig) {\r\n transformedShape.verticesConfig = {};\r\n }\r\n\r\n // 检查每个顶点是否为$ref,提取点名字\r\n originalGeometry.vertices.forEach((vertex: any, index: number) => {\r\n console.warn(`🔍 DEBUG: 检查顶点${index}:`, {\r\n vertex,\r\n isObject: vertex && typeof vertex === 'object',\r\n hasDollarRef: vertex && typeof vertex === 'object' && '$ref' in vertex,\r\n refName: vertex?.$ref\r\n });\r\n if (vertex && typeof vertex === 'object' && '$ref' in vertex) {\r\n const refName = vertex.$ref;\r\n console.warn(`🔍 DEBUG: 找到$ref引用 ${refName},检查context.geometryPresets`);\r\n if (context.geometryPresets && context.geometryPresets[refName]) {\r\n const pointDefinition = context.geometryPresets[refName];\r\n console.warn(`🔍 DEBUG: 找到点定义 ${refName}:`, pointDefinition);\r\n if (pointDefinition.name) {\r\n if (!transformedShape.verticesConfig[index]) {\r\n transformedShape.verticesConfig[index] = {};\r\n }\r\n transformedShape.verticesConfig[index].name = pointDefinition.name;\r\n console.warn(`✅ 从原始几何定义提取顶点${index}名字: ${pointDefinition.name}`);\r\n } else {\r\n console.warn(`⚠️ 点定义 ${refName} 没有name属性`);\r\n }\r\n } else {\r\n console.warn(`⚠️ context.geometryPresets 中未找到 ${refName}`);\r\n }\r\n } else {\r\n console.warn(`⚠️ 顶点${index}不是$ref对象`);\r\n }\r\n });\r\n\r\n // 如果原始几何定义有withLabel或label配置,合并到verticesConfig顶层\r\n if (originalGeometry.withLabel !== undefined) {\r\n transformedShape.verticesConfig.withLabel = originalGeometry.withLabel;\r\n }\r\n if (originalGeometry.label && typeof originalGeometry.label === 'object') {\r\n const label = originalGeometry.label;\r\n if (label.offset && Array.isArray(label.offset) && label.offset.length >= 2) {\r\n transformedShape.verticesConfig.offset = label.offset;\r\n }\r\n if (label.fontSize !== undefined) {\r\n transformedShape.verticesConfig.fontSize = label.fontSize;\r\n }\r\n if (label.color) {\r\n transformedShape.verticesConfig.color = label.color;\r\n }\r\n if (label.anchorX) {\r\n transformedShape.verticesConfig.anchorX = label.anchorX;\r\n }\r\n if (label.anchorY) {\r\n transformedShape.verticesConfig.anchorY = label.anchorY;\r\n }\r\n }\r\n\r\n console.warn(`✅ 构建的verticesConfig:`, transformedShape.verticesConfig);\r\n }\r\n\r\n if (geometryType === 'segment' || geometryType === 'line') {\r\n hasRequiredGeometry = 'endpoints' in transformedShape && Array.isArray(transformedShape.endpoints);\r\n } else if (geometryType === 'point') {\r\n hasRequiredGeometry = 'position' in transformedShape && transformedShape.position !== undefined;\r\n } else if (geometryType === 'polygon' || geometryType === 'triangle' || geometryType === 'rectangle' || geometryType === 'parallelogram') {\r\n hasRequiredGeometry = 'vertices' in transformedShape && Array.isArray(transformedShape.vertices);\r\n } else {\r\n // 未知类型,至少检查是否有任一几何属性\r\n hasRequiredGeometry = ('vertices' in transformedShape && Array.isArray(transformedShape.vertices)) ||\r\n ('endpoints' in transformedShape && Array.isArray(transformedShape.endpoints)) ||\r\n ('position' in transformedShape && transformedShape.position !== undefined);\r\n }\r\n\r\n if (!hasRequiredGeometry) {\r\n console.error(`❌ ERROR: After geometryRef merge, shape ${transformedShape.id} (type: ${geometryType}) has no valid geometry properties!`);\r\n console.error(` geometry keys:`, Object.keys(geometry));\r\n console.error(` geometry.type:`, geometry.type);\r\n console.error(` transformedShape keys:`, Object.keys(transformedShape));\r\n }\r\n\r\n // 如果几何中有样式引用,解析它\r\n if (geometry.styleRef) {\r\n console.error(`🎨 GraphTransformer处理几何styleRef: ${geometry.styleRef}`);\r\n const style = StyleRefResolver.resolve(geometry.styleRef, context);\r\n console.error(` 几何样式解析结果:`, style);\r\n transformedShape.style = style;\r\n }\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.error(`❌ 图形几何解析失败: ${transformedShape.geometryRef}`, error);\r\n console.error(` shape id: ${transformedShape.id}, type: ${transformedShape.type}`);\r\n console.error(` context.geometryPresets keys:`, context.geometryPresets ? Object.keys(context.geometryPresets) : 'undefined');\r\n }\r\n delete transformedShape.geometryRef;\r\n }\r\n\r\n // 处理 styleRef\r\n if (transformedShape.styleRef) {\r\n console.error(`🎨 GraphTransformer处理形状styleRef: ${transformedShape.styleRef}, shape id: ${transformedShape.id}`);\r\n try {\r\n const style = StyleRefResolver.resolve(transformedShape.styleRef, context);\r\n console.error(` 形状样式解析成功:`, style);\r\n // ✅ 扁平化样式属性到顶层,而不是嵌套\r\n // 排除样式中的 id 属性,避免覆盖形状的 id\r\n const { id: styleId, ...styleWithoutId } = style;\r\n transformedShape = {\r\n ...transformedShape,\r\n ...styleWithoutId, // 展开样式属性到顶层(不包含 id)\r\n // 保留原有的 style 对象(用于其他用途)\r\n style: {\r\n ...transformedShape.style,\r\n ...style\r\n }\r\n };\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`图形元素样式解析失败: ${transformedShape.styleRef}`, error);\r\n // 如果样式解析失败,删除可能已设置的样式(来自几何预设)\r\n delete transformedShape.style;\r\n }\r\n delete transformedShape.styleRef;\r\n }\r\n\r\n // 处理 transformations\r\n if (Array.isArray(transformedShape.transformations)) {\r\n transformedShape.transformations = transformedShape.transformations.map(\r\n (transform: any) => this.transformTransform(transform, context, { strictMode })\r\n );\r\n }\r\n\r\n // 处理 label(可能包含设计令牌)\r\n if (transformedShape.label && typeof transformedShape.label === 'object') {\r\n transformedShape.label = this.transformLabel(transformedShape.label, context);\r\n }\r\n\r\n // 类型映射:将 segment 转换为 line,并映射 endpoints 到 start/end\r\n console.warn(`🔍 Checking segment conversion for ${transformedShape.id}:`, {\r\n type: transformedShape.type,\r\n hasEndpoints: 'endpoints' in transformedShape,\r\n endpoints: transformedShape.endpoints,\r\n endpointsIsArray: Array.isArray(transformedShape.endpoints),\r\n endpointsLength: transformedShape.endpoints ? transformedShape.endpoints.length : 0,\r\n shapeKeys: Object.keys(transformedShape)\r\n });\r\n\r\n // 转换坐标格式(数组 -> 对象),并解析点引用\r\n transformedShape = this.convertShapeCoordinates(transformedShape, context);\r\n\r\n // 类型映射:将 segment 转换为 line,并映射 endpoints 到 start/end\r\n // 注意:此时 endpoints 可能已经被解析为坐标对象\r\n if (transformedShape.type === 'segment' && Array.isArray(transformedShape.endpoints) && transformedShape.endpoints.length >= 2) {\r\n console.warn(`🔄 Converting segment to line for ${transformedShape.id}:`, {\r\n originalType: transformedShape.type,\r\n endpoints: transformedShape.endpoints\r\n });\r\n transformedShape.type = 'line';\r\n\r\n // 解析端点(可能已经是坐标对象,也可能是引用)\r\n const startPoint = this.resolvePointReference(transformedShape.endpoints[0], context);\r\n const endPoint = this.resolvePointReference(transformedShape.endpoints[1], context);\r\n\r\n // 确保 start 和 end 是坐标对象\r\n if (Array.isArray(startPoint) && startPoint.length >= 2) {\r\n transformedShape.start = { x: startPoint[0], y: startPoint[1] };\r\n } else if (startPoint && typeof startPoint === 'object' && 'x' in startPoint && 'y' in startPoint) {\r\n transformedShape.start = startPoint;\r\n } else {\r\n // 如果无法解析,保持原样(可能是引用对象)\r\n transformedShape.start = transformedShape.endpoints[0];\r\n }\r\n\r\n if (Array.isArray(endPoint) && endPoint.length >= 2) {\r\n transformedShape.end = { x: endPoint[0], y: endPoint[1] };\r\n } else if (endPoint && typeof endPoint === 'object' && 'x' in endPoint && 'y' in endPoint) {\r\n transformedShape.end = endPoint;\r\n } else {\r\n transformedShape.end = transformedShape.endpoints[1];\r\n }\r\n\r\n delete transformedShape.endpoints;\r\n }\r\n\r\n // 调试:输出转换后的形状信息\r\n console.warn(`✅ GraphTransformer finished transforming shape ${transformedShape.id} (${transformedShape.type}):`, {\r\n id: transformedShape.id,\r\n type: transformedShape.type,\r\n hasVertices: 'vertices' in transformedShape,\r\n vertices: transformedShape.vertices,\r\n verticesIsArray: Array.isArray(transformedShape.vertices),\r\n verticesLength: transformedShape.vertices ? transformedShape.vertices.length : 0,\r\n hasVerticesConfig: 'verticesConfig' in transformedShape,\r\n verticesConfig: transformedShape.verticesConfig,\r\n verticesConfigKeys: transformedShape.verticesConfig ? Object.keys(transformedShape.verticesConfig) : [],\r\n hasPosition: 'position' in transformedShape,\r\n position: transformedShape.position,\r\n hasStart: 'start' in transformedShape,\r\n start: transformedShape.start,\r\n hasEnd: 'end' in transformedShape,\r\n end: transformedShape.end,\r\n hasEndpoints: 'endpoints' in transformedShape,\r\n endpoints: transformedShape.endpoints,\r\n hasGeometryRef: 'geometryRef' in transformedShape,\r\n geometryRef: transformedShape.geometryRef,\r\n keys: Object.keys(transformedShape)\r\n });\r\n\r\n return transformedShape;\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`图形元素转换失败:`, error);\r\n return transformedShape;\r\n }\r\n }\r\n\r\n /**\r\n * 解析点引用($ref 或 geometryRef)\r\n */\r\n private static resolvePointReference(pointRef: any, context?: any): any {\r\n if (!pointRef || typeof pointRef !== 'object') {\r\n return pointRef;\r\n }\r\n\r\n // 处理 $ref 引用\r\n if ('$ref' in pointRef) {\r\n const refName = pointRef.$ref;\r\n if (context && context.geometryPresets && context.geometryPresets[refName]) {\r\n const point = context.geometryPresets[refName];\r\n // 点对象应该包含 position 属性\r\n if (point.position) {\r\n return point.position;\r\n }\r\n // 如果点对象本身就是坐标格式\r\n if ('x' in point && 'y' in point) {\r\n return point;\r\n }\r\n }\r\n // 如果无法解析,返回原始引用\r\n return pointRef;\r\n }\r\n\r\n // 处理 geometryRef 引用\r\n if ('geometryRef' in pointRef) {\r\n const refName = pointRef.geometryRef;\r\n if (context && context.geometryPresets && context.geometryPresets[refName]) {\r\n const point = context.geometryPresets[refName];\r\n if (point.position) {\r\n return point.position;\r\n }\r\n if ('x' in point && 'y' in point) {\r\n return point;\r\n }\r\n }\r\n return pointRef;\r\n }\r\n\r\n return pointRef;\r\n }\r\n\r\n /**\r\n * 转换图形元素中的坐标格式(数组转对象),并解析点引用\r\n */\r\n private static convertShapeCoordinates(shape: any, context?: any): any {\r\n if (!shape || typeof shape !== 'object') {\r\n return shape;\r\n }\r\n\r\n console.warn(`🔄 GraphTransformer.convertShapeCoordinates START for shape:`, {\r\n id: shape.id,\r\n type: shape.type,\r\n hasVertices: 'vertices' in shape,\r\n verticesIsArray: Array.isArray(shape.vertices),\r\n verticesLength: shape.vertices ? shape.vertices.length : 'undefined',\r\n shapeKeys: Object.keys(shape)\r\n });\r\n\r\n const processedShape = { ...shape };\r\n\r\n // 转换 position 字段(数组 [x, y] -> 对象 {x, y}),并解析引用\r\n if (processedShape.position) {\r\n if (Array.isArray(processedShape.position) && processedShape.position.length >= 2) {\r\n console.warn(`🔄 Converting position array to object for ${processedShape.id}:`, {\r\n shapeId: processedShape.id,\r\n positionArray: processedShape.position,\r\n convertedTo: { x: processedShape.position[0], y: processedShape.position[1] }\r\n });\r\n processedShape.position = {\r\n x: processedShape.position[0],\r\n y: processedShape.position[1]\r\n };\r\n } else if (typeof processedShape.position === 'object') {\r\n // 可能是 $ref 引用,尝试解析\r\n const resolvedPosition = this.resolvePointReference(processedShape.position, context);\r\n if (resolvedPosition && typeof resolvedPosition === 'object') {\r\n processedShape.position = resolvedPosition;\r\n }\r\n }\r\n }\r\n\r\n // 转换 vertices 字段(数组的数组 -> 对象数组),并解析引用\r\n if (Array.isArray(processedShape.vertices)) {\r\n // 初始化 verticesConfig 对象,保留现有的配置\r\n const verticesConfig: any = processedShape.verticesConfig ? { ...processedShape.verticesConfig } : {};\r\n console.warn(`🔍 convertShapeCoordinates: 初始化 verticesConfig`, {\r\n hasExisting: !!processedShape.verticesConfig,\r\n existingKeys: processedShape.verticesConfig ? Object.keys(processedShape.verticesConfig) : [],\r\n verticesConfigKeys: Object.keys(verticesConfig)\r\n });\r\n\r\n processedShape.vertices = processedShape.vertices.map((vertex: any, index: number) => {\r\n // 先尝试解析引用\r\n const resolvedVertex = this.resolvePointReference(vertex, context);\r\n\r\n // 检查是否为 $ref 引用,尝试获取完整的点定义\r\n let pointDefinition: any = null;\r\n if (vertex && typeof vertex === 'object' && '$ref' in vertex) {\r\n const refName = vertex.$ref;\r\n if (context && context.geometryPresets && context.geometryPresets[refName]) {\r\n pointDefinition = context.geometryPresets[refName];\r\n console.warn(`📌 Found point definition for ${refName} at vertex ${index}:`, {\r\n hasWithLabel: 'withLabel' in pointDefinition,\r\n withLabel: pointDefinition.withLabel,\r\n hasLabel: 'label' in pointDefinition,\r\n labelKeys: pointDefinition.label ? Object.keys(pointDefinition.label) : 'none'\r\n });\r\n\r\n // 设置 name(从点定义的 name 属性)\r\n if (pointDefinition.name) {\r\n if (!verticesConfig[index]) {\r\n verticesConfig[index] = {};\r\n }\r\n verticesConfig[index].name = pointDefinition.name;\r\n }\r\n }\r\n }\r\n\r\n if (Array.isArray(resolvedVertex) && resolvedVertex.length >= 2) {\r\n return {\r\n x: resolvedVertex[0],\r\n y: resolvedVertex[1]\r\n };\r\n }\r\n // 如果已经是对象格式,保持原样\r\n if (resolvedVertex && typeof resolvedVertex === 'object' && 'x' in resolvedVertex && 'y' in resolvedVertex) {\r\n return resolvedVertex;\r\n }\r\n // 如果是引用对象但无法解析,保持原样\r\n if (vertex && typeof vertex === 'object' && ('$ref' in vertex || 'geometryRef' in vertex)) {\r\n return vertex;\r\n }\r\n return vertex;\r\n });\r\n\r\n // 如果多边形有 withLabel 配置或 label 配置,构建统一的 verticesConfig\r\n if (processedShape.withLabel !== undefined || processedShape.label) {\r\n // 创建统一的 verticesConfig 对象\r\n const unifiedConfig: any = {\r\n withLabel: processedShape.withLabel !== undefined ? processedShape.withLabel : true\r\n };\r\n\r\n // 如果多边形有 label 配置,添加到统一配置\r\n if (processedShape.label && typeof processedShape.label === 'object') {\r\n const label = processedShape.label;\r\n\r\n // 只添加顶层的 label 配置\r\n if (label.offset && Array.isArray(label.offset) && label.offset.length >= 2) {\r\n unifiedConfig.offset = label.offset;\r\n }\r\n if (label.fontSize !== undefined) {\r\n unifiedConfig.fontSize = label.fontSize;\r\n }\r\n if (label.color) {\r\n unifiedConfig.color = label.color;\r\n }\r\n if (label.anchorX) {\r\n unifiedConfig.anchorX = label.anchorX;\r\n }\r\n if (label.anchorY) {\r\n unifiedConfig.anchorY = label.anchorY;\r\n }\r\n }\r\n\r\n // 将统一配置与顶点名字配置合并\r\n // 统一配置(withLabel, offset等)放在顶层\r\n // 顶点名字配置放在数字键中\r\n const mergedConfig: any = { ...unifiedConfig };\r\n\r\n // 将顶点名字配置复制到合并后的配置中\r\n for (const key in verticesConfig) {\r\n if (!isNaN(Number(key))) {\r\n // 数字键表示顶点索引配置\r\n if (!mergedConfig[key]) {\r\n mergedConfig[key] = {};\r\n }\r\n Object.assign(mergedConfig[key], verticesConfig[key]);\r\n }\r\n }\r\n\r\n processedShape.verticesConfig = mergedConfig;\r\n console.warn(`✅ Added merged verticesConfig for polygon ${processedShape.id}:`, mergedConfig);\r\n } else if (Object.keys(verticesConfig).length > 0) {\r\n // 如果只有顶点的 name 配置(没有多边形级别的配置),保留现有的 verticesConfig\r\n processedShape.verticesConfig = verticesConfig;\r\n console.warn(`✅ Added verticesConfig for polygon ${processedShape.id}:`, verticesConfig);\r\n }\r\n }\r\n\r\n // 转换 endpoints 字段(数组的数组 -> 对象数组),并解析引用\r\n if (Array.isArray(processedShape.endpoints)) {\r\n processedShape.endpoints = processedShape.endpoints.map((endpoint: any) => {\r\n // 先尝试解析引用\r\n const resolvedEndpoint = this.resolvePointReference(endpoint, context);\r\n\r\n if (Array.isArray(resolvedEndpoint) && resolvedEndpoint.length >= 2) {\r\n return {\r\n x: resolvedEndpoint[0],\r\n y: resolvedEndpoint[1]\r\n };\r\n }\r\n if (resolvedEndpoint && typeof resolvedEndpoint === 'object' && 'x' in resolvedEndpoint && 'y' in resolvedEndpoint) {\r\n return resolvedEndpoint;\r\n }\r\n // 如果是引用对象但无法解析,保持原样\r\n if (endpoint && typeof endpoint === 'object' && ('$ref' in endpoint || 'geometryRef' in endpoint)) {\r\n return endpoint;\r\n }\r\n return endpoint;\r\n });\r\n }\r\n\r\n // 转换 center 字段(数组 [x, y] -> 对象 {x, y})\r\n if (Array.isArray(processedShape.center) && processedShape.center.length >= 2) {\r\n processedShape.center = {\r\n x: processedShape.center[0],\r\n y: processedShape.center[1]\r\n };\r\n } else if (processedShape.center && typeof processedShape.center === 'object') {\r\n // 尝试解析引用\r\n const resolvedCenter = this.resolvePointReference(processedShape.center, context);\r\n if (resolvedCenter && typeof resolvedCenter === 'object') {\r\n processedShape.center = resolvedCenter;\r\n }\r\n }\r\n\r\n // 转换 start 和 end 字段(如果是数组或引用)\r\n if (processedShape.start) {\r\n if (Array.isArray(processedShape.start) && processedShape.start.length >= 2) {\r\n processedShape.start = {\r\n x: processedShape.start[0],\r\n y: processedShape.start[1]\r\n };\r\n } else if (typeof processedShape.start === 'object') {\r\n const resolvedStart = this.resolvePointReference(processedShape.start, context);\r\n if (resolvedStart && typeof resolvedStart === 'object') {\r\n processedShape.start = resolvedStart;\r\n }\r\n }\r\n }\r\n\r\n if (processedShape.end) {\r\n if (Array.isArray(processedShape.end) && processedShape.end.length >= 2) {\r\n processedShape.end = {\r\n x: processedShape.end[0],\r\n y: processedShape.end[1]\r\n };\r\n } else if (typeof processedShape.end === 'object') {\r\n const resolvedEnd = this.resolvePointReference(processedShape.end, context);\r\n if (resolvedEnd && typeof resolvedEnd === 'object') {\r\n processedShape.end = resolvedEnd;\r\n }\r\n }\r\n }\r\n\r\n // 递归处理嵌套对象\r\n for (const [key, value] of Object.entries(processedShape)) {\r\n if (Array.isArray(value)) {\r\n processedShape[key] = value.map((item: any) =>\r\n typeof item === 'object' ? this.convertShapeCoordinates(item, context) : item\r\n );\r\n } else if (value && typeof value === 'object') {\r\n processedShape[key] = this.convertShapeCoordinates(value, context);\r\n }\r\n }\r\n\r\n return processedShape;\r\n }\r\n\r\n /**\r\n * 转换变换配置\r\n */\r\n private static transformTransform(\r\n transform: any,\r\n context: ReferenceContext,\r\n config: { strictMode?: boolean } = {}\r\n ): any {\r\n const { strictMode = false } = config;\r\n const transformedTransform = { ...transform };\r\n\r\n // 处理 transformRef\r\n if (transformedTransform.transformRef) {\r\n try {\r\n const transformDef = TransformRefResolver.resolve(transformedTransform.transformRef, context);\r\n Object.assign(transformedTransform, transformDef);\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`变换解析失败: ${transformedTransform.transformRef}`, error);\r\n }\r\n delete transformedTransform.transformRef;\r\n }\r\n\r\n return transformedTransform;\r\n }\r\n\r\n /**\r\n * 转换标签配置\r\n */\r\n private static transformLabel(label: any, context: ReferenceContext): any {\r\n const transformedLabel = { ...label };\r\n\r\n // 处理 styleRef\r\n if (transformedLabel.styleRef) {\r\n try {\r\n const style = StyleRefResolver.resolve(transformedLabel.styleRef, context);\r\n transformedLabel.style = style;\r\n } catch (error) {\r\n console.warn(`标签样式解析失败: ${transformedLabel.styleRef}`, error);\r\n }\r\n delete transformedLabel.styleRef;\r\n }\r\n\r\n return transformedLabel;\r\n }\r\n\r\n /**\r\n * 解析画板配置\r\n */\r\n private static resolveBoardConfig(boardRef: string, context: ReferenceContext): any {\r\n // 优先从 context.boardDefinitions 中读取配置\r\n if (context.boardDefinitions && context.boardDefinitions[boardRef]) {\r\n return context.boardDefinitions[boardRef];\r\n }\r\n\r\n // 回退配置:如果找不到定义,使用硬编码配置\r\n const fallbackConfigs = {\r\n default: {\r\n originX: 2,\r\n originY: 2,\r\n boundingBox: [0, 7, 10, 0] as [number, number, number, number],\r\n keepAspectRatio: true,\r\n showGrid: false,\r\n showAxis: false\r\n },\r\n extended: {\r\n originX: 0,\r\n originY: 0,\r\n boundingBox: [-5, 12, 15, -5] as [number, number, number, number],\r\n keepAspectRatio: true,\r\n showGrid: true,\r\n showAxis: true,\r\n gridSize: 1\r\n }\r\n };\r\n\r\n return fallbackConfigs[boardRef as keyof typeof fallbackConfigs] || fallbackConfigs.default;\r\n }\r\n\r\n /**\r\n * 验证图形内容块\r\n */\r\n static validate(contentBlock: any): string[] {\r\n const errors: string[] = [];\r\n\r\n if (!contentBlock) {\r\n errors.push('图形内容块不能为空');\r\n return errors;\r\n }\r\n\r\n if (contentBlock.type !== CONTENT_BLOCK_TYPES.GRAPH) {\r\n errors.push(`图形内容块类型应为 'graph',实际为 '${contentBlock.type}'`);\r\n }\r\n\r\n if (!Array.isArray(contentBlock.shapes)) {\r\n errors.push('图形内容块缺少 shapes 数组');\r\n } else if (contentBlock.shapes.length === 0) {\r\n errors.push('图形内容块 shapes 数组不能为空');\r\n }\r\n\r\n return errors;\r\n }\r\n\r\n /**\r\n * 批量转换图形内容块\r\n */\r\n static batchTransform(\r\n contentBlocks: any[],\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): any[] {\r\n return contentBlocks\r\n .filter(block => block.type === CONTENT_BLOCK_TYPES.GRAPH)\r\n .map(block => this.transform(block, context, config));\r\n }\r\n}\r\n\r\n/**\r\n * 创建图形转换器实例\r\n */\r\nexport function createGraphTransformer() {\r\n return {\r\n type: CONTENT_BLOCK_TYPES.GRAPH,\r\n transform: GraphTransformer.transform.bind(GraphTransformer),\r\n validate: GraphTransformer.validate.bind(GraphTransformer)\r\n };\r\n}","/**\r\n * 几何变换转换器\r\n *\r\n * 处理 geometryTransform 类型内容块的转换和引用解析\r\n */\r\n\r\nimport type { ReferenceContext } from '../types';\r\nimport { CONTENT_BLOCK_TYPES } from '../constants';\r\nimport {\r\n GeometryRefResolver,\r\n StyleRefResolver,\r\n TransformRefResolver,\r\n SliderRefResolver\r\n} from '../resolvers';\r\nimport { GeometryTransformRefResolver } from '../resolvers/geometryTransformRefResolver';\r\nimport { GLOBAL_REFERENCE_CONTEXT } from '../config/embeddedConfigs';\r\n\r\n/**\r\n * 几何变换转换器\r\n */\r\nexport class GeometryTransformTransformer {\r\n /**\r\n * 规范化shapes对象,确保有static和animated属性\r\n */\r\n private static normalizeShapes(shapes: any): { static: any[]; animated: any[] } {\r\n if (!shapes || typeof shapes !== 'object') {\r\n return { static: [], animated: [] };\r\n }\r\n\r\n // 确保有static和animated属性\r\n const normalized = {\r\n static: Array.isArray(shapes.static) ? shapes.static : [],\r\n animated: Array.isArray(shapes.animated) ? shapes.animated : []\r\n };\r\n\r\n console.error('🔍 GeometryTransformTransformer.normalizeShapes:', {\r\n inputShapes: shapes,\r\n normalized,\r\n hasStatic: Array.isArray(shapes.static),\r\n hasAnimated: Array.isArray(shapes.animated),\r\n staticLength: normalized.static.length,\r\n animatedLength: normalized.animated.length\r\n });\r\n\r\n return normalized;\r\n }\r\n\r\n /**\r\n * 转换几何变换内容块\r\n */\r\n static transform(\r\n contentBlock: any,\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): any {\r\n const {\r\n enableReferenceResolution = true,\r\n strictMode = false\r\n } = config;\r\n\r\n // 检测是否有几何变换引用\r\n if (contentBlock.geometryTransformRef) {\r\n console.error('🔍 GeometryTransformTransformer.transform: 检测到几何变换引用', {\r\n geometryTransformRef: contentBlock.geometryTransformRef,\r\n hasOverride: !!contentBlock.override\r\n });\r\n\r\n try {\r\n if (enableReferenceResolution) {\r\n // 解析几何变换引用\r\n console.error('🔍 GeometryTransformTransformer: 解析 geometryTransformRef:', contentBlock.geometryTransformRef);\r\n const resolvedConfig = GeometryTransformRefResolver.resolve(\r\n contentBlock.geometryTransformRef,\r\n context,\r\n contentBlock.override\r\n );\r\n\r\n console.error('🔍 GeometryTransformTransformer: resolvedConfig:', resolvedConfig);\r\n console.error('🔍 GeometryTransformTransformer: resolvedConfig keys:', Object.keys(resolvedConfig || {}));\r\n\r\n // 转换为标准格式\r\n const transformed = {\r\n type: CONTENT_BLOCK_TYPES.GEOMETRY_TRANSFORM,\r\n metadata: {\r\n componentType: 'geometry-transform',\r\n config: resolvedConfig\r\n }\r\n };\r\n\r\n console.error('🔍 几何变换引用解析完成,继续处理几何引用:', transformed.metadata.config);\r\n\r\n // 重要:即使使用了引用解析,也需要处理其中的 geometryRef\r\n if (transformed.metadata.config && typeof transformed.metadata.config === 'object') {\r\n console.error('🔍 处理引用配置中的 geometryRef');\r\n transformed.metadata.config = this.transformConfig(transformed.metadata.config, context, { strictMode });\r\n }\r\n\r\n console.error('🔍 GeometryTransformTransformer: 返回解析后的 transformed:', transformed);\r\n console.error('🔍 GeometryTransformTransformer: transformed.metadata.config:', transformed.metadata.config);\r\n return transformed;\r\n } else {\r\n // 禁用引用解析时的回退处理\r\n console.warn('⚠️ 几何变换引用解析被禁用,使用默认配置');\r\n return {\r\n type: CONTENT_BLOCK_TYPES.GEOMETRY_TRANSFORM,\r\n metadata: {\r\n componentType: 'geometry-transform',\r\n config: {\r\n base: 6,\r\n height: 4,\r\n unit: 'cm',\r\n strategy: 'default',\r\n shapes: { static: [], animated: [] },\r\n transform: { type: 'composite', transforms: [] }\r\n }\r\n }\r\n };\r\n }\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.error('❌ 几何变换引用解析失败:', error);\r\n console.error('❌ contentBlock:', contentBlock);\r\n console.error('❌ context.geometryTransformConfigs:', context.geometryTransformConfigs);\r\n // 回退到内联配置\r\n }\r\n }\r\n\r\n // 从 context 获取基础几何属性(优先从 contentBlock,其次从 context.basicInfo)\r\n const base = contentBlock.base || contentBlock.config?.base || context.basicInfo?.base || 0;\r\n const height = contentBlock.height || contentBlock.config?.height || context.basicInfo?.height || 0;\r\n const unit = contentBlock.unit || contentBlock.config?.unit || context.basicInfo?.baseUnit || 'cm';\r\n\r\n // 基础转换\r\n const transformed = {\r\n ...contentBlock,\r\n type: CONTENT_BLOCK_TYPES.GEOMETRY_TRANSFORM,\r\n // 添加符合 MathCardV2 期望的 metadata 结构\r\n metadata: {\r\n componentType: 'geometry-transform',\r\n config: {\r\n // 基础几何属性\r\n base,\r\n height,\r\n unit,\r\n // 原始 config 内容(可能包含 strategy, shapes, transform 等)\r\n ...(contentBlock.config || {}),\r\n // 确保必要的字段存在,规范化shapes对象\r\n shapes: this.normalizeShapes(contentBlock.shapes || contentBlock.config?.shapes),\r\n transform: contentBlock.transform || contentBlock.config?.transform || {},\r\n animation: contentBlock.animation || contentBlock.config?.animation || {},\r\n boardConfig: contentBlock.boardConfig || contentBlock.config?.boardConfig || {}\r\n }\r\n }\r\n };\r\n\r\n // 调试日志:检查转换后的配置\r\n console.error('🔍 GeometryTransformTransformer.transform: 转换后配置 =', {\r\n metadataConfig: transformed.metadata?.config,\r\n shapesAnimatedLength: transformed.metadata?.config?.shapes?.animated?.length,\r\n shapesStaticLength: transformed.metadata?.config?.shapes?.static?.length,\r\n base: transformed.metadata?.config?.base,\r\n height: transformed.metadata?.config?.height,\r\n unit: transformed.metadata?.config?.unit,\r\n hasGeometryRef: !!contentBlock.geometryRef,\r\n geometryRef: contentBlock.geometryRef,\r\n hasTransformRef: !!contentBlock.transformRef,\r\n transformRef: contentBlock.transformRef,\r\n originalContentBlock: contentBlock\r\n });\r\n\r\n // 删除原始字段,避免混淆 - 使用 delete 操作符\r\n delete transformed.config;\r\n delete transformed.base;\r\n delete transformed.height;\r\n delete transformed.unit;\r\n delete transformed.shapes;\r\n delete transformed.transform;\r\n delete transformed.animation;\r\n delete transformed.boardConfig;\r\n\r\n // 如果禁用引用解析,直接返回(保持原有逻辑,避免重复处理)\r\n if (!enableReferenceResolution) {\r\n return transformed;\r\n }\r\n\r\n try {\r\n // 处理 geometryRef\r\n if (transformed.geometryRef) {\r\n try {\r\n const geometry = GeometryRefResolver.resolve(transformed.geometryRef, context);\r\n\r\n // 合并几何属性到 metadata.config\r\n if (!transformed.metadata.config) {\r\n transformed.metadata.config = {};\r\n }\r\n Object.assign(transformed.metadata.config, geometry);\r\n\r\n // 如果几何中有样式引用,解析它\r\n if (geometry.styleRef) {\r\n const style = StyleRefResolver.resolve(geometry.styleRef, context);\r\n transformed.metadata.config.style = style;\r\n }\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`几何变换几何解析失败: ${transformed.geometryRef}`, error);\r\n }\r\n delete transformed.geometryRef;\r\n }\r\n\r\n // 处理 transformRef\r\n if (transformed.transformRef) {\r\n try {\r\n const transform = TransformRefResolver.resolve(transformed.transformRef, context);\r\n\r\n // 确保 metadata.config 存在\r\n if (!transformed.metadata.config) {\r\n transformed.metadata.config = {};\r\n }\r\n\r\n // 将变换属性合并到 config.transform 对象,而不是根配置\r\n // 这样可以避免覆盖几何属性(id, type, vertices等)\r\n if (!transformed.metadata.config.transform) {\r\n transformed.metadata.config.transform = {};\r\n }\r\n\r\n // 将变换属性合并到 transform 对象\r\n Object.assign(transformed.metadata.config.transform, transform);\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`几何变换变换解析失败: ${transformed.transformRef}`, error);\r\n }\r\n delete transformed.transformRef;\r\n }\r\n\r\n // 处理 config 对象中的引用\r\n\r\n // 应该访问 transformed.metadata.config\r\n console.error('🔍 GeometryTransformTransformer.transform: 检查 metadata.config', {\r\n hasMetadata: !!transformed.metadata,\r\n hasConfig: !!transformed.metadata?.config,\r\n configType: transformed.metadata?.config ? typeof transformed.metadata.config : 'undefined',\r\n configIsObject: transformed.metadata?.config ? typeof transformed.metadata.config === 'object' : false,\r\n configKeys: transformed.metadata?.config ? Object.keys(transformed.metadata.config) : []\r\n });\r\n\r\n if (transformed.metadata?.config && typeof transformed.metadata.config === 'object') {\r\n console.error('🔍 GeometryTransformTransformer.transform: 调用 transformConfig');\r\n transformed.metadata.config = this.transformConfig(transformed.metadata.config, context, { strictMode });\r\n console.error('🔍 GeometryTransformTransformer.transform: transformConfig 调用完成');\r\n } else {\r\n console.error('🔍 GeometryTransformTransformer.transform: 不满足调用条件,跳过 transformConfig');\r\n }\r\n\r\n // 处理 styleRef\r\n if (transformed.styleRef) {\r\n try {\r\n const style = StyleRefResolver.resolve(transformed.styleRef, context);\r\n if (!transformed.metadata.config) {\r\n transformed.metadata.config = {};\r\n }\r\n transformed.metadata.config.style = style;\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`几何变换样式解析失败: ${transformed.styleRef}`, error);\r\n }\r\n delete transformed.styleRef;\r\n }\r\n\r\n // 处理顶层的 animationRef\r\n if (transformed.animationRef) {\r\n try {\r\n const animationConfig = this.resolveAnimationConfig(\r\n transformed.animationRef,\r\n context,\r\n { strictMode }\r\n );\r\n if (!transformed.metadata.config) {\r\n transformed.metadata.config = {};\r\n }\r\n transformed.metadata.config.animation = {\r\n ...animationConfig,\r\n ...(transformed.metadata.config.animation || {})\r\n };\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`顶层动画引用解析失败: ${transformed.animationRef}`, error);\r\n }\r\n delete transformed.animationRef;\r\n }\r\n\r\n // 处理顶层的 sliderRef\r\n if (transformed.sliderRef) {\r\n try {\r\n const sliderConfig = SliderRefResolver.resolve(\r\n transformed.sliderRef,\r\n context\r\n );\r\n if (!transformed.metadata.config) {\r\n transformed.metadata.config = {};\r\n }\r\n transformed.metadata.config.animation = {\r\n ...sliderConfig,\r\n ...(transformed.metadata.config.animation || {})\r\n };\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`顶层滑块引用解析失败: ${transformed.sliderRef}`, error);\r\n }\r\n delete transformed.sliderRef;\r\n }\r\n\r\n // 处理顶层的 boardRef\r\n if (transformed.boardRef) {\r\n console.error('🔍 GeometryTransformTransformer.transform: 处理顶层 boardRef', {\r\n boardRef: transformed.boardRef,\r\n hasMetadataConfig: !!transformed.metadata?.config,\r\n currentBoardConfig: transformed.metadata?.config?.boardConfig\r\n });\r\n try {\r\n const boardConfig = this.resolveBoardConfig(\r\n transformed.boardRef,\r\n context,\r\n { strictMode }\r\n );\r\n console.error('🔍 解析后的 boardConfig:', boardConfig);\r\n if (!transformed.metadata.config) {\r\n transformed.metadata.config = {};\r\n }\r\n transformed.metadata.config.boardConfig = {\r\n ...boardConfig,\r\n ...(transformed.metadata.config.boardConfig || {})\r\n };\r\n console.error('🔍 设置后的 metadata.config.boardConfig:', transformed.metadata.config.boardConfig);\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`顶层画板引用解析失败: ${transformed.boardRef}`, error);\r\n }\r\n delete transformed.boardRef;\r\n }\r\n\r\n // 确保 boardConfig 有 boundingBox\r\n if (transformed.metadata?.config?.boardConfig && typeof transformed.metadata.config.boardConfig === 'object') {\r\n const boardConfig = transformed.metadata.config.boardConfig;\r\n if (!boardConfig.boundingBox || !Array.isArray(boardConfig.boundingBox) || boardConfig.boundingBox.length !== 4) {\r\n console.error('🔍 GeometryTransformTransformer: boardConfig 缺少 boundingBox,使用默认值');\r\n boardConfig.boundingBox = [0, 7, 10, 0];\r\n boardConfig.originX = boardConfig.originX ?? 2;\r\n boardConfig.originY = boardConfig.originY ?? 2;\r\n boardConfig.keepAspectRatio = boardConfig.keepAspectRatio ?? true;\r\n boardConfig.showGrid = boardConfig.showGrid ?? false;\r\n boardConfig.showAxis = boardConfig.showAxis ?? false;\r\n boardConfig.description = boardConfig.description || '默认画板配置';\r\n }\r\n }\r\n\r\n // 调试日志:检查最终转换结果\r\n console.error('🔍 GeometryTransformTransformer.transform: 最终转换结果 =', {\r\n type: transformed.type,\r\n metadataConfig: transformed.metadata?.config,\r\n shapesAnimatedLength: transformed.metadata?.config?.shapes?.animated?.length,\r\n shapesStaticLength: transformed.metadata?.config?.shapes?.static?.length,\r\n base: transformed.metadata?.config?.base,\r\n height: transformed.metadata?.config?.height,\r\n unit: transformed.metadata?.config?.unit,\r\n hasTransform: !!transformed.metadata?.config?.transform,\r\n transform: transformed.metadata?.config?.transform,\r\n hasAnimation: !!transformed.metadata?.config?.animation,\r\n animation: transformed.metadata?.config?.animation,\r\n hasBoardConfig: !!transformed.metadata?.config?.boardConfig,\r\n boardConfig: transformed.metadata?.config?.boardConfig\r\n });\r\n\r\n return transformed;\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`几何变换转换失败:`, error);\r\n return transformed;\r\n }\r\n }\r\n\r\n /**\r\n * 转换配置对象\r\n */\r\n private static transformConfig(\r\n config: any,\r\n context: ReferenceContext,\r\n configOptions: { strictMode?: boolean } = {}\r\n ): any {\r\n const { strictMode = false } = configOptions;\r\n const transformedConfig = { ...config };\r\n\r\n // 创建 geometryRef 到 shapeId 的映射表\r\n const geometryRefToShapeId: Record<string, string> = {};\r\n\r\n // 处理 shapes 中的 geometryRef\r\n if (transformedConfig.shapes) {\r\n console.error('🔍 GeometryTransformTransformer.transformConfig: 处理 shapes');\r\n console.error(' transformedConfig.shapes:', transformedConfig.shapes);\r\n if (transformedConfig.shapes.static) {\r\n console.error(` 处理 static shapes (${transformedConfig.shapes.static.length}):`);\r\n transformedConfig.shapes.static = transformedConfig.shapes.static.map((shape: any, index: number) => {\r\n console.error(` 处理 static shape[${index}]:`, {\r\n id: shape.id,\r\n type: shape.type,\r\n hasGeometryRef: !!shape.geometryRef,\r\n geometryRef: shape.geometryRef,\r\n shapeKeys: Object.keys(shape)\r\n });\r\n const transformed = this.transformShape(shape, context, { strictMode });\r\n\r\n // 记录 geometryRef 到 shapeId 的映射(使用转换后的ID)\r\n if (shape.geometryRef && transformed.id) {\r\n geometryRefToShapeId[shape.geometryRef] = transformed.id;\r\n console.error(` 记录映射: geometryRef \"${shape.geometryRef}\" -> shapeId \"${transformed.id}\" (转换后)`);\r\n }\r\n\r\n console.error(` 转换后的 static shape[${index}]:`, {\r\n id: transformed.id,\r\n type: transformed.type,\r\n hasGeometryRef: !!transformed.geometryRef,\r\n geometryRef: transformed.geometryRef,\r\n hasVertices: !!transformed.vertices,\r\n vertices: transformed.vertices\r\n });\r\n return transformed;\r\n });\r\n }\r\n if (transformedConfig.shapes.animated) {\r\n console.error(` 处理 animated shapes (${transformedConfig.shapes.animated.length}):`);\r\n transformedConfig.shapes.animated = transformedConfig.shapes.animated.map((shape: any, index: number) => {\r\n console.error(` 处理 animated shape[${index}]:`, {\r\n id: shape.id,\r\n type: shape.type,\r\n hasGeometryRef: !!shape.geometryRef,\r\n geometryRef: shape.geometryRef,\r\n shapeKeys: Object.keys(shape)\r\n });\r\n const transformed = this.transformShape(shape, context, { strictMode });\r\n\r\n // 记录 geometryRef 到 shapeId 的映射(使用转换后的ID)\r\n if (shape.geometryRef && transformed.id) {\r\n geometryRefToShapeId[shape.geometryRef] = transformed.id;\r\n console.error(` 记录映射: geometryRef \"${shape.geometryRef}\" -> shapeId \"${transformed.id}\" (转换后)`);\r\n }\r\n\r\n console.error(` 转换后的 animated shape[${index}]:`, {\r\n id: transformed.id,\r\n type: transformed.type,\r\n hasGeometryRef: !!transformed.geometryRef,\r\n geometryRef: transformed.geometryRef,\r\n hasVertices: !!transformed.vertices,\r\n vertices: transformed.vertices\r\n });\r\n return transformed;\r\n });\r\n }\r\n }\r\n\r\n // 处理 transform 中的 transformRef\r\n if (transformedConfig.transform) {\r\n // 首先处理 transform 对象本身的 transformRef\r\n if (transformedConfig.transform.transformRef) {\r\n try {\r\n const resolvedTransform = TransformRefResolver.resolve(\r\n transformedConfig.transform.transformRef,\r\n context\r\n );\r\n // 合并解析后的变换,删除 transformRef\r\n transformedConfig.transform = {\r\n ...resolvedTransform,\r\n ...transformedConfig.transform,\r\n transformRef: undefined\r\n };\r\n console.error('🔍 GeometryTransformTransformer.transformConfig: 处理 transform 对象中的 transformRef', {\r\n originalTransformRef: transformedConfig.transform.transformRef,\r\n resolvedTransform,\r\n mergedTransform: transformedConfig.transform\r\n });\r\n } catch (error) {\r\n if (strictMode) throw error;\r\n console.warn(`Transform ref解析失败: ${transformedConfig.transform.transformRef}`, error);\r\n }\r\n }\r\n\r\n // 规范化 transform 配置,确保符合 GeometryTransform 组件要求\r\n transformedConfig.transform = this.normalizeTransformConfig(\r\n transformedConfig.transform,\r\n geometryRefToShapeId\r\n );\r\n\r\n if (Array.isArray(transformedConfig.transform.transforms)) {\r\n console.error('🔍 GeometryTransformTransformer.transformConfig: 处理 transforms 数组', {\r\n transformsLength: transformedConfig.transform.transforms.length,\r\n transforms: transformedConfig.transform.transforms\r\n });\r\n transformedConfig.transform.transforms = transformedConfig.transform.transforms.map(\r\n (transformItem: any, index: number) => {\r\n console.error(`🔍 处理 transform[${index}]:`, {\r\n type: typeof transformItem,\r\n isString: typeof transformItem === 'string',\r\n isObject: typeof transformItem === 'object' && transformItem !== null,\r\n transformItem,\r\n hasTransformRef: transformItem && typeof transformItem === 'object' && 'transformRef' in transformItem,\r\n transformRef: transformItem && typeof transformItem === 'object' ? transformItem.transformRef : undefined\r\n });\r\n\r\n // 处理字符串形式的transformRef\r\n if (typeof transformItem === 'string') {\r\n console.error(`🔍 transform[${index}] 是字符串格式`);\r\n if (transformItem.startsWith('transformRef:')) {\r\n const refName = transformItem.replace('transformRef:', '');\r\n console.error(`🔍 解析 transformRef 字符串: ${refName}`);\r\n try {\r\n const resolved = TransformRefResolver.resolve(refName, context);\r\n console.error(`🔍 transform[${index}] 解析成功:`, resolved);\r\n const normalized = this.normalizeTransformConfig(resolved, geometryRefToShapeId);\r\n console.error(`🔍 transform[${index}] 标准化后:`, normalized);\r\n return normalized;\r\n } catch (error) {\r\n if (strictMode) throw error;\r\n console.warn(`Transform ref解析失败: ${refName}`, error);\r\n return transformItem;\r\n }\r\n }\r\n // 直接名称引用\r\n try {\r\n const resolved = TransformRefResolver.resolve(transformItem, context);\r\n const normalized = this.normalizeTransformConfig(resolved, geometryRefToShapeId);\r\n return normalized;\r\n } catch (error) {\r\n if (strictMode) throw error;\r\n console.warn(`Transform ref解析失败: ${transformItem}`, error);\r\n return transformItem;\r\n }\r\n }\r\n // 处理对象形式的transformRef\r\n else if (transformItem && typeof transformItem === 'object' && transformItem.transformRef) {\r\n const refName = transformItem.transformRef;\r\n console.error(`🔍 transform[${index}] 是对象格式,refName=${refName}`);\r\n try {\r\n const resolvedTransform = TransformRefResolver.resolve(refName, context);\r\n console.error(`🔍 transform[${index}] 解析成功:`, resolvedTransform);\r\n // 合并其他字段(如targetGroup覆盖等)\r\n const merged = {\r\n ...resolvedTransform,\r\n ...transformItem,\r\n transformRef: undefined // 删除原始引用字段\r\n };\r\n console.error(`🔍 transform[${index}] 合并后:`, merged);\r\n const normalized = this.normalizeTransformConfig(merged, geometryRefToShapeId);\r\n console.error(`🔍 transform[${index}] 标准化后:`, normalized);\r\n return normalized;\r\n } catch (error) {\r\n if (strictMode) throw error;\r\n console.warn(`Transform ref解析失败: ${refName}`, error);\r\n return transformItem;\r\n }\r\n }\r\n // 已经是解析后的变换配置,确保格式正确\r\n else if (transformItem && typeof transformItem === 'object') {\r\n console.error(`🔍 transform[${index}] 已是对象格式,标准化`);\r\n return this.normalizeTransformConfig(transformItem, geometryRefToShapeId);\r\n }\r\n console.error(`🔍 transform[${index}] 未处理,返回原始值:`, transformItem);\r\n return transformItem;\r\n }\r\n );\r\n }\r\n }\r\n\r\n\r\n // 处理 geometry\r\n if (transformedConfig.geometry && typeof transformedConfig.geometry === 'object') {\r\n transformedConfig.geometry = this.transformGeometry(\r\n transformedConfig.geometry,\r\n context,\r\n { strictMode }\r\n );\r\n }\r\n\r\n // 处理 transformations 数组\r\n if (Array.isArray(transformedConfig.transformations)) {\r\n transformedConfig.transformations = transformedConfig.transformations.map(\r\n (transformItem: any) => {\r\n if (transformItem.transformRef) {\r\n try {\r\n const transform = TransformRefResolver.resolve(transformItem.transformRef, context);\r\n return {\r\n ...transformItem,\r\n ...transform,\r\n transformRef: undefined // 删除原始引用\r\n };\r\n } catch (error) {\r\n if (strictMode) throw error;\r\n console.warn(`Transformations解析失败: ${transformItem.transformRef}`, error);\r\n return transformItem;\r\n }\r\n }\r\n return transformItem;\r\n }\r\n );\r\n }\r\n\r\n // 处理 style\r\n if (transformedConfig.style && typeof transformedConfig.style === 'object') {\r\n transformedConfig.style = this.transformStyle(\r\n transformedConfig.style,\r\n context,\r\n { strictMode }\r\n );\r\n }\r\n\r\n // 处理 animationRef\r\n if (transformedConfig.animationRef) {\r\n try {\r\n const animationConfig = this.resolveAnimationConfig(\r\n transformedConfig.animationRef,\r\n context,\r\n { strictMode }\r\n );\r\n transformedConfig.animation = {\r\n ...animationConfig,\r\n // 保留原始配置中可能存在的覆盖值\r\n ...(transformedConfig.animation || {})\r\n };\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`动画引用解析失败: ${transformedConfig.animationRef}`, error);\r\n }\r\n delete transformedConfig.animationRef;\r\n }\r\n\r\n // 处理 sliderRef\r\n if (transformedConfig.sliderRef) {\r\n console.error('🔍 GeometryTransformTransformer.transformConfig: 处理 sliderRef', {\r\n sliderRef: transformedConfig.sliderRef,\r\n hasAnimationDefinitions: !!context.animationDefinitions,\r\n animationDefinitionKeys: context.animationDefinitions ? Object.keys(context.animationDefinitions) : []\r\n });\r\n try {\r\n // 增强上下文,确保包含 animationDefinitions\r\n const enhancedContext = {\r\n ...GLOBAL_REFERENCE_CONTEXT,\r\n ...context, // 传入的上下文优先级更高\r\n // 确保 animationDefinitions 存在\r\n animationDefinitions: context.animationDefinitions || GLOBAL_REFERENCE_CONTEXT.animationDefinitions\r\n };\r\n const sliderConfig = SliderRefResolver.resolve(\r\n transformedConfig.sliderRef,\r\n enhancedContext\r\n );\r\n transformedConfig.animation = {\r\n ...sliderConfig,\r\n // 保留原始配置中可能存在的覆盖值\r\n ...(transformedConfig.animation || {})\r\n };\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`滑块引用解析失败: ${transformedConfig.sliderRef}`, error);\r\n }\r\n delete transformedConfig.sliderRef;\r\n }\r\n\r\n // 处理 boardRef\r\n if (transformedConfig.boardRef) {\r\n console.error('🔍 GeometryTransformTransformer.transformConfig: 处理 config 中的 boardRef', {\r\n boardRef: transformedConfig.boardRef,\r\n currentBoardConfig: transformedConfig.boardConfig\r\n });\r\n try {\r\n const boardConfig = this.resolveBoardConfig(\r\n transformedConfig.boardRef,\r\n context,\r\n { strictMode }\r\n );\r\n console.error('🔍 解析后的 boardConfig (config):', boardConfig);\r\n transformedConfig.boardConfig = {\r\n ...boardConfig,\r\n // 保留原始配置中可能存在的覆盖值\r\n ...(transformedConfig.boardConfig || {})\r\n };\r\n console.error('🔍 设置后的 transformedConfig.boardConfig:', transformedConfig.boardConfig);\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`画板引用解析失败: ${transformedConfig.boardRef}`, error);\r\n }\r\n delete transformedConfig.boardRef;\r\n }\r\n\r\n return transformedConfig;\r\n }\r\n\r\n /**\r\n * 规范化变换配置,确保符合 GeometryTransform 的 TransformConfig 接口要求\r\n */\r\n private static normalizeTransformConfig(\r\n transform: any,\r\n geometryRefToShapeId?: Record<string, string>\r\n ): any {\r\n if (!transform || typeof transform !== 'object') {\r\n return transform;\r\n }\r\n\r\n console.error('🔍 GeometryTransformTransformer.normalizeTransformConfig: 输入', {\r\n transformId: transform.id,\r\n transformType: transform.type,\r\n hasTargetGroup: !!transform.targetGroup,\r\n targetGroup: transform.targetGroup,\r\n geometryRefToShapeIdKeys: geometryRefToShapeId ? Object.keys(geometryRefToShapeId) : [],\r\n geometryRefToShapeId\r\n });\r\n\r\n const normalized = { ...transform };\r\n\r\n // 如果 transform 有 id 字段,保留它(可能用于调试)\r\n // 但确保 type 字段存在\r\n if (!normalized.type && normalized.config && normalized.config.type) {\r\n normalized.type = normalized.config.type;\r\n }\r\n\r\n // 处理不同类型的变换配置\r\n switch (normalized.type) {\r\n case 'rotation':\r\n // 确保 rotation 配置符合 RotationConfig 接口\r\n if (normalized.config) {\r\n normalized.rotation = { ...normalized.config };\r\n\r\n // 处理 center 字段,确保是数组 [x, y] 或 'auto'\r\n if (normalized.rotation.center && typeof normalized.rotation.center === 'object') {\r\n const center = normalized.rotation.center;\r\n if ('x' in center && 'y' in center) {\r\n normalized.rotation.center = [center.x, center.y];\r\n }\r\n }\r\n\r\n // ✅ 删除 config 字段,统一格式\r\n delete normalized.config;\r\n }\r\n break;\r\n\r\n case 'translation':\r\n if (normalized.config) {\r\n normalized.translation = { ...normalized.config };\r\n // ✅ 删除 config 字段,统一格式\r\n delete normalized.config;\r\n }\r\n break;\r\n\r\n case 'scale':\r\n if (normalized.config) {\r\n normalized.scale = { ...normalized.config };\r\n\r\n // 处理 center 字段\r\n if (normalized.scale.center && typeof normalized.scale.center === 'object') {\r\n const center = normalized.scale.center;\r\n if ('x' in center && 'y' in center) {\r\n normalized.scale.center = [center.x, center.y];\r\n }\r\n }\r\n\r\n // ✅ 删除 config 字段,统一格式\r\n delete normalized.config;\r\n }\r\n break;\r\n\r\n case 'composite':\r\n // 复合变换可能已经包含 transforms 数组\r\n if (normalized.config && Array.isArray(normalized.config.transforms)) {\r\n normalized.composite = normalized.config.transforms.map((t: any) =>\r\n this.normalizeTransformConfig(t, geometryRefToShapeId)\r\n );\r\n // ✅ 删除 config 字段,统一格式\r\n delete normalized.config;\r\n }\r\n break;\r\n\r\n default:\r\n // 其他类型,保留原有结构\r\n if (normalized.config) {\r\n // 将 config 合并到顶层,但保留 type 字段\r\n const { type, ...configWithoutType } = normalized.config;\r\n Object.assign(normalized, configWithoutType);\r\n delete normalized.config;\r\n }\r\n }\r\n\r\n // 映射 targetGroup:将 geometryRef 或简写标识转换为对应的 shapeId\r\n if (normalized.targetGroup && geometryRefToShapeId) {\r\n const originalTargetGroup = normalized.targetGroup;\r\n let mappedShapeId: string | undefined;\r\n\r\n // 1. 精确匹配:targetGroup 直接等于 geometryRef\r\n if (geometryRefToShapeId[originalTargetGroup]) {\r\n mappedShapeId = geometryRefToShapeId[originalTargetGroup];\r\n console.error('🔍 GeometryTransformTransformer.normalizeTransformConfig: 精确匹配 targetGroup', {\r\n original: originalTargetGroup,\r\n mapped: mappedShapeId,\r\n type: 'exact'\r\n });\r\n }\r\n // 2. 启发式匹配:targetGroup 是 geometryRef 的前缀或子字符串\r\n else {\r\n // 查找包含 targetGroup 的 geometryRef\r\n const matchingRef = Object.keys(geometryRefToShapeId).find(ref => {\r\n // 情况1: targetGroup 是 geometryRef 的前缀 (如 \"left\" → \"left_triangle\")\r\n if (ref.startsWith(originalTargetGroup + '_') || ref === originalTargetGroup) {\r\n return true;\r\n }\r\n // 情况2: geometryRef 包含 targetGroup (如 \"trapezoid_copy\" 包含 \"trapezoid\")\r\n if (ref.includes(originalTargetGroup)) {\r\n return true;\r\n }\r\n // 情况3: targetGroup 包含 geometryRef 的关键部分\r\n const refParts = ref.split('_');\r\n const targetParts = originalTargetGroup.split('_');\r\n return refParts.some(part => targetParts.includes(part));\r\n });\r\n\r\n if (matchingRef) {\r\n mappedShapeId = geometryRefToShapeId[matchingRef];\r\n console.error('🔍 GeometryTransformTransformer.normalizeTransformConfig: 启发式匹配 targetGroup', {\r\n original: originalTargetGroup,\r\n geometryRef: matchingRef,\r\n mapped: mappedShapeId,\r\n type: 'heuristic'\r\n });\r\n }\r\n }\r\n\r\n if (mappedShapeId) {\r\n normalized.targetGroup = mappedShapeId;\r\n } else {\r\n console.error('🔍 GeometryTransformTransformer.normalizeTransformConfig: 无法映射 targetGroup', {\r\n original: originalTargetGroup,\r\n geometryRefToShapeId,\r\n warning: 'targetGroup 无法映射到任何 shapeId,可能导致旋转失败'\r\n });\r\n }\r\n }\r\n\r\n // 确保 targetGroup 字段存在(如果原始 transform 有 targetGroup)\r\n if (transform.targetGroup && !normalized.targetGroup) {\r\n normalized.targetGroup = transform.targetGroup;\r\n }\r\n\r\n // 删除可能多余的 id 字段(可选,保留用于调试)\r\n // delete normalized.id;\r\n\r\n console.error('🔍 GeometryTransformTransformer.normalizeTransformConfig:', {\r\n input: transform,\r\n output: normalized,\r\n hasRotation: !!normalized.rotation,\r\n hasTranslation: !!normalized.translation,\r\n hasScale: !!normalized.scale,\r\n hasComposite: !!normalized.composite\r\n });\r\n\r\n return normalized;\r\n }\r\n\r\n // 添加新方法处理 shape 中的 geometryRef\r\n private static transformShape(\r\n shape: any,\r\n context: ReferenceContext,\r\n config: { strictMode?: boolean } = {}\r\n ): any {\r\n console.error('🔍 transformShape 被调用:', {\r\n shapeId: shape.id,\r\n shapeType: shape.type,\r\n hasGeometryRef: !!shape.geometryRef,\r\n geometryRef: shape.geometryRef,\r\n hasStyleRef: !!shape.styleRef,\r\n styleRef: shape.styleRef,\r\n shapeKeys: Object.keys(shape),\r\n contextHasGeometryPresets: !!context.geometryPresets,\r\n contextGeometryPresetKeys: context.geometryPresets ? Object.keys(context.geometryPresets) : []\r\n });\r\n\r\n const { strictMode = false } = config;\r\n const transformedShape = { ...shape };\r\n\r\n if (transformedShape.geometryRef) {\r\n console.error('🔍 transformShape: 处理 geometryRef:', transformedShape.geometryRef);\r\n console.error('🔍 transformShape: context.geometryPresets:', context.geometryPresets);\r\n console.error('🔍 transformShape: context.geometryPresets keys:', context.geometryPresets ? Object.keys(context.geometryPresets) : []);\r\n try {\r\n console.error('🔍 transformShape: 调用 GeometryRefResolver.resolve');\r\n const geometry = GeometryRefResolver.resolve(transformedShape.geometryRef, context);\r\n console.error('🔍 transformShape: geometry 解析结果:', geometry);\r\n Object.assign(transformedShape, geometry);\r\n console.error('🔍 transformShape: 合并后的 shape:', transformedShape);\r\n // 调试顶点数据\r\n if (transformedShape.vertices && Array.isArray(transformedShape.vertices)) {\r\n console.error('🔍 transformShape: 顶点数据:', {\r\n count: transformedShape.vertices.length,\r\n sample: transformedShape.vertices.slice(0, 3).map((v: any, i: number) => ({\r\n index: i,\r\n value: v,\r\n isArray: Array.isArray(v),\r\n length: Array.isArray(v) ? v.length : 'N/A'\r\n }))\r\n });\r\n }\r\n } catch (error) {\r\n console.error('🔍 transformShape: geometryRef 解析错误:', error);\r\n if (strictMode) throw error;\r\n console.warn(`Shape geometryRef解析失败: ${transformedShape.geometryRef}`, error);\r\n }\r\n delete transformedShape.geometryRef;\r\n console.error('🔍 transformShape: 删除 geometryRef 后的 shape:', transformedShape);\r\n }\r\n\r\n if (transformedShape.styleRef) {\r\n try {\r\n const style = StyleRefResolver.resolve(transformedShape.styleRef, context);\r\n transformedShape.style = style;\r\n } catch (error) {\r\n if (strictMode) throw error;\r\n console.warn(`Shape styleRef解析失败: ${transformedShape.styleRef}`, error);\r\n }\r\n delete transformedShape.styleRef;\r\n }\r\n\r\n // 确保形状有metadata对象\r\n if (!transformedShape.metadata) {\r\n transformedShape.metadata = {};\r\n }\r\n\r\n // 设置metadata.id(如果不存在)\r\n if (!transformedShape.metadata.id && transformedShape.id) {\r\n transformedShape.metadata.id = transformedShape.id;\r\n }\r\n\r\n // 处理几何对象的 withLabel 和 label 配置\r\n // 将几何级别的标签配置转换为 metadata 格式,供 GeometryTransform 组件使用\r\n if (transformedShape.withLabel !== undefined) {\r\n transformedShape.metadata.showLabel = transformedShape.withLabel;\r\n // 删除原始字段,避免重复\r\n delete transformedShape.withLabel;\r\n }\r\n\r\n if (transformedShape.label) {\r\n // 如果 label 是对象,提取文本内容\r\n if (typeof transformedShape.label === 'object') {\r\n transformedShape.metadata.label = transformedShape.label.text || transformedShape.metadata.id || '';\r\n } else if (typeof transformedShape.label === 'string') {\r\n transformedShape.metadata.label = transformedShape.label;\r\n }\r\n // 删除原始字段,避免重复\r\n delete transformedShape.label;\r\n }\r\n\r\n // 如果 metadata 有 showLabel 但没有 label,使用 id 作为默认标签\r\n if (transformedShape.metadata.showLabel && !transformedShape.metadata.label && transformedShape.metadata.id) {\r\n transformedShape.metadata.label = transformedShape.metadata.id;\r\n }\r\n\r\n // 根据形状id设置rotationGroup(用于目标组匹配)\r\n if (transformedShape.metadata.id) {\r\n const id = transformedShape.metadata.id.toLowerCase();\r\n if (id.includes('left')) {\r\n transformedShape.metadata.rotationGroup = 'left';\r\n } else if (id.includes('right')) {\r\n transformedShape.metadata.rotationGroup = 'right';\r\n } else {\r\n // ✅ 兜底:对其他形状,rotationGroup = id(确保 targetGroup 能匹配)\r\n transformedShape.metadata.rotationGroup = transformedShape.metadata.id;\r\n }\r\n }\r\n\r\n // 处理point类型,将其转换为circle(GeometryTransform不支持point类型)\r\n if (transformedShape.type === 'point' && transformedShape.position) {\r\n console.error('🔍 transformShape: 转换point为circle:', {\r\n shapeId: transformedShape.metadata?.id,\r\n position: transformedShape.position,\r\n originalType: transformedShape.type\r\n });\r\n\r\n // 将point转换为circle:圆心和半径点\r\n const centerX = transformedShape.position.x;\r\n const centerY = transformedShape.position.y;\r\n const radius = 0.1; // 小半径,显示为点\r\n\r\n transformedShape.type = 'circle';\r\n transformedShape.vertices = [\r\n [centerX, centerY], // 圆心\r\n [centerX + radius, centerY] // 半径上的点\r\n ];\r\n\r\n // 删除position字段,避免混淆\r\n delete transformedShape.position;\r\n\r\n console.error('🔍 transformShape: point转换为circle完成:', {\r\n newType: transformedShape.type,\r\n vertices: transformedShape.vertices\r\n });\r\n }\r\n\r\n return transformedShape;\r\n }\r\n\r\n /**\r\n * 转换几何对象\r\n */\r\n private static transformGeometry(\r\n geometry: any,\r\n context: ReferenceContext,\r\n config: { strictMode?: boolean } = {}\r\n ): any {\r\n const { strictMode = false } = config;\r\n const transformedGeometry = { ...geometry };\r\n\r\n // 处理 geometryRef\r\n if (transformedGeometry.geometryRef) {\r\n try {\r\n const resolvedGeometry = GeometryRefResolver.resolve(transformedGeometry.geometryRef, context);\r\n Object.assign(transformedGeometry, resolvedGeometry);\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`几何对象解析失败: ${transformedGeometry.geometryRef}`, error);\r\n }\r\n delete transformedGeometry.geometryRef;\r\n }\r\n\r\n return transformedGeometry;\r\n }\r\n\r\n /**\r\n * 转换变换对象\r\n */\r\n private static transformTransform(\r\n transform: any,\r\n context: ReferenceContext,\r\n config: { strictMode?: boolean } = {}\r\n ): any {\r\n const { strictMode = false } = config;\r\n const transformedTransform = { ...transform };\r\n\r\n // 处理 transformRef\r\n if (transformedTransform.transformRef) {\r\n try {\r\n const resolvedTransform = TransformRefResolver.resolve(transformedTransform.transformRef, context);\r\n Object.assign(transformedTransform, resolvedTransform);\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`变换对象解析失败: ${transformedTransform.transformRef}`, error);\r\n }\r\n delete transformedTransform.transformRef;\r\n }\r\n\r\n return transformedTransform;\r\n }\r\n\r\n /**\r\n * 转换样式对象\r\n */\r\n private static transformStyle(\r\n style: any,\r\n context: ReferenceContext,\r\n config: { strictMode?: boolean } = {}\r\n ): any {\r\n const { strictMode = false } = config;\r\n const transformedStyle = { ...style };\r\n\r\n // 处理 styleRef\r\n if (transformedStyle.styleRef) {\r\n try {\r\n const resolvedStyle = StyleRefResolver.resolve(transformedStyle.styleRef, context);\r\n Object.assign(transformedStyle, resolvedStyle);\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`样式对象解析失败: ${transformedStyle.styleRef}`, error);\r\n }\r\n delete transformedStyle.styleRef;\r\n }\r\n\r\n return transformedStyle;\r\n }\r\n\r\n /**\r\n * 解析动画配置\r\n */\r\n private static resolveAnimationConfig(\r\n animationRef: string,\r\n context: ReferenceContext,\r\n config: { strictMode?: boolean } = {}\r\n ): any {\r\n const { strictMode = false } = config;\r\n\r\n if (!animationRef || typeof animationRef !== 'string') {\r\n if (strictMode) {\r\n throw new Error(`无效的动画引用: ${animationRef}`);\r\n }\r\n console.warn(`无效的动画引用: ${animationRef}`);\r\n return {};\r\n }\r\n\r\n try {\r\n // 移除可能的 \"animationRef:\" 前缀\r\n const refName = animationRef.replace('animationRef:', '');\r\n\r\n // 从上下文中获取动画配置\r\n if (context.animationDefinitions && context.animationDefinitions[refName]) {\r\n return { ...context.animationDefinitions[refName] };\r\n }\r\n\r\n // 严格模式下抛出错误\r\n if (strictMode) {\r\n throw new Error(`动画引用未找到: ${refName}`);\r\n }\r\n\r\n // 非严格模式下回退到默认配置\r\n const fallbackConfig = this.getFallbackAnimationConfig(refName);\r\n console.warn(`动画引用未在上下文中找到,使用回退配置: ${refName}`);\r\n return fallbackConfig;\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`动画配置解析失败: ${animationRef}`, error);\r\n return {};\r\n }\r\n }\r\n\r\n /**\r\n * 解析画板配置\r\n */\r\n private static resolveBoardConfig(\r\n boardRef: string,\r\n context: ReferenceContext,\r\n config: { strictMode?: boolean } = {}\r\n ): any {\r\n const { strictMode = false } = config;\r\n\r\n if (!boardRef || typeof boardRef !== 'string') {\r\n if (strictMode) {\r\n throw new Error(`无效的画板引用: ${boardRef}`);\r\n }\r\n console.warn(`无效的画板引用: ${boardRef}`);\r\n return {};\r\n }\r\n\r\n try {\r\n // 移除可能的 \"boardRef:\" 前缀\r\n const refName = boardRef.replace('boardRef:', '');\r\n\r\n console.error('🔍 GeometryTransformTransformer.resolveBoardConfig:', {\r\n boardRef,\r\n refName,\r\n hasContextBoardDefinitions: !!context.boardDefinitions,\r\n contextBoardDefinitionKeys: context.boardDefinitions ? Object.keys(context.boardDefinitions) : [],\r\n hasRefInContext: context.boardDefinitions && !!context.boardDefinitions[refName]\r\n });\r\n\r\n // 从上下文中获取画板配置\r\n if (context.boardDefinitions && context.boardDefinitions[refName]) {\r\n const config = { ...context.boardDefinitions[refName] };\r\n console.error('🔍 从上下文获取画板配置:', config);\r\n return config;\r\n }\r\n\r\n // 严格模式下抛出错误\r\n if (strictMode) {\r\n throw new Error(`画板引用未找到: ${refName}`);\r\n }\r\n\r\n // 非严格模式下回退到默认配置\r\n const fallbackConfig = this.getFallbackBoardConfig(refName);\r\n console.warn(`画板引用未在上下文中找到,使用回退配置: ${refName}`);\r\n console.error('🔍 使用回退画板配置:', fallbackConfig);\r\n return fallbackConfig;\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`画板配置解析失败: ${boardRef}`, error);\r\n return {};\r\n }\r\n }\r\n\r\n /**\r\n * 获取回退动画配置\r\n */\r\n private static getFallbackAnimationConfig(refName: string): any {\r\n const fallbackPresets: Record<string, any> = {\r\n slider_horizontal: {\r\n id: \"slider_horizontal\",\r\n slider: {\r\n position: [0, -6],\r\n length: 10,\r\n orientation: 'horizontal',\r\n min: 0,\r\n max: 1,\r\n step: 0.01\r\n },\r\n progressIndicator: {\r\n enabled: true,\r\n stages: 4,\r\n labels: ['开始', '25%', '50%', '75%', '完成'],\r\n showPercentage: true\r\n },\r\n duration: 2000,\r\n easing: 'ease-in-out',\r\n description: \"水平滑块动画\"\r\n },\r\n slider_vertical: {\r\n id: \"slider_vertical\",\r\n slider: {\r\n position: [-6, 0],\r\n length: 10,\r\n orientation: 'vertical',\r\n min: 0,\r\n max: 1,\r\n step: 0.01\r\n },\r\n progressIndicator: {\r\n enabled: true,\r\n stages: 4,\r\n labels: ['开始', '25%', '50%', '75%', '完成'],\r\n showPercentage: true\r\n },\r\n duration: 2000,\r\n easing: 'ease-in-out',\r\n description: \"垂直滑块动画\"\r\n }\r\n };\r\n\r\n return fallbackPresets[refName] || fallbackPresets.slider_horizontal;\r\n }\r\n\r\n /**\r\n * 获取回退画板配置\r\n */\r\n private static getFallbackBoardConfig(refName: string): any {\r\n const fallbackPresets: Record<string, any> = {\r\n default: {\r\n id: \"default\",\r\n originX: 2,\r\n originY: 2,\r\n boundingBox: [0, 7, 10, 0],\r\n keepAspectRatio: true,\r\n showGrid: false,\r\n showAxis: false,\r\n description: \"默认画板配置\"\r\n },\r\n extended: {\r\n id: \"extended\",\r\n originX: 0,\r\n originY: 0,\r\n boundingBox: [-5, 12, 15, -5],\r\n keepAspectRatio: true,\r\n showGrid: true,\r\n showAxis: true,\r\n gridSize: 1,\r\n description: \"扩展画板配置(带网格和坐标轴)\"\r\n }\r\n };\r\n\r\n return fallbackPresets[refName] || fallbackPresets.default;\r\n }\r\n\r\n /**\r\n * 验证几何变换内容块\r\n */\r\n static validate(contentBlock: any): string[] {\r\n const errors: string[] = [];\r\n\r\n if (!contentBlock) {\r\n errors.push('几何变换内容块不能为空');\r\n return errors;\r\n }\r\n\r\n if (contentBlock.type !== CONTENT_BLOCK_TYPES.GEOMETRY_TRANSFORM) {\r\n errors.push(`几何变换内容块类型应为 'geometryTransform',实际为 '${contentBlock.type}'`);\r\n }\r\n\r\n if (!contentBlock.config || typeof contentBlock.config !== 'object') {\r\n // 如果没有 config 对象,检查是否有 geometryRef\r\n if (!contentBlock.geometryRef) {\r\n errors.push('几何变换内容块缺少 config 对象或 geometryRef');\r\n }\r\n } else {\r\n if (!contentBlock.config.geometry && !contentBlock.geometryRef) {\r\n errors.push('几何变换内容块缺少 geometry 或 geometryRef');\r\n }\r\n }\r\n\r\n return errors;\r\n }\r\n\r\n /**\r\n * 批量转换几何变换内容块\r\n */\r\n static batchTransform(\r\n contentBlocks: any[],\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): any[] {\r\n return contentBlocks\r\n .filter(block => block.type === CONTENT_BLOCK_TYPES.GEOMETRY_TRANSFORM)\r\n .map(block => this.transform(block, context, config));\r\n }\r\n}\r\n\r\n/**\r\n * 创建几何变换转换器实例\r\n */\r\nexport function createGeometryTransformTransformer() {\r\n return {\r\n type: CONTENT_BLOCK_TYPES.GEOMETRY_TRANSFORM,\r\n transform: GeometryTransformTransformer.transform.bind(GeometryTransformTransformer),\r\n validate: GeometryTransformTransformer.validate.bind(GeometryTransformTransformer)\r\n };\r\n}","/**\r\n * 文本和公式转换器\r\n *\r\n * 处理 text 和 formula 类型内容块的转换和引用解析\r\n */\r\n\r\nimport type { ReferenceContext } from '../types';\r\nimport { CONTENT_BLOCK_TYPES } from '../constants';\r\nimport { DesignTokenResolver, StyleRefResolver } from '../resolvers';\r\n\r\n/**\r\n * 文本和公式转换器\r\n */\r\nexport class TextTransformer {\r\n /**\r\n * 转换文本内容块\r\n */\r\n static transformText(\r\n contentBlock: any,\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): any {\r\n const {\r\n enableReferenceResolution = true,\r\n strictMode = false\r\n } = config;\r\n\r\n console.error(`📄 TextTransformer.transformText: type=${contentBlock.type}, content=${contentBlock.content?.substring(0, 50)}..., styleRef=${contentBlock.styleRef}, enableReferenceResolution=${enableReferenceResolution}`);\r\n\r\n // 基础转换\r\n const transformed = {\r\n ...contentBlock,\r\n type: CONTENT_BLOCK_TYPES.TEXT\r\n };\r\n\r\n // 如果禁用引用解析,直接返回\r\n if (!enableReferenceResolution) {\r\n return transformed;\r\n }\r\n\r\n try {\r\n // 处理 content 中的设计令牌引用\r\n if (typeof transformed.content === 'string') {\r\n transformed.content = this.resolveTextContent(transformed.content, context, { strictMode });\r\n }\r\n\r\n // 处理 style\r\n if (transformed.style && typeof transformed.style === 'object') {\r\n transformed.style = this.resolveStyle(transformed.style, context, { strictMode });\r\n }\r\n\r\n // 处理 styleRef\r\n if (transformed.styleRef) {\r\n console.error(`🎨 TextTransformer处理styleRef: ${transformed.styleRef}`);\r\n try {\r\n // 使用 StyleRefResolver 解析样式引用,它会自动处理嵌套的设计令牌引用\r\n const style = StyleRefResolver.resolve(transformed.styleRef, context);\r\n console.error(` StyleRefResolver解析结果:`, style);\r\n transformed.style = { ...transformed.style, ...style };\r\n console.error(` 合并后style:`, transformed.style);\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`文本样式解析失败: ${transformed.styleRef}`, error);\r\n }\r\n delete transformed.styleRef;\r\n }\r\n\r\n return transformed;\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`文本转换失败:`, error);\r\n return transformed;\r\n }\r\n }\r\n\r\n /**\r\n * 转换公式内容块\r\n */\r\n static transformFormula(\r\n contentBlock: any,\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): any {\r\n const {\r\n enableReferenceResolution = true,\r\n strictMode = false\r\n } = config;\r\n\r\n // 基础转换\r\n const transformed = {\r\n ...contentBlock,\r\n type: CONTENT_BLOCK_TYPES.FORMULA\r\n };\r\n\r\n // 公式内容通常不需要引用解析,但可以处理样式\r\n if (!enableReferenceResolution) {\r\n return transformed;\r\n }\r\n\r\n try {\r\n // 处理 style\r\n if (transformed.style && typeof transformed.style === 'object') {\r\n transformed.style = this.resolveStyle(transformed.style, context, { strictMode });\r\n }\r\n\r\n // 处理 styleRef\r\n if (transformed.styleRef) {\r\n try {\r\n // 使用 StyleRefResolver 解析样式引用,它会自动处理嵌套的设计令牌引用\r\n const style = StyleRefResolver.resolve(transformed.styleRef, context);\r\n transformed.style = { ...transformed.style, ...style };\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`公式样式解析失败: ${transformed.styleRef}`, error);\r\n }\r\n delete transformed.styleRef;\r\n }\r\n\r\n return transformed;\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`公式转换失败:`, error);\r\n return transformed;\r\n }\r\n }\r\n\r\n /**\r\n * 解析文本内容中的设计令牌引用\r\n */\r\n private static resolveTextContent(\r\n text: string,\r\n context: ReferenceContext,\r\n config: { strictMode?: boolean } = {}\r\n ): string {\r\n const { strictMode = false } = config;\r\n console.error(`📝 TextTransformer.resolveTextContent START: text=\"${text}\", hasDesignTokens=${text.includes('$')}`);\r\n\r\n if (!text.includes('$')) {\r\n console.error(` resolveTextContent END (no design tokens): \"${text}\"`);\r\n return text;\r\n }\r\n\r\n // 改进的设计令牌匹配模式\r\n // 匹配 $colors.primary, $fonts.body, $spacing.md 等模式\r\n // 支持路径如 colors.primary, fonts.formula.size 等\r\n const tokenRegex = /\\$([a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*)/g;\r\n\r\n let result = text;\r\n let match;\r\n const tokenRegex2 = /\\$([a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*)/g;\r\n\r\n while ((match = tokenRegex2.exec(text)) !== null) {\r\n const fullMatch = match[0]; // 如 $colors.primary\r\n const path = match[1]; // 如 colors.primary\r\n\r\n console.error(` 发现设计令牌: ${fullMatch}, path=${path}`);\r\n try {\r\n // 使用 DesignTokenResolver 解析\r\n const resolved = DesignTokenResolver.resolve(fullMatch, context);\r\n console.error(` 解析结果: ${fullMatch} -> ${resolved}`);\r\n\r\n // 替换所有出现的令牌\r\n result = result.replace(fullMatch, String(resolved));\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`文本中的设计令牌解析失败: ${fullMatch}`, error);\r\n // 保留原始令牌\r\n }\r\n }\r\n\r\n console.error(` resolveTextContent END: original=\"${text}\", resolved=\"${result}\"`);\r\n return result;\r\n }\r\n\r\n /**\r\n * 解析样式对象\r\n */\r\n private static resolveStyle(\r\n style: any,\r\n context: ReferenceContext,\r\n config: { strictMode?: boolean } = {}\r\n ): any {\r\n const { strictMode = false } = config;\r\n\r\n try {\r\n return DesignTokenResolver.replaceDesignTokenRefs(\r\n style,\r\n context,\r\n (ref) => {\r\n if (strictMode) {\r\n throw new Error(`设计令牌未找到: ${ref}`);\r\n }\r\n console.warn(`设计令牌未找到: ${ref}`);\r\n return ref;\r\n }\r\n );\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`样式解析失败:`, error);\r\n return style;\r\n }\r\n }\r\n\r\n /**\r\n * 验证文本内容块\r\n */\r\n static validateText(contentBlock: any): string[] {\r\n const errors: string[] = [];\r\n\r\n if (!contentBlock) {\r\n errors.push('文本内容块不能为空');\r\n return errors;\r\n }\r\n\r\n if (contentBlock.type !== CONTENT_BLOCK_TYPES.TEXT) {\r\n errors.push(`文本内容块类型应为 'text',实际为 '${contentBlock.type}'`);\r\n }\r\n\r\n if (contentBlock.content === undefined || contentBlock.content === null) {\r\n errors.push('文本内容块缺少 content 字段');\r\n }\r\n\r\n return errors;\r\n }\r\n\r\n /**\r\n * 验证公式内容块\r\n */\r\n static validateFormula(contentBlock: any): string[] {\r\n const errors: string[] = [];\r\n\r\n if (!contentBlock) {\r\n errors.push('公式内容块不能为空');\r\n return errors;\r\n }\r\n\r\n if (contentBlock.type !== CONTENT_BLOCK_TYPES.FORMULA) {\r\n errors.push(`公式内容块类型应为 'formula',实际为 '${contentBlock.type}'`);\r\n }\r\n\r\n if (contentBlock.content === undefined || contentBlock.content === null) {\r\n errors.push('公式内容块缺少 content 字段');\r\n }\r\n\r\n return errors;\r\n }\r\n\r\n /**\r\n * 批量转换文本内容块\r\n */\r\n static batchTransformText(\r\n contentBlocks: any[],\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): any[] {\r\n return contentBlocks\r\n .filter(block => block.type === CONTENT_BLOCK_TYPES.TEXT)\r\n .map(block => this.transformText(block, context, config));\r\n }\r\n\r\n /**\r\n * 批量转换公式内容块\r\n */\r\n static batchTransformFormula(\r\n contentBlocks: any[],\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): any[] {\r\n return contentBlocks\r\n .filter(block => block.type === CONTENT_BLOCK_TYPES.FORMULA)\r\n .map(block => this.transformFormula(block, context, config));\r\n }\r\n}\r\n\r\n/**\r\n * 创建文本转换器实例\r\n */\r\nexport function createTextTransformer() {\r\n return {\r\n type: CONTENT_BLOCK_TYPES.TEXT,\r\n transform: TextTransformer.transformText.bind(TextTransformer),\r\n validate: TextTransformer.validateText.bind(TextTransformer)\r\n };\r\n}\r\n\r\n/**\r\n * 创建公式转换器实例\r\n */\r\nexport function createFormulaTransformer() {\r\n return {\r\n type: CONTENT_BLOCK_TYPES.FORMULA,\r\n transform: TextTransformer.transformFormula.bind(TextTransformer),\r\n validate: TextTransformer.validateFormula.bind(TextTransformer)\r\n };\r\n}","/**\r\n * TriangleAdapterV3 转换器模块导出\r\n */\r\n\r\nimport type { ReferenceContext } from '../types';\r\nimport { CONTENT_BLOCK_TYPES } from '../constants';\r\n\r\n// 导入转换器工厂函数\r\nimport { createGraphTransformer } from './graphTransformer';\r\nimport { createGeometryTransformTransformer } from './geometryTransformTransformer';\r\nimport { createTextTransformer, createFormulaTransformer } from './textTransformer';\r\nimport { LayoutRefResolver } from '../resolvers/layoutRefResolver';\r\nimport { DesignTokenResolver } from '../resolvers/designTokenResolver';\r\n\r\n// 导出转换器类\r\nexport * from './graphTransformer';\r\nexport * from './geometryTransformTransformer';\r\nexport * from './textTransformer';\r\n\r\n// 转换器接口\r\nexport interface Transformer {\r\n type: string;\r\n transform(contentBlock: any, context: ReferenceContext, config?: any): any;\r\n validate?(contentBlock: any): string[];\r\n}\r\n\r\n/**\r\n * 转换器注册表\r\n */\r\nexport class TransformerRegistry {\r\n private transformers: Map<string, Transformer> = new Map();\r\n\r\n constructor() {\r\n this.registerDefaultTransformers();\r\n }\r\n\r\n /**\r\n * 注册默认转换器\r\n */\r\n private registerDefaultTransformers() {\r\n this.register(createGraphTransformer());\r\n this.register(createGeometryTransformTransformer());\r\n this.register(createTextTransformer());\r\n this.register(createFormulaTransformer());\r\n }\r\n\r\n /**\r\n * 注册转换器\r\n */\r\n register(transformer: Transformer): void {\r\n this.transformers.set(transformer.type, transformer);\r\n }\r\n\r\n /**\r\n * 获取所有转换器\r\n */\r\n getAllTransformers(): Transformer[] {\r\n return Array.from(this.transformers.values());\r\n }\r\n\r\n /**\r\n * 根据内容块类型获取转换器\r\n */\r\n getTransformer(type: string): Transformer | undefined {\r\n return this.transformers.get(type);\r\n }\r\n\r\n /**\r\n * 转换单个内容块\r\n */\r\n transform(\r\n contentBlock: any,\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): any {\r\n if (!contentBlock || !contentBlock.type) {\r\n throw new Error('内容块缺少 type 字段');\r\n }\r\n\r\n const transformer = this.getTransformer(contentBlock.type);\r\n if (!transformer) {\r\n console.error(`没有找到适合的转换器: ${contentBlock.type}`);\r\n return contentBlock; // 返回原始内容块\r\n }\r\n\r\n console.error(`🔄 TransformerRegistry.transform: type=\"${contentBlock.type}\", transformer.type=\"${transformer.type}\", enableReferenceResolution=${config.enableReferenceResolution}`);\r\n return transformer.transform(contentBlock, context, config);\r\n }\r\n\r\n /**\r\n * 批量转换内容块\r\n */\r\n batchTransform(\r\n contentBlocks: any[],\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): any[] {\r\n return contentBlocks.map(block => this.transform(block, context, config));\r\n }\r\n\r\n /**\r\n * 转换场景内容\r\n * 支持新旧字段名:items(新)和content(旧)\r\n * 输出统一使用items字段(新标准)\r\n */\r\n transformScene(\r\n scene: { content?: any[]; items?: any[]; layout?: any },\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): { items: any[]; layout?: any } {\r\n // 支持items字段(新)和content字段(旧)\r\n const sceneContent = scene.items || scene.content;\r\n\r\n if (!scene || !Array.isArray(sceneContent)) {\r\n return { items: [], layout: scene?.layout };\r\n }\r\n\r\n const transformedContent = this.batchTransform(sceneContent, context, config);\r\n\r\n // 处理布局引用\r\n let transformedLayout = scene.layout;\r\n if (scene.layout && typeof scene.layout === 'object') {\r\n // 解析布局引用\r\n transformedLayout = this.resolveLayoutReferences(scene.layout, context, config);\r\n } else if (typeof scene.layout === 'string' && scene.layout.startsWith('layoutRef:')) {\r\n // 如果是字符串类型的布局引用,直接解析\r\n try {\r\n transformedLayout = LayoutRefResolver.resolve(scene.layout, context);\r\n } catch (error) {\r\n if (config.strictMode) {\r\n throw error;\r\n }\r\n console.warn(`布局引用解析失败: ${scene.layout}`, error);\r\n transformedLayout = scene.layout; // 保留原始值\r\n }\r\n }\r\n\r\n return {\r\n items: transformedContent,\r\n layout: transformedLayout\r\n };\r\n }\r\n\r\n /**\r\n * 解析布局对象中的引用\r\n */\r\n private resolveLayoutReferences(\r\n layout: any,\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n }\r\n ): any {\r\n if (!layout || !config.enableReferenceResolution) {\r\n return layout;\r\n }\r\n\r\n // 如果是字符串类型的布局引用,直接解析\r\n if (typeof layout === 'string' && layout.startsWith('layoutRef:')) {\r\n try {\r\n return LayoutRefResolver.resolve(layout, context);\r\n } catch (error) {\r\n if (config.strictMode) {\r\n throw error;\r\n }\r\n console.warn(`布局引用解析失败: ${layout}`, error);\r\n return layout; // 保留原始值\r\n }\r\n }\r\n\r\n // 如果是对象,递归处理其属性\r\n if (typeof layout === 'object') {\r\n // 特殊情况:如果 layout.layoutRef 存在,解析布局引用\r\n if (layout.layoutRef && typeof layout.layoutRef === 'string') {\r\n try {\r\n // 构建 layoutRef 字符串\r\n const layoutRefString = `layoutRef:${layout.layoutRef}`;\r\n const resolvedLayout = LayoutRefResolver.resolve(layoutRefString, context);\r\n // 合并原始 layout 的其他属性\r\n const { layoutRef, ...otherProps } = layout;\r\n return { ...resolvedLayout, ...otherProps };\r\n } catch (error) {\r\n if (config.strictMode) {\r\n throw error;\r\n }\r\n console.warn(`布局引用解析失败: ${layout.layoutRef}`, error);\r\n // 保留原始 layout\r\n }\r\n }\r\n\r\n const resolvedLayout: any = Array.isArray(layout) ? [] : {};\r\n\r\n for (const [key, value] of Object.entries(layout)) {\r\n if (typeof value === 'string' && value.startsWith('layoutRef:')) {\r\n try {\r\n resolvedLayout[key] = LayoutRefResolver.resolve(value, context);\r\n } catch (error) {\r\n if (config.strictMode) {\r\n throw error;\r\n }\r\n console.warn(`布局引用解析失败: ${value}`, error);\r\n resolvedLayout[key] = value; // 保留原始值\r\n }\r\n } else if (typeof value === 'string' && value.startsWith('$')) {\r\n // 处理设计令牌引用\r\n try {\r\n resolvedLayout[key] = DesignTokenResolver.resolve(value, context);\r\n } catch (error) {\r\n if (config.strictMode) {\r\n throw error;\r\n }\r\n console.warn(`布局中的设计令牌解析失败: ${key}=${value}`, error);\r\n resolvedLayout[key] = value; // 保留原始值\r\n }\r\n } else if (value && typeof value === 'object') {\r\n resolvedLayout[key] = this.resolveLayoutReferences(value, context, config);\r\n } else {\r\n resolvedLayout[key] = value;\r\n }\r\n }\r\n\r\n return resolvedLayout;\r\n }\r\n\r\n return layout;\r\n }\r\n\r\n /**\r\n * 转换所有场景\r\n * 支持新旧字段名:items(新)和content(旧)\r\n * 输出统一使用items字段(新标准)\r\n */\r\n transformScenes(\r\n scenes: Record<string, { content?: any[]; items?: any[]; layout?: any }>,\r\n context: ReferenceContext,\r\n config: {\r\n enableReferenceResolution?: boolean;\r\n strictMode?: boolean;\r\n } = {}\r\n ): Record<string, { items: any[]; layout?: any }> {\r\n const transformedScenes: Record<string, { items: any[]; layout?: any }> = {};\r\n\r\n for (const [sceneName, scene] of Object.entries(scenes)) {\r\n transformedScenes[sceneName] = this.transformScene(scene, context, config);\r\n }\r\n\r\n return transformedScenes;\r\n }\r\n\r\n /**\r\n * 验证内容块\r\n */\r\n validate(contentBlock: any): string[] {\r\n if (!contentBlock || !contentBlock.type) {\r\n return ['内容块缺少 type 字段'];\r\n }\r\n\r\n const transformer = this.getTransformer(contentBlock.type);\r\n if (!transformer || !transformer.validate) {\r\n return []; // 没有验证器,返回空数组\r\n }\r\n\r\n return transformer.validate(contentBlock);\r\n }\r\n\r\n /**\r\n * 批量验证内容块\r\n */\r\n batchValidate(contentBlocks: any[]): Array<{ block: any; errors: string[] }> {\r\n return contentBlocks.map(block => ({\r\n block,\r\n errors: this.validate(block)\r\n }));\r\n }\r\n}\r\n\r\n/**\r\n * 创建默认转换器注册表\r\n */\r\nexport function createDefaultTransformerRegistry(): TransformerRegistry {\r\n return new TransformerRegistry();\r\n}","/**\r\n * 输入验证器\r\n *\r\n * 验证原始输入数据的完整性和有效性\r\n */\r\n\r\nimport type { RawTriangleProblemData } from '../types';\r\nimport { REQUIRED_FIELDS, SCENE_NAMES } from '../constants';\r\n\r\n/**\r\n * 输入验证器\r\n */\r\nexport class InputValidator {\r\n /**\r\n * 验证原始输入数据\r\n */\r\n static validate(\r\n input: any,\r\n options: {\r\n strictMode?: boolean;\r\n skipOptionalFields?: boolean;\r\n } = {}\r\n ): { isValid: boolean; errors: string[]; warnings: string[] } {\r\n const { strictMode = false, skipOptionalFields = false } = options;\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // 基本类型检查\r\n if (!input || typeof input !== 'object') {\r\n errors.push('输入数据必须是对象');\r\n return { isValid: false, errors, warnings };\r\n }\r\n\r\n // 检查必需字段\r\n this.validateRequiredFields(input, errors, warnings, { skipOptionalFields });\r\n\r\n // 检查字段类型\r\n this.validateFieldTypes(input, errors, warnings);\r\n\r\n // 检查场景结构\r\n this.validateScenes(input, errors, warnings);\r\n\r\n // 检查基础信息\r\n this.validateBasicInfo(input, errors, warnings);\r\n\r\n // 检查答案信息\r\n this.validateAnswerInfo(input, errors, warnings);\r\n\r\n // 严格模式下的额外检查\r\n if (strictMode) {\r\n this.validateStrictMode(input, errors, warnings);\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n warnings\r\n };\r\n }\r\n\r\n /**\r\n * 验证必需字段\r\n */\r\n private static validateRequiredFields(\r\n input: any,\r\n errors: string[],\r\n warnings: string[],\r\n options: { skipOptionalFields?: boolean }\r\n ): void {\r\n const { skipOptionalFields } = options;\r\n\r\n // 检查顶层必需字段\r\n for (const field of REQUIRED_FIELDS.RAW_DATA) {\r\n if (input[field] === undefined) {\r\n errors.push(`缺少必需字段: ${field}`);\r\n }\r\n }\r\n\r\n // 检查 basic_info 中的必需字段\r\n if (input.basic_info) {\r\n for (const field of REQUIRED_FIELDS.BASIC_INFO) {\r\n if (input.basic_info[field] === undefined) {\r\n errors.push(`basic_info 缺少必需字段: ${field}`);\r\n }\r\n }\r\n }\r\n\r\n // 检查 answer_info 中的必需字段\r\n if (input.answer_info) {\r\n for (const field of REQUIRED_FIELDS.ANSWER_INFO) {\r\n if (input.answer_info[field] === undefined) {\r\n errors.push(`answer_info 缺少必需字段: ${field}`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 验证字段类型\r\n */\r\n private static validateFieldTypes(\r\n input: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n // 检查字符串字段\r\n const stringFields = ['math_prob_id', 'title', 'grade_id', 'unit_name', 'lesson_name', 'skill_description', 'objective'];\r\n stringFields.forEach(field => {\r\n if (input[field] !== undefined && typeof input[field] !== 'string') {\r\n errors.push(`${field} 应为字符串类型`);\r\n }\r\n });\r\n\r\n // 检查数字字段\r\n const numberFields = ['difficulty', 'unit_id', 'lesson_id', 'module_id', 'skill_id'];\r\n numberFields.forEach(field => {\r\n if (input[field] !== undefined && typeof input[field] !== 'number') {\r\n errors.push(`${field} 应为数字类型`);\r\n }\r\n });\r\n\r\n // 检查数组字段\r\n if (input.knowledge_points !== undefined && !Array.isArray(input.knowledge_points)) {\r\n errors.push('knowledge_points 应为数组类型');\r\n }\r\n\r\n // 检查对象字段\r\n const objectFields = ['metadata', 'basic_info', 'answer_info', 'scenes'];\r\n objectFields.forEach(field => {\r\n if (input[field] !== undefined && (typeof input[field] !== 'object' || Array.isArray(input[field]))) {\r\n errors.push(`${field} 应为对象类型`);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * 验证场景结构\r\n */\r\n private static validateScenes(\r\n input: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n if (!input.scenes || typeof input.scenes !== 'object') {\r\n errors.push('scenes 应为对象类型');\r\n return;\r\n }\r\n\r\n // 检查必需场景\r\n const requiredScenes = ['question', 'solve', 'review'];\r\n for (const sceneName of requiredScenes) {\r\n if (!input.scenes[sceneName]) {\r\n errors.push(`缺少必需场景: ${sceneName}`);\r\n }\r\n }\r\n\r\n // 检查每个场景的结构\r\n for (const [sceneName, scene] of Object.entries(input.scenes)) {\r\n if (!scene || typeof scene !== 'object') {\r\n errors.push(`场景 ${sceneName} 应为对象类型`);\r\n continue;\r\n }\r\n\r\n const sceneObj = scene as any;\r\n\r\n // 检查 content\r\n if (!Array.isArray(sceneObj.content)) {\r\n errors.push(`场景 ${sceneName} 的 content 应为数组类型`);\r\n }\r\n\r\n // 检查 layout(可选)\r\n if (sceneObj.layout !== undefined && typeof sceneObj.layout !== 'object') {\r\n errors.push(`场景 ${sceneName} 的 layout 应为对象类型`);\r\n }\r\n\r\n // 检查场景名称是否有效\r\n if (!SCENE_NAMES.includes(sceneName as any)) {\r\n warnings.push(`未知的场景名称: ${sceneName}`);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 验证基础信息\r\n */\r\n private static validateBasicInfo(\r\n input: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n if (!input.basic_info || typeof input.basic_info !== 'object') {\r\n return;\r\n }\r\n\r\n const basicInfo = input.basic_info;\r\n\r\n // 检查数值字段\r\n const numberFields = ['base', 'height', 'length', 'width', 'score'];\r\n numberFields.forEach(field => {\r\n if (basicInfo[field] !== undefined && typeof basicInfo[field] !== 'number') {\r\n errors.push(`basic_info.${field} 应为数字类型`);\r\n }\r\n });\r\n\r\n // 检查字符串字段\r\n const stringFields = ['question', 'answerUnit', 'areaUnit', 'shape', 'baseUnit', 'heightUnit', 'lengthUnit', 'widthUnit'];\r\n stringFields.forEach(field => {\r\n if (basicInfo[field] !== undefined && typeof basicInfo[field] !== 'string') {\r\n errors.push(`basic_info.${field} 应为字符串类型`);\r\n }\r\n });\r\n\r\n // 检查对象字段\r\n if (basicInfo.variables !== undefined && typeof basicInfo.variables !== 'object') {\r\n errors.push('basic_info.variables 应为对象类型');\r\n }\r\n\r\n if (basicInfo.context !== undefined && typeof basicInfo.context !== 'object') {\r\n errors.push('basic_info.context 应为对象类型');\r\n }\r\n\r\n // 检查 shape 是否有效\r\n if (basicInfo.shape && !['acute_triangle', 'right_triangle', 'rectangle', 'circle'].includes(basicInfo.shape)) {\r\n warnings.push(`未知的形状类型: ${basicInfo.shape}`);\r\n }\r\n }\r\n\r\n /**\r\n * 验证答案信息\r\n */\r\n private static validateAnswerInfo(\r\n input: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n if (!input.answer_info || typeof input.answer_info !== 'object') {\r\n return;\r\n }\r\n\r\n const answerInfo = input.answer_info;\r\n\r\n // 检查必需字段\r\n if (typeof answerInfo.value !== 'number') {\r\n errors.push('answer_info.value 应为数字类型');\r\n }\r\n\r\n if (typeof answerInfo.unit !== 'string') {\r\n errors.push('answer_info.unit 应为字符串类型');\r\n }\r\n\r\n if (typeof answerInfo.explanation_text !== 'string') {\r\n errors.push('answer_info.explanation_text 应为字符串类型');\r\n }\r\n\r\n // 检查数值合理性\r\n if (answerInfo.value !== undefined) {\r\n if (answerInfo.value < 0) {\r\n warnings.push('answer_info.value 为负数,可能不正确');\r\n }\r\n if (answerInfo.value > 10000) {\r\n warnings.push('answer_info.value 过大,可能不正确');\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 严格模式验证\r\n */\r\n private static validateStrictMode(\r\n input: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n // 检查 schema_version\r\n if (!input.schema_version) {\r\n warnings.push('建议添加 schema_version 字段');\r\n }\r\n\r\n // 检查 config_version\r\n if (!input.config_version) {\r\n warnings.push('建议添加 config_version 字段');\r\n }\r\n\r\n // 检查 knowledge_points 非空\r\n if (input.knowledge_points && input.knowledge_points.length === 0) {\r\n warnings.push('knowledge_points 数组为空');\r\n }\r\n\r\n // 检查场景内容非空\r\n if (input.scenes) {\r\n for (const [sceneName, scene] of Object.entries(input.scenes)) {\r\n const sceneObj = scene as any;\r\n if (sceneObj.content && sceneObj.content.length === 0) {\r\n warnings.push(`场景 ${sceneName} 的 content 数组为空`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 快速验证(只检查必需字段)\r\n */\r\n static quickValidate(input: any): boolean {\r\n if (!input || typeof input !== 'object') {\r\n return false;\r\n }\r\n\r\n // 检查最关键的必需字段\r\n const criticalFields = ['math_prob_id', 'title', 'basic_info', 'scenes', 'answer_info'];\r\n for (const field of criticalFields) {\r\n if (input[field] === undefined) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * 验证并清理输入数据\r\n */\r\n static validateAndClean(\r\n input: any,\r\n options: {\r\n strictMode?: boolean;\r\n removeInvalidFields?: boolean;\r\n } = {}\r\n ): { data: any; errors: string[]; warnings: string[] } {\r\n const { strictMode = false, removeInvalidFields = false } = options;\r\n const validation = this.validate(input, { strictMode });\r\n\r\n let cleanedData = input;\r\n\r\n if (removeInvalidFields && !validation.isValid) {\r\n // 简单清理:移除明显无效的字段\r\n cleanedData = { ...input };\r\n const invalidFields = ['__proto__', 'constructor', 'prototype'];\r\n invalidFields.forEach(field => {\r\n if (field in cleanedData) {\r\n delete cleanedData[field];\r\n }\r\n });\r\n }\r\n\r\n return {\r\n data: cleanedData,\r\n errors: validation.errors,\r\n warnings: validation.warnings\r\n };\r\n }\r\n}","/**\r\n * 输出验证器\r\n *\r\n * 验证转换后的数据是否符合 MathPracticeProblemData 接口\r\n */\r\n\r\nimport type { MathPracticeProblemData } from '../types';\r\nimport { SCENE_NAMES } from '../constants';\r\n\r\n/**\r\n * 输出验证器\r\n */\r\nexport class OutputValidator {\r\n /**\r\n * 验证转换后的数据\r\n */\r\n static validate(\r\n output: any,\r\n options: {\r\n strictMode?: boolean;\r\n checkSceneContent?: boolean;\r\n } = {}\r\n ): { isValid: boolean; errors: string[]; warnings: string[] } {\r\n const { strictMode = false, checkSceneContent = true } = options;\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // 基本类型检查\r\n if (!output || typeof output !== 'object') {\r\n errors.push('输出数据必须是对象');\r\n return { isValid: false, errors, warnings };\r\n }\r\n\r\n // 检查必需字段\r\n this.validateRequiredFields(output, errors, warnings);\r\n\r\n // 检查字段类型\r\n this.validateFieldTypes(output, errors, warnings);\r\n\r\n // 检查场景结构\r\n if (checkSceneContent) {\r\n this.validateScenes(output, errors, warnings);\r\n }\r\n\r\n // 检查基础信息\r\n this.validateBasicInfo(output, errors, warnings);\r\n\r\n // 检查答案\r\n this.validateAnswer(output, errors, warnings);\r\n\r\n // 检查解释\r\n this.validateExplanation(output, errors, warnings);\r\n\r\n // 严格模式下的额外检查\r\n if (strictMode) {\r\n this.validateStrictMode(output, errors, warnings);\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n warnings\r\n };\r\n }\r\n\r\n /**\r\n * 验证必需字段\r\n */\r\n private static validateRequiredFields(\r\n output: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n const requiredFields = [\r\n 'id', 'title', 'grade', 'unit', 'lesson', 'skill', 'objective',\r\n 'knowledgePoints', 'difficulty', 'metadata', 'basicInfo', 'scenes', 'answer'\r\n ];\r\n\r\n for (const field of requiredFields) {\r\n if (output[field] === undefined) {\r\n errors.push(`缺少必需字段: ${field}`);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 验证字段类型\r\n */\r\n private static validateFieldTypes(\r\n output: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n // 检查字符串字段\r\n const stringFields = ['id', 'title', 'unit', 'lesson', 'skill', 'objective'];\r\n stringFields.forEach(field => {\r\n if (output[field] !== undefined && typeof output[field] !== 'string') {\r\n errors.push(`${field} 应为字符串类型`);\r\n }\r\n });\r\n\r\n // 检查数字字段\r\n if (output.grade !== undefined && typeof output.grade !== 'number') {\r\n errors.push('grade 应为数字类型');\r\n }\r\n\r\n if (output.difficulty !== undefined && typeof output.difficulty !== 'number') {\r\n errors.push('difficulty 应为数字类型');\r\n }\r\n\r\n // 检查数组字段\r\n if (output.knowledgePoints !== undefined && !Array.isArray(output.knowledgePoints)) {\r\n errors.push('knowledgePoints 应为数组类型');\r\n }\r\n\r\n // 检查对象字段\r\n const objectFields = ['metadata', 'basicInfo', 'scenes', 'answer'];\r\n objectFields.forEach(field => {\r\n if (output[field] !== undefined && (typeof output[field] !== 'object' || Array.isArray(output[field]))) {\r\n errors.push(`${field} 应为对象类型`);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * 验证场景结构\r\n * 支持新旧字段名:items(新)和content(旧)\r\n */\r\n private static validateScenes(\r\n output: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n if (!output.scenes || typeof output.scenes !== 'object') {\r\n errors.push('scenes 应为对象类型');\r\n return;\r\n }\r\n\r\n // 检查必需场景\r\n const requiredScenes = ['question', 'solve', 'review'];\r\n for (const sceneName of requiredScenes) {\r\n if (!output.scenes[sceneName]) {\r\n errors.push(`缺少必需场景: ${sceneName}`);\r\n }\r\n }\r\n\r\n // 检查每个场景的结构\r\n for (const [sceneName, scene] of Object.entries(output.scenes)) {\r\n if (!scene || typeof scene !== 'object') {\r\n errors.push(`场景 ${sceneName} 应为对象类型`);\r\n continue;\r\n }\r\n\r\n const sceneObj = scene as any;\r\n\r\n // 检查 content/items(支持新旧两种字段名)\r\n // 优先检查 items(新字段),如果存在则使用它\r\n const contentItems = sceneObj.items || sceneObj.content;\r\n\r\n if (!Array.isArray(contentItems)) {\r\n // 如果既不是 items 也不是 content,或者不是数组,则报错\r\n errors.push(`场景 ${sceneName} 缺少有效的内容数组(应为 items 或 content 字段)`);\r\n } else if (contentItems.length === 0) {\r\n warnings.push(`场景 ${sceneName} 的内容数组为空`);\r\n }\r\n\r\n // 检查 layout(可选)\r\n if (sceneObj.layout !== undefined && typeof sceneObj.layout !== 'object') {\r\n errors.push(`场景 ${sceneName} 的 layout 应为对象类型`);\r\n }\r\n\r\n // 检查场景名称是否有效\r\n if (!SCENE_NAMES.includes(sceneName as any)) {\r\n warnings.push(`未知的场景名称: ${sceneName}`);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 验证基础信息\r\n */\r\n private static validateBasicInfo(\r\n output: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n if (!output.basicInfo || typeof output.basicInfo !== 'object') {\r\n errors.push('basicInfo 应为对象类型');\r\n return;\r\n }\r\n\r\n const basicInfo = output.basicInfo;\r\n\r\n // 检查必需字段\r\n if (basicInfo.question === undefined || typeof basicInfo.question !== 'string') {\r\n errors.push('basicInfo.question 应为字符串类型');\r\n }\r\n\r\n // 检查数值字段\r\n const numberFields = ['base', 'height', 'length', 'width', 'score'];\r\n numberFields.forEach(field => {\r\n if (basicInfo[field] !== undefined && typeof basicInfo[field] !== 'number') {\r\n errors.push(`basicInfo.${field} 应为数字类型`);\r\n }\r\n });\r\n\r\n // 检查字符串字段\r\n const stringFields = ['answerUnit', 'areaUnit', 'shape', 'baseUnit', 'heightUnit', 'lengthUnit', 'widthUnit'];\r\n stringFields.forEach(field => {\r\n if (basicInfo[field] !== undefined && typeof basicInfo[field] !== 'string') {\r\n errors.push(`basicInfo.${field} 应为字符串类型`);\r\n }\r\n });\r\n\r\n // 检查对象字段\r\n if (basicInfo.variables !== undefined && typeof basicInfo.variables !== 'object') {\r\n errors.push('basicInfo.variables 应为对象类型');\r\n }\r\n\r\n if (basicInfo.context !== undefined && typeof basicInfo.context !== 'object') {\r\n errors.push('basicInfo.context 应为对象类型');\r\n }\r\n }\r\n\r\n /**\r\n * 验证答案\r\n */\r\n private static validateAnswer(\r\n output: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n if (!output.answer || typeof output.answer !== 'object') {\r\n errors.push('answer 应为对象类型');\r\n return;\r\n }\r\n\r\n const answer = output.answer;\r\n\r\n // 检查必需字段\r\n if (typeof answer.value !== 'number') {\r\n errors.push('answer.value 应为数字类型');\r\n }\r\n\r\n if (typeof answer.unit !== 'string') {\r\n errors.push('answer.unit 应为字符串类型');\r\n }\r\n\r\n if (typeof answer.explanation !== 'string') {\r\n errors.push('answer.explanation 应为字符串类型');\r\n }\r\n\r\n // 检查数值合理性\r\n if (answer.value !== undefined) {\r\n if (answer.value < 0) {\r\n warnings.push('answer.value 为负数,可能不正确');\r\n }\r\n if (answer.value > 10000) {\r\n warnings.push('answer.value 过大,可能不正确');\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 验证解释\r\n */\r\n private static validateExplanation(\r\n output: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n if (output.explanation === undefined) {\r\n // explanation 是必需的\r\n errors.push('缺少 explanation 字段');\r\n return;\r\n }\r\n\r\n // explanation 可以是对象或数组\r\n if (typeof output.explanation !== 'object') {\r\n errors.push('explanation 应为对象或数组类型');\r\n return;\r\n }\r\n\r\n // 如果是数组,检查每个元素\r\n if (Array.isArray(output.explanation)) {\r\n if (output.explanation.length === 0) {\r\n warnings.push('explanation 数组为空');\r\n }\r\n\r\n output.explanation.forEach((step: any, index: number) => {\r\n if (!step || typeof step !== 'object') {\r\n errors.push(`explanation[${index}] 应为对象类型`);\r\n }\r\n });\r\n }\r\n // 如果是对象,检查 steps 字段\r\n else if (output.explanation.steps === undefined) {\r\n errors.push('explanation 对象缺少 steps 字段');\r\n } else if (!Array.isArray(output.explanation.steps)) {\r\n errors.push('explanation.steps 应为数组类型');\r\n }\r\n }\r\n\r\n /**\r\n * 严格模式验证\r\n */\r\n private static validateStrictMode(\r\n output: any,\r\n errors: string[],\r\n warnings: string[]\r\n ): void {\r\n // 检查 id 格式\r\n if (output.id && typeof output.id === 'string') {\r\n if (!output.id.includes('-')) {\r\n warnings.push('id 格式可能不符合规范,建议使用连字符分隔');\r\n }\r\n }\r\n\r\n // 检查 grade 范围\r\n if (output.grade !== undefined) {\r\n if (output.grade < 1 || output.grade > 12) {\r\n warnings.push(`grade 值 ${output.grade} 超出常见范围 (1-12)`);\r\n }\r\n }\r\n\r\n // 检查 difficulty 范围\r\n if (output.difficulty !== undefined) {\r\n if (output.difficulty < 1 || output.difficulty > 5) {\r\n warnings.push(`difficulty 值 ${output.difficulty} 超出范围 (1-5)`);\r\n }\r\n }\r\n\r\n // 检查 knowledgePoints 非空\r\n if (output.knowledgePoints && output.knowledgePoints.length === 0) {\r\n warnings.push('knowledgePoints 数组为空');\r\n }\r\n\r\n // 检查 metadata 结构\r\n if (output.metadata && typeof output.metadata === 'object') {\r\n const metadata = output.metadata;\r\n if (!metadata.topic || typeof metadata.topic !== 'string') {\r\n warnings.push('metadata.topic 应为字符串类型');\r\n }\r\n if (!metadata.skill || typeof metadata.skill !== 'string') {\r\n warnings.push('metadata.skill 应为字符串类型');\r\n }\r\n if (!metadata.tags || !Array.isArray(metadata.tags)) {\r\n warnings.push('metadata.tags 应为数组类型');\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 快速验证(只检查关键字段)\r\n */\r\n static quickValidate(output: any): boolean {\r\n if (!output || typeof output !== 'object') {\r\n return false;\r\n }\r\n\r\n // 检查最关键的必需字段\r\n const criticalFields = ['id', 'title', 'basicInfo', 'scenes', 'answer'];\r\n for (const field of criticalFields) {\r\n if (output[field] === undefined) {\r\n return false;\r\n }\r\n }\r\n\r\n // 检查基本类型\r\n if (typeof output.title !== 'string') {\r\n return false;\r\n }\r\n\r\n if (output.basicInfo && typeof output.basicInfo !== 'object') {\r\n return false;\r\n }\r\n\r\n if (output.scenes && typeof output.scenes !== 'object') {\r\n return false;\r\n }\r\n\r\n if (output.answer && typeof output.answer !== 'object') {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * 验证是否为有效的 MathPracticeProblemData\r\n */\r\n static isValidMathPracticeProblemData(output: any): output is MathPracticeProblemData {\r\n const validation = this.validate(output, { strictMode: false, checkSceneContent: false });\r\n return validation.isValid;\r\n }\r\n}","/**\r\n * TriangleAdapterV3 验证器模块导出\r\n */\r\n\r\nexport * from './inputValidator';\r\nexport * from './outputValidator';\r\n\r\n// 导入验证器类\r\nimport { InputValidator } from './inputValidator';\r\nimport { OutputValidator } from './outputValidator';\r\n\r\n/**\r\n * 验证结果\r\n */\r\nexport interface ValidationResult {\r\n isValid: boolean;\r\n errors: string[];\r\n warnings: string[];\r\n timestamp: number;\r\n}\r\n\r\n/**\r\n * 验证管理器\r\n */\r\nexport class ValidationManager {\r\n /**\r\n * 验证输入数据\r\n */\r\n static validateInput(\r\n input: any,\r\n options: {\r\n strictMode?: boolean;\r\n skipOptionalFields?: boolean;\r\n } = {}\r\n ): ValidationResult {\r\n const { isValid, errors, warnings } = InputValidator.validate(input, options);\r\n\r\n return {\r\n isValid,\r\n errors,\r\n warnings,\r\n timestamp: Date.now()\r\n };\r\n }\r\n\r\n /**\r\n * 验证输出数据\r\n */\r\n static validateOutput(\r\n output: any,\r\n options: {\r\n strictMode?: boolean;\r\n checkSceneContent?: boolean;\r\n } = {}\r\n ): ValidationResult {\r\n const { isValid, errors, warnings } = OutputValidator.validate(output, options);\r\n\r\n return {\r\n isValid,\r\n errors,\r\n warnings,\r\n timestamp: Date.now()\r\n };\r\n }\r\n\r\n /**\r\n * 完整验证流程\r\n */\r\n static validateComplete(\r\n input: any,\r\n output: any,\r\n options: {\r\n inputStrictMode?: boolean;\r\n outputStrictMode?: boolean;\r\n } = {}\r\n ): {\r\n input: ValidationResult;\r\n output: ValidationResult;\r\n overall: { isValid: boolean; errors: string[]; warnings: string[] };\r\n } {\r\n const { inputStrictMode = false, outputStrictMode = false } = options;\r\n\r\n const inputResult = this.validateInput(input, { strictMode: inputStrictMode });\r\n const outputResult = this.validateOutput(output, { strictMode: outputStrictMode });\r\n\r\n // 合并错误和警告\r\n const allErrors = [...inputResult.errors, ...outputResult.errors];\r\n const allWarnings = [...inputResult.warnings, ...outputResult.warnings];\r\n\r\n const overall = {\r\n isValid: inputResult.isValid && outputResult.isValid,\r\n errors: allErrors,\r\n warnings: allWarnings\r\n };\r\n\r\n return {\r\n input: inputResult,\r\n output: outputResult,\r\n overall\r\n };\r\n }\r\n\r\n /**\r\n * 快速验证输入数据\r\n */\r\n static quickValidateInput(input: any): boolean {\r\n return InputValidator.quickValidate(input);\r\n }\r\n\r\n /**\r\n * 快速验证输出数据\r\n */\r\n static quickValidateOutput(output: any): boolean {\r\n return OutputValidator.quickValidate(output);\r\n }\r\n\r\n /**\r\n * 验证并报告\r\n */\r\n static validateAndReport(\r\n data: any,\r\n type: 'input' | 'output',\r\n options: any = {}\r\n ): void {\r\n const result = type === 'input'\r\n ? this.validateInput(data, options)\r\n : this.validateOutput(data, options);\r\n\r\n console.group(`${type.toUpperCase()} 验证结果`);\r\n console.log(`有效性: ${result.isValid ? '✅ 通过' : '❌ 失败'}`);\r\n\r\n if (result.errors.length > 0) {\r\n console.group('❌ 错误:');\r\n result.errors.forEach(error => console.log(` - ${error}`));\r\n console.groupEnd();\r\n }\r\n\r\n if (result.warnings.length > 0) {\r\n console.group('⚠️ 警告:');\r\n result.warnings.forEach(warning => console.log(` - ${warning}`));\r\n console.groupEnd();\r\n }\r\n\r\n console.groupEnd();\r\n }\r\n}","/**\r\n * 引用处理工具\r\n *\r\n * 提供引用解析、提取、替换等工具函数\r\n */\r\n\r\nimport type { ReferenceContext } from '../types';\r\nimport { ReferenceType } from '../types';\r\nimport { ResolverRegistry } from '../resolvers';\r\n\r\n/**\r\n * 引用处理工具\r\n */\r\nexport class ReferenceUtils {\r\n /**\r\n * 提取对象中的所有引用\r\n */\r\n static extractAllReferences(obj: any): string[] {\r\n const refs: string[] = [];\r\n\r\n const traverse = (value: any) => {\r\n if (typeof value === 'string') {\r\n refs.push(value);\r\n } else if (Array.isArray(value)) {\r\n value.forEach(traverse);\r\n } else if (value && typeof value === 'object') {\r\n Object.values(value).forEach(traverse);\r\n }\r\n };\r\n\r\n traverse(obj);\r\n return [...new Set(refs)]; // 去重\r\n }\r\n\r\n /**\r\n * 分类引用\r\n */\r\n static categorizeReferences(refs: string[], context: ReferenceContext): { [key: string]: string[] } {\r\n const categorized: { [key: string]: string[] } = {\r\n [ReferenceType.DESIGN_TOKEN]: [],\r\n [ReferenceType.STYLE_REF]: [],\r\n [ReferenceType.GEOMETRY_REF]: [],\r\n [ReferenceType.TRANSFORM_REF]: [],\r\n [ReferenceType.LAYOUT_REF]: []\r\n };\r\n\r\n const resolverRegistry = new ResolverRegistry();\r\n\r\n for (const ref of refs) {\r\n const resolver = resolverRegistry.getResolverForRef(ref);\r\n if (resolver) {\r\n categorized[resolver.type].push(ref);\r\n }\r\n }\r\n\r\n return categorized;\r\n }\r\n\r\n /**\r\n * 批量解析引用\r\n */\r\n static batchResolveReferences(\r\n refs: string[],\r\n context: ReferenceContext,\r\n options: {\r\n strictMode?: boolean;\r\n onMissing?: (ref: string) => any;\r\n } = {}\r\n ): Record<string, any> {\r\n const { strictMode = false, onMissing } = options;\r\n const resolverRegistry = new ResolverRegistry();\r\n const results: Record<string, any> = {};\r\n\r\n for (const ref of refs) {\r\n const resolver = resolverRegistry.getResolverForRef(ref);\r\n if (resolver) {\r\n try {\r\n results[ref] = resolver.resolve(ref, context);\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`引用解析失败: ${ref}`, error);\r\n if (onMissing) {\r\n results[ref] = onMissing(ref);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * 替换对象中的引用\r\n */\r\n static replaceReferences(\r\n obj: any,\r\n context: ReferenceContext,\r\n options: {\r\n strictMode?: boolean;\r\n onMissing?: (ref: string) => any;\r\n maxDepth?: number;\r\n } = {}\r\n ): any {\r\n const { strictMode = false, onMissing, maxDepth = 10 } = options;\r\n const resolverRegistry = new ResolverRegistry();\r\n\r\n // 定义不应由通用解析器处理的保留字段名\r\n // 这些字段的值是标识符,应由专用转换器处理\r\n const RESERVED_REF_FIELDS = new Set([\r\n 'geometryRef', 'styleRef', 'transformRef',\r\n 'layoutRef', 'boardRef', 'animationRef',\r\n 'appearanceRef', 'position', 'vertices',\r\n 'endpoints', 'center', 'start', 'end',\r\n // 常见配置字段,其值不应被通用解析器处理\r\n 'type', 'theme', 'strategy', 'content', 'description', 'title',\r\n 'question', 'answer', 'unit', 'id', 'name', 'label',\r\n 'config', 'metadata', 'layout', 'renderer', 'padding',\r\n 'component', 'inputType', 'placeholder', 'submitButton',\r\n // 'color' removed - 可能包含设计令牌引用\r\n 'targetGroup', 'direction', 'executionMode',\r\n 'transformSource', 'rotationGroup', 'isMovable', 'isStatic',\r\n 'shapes', 'animated', 'static', 'transform', 'chartConfig',\r\n 'steps', 'value', 'tolerance', 'validation', 'explanation_text',\r\n 'solution_steps', 'variables', 'originX', 'originY', 'areaUnit',\r\n 'baseUnit', 'heightUnit', 'answerUnit', 'base', 'height',\r\n 'displayMode', 'parts', 'fontSize', 'fontWeight', 'anchorX'\r\n ]);\r\n\r\n const replace = (value: any, depth: number = 0, parentKey?: string): any => {\r\n if (depth > maxDepth) {\r\n console.warn(`引用替换达到最大深度: ${maxDepth}`);\r\n return value;\r\n }\r\n\r\n if (typeof value === 'string') {\r\n // 检查是否是保留字段的值(不应由通用解析器处理)\r\n if (parentKey && RESERVED_REF_FIELDS.has(parentKey)) {\r\n // 保持原样,让专用转换器处理\r\n console.warn(`🛡️ 跳过保留字段 \"${parentKey}\" 的通用解析: \"${value}\"`);\r\n return value;\r\n }\r\n\r\n // 检查是否是明显的引用模式(以$开头或包含\"Ref:\")\r\n // 如果不是,很可能是普通字符串,不应尝试解析\r\n const isLikelyReference = value.startsWith('$') || value.includes('Ref:');\r\n if (!isLikelyReference) {\r\n // 不是明显的引用模式,保持原样\r\n return value;\r\n }\r\n\r\n const resolver = resolverRegistry.getResolverForRef(value);\r\n if (resolver) {\r\n try {\r\n return resolver.resolve(value, context);\r\n } catch (error) {\r\n if (strictMode) {\r\n throw error;\r\n }\r\n console.warn(`引用解析失败: ${value}`, error);\r\n if (onMissing) {\r\n return onMissing(value);\r\n }\r\n return value; // 保留原始引用\r\n }\r\n }\r\n return value;\r\n } else if (Array.isArray(value)) {\r\n return value.map(item => replace(item, depth + 1, undefined));\r\n } else if (value && typeof value === 'object') {\r\n const result: Record<string, any> = {};\r\n for (const [key, val] of Object.entries(value)) {\r\n result[key] = replace(val, depth + 1, key); // 传递当前字段名\r\n }\r\n return result;\r\n }\r\n return value;\r\n };\r\n\r\n return replace(obj);\r\n }\r\n\r\n /**\r\n * 计算引用解析统计\r\n */\r\n static calculateReferenceStats(\r\n refs: string[],\r\n context: ReferenceContext\r\n ): {\r\n total: number;\r\n resolved: number;\r\n failed: number;\r\n byType: { [key: string]: { total: number; resolved: number; failed: number } };\r\n } {\r\n const resolverRegistry = new ResolverRegistry();\r\n const stats = {\r\n total: refs.length,\r\n resolved: 0,\r\n failed: 0,\r\n byType: {} as { [key: string]: { total: number; resolved: number; failed: number } }\r\n };\r\n\r\n // 初始化按类型统计\r\n Object.values(ReferenceType).forEach(type => {\r\n stats.byType[type] = { total: 0, resolved: 0, failed: 0 };\r\n });\r\n\r\n console.log('🔍 calculateReferenceStats: 开始处理引用,总数=', refs.length);\r\n for (const ref of refs) {\r\n console.log('🔍 处理引用:', ref);\r\n const resolver = resolverRegistry.getResolverForRef(ref);\r\n if (resolver) {\r\n const type = resolver.type;\r\n stats.byType[type].total++;\r\n console.log(`🔍 找到解析器: type=${type}`);\r\n\r\n try {\r\n const result = resolver.resolve(ref, context);\r\n console.log(`🔍 引用解析成功: ${ref} =>`, result);\r\n stats.resolved++;\r\n stats.byType[type].resolved++;\r\n } catch (error) {\r\n console.error(`🔍 引用解析失败: ${ref}`, error);\r\n stats.failed++;\r\n stats.byType[type].failed++;\r\n }\r\n } else {\r\n console.log(`🔍 未找到解析器: ${ref}`);\r\n }\r\n }\r\n\r\n return stats;\r\n }\r\n\r\n /**\r\n * 检查引用是否存在\r\n */\r\n static checkReferenceExists(ref: string, context: ReferenceContext): boolean {\r\n const resolverRegistry = new ResolverRegistry();\r\n const resolver = resolverRegistry.getResolverForRef(ref);\r\n if (!resolver) {\r\n return false;\r\n }\r\n\r\n if (resolver.validate) {\r\n return resolver.validate(ref, context);\r\n }\r\n\r\n try {\r\n resolver.resolve(ref, context);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * 获取引用路径\r\n */\r\n static getReferencePath(ref: string): string[] {\r\n if (ref.startsWith('$')) {\r\n return ref.substring(1).split('.');\r\n }\r\n\r\n // 处理其他类型的引用\r\n const match = ref.match(/^(\\w+):(\\w+)$/);\r\n if (match) {\r\n return [match[1], match[2]];\r\n }\r\n\r\n return [ref];\r\n }\r\n\r\n /**\r\n * 创建引用\r\n */\r\n static createReference(type: ReferenceType, path: string[]): string {\r\n switch (type) {\r\n case ReferenceType.DESIGN_TOKEN:\r\n return `$${path.join('.')}`;\r\n case ReferenceType.STYLE_REF:\r\n return `styleRef:${path[0]}`;\r\n case ReferenceType.GEOMETRY_REF:\r\n return `geometryRef:${path[0]}`;\r\n case ReferenceType.TRANSFORM_REF:\r\n return `transformRef:${path[0]}`;\r\n case ReferenceType.LAYOUT_REF:\r\n return `layoutRef:${path[0]}`;\r\n default:\r\n return path.join(':');\r\n }\r\n }\r\n\r\n /**\r\n * 扁平化嵌套引用\r\n */\r\n static flattenNestedReferences(obj: any): string[] {\r\n const refs: string[] = [];\r\n\r\n const traverse = (value: any, path: string[] = []) => {\r\n if (typeof value === 'string') {\r\n refs.push(`${path.join('.')}=${value}`);\r\n } else if (Array.isArray(value)) {\r\n value.forEach((item, index) => {\r\n traverse(item, [...path, `[${index}]`]);\r\n });\r\n } else if (value && typeof value === 'object') {\r\n for (const [key, val] of Object.entries(value)) {\r\n traverse(val, [...path, key]);\r\n }\r\n }\r\n };\r\n\r\n traverse(obj);\r\n return refs;\r\n }\r\n}","/**\r\n * 性能工具\r\n *\r\n * 提供性能监控、测量和优化工具\r\n */\r\n\r\nimport type { PerformanceMark, PerformanceStats } from '../types';\r\nimport { PERFORMANCE_THRESHOLDS } from '../constants';\r\n\r\n/**\r\n * 性能监控器\r\n */\r\nexport class PerformanceMonitor {\r\n private marks: Map<string, PerformanceMark> = new Map();\r\n private stats: PerformanceStats = {\r\n totalTime: 0,\r\n referenceResolutionTime: 0,\r\n transformationTime: 0,\r\n validationTime: 0,\r\n memoryUsage: 0,\r\n referenceCount: 0\r\n };\r\n private memoryStart: number = 0;\r\n\r\n constructor() {\r\n this.startMemoryTracking();\r\n }\r\n\r\n /**\r\n * 开始性能标记\r\n */\r\n markStart(name: string): void {\r\n this.marks.set(name, {\r\n name,\r\n startTime: performance.now()\r\n });\r\n }\r\n\r\n /**\r\n * 结束性能标记\r\n */\r\n markEnd(name: string): void {\r\n const mark = this.marks.get(name);\r\n if (!mark) {\r\n console.warn(`性能标记未找到: ${name}`);\r\n return;\r\n }\r\n\r\n const endTime = performance.now();\r\n const duration = endTime - mark.startTime;\r\n\r\n mark.endTime = endTime;\r\n mark.duration = duration;\r\n\r\n // 更新统计\r\n this.updateStats(name, duration);\r\n }\r\n\r\n /**\r\n * 更新性能统计\r\n */\r\n private updateStats(name: string, duration: number): void {\r\n switch (name) {\r\n case 'reference-resolution':\r\n this.stats.referenceResolutionTime = duration;\r\n break;\r\n case 'transformation':\r\n this.stats.transformationTime = duration;\r\n break;\r\n case 'validation':\r\n this.stats.validationTime = duration;\r\n break;\r\n case 'total':\r\n this.stats.totalTime = duration;\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * 开始内存跟踪\r\n */\r\n private startMemoryTracking(): void {\r\n if (typeof performance !== 'undefined' && (performance as any).memory) {\r\n this.memoryStart = (performance as any).memory.usedJSHeapSize;\r\n }\r\n }\r\n\r\n /**\r\n * 结束内存跟踪\r\n */\r\n private endMemoryTracking(): void {\r\n if (typeof performance !== 'undefined' && (performance as any).memory) {\r\n const memoryEnd = (performance as any).memory.usedJSHeapSize;\r\n this.stats.memoryUsage = memoryEnd - this.memoryStart;\r\n }\r\n }\r\n\r\n /**\r\n * 设置引用计数\r\n */\r\n setReferenceCount(count: number): void {\r\n this.stats.referenceCount = count;\r\n }\r\n\r\n /**\r\n * 获取性能统计\r\n */\r\n getStats(): PerformanceStats {\r\n this.endMemoryTracking();\r\n return { ...this.stats };\r\n }\r\n\r\n /**\r\n * 获取所有性能标记\r\n */\r\n getMarks(): PerformanceMark[] {\r\n return Array.from(this.marks.values());\r\n }\r\n\r\n /**\r\n * 检查性能是否达标\r\n */\r\n checkPerformance(): { passed: boolean; warnings: string[] } {\r\n const warnings: string[] = [];\r\n\r\n // 检查转换时间\r\n if (this.stats.transformationTime > PERFORMANCE_THRESHOLDS.WARNING_TRANSFORMATION_TIME) {\r\n warnings.push(`转换时间较长: ${this.stats.transformationTime.toFixed(2)}ms (警告阈值: ${PERFORMANCE_THRESHOLDS.WARNING_TRANSFORMATION_TIME}ms)`);\r\n }\r\n\r\n if (this.stats.transformationTime > PERFORMANCE_THRESHOLDS.MAX_TRANSFORMATION_TIME) {\r\n warnings.push(`转换时间过长: ${this.stats.transformationTime.toFixed(2)}ms (最大阈值: ${PERFORMANCE_THRESHOLDS.MAX_TRANSFORMATION_TIME}ms)`);\r\n }\r\n\r\n // 检查内存使用\r\n if (this.stats.memoryUsage > PERFORMANCE_THRESHOLDS.MAX_MEMORY_INCREASE) {\r\n warnings.push(`内存增加过多: ${(this.stats.memoryUsage / 1024).toFixed(2)}KB (最大阈值: ${PERFORMANCE_THRESHOLDS.MAX_MEMORY_INCREASE / 1024}KB)`);\r\n }\r\n\r\n // 检查引用计数\r\n if (this.stats.referenceCount > PERFORMANCE_THRESHOLDS.MAX_REFERENCE_DEPTH * 10) {\r\n warnings.push(`引用数量较多: ${this.stats.referenceCount} (可能影响性能)`);\r\n }\r\n\r\n return {\r\n passed: warnings.length === 0,\r\n warnings\r\n };\r\n }\r\n\r\n /**\r\n * 重置性能监控器\r\n */\r\n reset(): void {\r\n this.marks.clear();\r\n this.stats = {\r\n totalTime: 0,\r\n referenceResolutionTime: 0,\r\n transformationTime: 0,\r\n validationTime: 0,\r\n memoryUsage: 0,\r\n referenceCount: 0\r\n };\r\n this.startMemoryTracking();\r\n }\r\n}\r\n\r\n/**\r\n * 性能测量装饰器\r\n */\r\nexport function measurePerformance(target: any, propertyKey: string, descriptor: PropertyDescriptor) {\r\n const originalMethod = descriptor.value;\r\n\r\n descriptor.value = function(...args: any[]) {\r\n const monitor = new PerformanceMonitor();\r\n monitor.markStart(propertyKey);\r\n\r\n try {\r\n const result = originalMethod.apply(this, args);\r\n\r\n // 处理异步方法\r\n if (result && typeof result.then === 'function') {\r\n return result.then((res: any) => {\r\n monitor.markEnd(propertyKey);\r\n console.log(`方法 ${propertyKey} 执行时间: ${monitor.getStats().totalTime.toFixed(2)}ms`);\r\n return res;\r\n });\r\n }\r\n\r\n // 同步方法\r\n monitor.markEnd(propertyKey);\r\n console.log(`方法 ${propertyKey} 执行时间: ${monitor.getStats().totalTime.toFixed(2)}ms`);\r\n return result;\r\n } catch (error) {\r\n monitor.markEnd(propertyKey);\r\n console.log(`方法 ${propertyKey} 执行时间: ${monitor.getStats().totalTime.toFixed(2)}ms (出错)`);\r\n throw error;\r\n }\r\n };\r\n\r\n return descriptor;\r\n}\r\n\r\n/**\r\n * 批量操作性能优化\r\n */\r\nexport class BatchProcessor {\r\n private batchSize: number;\r\n private delayMs: number;\r\n\r\n constructor(batchSize: number = 10, delayMs: number = 0) {\r\n this.batchSize = batchSize;\r\n this.delayMs = delayMs;\r\n }\r\n\r\n /**\r\n * 批量处理数组\r\n */\r\n async processBatch<T, R>(\r\n items: T[],\r\n processor: (item: T) => R | Promise<R>,\r\n options: {\r\n onProgress?: (processed: number, total: number) => void;\r\n onError?: (error: Error, item: T, index: number) => void;\r\n } = {}\r\n ): Promise<R[]> {\r\n const { onProgress, onError } = options;\r\n const results: R[] = [];\r\n const total = items.length;\r\n\r\n for (let i = 0; i < total; i += this.batchSize) {\r\n const batch = items.slice(i, i + this.batchSize);\r\n const batchPromises = batch.map((item, batchIndex) => {\r\n const index = i + batchIndex;\r\n try {\r\n const result = processor(item);\r\n return Promise.resolve(result)\r\n .then(res => ({ success: true, data: res, index }))\r\n .catch(error => {\r\n if (onError) {\r\n onError(error, item, index);\r\n }\r\n return { success: false, error, index };\r\n });\r\n } catch (error) {\r\n if (onError) {\r\n onError(error as Error, item, index);\r\n }\r\n return Promise.resolve({ success: false, error, index });\r\n }\r\n });\r\n\r\n const batchResults = await Promise.all(batchPromises);\r\n batchResults.forEach(result => {\r\n if (result.success) {\r\n // 类型守卫确保result有data属性\r\n results[result.index] = (result as any).data;\r\n }\r\n });\r\n\r\n if (onProgress) {\r\n onProgress(Math.min(i + this.batchSize, total), total);\r\n }\r\n\r\n if (this.delayMs > 0 && i + this.batchSize < total) {\r\n await new Promise(resolve => setTimeout(resolve, this.delayMs));\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n}\r\n\r\n/**\r\n * 内存优化工具\r\n */\r\nexport class MemoryOptimizer {\r\n /**\r\n * 浅拷贝对象(避免深拷贝的内存开销)\r\n */\r\n static shallowCopy<T>(obj: T): T {\r\n if (Array.isArray(obj)) {\r\n return [...obj] as T;\r\n } else if (obj && typeof obj === 'object') {\r\n return { ...obj } as T;\r\n }\r\n return obj;\r\n }\r\n\r\n /**\r\n * 选择性深拷贝(只拷贝需要的部分)\r\n */\r\n static selectiveDeepCopy<T>(obj: T, depth: number = 3): T {\r\n if (depth <= 0 || obj === null || typeof obj !== 'object') {\r\n return obj;\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(item => this.selectiveDeepCopy(item, depth - 1)) as T;\r\n }\r\n\r\n const result: Record<string, any> = {};\r\n for (const [key, value] of Object.entries(obj as object)) {\r\n // 跳过不需要深拷贝的大对象\r\n if (typeof value === 'object' && value !== null) {\r\n if (Array.isArray(value) && value.length > 100) {\r\n // 大数组使用浅拷贝\r\n result[key] = [...value];\r\n } else if (Object.keys(value).length > 50) {\r\n // 大对象使用浅拷贝\r\n result[key] = { ...value };\r\n } else {\r\n result[key] = this.selectiveDeepCopy(value, depth - 1);\r\n }\r\n } else {\r\n result[key] = value;\r\n }\r\n }\r\n\r\n return result as T;\r\n }\r\n\r\n /**\r\n * 清理未使用的引用\r\n */\r\n static cleanUnusedReferences(obj: any, usedRefs: Set<string>): any {\r\n const clean = (value: any): any => {\r\n if (typeof value === 'string' && value.startsWith('$')) {\r\n if (!usedRefs.has(value)) {\r\n return undefined; // 标记为删除\r\n }\r\n return value;\r\n } else if (Array.isArray(value)) {\r\n const cleaned = value.map(clean).filter(item => item !== undefined);\r\n return cleaned.length > 0 ? cleaned : undefined;\r\n } else if (value && typeof value === 'object') {\r\n const cleaned: Record<string, any> = {};\r\n let hasProperties = false;\r\n\r\n for (const [key, val] of Object.entries(value)) {\r\n const cleanedVal = clean(val);\r\n if (cleanedVal !== undefined) {\r\n cleaned[key] = cleanedVal;\r\n hasProperties = true;\r\n }\r\n }\r\n\r\n return hasProperties ? cleaned : undefined;\r\n }\r\n return value;\r\n };\r\n\r\n return clean(obj);\r\n }\r\n}","/**\r\n * TriangleAdapterV3 工具模块导出\r\n */\r\n\r\nexport * from './referenceUtils';\r\nexport * from './performanceUtils';\r\n\r\n/**\r\n * 通用工具函数\r\n */\r\nexport class CommonUtils {\r\n /**\r\n * 深度合并对象\r\n */\r\n static deepMerge(target: any, source: any): any {\r\n if (source === null || typeof source !== 'object') {\r\n return source;\r\n }\r\n\r\n if (Array.isArray(source)) {\r\n if (!Array.isArray(target)) {\r\n return [...source];\r\n }\r\n return target.map((item, index) =>\r\n index < source.length ? this.deepMerge(item, source[index]) : item\r\n );\r\n }\r\n\r\n const result = { ...target };\r\n for (const [key, value] of Object.entries(source)) {\r\n if (value === undefined) {\r\n continue;\r\n }\r\n\r\n if (key in result && typeof result[key] === 'object' && typeof value === 'object') {\r\n result[key] = this.deepMerge(result[key], value);\r\n } else {\r\n result[key] = value;\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 深度比较两个对象\r\n */\r\n static deepEqual(a: any, b: any): boolean {\r\n if (a === b) {\r\n return true;\r\n }\r\n\r\n if (typeof a !== typeof b) {\r\n return false;\r\n }\r\n\r\n if (typeof a !== 'object' || a === null || b === null) {\r\n return false;\r\n }\r\n\r\n if (Array.isArray(a) !== Array.isArray(b)) {\r\n return false;\r\n }\r\n\r\n if (Array.isArray(a)) {\r\n if (a.length !== b.length) {\r\n return false;\r\n }\r\n return a.every((item, index) => this.deepEqual(item, b[index]));\r\n }\r\n\r\n const aKeys = Object.keys(a);\r\n const bKeys = Object.keys(b);\r\n\r\n if (aKeys.length !== bKeys.length) {\r\n return false;\r\n }\r\n\r\n return aKeys.every(key => {\r\n if (!(key in b)) {\r\n return false;\r\n }\r\n return this.deepEqual(a[key], b[key]);\r\n });\r\n }\r\n\r\n /**\r\n * 安全获取嵌套属性值\r\n */\r\n static safeGet(obj: any, path: string | string[], defaultValue: any = undefined): any {\r\n const pathArray = Array.isArray(path) ? path : path.split('.');\r\n let current = obj;\r\n\r\n for (const key of pathArray) {\r\n if (current === null || current === undefined || typeof current !== 'object') {\r\n return defaultValue;\r\n }\r\n\r\n // 处理数组索引\r\n const arrayMatch = key.match(/^\\[(\\d+)\\]$/);\r\n if (arrayMatch && Array.isArray(current)) {\r\n const index = parseInt(arrayMatch[1], 10);\r\n current = current[index];\r\n } else {\r\n current = current[key];\r\n }\r\n }\r\n\r\n return current !== undefined ? current : defaultValue;\r\n }\r\n\r\n /**\r\n * 安全设置嵌套属性值\r\n */\r\n static safeSet(obj: any, path: string | string[], value: any): any {\r\n const pathArray = Array.isArray(path) ? path : path.split('.');\r\n const result = Array.isArray(obj) ? [...obj] : { ...obj };\r\n let current = result;\r\n\r\n for (let i = 0; i < pathArray.length - 1; i++) {\r\n const key = pathArray[i];\r\n const arrayMatch = key.match(/^\\[(\\d+)\\]$/);\r\n\r\n if (arrayMatch && Array.isArray(current)) {\r\n const index = parseInt(arrayMatch[1], 10);\r\n if (current[index] === undefined) {\r\n current[index] = {};\r\n }\r\n current = current[index];\r\n } else {\r\n if (current[key] === undefined) {\r\n const nextKey = pathArray[i + 1];\r\n const nextArrayMatch = nextKey.match(/^\\[(\\d+)\\]$/);\r\n current[key] = nextArrayMatch ? [] : {};\r\n }\r\n current = current[key];\r\n }\r\n }\r\n\r\n const lastKey = pathArray[pathArray.length - 1];\r\n const lastArrayMatch = lastKey.match(/^\\[(\\d+)\\]$/);\r\n\r\n if (lastArrayMatch && Array.isArray(current)) {\r\n const index = parseInt(lastArrayMatch[1], 10);\r\n current[index] = value;\r\n } else {\r\n current[lastKey] = value;\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 生成唯一ID\r\n */\r\n static generateId(prefix: string = 'id'): string {\r\n return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\r\n }\r\n\r\n /**\r\n * 节流函数\r\n */\r\n static throttle(\r\n func: (...args: any[]) => any,\r\n delay: number\r\n ): (...args: any[]) => void {\r\n let lastCall = 0;\r\n return (...args: any[]) => {\r\n const now = Date.now();\r\n if (now - lastCall >= delay) {\r\n lastCall = now;\r\n func(...args);\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * 防抖函数\r\n */\r\n static debounce(\r\n func: (...args: any[]) => any,\r\n delay: number\r\n ): (...args: any[]) => void {\r\n let timeoutId: NodeJS.Timeout;\r\n return (...args: any[]) => {\r\n clearTimeout(timeoutId);\r\n timeoutId = setTimeout(() => func(...args), delay);\r\n };\r\n }\r\n\r\n /**\r\n * 格式化字节大小\r\n */\r\n static formatBytes(bytes: number, decimals: number = 2): string {\r\n if (bytes === 0) return '0 Bytes';\r\n\r\n const k = 1024;\r\n const dm = decimals < 0 ? 0 : decimals;\r\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\r\n\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n\r\n return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];\r\n }\r\n\r\n /**\r\n * 计算对象大小(近似值)\r\n */\r\n static estimateObjectSize(obj: any): number {\r\n const visited = new Set<any>();\r\n\r\n const calculate = (value: any): number => {\r\n if (visited.has(value)) {\r\n return 0; // 避免循环引用\r\n }\r\n\r\n if (typeof value === 'string') {\r\n // 字符串不可变,不需要添加到visited检测循环引用\r\n return value.length * 2; // UTF-16 每个字符2字节\r\n } else if (typeof value === 'number') {\r\n return 8; // 64位浮点数\r\n } else if (typeof value === 'boolean') {\r\n return 4;\r\n } else if (value === null || value === undefined) {\r\n return 0;\r\n } else if (Array.isArray(value)) {\r\n visited.add(value);\r\n return value.reduce((sum: number, item) => sum + calculate(item), 0);\r\n } else if (typeof value === 'object') {\r\n visited.add(value);\r\n return Object.values(value).reduce((sum: number, item) => sum + calculate(item), 0);\r\n }\r\n\r\n return 0;\r\n };\r\n\r\n return calculate(obj);\r\n }\r\n}","/**\r\n * 同步适配器核心\r\n *\r\n * TriangleAdapterV3 的主适配器函数实现\r\n */\r\n\r\nimport type {\r\n RawTriangleProblemData,\r\n MathPracticeProblemData,\r\n SyncAdapterConfig,\r\n AdapterResult,\r\n AdapterWarning\r\n} from '../types';\r\n\r\nimport { AdapterError, AdapterErrorCode } from '../types';\r\n\r\nimport { DEFAULT_SYNC_ADAPTER_CONFIG } from '../types';\r\nimport { DEFAULT_FALLBACK_DATA, ERROR_MESSAGES } from '../constants';\r\n\r\nimport { getDefaultReferenceContext } from '../config';\r\nimport { createDefaultResolverRegistry } from '../resolvers';\r\nimport { createDefaultTransformerRegistry } from '../transformers';\r\nimport { ValidationManager } from '../validators';\r\nimport { ReferenceUtils, PerformanceMonitor, CommonUtils } from '../utils';\r\n\r\n/**\r\n * 同步适配器核心类\r\n */\r\nexport class SyncAdapterCore {\r\n private config: SyncAdapterConfig;\r\n private referenceContext: any;\r\n private resolverRegistry: any;\r\n private transformerRegistry: any;\r\n private performanceMonitor: PerformanceMonitor;\r\n\r\n constructor(config: SyncAdapterConfig = {}) {\r\n this.config = { ...DEFAULT_SYNC_ADAPTER_CONFIG, ...config };\r\n this.referenceContext = getDefaultReferenceContext();\r\n this.resolverRegistry = createDefaultResolverRegistry();\r\n this.transformerRegistry = createDefaultTransformerRegistry();\r\n this.performanceMonitor = new PerformanceMonitor();\r\n }\r\n\r\n /**\r\n * 主适配器函数\r\n */\r\n adapt(inputData: RawTriangleProblemData): AdapterResult {\r\n console.error('🔧 SyncAdapter.adapt called with inputData:', {\r\n math_prob_id: inputData?.math_prob_id,\r\n hasGeometryShapes: !!inputData?.geometry_shapes,\r\n geometryShapeKeys: inputData?.geometry_shapes ? Object.keys(inputData.geometry_shapes) : [],\r\n hasScenes: !!inputData?.scenes,\r\n sceneKeys: inputData?.scenes ? Object.keys(inputData.scenes) : []\r\n });\r\n\r\n this.performanceMonitor.markStart('total');\r\n\r\n try {\r\n // 1. 输入验证\r\n this.performanceMonitor.markStart('validation');\r\n const inputValidation = this.validateInput(inputData);\r\n if (!inputValidation.isValid && this.config.strictMode) {\r\n throw new AdapterError(\r\n AdapterErrorCode.INVALID_INPUT,\r\n ERROR_MESSAGES[AdapterErrorCode.INVALID_INPUT],\r\n { errors: inputValidation.errors }\r\n );\r\n }\r\n this.performanceMonitor.markEnd('validation');\r\n\r\n // 2. 基础数据转换\r\n this.performanceMonitor.markStart('base-transformation');\r\n const baseData = this.transformBaseData(inputData);\r\n this.performanceMonitor.markEnd('base-transformation');\r\n\r\n // 3. 引用解析(如果启用)\r\n let resolvedData = baseData;\r\n if (this.config.enableReferenceResolution) {\r\n this.performanceMonitor.markStart('reference-resolution');\r\n resolvedData = this.resolveReferences(baseData);\r\n this.performanceMonitor.markEnd('reference-resolution');\r\n }\r\n\r\n // 4. 场景内容转换\r\n this.performanceMonitor.markStart('scene-transformation');\r\n // 确保 basicInfo 已设置到 referenceContext(保险措施:已在 transformBaseData 中设置)\r\n if (!this.referenceContext.basicInfo && resolvedData.basicInfo) {\r\n this.referenceContext.basicInfo = resolvedData.basicInfo;\r\n }\r\n const transformedData = this.transformScenes(resolvedData);\r\n this.performanceMonitor.markEnd('scene-transformation');\r\n\r\n // 5. 输出验证\r\n this.performanceMonitor.markStart('output-validation');\r\n const outputValidation = this.validateOutput(transformedData);\r\n if (!outputValidation.isValid && this.config.strictMode) {\r\n throw new AdapterError(\r\n AdapterErrorCode.OUTPUT_VALIDATION_FAILED,\r\n ERROR_MESSAGES[AdapterErrorCode.OUTPUT_VALIDATION_FAILED],\r\n { errors: outputValidation.errors }\r\n );\r\n }\r\n this.performanceMonitor.markEnd('output-validation');\r\n\r\n // 6. 生成结果\r\n this.performanceMonitor.markEnd('total');\r\n console.error('🔧 adapt: transformedData before buildResult:', transformedData);\r\n console.error('🔧 adapt: transformedData.basicInfo:', transformedData.basicInfo);\r\n console.error('🔧 adapt: transformedData.basicInfo?.answerUnit:', transformedData.basicInfo?.answerUnit);\r\n const result = this.buildResult(transformedData, {\r\n inputValidation,\r\n outputValidation,\r\n inputWarnings: inputValidation.warnings,\r\n outputWarnings: outputValidation.warnings\r\n }, inputData);\r\n\r\n console.error('🔧 adapt: result.data.basicInfo:', result.data.basicInfo);\r\n console.error('🔧 adapt: result.data.basicInfo?.answerUnit:', result.data.basicInfo?.answerUnit);\r\n return result;\r\n\r\n } catch (error) {\r\n this.performanceMonitor.markEnd('total');\r\n\r\n // 处理错误\r\n // 如果启用了严格模式,总是抛出错误\r\n if (this.config.strictMode) {\r\n throw error;\r\n }\r\n\r\n // 非严格模式下,根据fallbackOnError决定是否使用回退数据\r\n if (this.config.fallbackOnError) {\r\n console.warn('适配失败,使用回退数据:', error);\r\n return this.createFallbackResult(inputData, error);\r\n }\r\n\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * 验证输入数据\r\n */\r\n private validateInput(inputData: any): { isValid: boolean; errors: string[]; warnings: string[] } {\r\n return ValidationManager.validateInput(inputData, {\r\n strictMode: this.config.strictMode || this.config.validationLevel === 'strict'\r\n });\r\n }\r\n\r\n /**\r\n * 从输入数据中提取几何定义到referenceContext(方案A修复)\r\n */\r\n private extractGeometryDefinitionsFromInput(inputData: RawTriangleProblemData): void {\r\n // 如果输入数据为空,直接返回\r\n if (!inputData) {\r\n console.error('⚠️ extractGeometryDefinitionsFromInput: inputData is null or undefined');\r\n return;\r\n }\r\n\r\n // 确保referenceContext有geometryPresets和transformDefinitions字段\r\n if (!this.referenceContext.geometryPresets) {\r\n this.referenceContext.geometryPresets = {};\r\n }\r\n if (!this.referenceContext.transformDefinitions) {\r\n this.referenceContext.transformDefinitions = {};\r\n }\r\n\r\n // 提取geometry_shapes(如果存在)\r\n if (inputData.geometry_shapes && typeof inputData.geometry_shapes === 'object') {\r\n console.error(`📦 Extracting geometry_shapes:`, Object.keys(inputData.geometry_shapes));\r\n // 合并几何形状预设\r\n Object.entries(inputData.geometry_shapes).forEach(([key, shape]) => {\r\n if (shape && typeof shape === 'object') {\r\n console.error(` 🔍 Processing geometry shape ${key}:`, {\r\n id: shape.id,\r\n type: shape.type,\r\n hasEndpoints: 'endpoints' in shape,\r\n endpoints: shape.endpoints,\r\n endpointsIsArray: Array.isArray(shape.endpoints),\r\n shapeKeys: Object.keys(shape)\r\n });\r\n // 深度复制并转换坐标格式\r\n const processedShape = this.convertGeometryShapeCoordinates(shape);\r\n console.error(` 📍 ${key}:`, { type: shape.type, position: shape.position, vertices: shape.vertices });\r\n this.referenceContext.geometryPresets[key] = processedShape;\r\n }\r\n });\r\n console.error(`✅ geometryPresets after extraction:`, Object.keys(this.referenceContext.geometryPresets));\r\n } else {\r\n console.error(`⚠️ No geometry_shapes found in input data`);\r\n }\r\n\r\n // 提取transform_definitions(如果存在)\r\n if (inputData.transform_definitions && typeof inputData.transform_definitions === 'object') {\r\n // 合并变换定义\r\n Object.entries(inputData.transform_definitions).forEach(([key, transform]) => {\r\n if (transform && typeof transform === 'object') {\r\n // 转换坐标格式\r\n const processedTransform = this.convertTransformDefinitionCoordinates(transform);\r\n this.referenceContext.transformDefinitions[key] = processedTransform;\r\n }\r\n });\r\n }\r\n\r\n // 提取点坐标信息:将原始JSON中的点定义提取为geometryRef引用\r\n // 处理scenes中的graph内容块\r\n if (inputData.scenes && typeof inputData.scenes === 'object') {\r\n Object.values(inputData.scenes).forEach((scene: any) => {\r\n if (scene && scene.content && Array.isArray(scene.content)) {\r\n scene.content.forEach((contentBlock: any) => {\r\n // 处理graph类型内容块中的点坐标\r\n if (contentBlock.type === 'graph' && contentBlock.shapes) {\r\n this.extractPointCoordinatesFromShapes(contentBlock.shapes);\r\n }\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * 从输入数据中提取几何变换配置到referenceContext\r\n * 用于几何变换定义与引用系统\r\n */\r\n private extractGeometryTransformConfigsFromInput(inputData: RawTriangleProblemData): void {\r\n // 如果输入数据为空,直接返回\r\n if (!inputData) {\r\n console.error('⚠️ extractGeometryTransformConfigsFromInput: inputData is null or undefined');\r\n return;\r\n }\r\n\r\n // 确保referenceContext有geometryTransformConfigs字段\r\n if (!this.referenceContext.geometryTransformConfigs) {\r\n this.referenceContext.geometryTransformConfigs = {};\r\n }\r\n\r\n // 提取geometry_transform_configs(如果存在)\r\n if (inputData.geometry_transform_configs && typeof inputData.geometry_transform_configs === 'object') {\r\n console.error(`📦 Extracting geometry_transform_configs:`, Object.keys(inputData.geometry_transform_configs));\r\n // 合并几何变换配置\r\n Object.entries(inputData.geometry_transform_configs).forEach(([key, config]) => {\r\n if (config && typeof config === 'object') {\r\n console.error(` 🔍 Processing geometry transform config ${key}:`, {\r\n id: config.id,\r\n strategy: config.strategy,\r\n hasBase: 'base' in config,\r\n hasHeight: 'height' in config,\r\n hasShapes: 'shapes' in config,\r\n hasTransform: 'transform' in config\r\n });\r\n this.referenceContext.geometryTransformConfigs![key] = config;\r\n }\r\n });\r\n console.error(`✅ geometryTransformConfigs after extraction:`, Object.keys(this.referenceContext.geometryTransformConfigs));\r\n } else {\r\n console.error(`⚠️ No geometry_transform_configs found in input data`);\r\n }\r\n }\r\n\r\n /**\r\n * 从输入数据中提取动画配置到referenceContext\r\n * 用于动画定义与引用系统\r\n */\r\n private extractAnimationConfigsFromInput(inputData: RawTriangleProblemData): void {\r\n // 如果输入数据为空,直接返回\r\n if (!inputData) {\r\n console.error('⚠️ extractAnimationConfigsFromInput: inputData is null or undefined');\r\n return;\r\n }\r\n\r\n // 确保referenceContext有animationConfigs字段\r\n if (!this.referenceContext.animationConfigs) {\r\n this.referenceContext.animationConfigs = {};\r\n }\r\n\r\n // 提取animation_configs(如果存在)\r\n if (inputData.animation_configs && typeof inputData.animation_configs === 'object') {\r\n console.error(`📦 Extracting animation_configs:`, Object.keys(inputData.animation_configs));\r\n // 合并动画配置\r\n Object.entries(inputData.animation_configs).forEach(([key, config]) => {\r\n if (config && typeof config === 'object') {\r\n console.error(` 🔍 Processing animation config ${key}:`, {\r\n id: (config as any).id,\r\n description: (config as any).description,\r\n hasTransforms: 'transforms' in config,\r\n hasVisualEffects: 'visualEffects' in config\r\n });\r\n this.referenceContext.animationConfigs![key] = config;\r\n }\r\n });\r\n console.error(`✅ animationConfigs after extraction:`, Object.keys(this.referenceContext.animationConfigs));\r\n } else {\r\n console.error(`⚠️ No animation_configs found in input data`);\r\n }\r\n }\r\n\r\n /**\r\n * 转换几何形状中的坐标格式(数组转对象)\r\n */\r\n private convertGeometryShapeCoordinates(shape: any): any {\r\n if (!shape || typeof shape !== 'object') {\r\n return shape;\r\n }\r\n\r\n console.error(`🔄 convertGeometryShapeCoordinates called for shape:`, {\r\n id: shape.id,\r\n type: shape.type,\r\n hasEndpoints: 'endpoints' in shape,\r\n endpoints: shape.endpoints,\r\n endpointsIsArray: Array.isArray(shape.endpoints),\r\n endpointsLength: shape.endpoints ? shape.endpoints.length : 0\r\n });\r\n\r\n const processedShape = { ...shape };\r\n\r\n // 将 segment 类型转换为 line(兼容 MathGraph)\r\n if (processedShape.type === 'segment') {\r\n console.error(`🔄 Converting segment to line for shape ${processedShape.id || 'unknown'}`);\r\n processedShape.type = 'line';\r\n }\r\n\r\n // 转换 position 字段(数组 [x, y] -> 对象 {x, y})\r\n if (Array.isArray(processedShape.position) && processedShape.position.length >= 2) {\r\n processedShape.position = {\r\n x: processedShape.position[0],\r\n y: processedShape.position[1]\r\n };\r\n }\r\n\r\n // 转换 vertices 字段(数组的数组 -> 对象数组)\r\n if (Array.isArray(processedShape.vertices)) {\r\n processedShape.vertices = processedShape.vertices.map((vertex: any) => {\r\n if (Array.isArray(vertex) && vertex.length >= 2) {\r\n return {\r\n x: vertex[0],\r\n y: vertex[1]\r\n };\r\n }\r\n // 如果已经是对象格式,保持原样\r\n return vertex;\r\n });\r\n }\r\n\r\n // 转换 endpoints 字段(数组的数组 -> 对象数组)\r\n if (Array.isArray(processedShape.endpoints)) {\r\n console.error(`🔄 Processing endpoints for shape ${processedShape.id || 'unknown'}:`, {\r\n endpointsLength: processedShape.endpoints.length,\r\n firstEndpoint: processedShape.endpoints[0],\r\n firstEndpointType: typeof processedShape.endpoints[0],\r\n firstEndpointIsArray: Array.isArray(processedShape.endpoints[0])\r\n });\r\n processedShape.endpoints = processedShape.endpoints.map((endpoint: any, index: number) => {\r\n if (Array.isArray(endpoint) && endpoint.length >= 2) {\r\n return {\r\n x: endpoint[0],\r\n y: endpoint[1]\r\n };\r\n }\r\n console.error(` Endpoint ${index} is not array:`, endpoint);\r\n return endpoint;\r\n });\r\n\r\n // 特殊处理:将 segment 类型转换为 line,并创建 start/end 属性\r\n if (processedShape.type === 'segment' && Array.isArray(processedShape.endpoints) && processedShape.endpoints.length === 2) {\r\n console.error(`🔄 Converting segment to line for shape ${processedShape.id || 'unknown'}`);\r\n processedShape.type = 'line';\r\n processedShape.start = processedShape.endpoints[0];\r\n processedShape.end = processedShape.endpoints[1];\r\n // 删除 endpoints 字段,因为 MathGraph 使用 start/end\r\n delete processedShape.endpoints;\r\n }\r\n } else if ('endpoints' in processedShape) {\r\n console.error(`⚠️ Shape ${processedShape.id || 'unknown'} has endpoints but not array:`, {\r\n endpoints: processedShape.endpoints,\r\n endpointsType: typeof processedShape.endpoints\r\n });\r\n }\r\n\r\n // 递归处理嵌套对象\r\n for (const [key, value] of Object.entries(processedShape)) {\r\n if (Array.isArray(value)) {\r\n processedShape[key] = value.map((item: any) => {\r\n // 检查是否为 $ref 引用对象,如果是则保持原样\r\n if (item && typeof item === 'object' && '$ref' in item) {\r\n return item; // 保留 $ref 引用,不进行转换\r\n }\r\n return typeof item === 'object' ? this.convertGeometryShapeCoordinates(item) : item;\r\n });\r\n } else if (value && typeof value === 'object') {\r\n // 检查是否为 $ref 引用对象,如果是则保持原样\r\n if ('$ref' in value) {\r\n processedShape[key] = value; // 保留 $ref 引用,不进行转换\r\n } else {\r\n processedShape[key] = this.convertGeometryShapeCoordinates(value);\r\n }\r\n }\r\n }\r\n\r\n console.error(`✅ convertGeometryShapeCoordinates result for ${shape.id}:`, {\r\n type: processedShape.type,\r\n hasEndpoints: 'endpoints' in processedShape,\r\n endpoints: processedShape.endpoints,\r\n endpointsIsArray: Array.isArray(processedShape.endpoints),\r\n endpointsLength: processedShape.endpoints ? processedShape.endpoints.length : 0,\r\n keys: Object.keys(processedShape)\r\n });\r\n\r\n return processedShape;\r\n }\r\n\r\n /**\r\n * 转换变换定义中的坐标格式\r\n */\r\n private convertTransformDefinitionCoordinates(transform: any): any {\r\n if (!transform || typeof transform !== 'object') {\r\n return transform;\r\n }\r\n\r\n const processedTransform = { ...transform };\r\n\r\n // 处理 config.center 字段 - 确保符合 GeometryTransform 的 RotationConfig 格式\r\n if (processedTransform.config && processedTransform.config.center) {\r\n const center = processedTransform.config.center;\r\n\r\n // 如果 center 是对象格式 {x, y},转换为数组 [x, y]\r\n if (center && typeof center === 'object' && 'x' in center && 'y' in center) {\r\n processedTransform.config.center = [center.x, center.y];\r\n }\r\n // 如果 center 是数组格式,保持原样(符合 RotationConfig 要求)\r\n // 如果 center 是字符串 'auto',保持原样\r\n }\r\n\r\n // 递归处理嵌套对象\r\n for (const [key, value] of Object.entries(processedTransform)) {\r\n if (Array.isArray(value)) {\r\n processedTransform[key] = value.map((item: any) =>\r\n typeof item === 'object' ? this.convertTransformDefinitionCoordinates(item) : item\r\n );\r\n } else if (value && typeof value === 'object') {\r\n processedTransform[key] = this.convertTransformDefinitionCoordinates(value);\r\n }\r\n }\r\n\r\n return processedTransform;\r\n }\r\n\r\n /**\r\n * 从图形数据中提取点坐标并转换为geometryRef\r\n */\r\n private extractPointCoordinatesFromShapes(shapes: any[]): void {\r\n if (!Array.isArray(shapes)) return;\r\n\r\n shapes.forEach((shape: any) => {\r\n if (shape && shape.type === 'point' && shape.position && Array.isArray(shape.position) && shape.position.length >= 2) {\r\n // 为点创建geometryRef引用\r\n const pointId = shape.id || `point_${shape.position[0]}_${shape.position[1]}`;\r\n this.referenceContext.geometryPresets[pointId] = {\r\n type: 'point',\r\n position: {\r\n x: shape.position[0],\r\n y: shape.position[1]\r\n }\r\n };\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * 转换基础数据\r\n */\r\n private transformBaseData(inputData: RawTriangleProblemData): any {\r\n // 如果输入数据为空,返回空的基础数据\r\n if (!inputData) {\r\n console.error('⚠️ transformBaseData: inputData is null or undefined');\r\n return {\r\n id: 'fallback-empty-input',\r\n title: '回退数据',\r\n grade: 5,\r\n unit: '未知单元',\r\n lesson: '未知课程',\r\n skill: '未知技能',\r\n objective: '未知目标',\r\n knowledgePoints: [],\r\n difficulty: 1,\r\n metadata: {},\r\n basicInfo: { question: '' },\r\n scenes: { question: { items: [] }, solve: { items: [] }, review: { items: [] } },\r\n explanation: { steps: [] },\r\n answer: { value: 0, unit: '', explanation: '' }\r\n };\r\n }\r\n\r\n // 提取JSON中的几何定义到referenceContext(方案A修复)\r\n this.extractGeometryDefinitionsFromInput(inputData);\r\n\r\n // 提取几何变换配置到referenceContext(几何变换定义与引用系统)\r\n this.extractGeometryTransformConfigsFromInput(inputData);\r\n\r\n // 提取动画配置到referenceContext(动画定义与引用系统)\r\n this.extractAnimationConfigsFromInput(inputData);\r\n\r\n // 转换字段名映射\r\n const transformed: any = {\r\n id: inputData.math_prob_id || CommonUtils.generateId('triangle'),\r\n title: inputData.title,\r\n grade: this.parseGrade(inputData.grade_id),\r\n unit: inputData.unit_name,\r\n lesson: inputData.lesson_name,\r\n skill: inputData.skill_description,\r\n objective: inputData.objective,\r\n knowledgePoints: inputData.knowledge_points || [],\r\n difficulty: inputData.difficulty || 1,\r\n metadata: this.transformMetadata(inputData),\r\n description: inputData.description,\r\n scenes: this.transformScenesStructure(inputData.scenes),\r\n answer: this.transformAnswer(inputData.answer_info),\r\n answer_info: this.transformAnswerInfo(inputData.answer_info)\r\n };\r\n\r\n // 添加可选字段\r\n const optionalFields = [\r\n 'unit_id', 'lesson_id', 'module_id', 'skill_item_id', 'skill_id',\r\n 'created_at', 'updated_at', 'layout'\r\n ];\r\n\r\n optionalFields.forEach(field => {\r\n if ((inputData as any)[field] !== undefined) {\r\n (transformed as any)[field] = (inputData as any)[field];\r\n }\r\n });\r\n\r\n // 关键:在转换 explanation 之前,先设置 basicInfo 到 referenceContext\r\n // 这样 GeometryTransformTransformer 在转换 explanation 时就能获取到 base/height\r\n console.error('🔧 transformBaseData: inputData.basic_info =', inputData.basic_info);\r\n const basicInfo = this.transformBasicInfo(inputData.basic_info);\r\n console.error('🔧 transformBaseData: basicInfo after transform =', basicInfo);\r\n console.error('🔧 transformBaseData: basicInfo.answerUnit =', basicInfo?.answerUnit);\r\n this.referenceContext.basicInfo = basicInfo;\r\n transformed.basicInfo = basicInfo;\r\n console.error('🔧 transformBaseData: transformed.basicInfo set =', transformed.basicInfo);\r\n\r\n // 现在转换 explanation(可以访问 basicInfo 了)\r\n transformed.explanation = this.transformExplanation(inputData.explanation);\r\n\r\n return transformed;\r\n }\r\n\r\n /**\r\n * 解析年级\r\n */\r\n private parseGrade(gradeId: string): number {\r\n const match = gradeId.match(/g(\\d+)/);\r\n return match ? parseInt(match[1], 10) : 5; // 默认5年级\r\n }\r\n\r\n /**\r\n * 转换元数据\r\n */\r\n private transformMetadata(inputData: RawTriangleProblemData): any {\r\n if (inputData.metadata && typeof inputData.metadata === 'object') {\r\n return inputData.metadata;\r\n }\r\n\r\n return {\r\n topic: inputData.unit_name || '三角形面积计算',\r\n skill: inputData.skill_description || '三角形面积求解技能',\r\n tags: inputData.knowledge_points || ['三角形面积公式']\r\n };\r\n }\r\n\r\n /**\r\n * 转换基础信息\r\n */\r\n private transformBasicInfo(basicInfo: any): any {\r\n console.error('🔄 transformBasicInfo called with:', basicInfo);\r\n if (!basicInfo || typeof basicInfo !== 'object') {\r\n console.error('⚠️ transformBasicInfo: basicInfo is empty, returning default');\r\n return { question: '' };\r\n }\r\n\r\n const transformed = { ...basicInfo };\r\n console.error('🔄 transformBasicInfo: transformed copy:', transformed);\r\n\r\n // 标准化字段名\r\n if (transformed.question === undefined && transformed.content !== undefined) {\r\n transformed.question = transformed.content;\r\n }\r\n\r\n // 确保 question 字段存在\r\n if (transformed.question === undefined) {\r\n transformed.question = '';\r\n }\r\n\r\n console.error('🔄 transformBasicInfo: returning:', transformed);\r\n return transformed;\r\n }\r\n\r\n /**\r\n * 转换场景结构\r\n * 支持新旧字段名:items(新)和content(旧)\r\n * 输出统一使用items字段(新标准)\r\n */\r\n private transformScenesStructure(scenes: any): any {\r\n if (!scenes || typeof scenes !== 'object') {\r\n return {\r\n question: { items: [] },\r\n solve: { items: [] },\r\n review: { items: [] }\r\n };\r\n }\r\n\r\n const transformedScenes: Record<string, any> = {};\r\n\r\n // 确保必需场景存在\r\n const requiredScenes = ['question', 'solve', 'review'];\r\n requiredScenes.forEach(sceneName => {\r\n if (scenes[sceneName]) {\r\n const scene = scenes[sceneName];\r\n // 支持items字段(新)和content字段(旧)\r\n const sceneItems = scene.items || scene.content || [];\r\n transformedScenes[sceneName] = {\r\n ...scene,\r\n items: sceneItems // 统一使用items字段输出(新标准)\r\n };\r\n // 如果原始有content字段,删除它以避免混淆\r\n if (scene.content !== undefined) {\r\n delete transformedScenes[sceneName].content;\r\n }\r\n } else {\r\n transformedScenes[sceneName] = { items: [] };\r\n }\r\n });\r\n\r\n // 添加可选场景\r\n const optionalScenes = ['remember'];\r\n optionalScenes.forEach(sceneName => {\r\n if (scenes[sceneName]) {\r\n const scene = scenes[sceneName];\r\n // 支持items字段(新)和content字段(旧)\r\n const sceneItems = scene.items || scene.content || [];\r\n transformedScenes[sceneName] = {\r\n ...scene,\r\n items: sceneItems // 统一使用items字段输出(新标准)\r\n };\r\n // 如果原始有content字段,删除它以避免混淆\r\n if (scene.content !== undefined) {\r\n delete transformedScenes[sceneName].content;\r\n }\r\n }\r\n });\r\n\r\n return transformedScenes;\r\n }\r\n\r\n /**\r\n * 转换解释\r\n */\r\n private transformExplanation(explanation: any): any {\r\n console.error(`🔄 transformExplanation called:`, {\r\n hasExplanation: !!explanation,\r\n isArray: Array.isArray(explanation),\r\n hasSteps: explanation && explanation.steps && Array.isArray(explanation.steps),\r\n stepsCount: explanation && explanation.steps ? explanation.steps.length : 0\r\n });\r\n\r\n if (!explanation) {\r\n return { steps: [] };\r\n }\r\n\r\n // 如果已经是数组,直接使用\r\n if (Array.isArray(explanation)) {\r\n return { steps: explanation };\r\n }\r\n\r\n // 如果是对象且有 steps 字段\r\n if (explanation.steps && Array.isArray(explanation.steps)) {\r\n console.error(`🔄 transformExplanation: processing ${explanation.steps.length} steps`);\r\n // 转换每个步骤中的 chartConfig\r\n const transformedSteps = explanation.steps.map((step: any, index: number) => {\r\n console.error(` Step ${index}: hasChartConfig=${!!step.chartConfig}`);\r\n return this.transformExplanationStep(step);\r\n });\r\n return {\r\n ...explanation,\r\n steps: transformedSteps\r\n };\r\n }\r\n\r\n // 其他情况创建空解释\r\n return { steps: [] };\r\n }\r\n\r\n /**\r\n * 转换解释步骤中的 chartConfig\r\n */\r\n private transformExplanationStep(step: any): any {\r\n if (!step || !step.chartConfig) {\r\n return step;\r\n }\r\n\r\n const chartConfig = step.chartConfig;\r\n const chartConfigType = chartConfig.type;\r\n\r\n console.error(`🔄 transformExplanationStep: step.title=${step.title}, chartConfigType=${chartConfigType}`);\r\n console.error(` chartConfig keys:`, Object.keys(chartConfig));\r\n\r\n // 检查是否为支持的图表类型\r\n if (chartConfigType !== 'graph' && chartConfigType !== 'geometryTransform') {\r\n console.warn(`⚠️ 不支持的 chartConfig 类型: ${chartConfigType},跳过转换`);\r\n return step;\r\n }\r\n\r\n try {\r\n // 将 chartConfig 包装成标准内容块格式\r\n const contentBlock = {\r\n type: chartConfigType,\r\n ...chartConfig\r\n };\r\n\r\n console.error(` contentBlock keys:`, Object.keys(contentBlock));\r\n if (chartConfigType === 'graph' && contentBlock.shapes) {\r\n console.error(` shapes count:`, contentBlock.shapes.length);\r\n if (contentBlock.shapes.length > 0) {\r\n console.error(` first shape:`, contentBlock.shapes[0]);\r\n }\r\n }\r\n\r\n // 调试:检查 referenceContext 中的 transformDefinitions\r\n console.error(`🔍 transformExplanationStep: referenceContext.transformDefinitions =`, this.referenceContext.transformDefinitions);\r\n console.error(`🔍 transformExplanationStep: transformDefinitions keys =`, this.referenceContext.transformDefinitions ? Object.keys(this.referenceContext.transformDefinitions) : []);\r\n\r\n // 使用 transformerRegistry 转换 chartConfig\r\n const transformedBlock = this.transformerRegistry.transform(\r\n contentBlock,\r\n this.referenceContext,\r\n {\r\n enableReferenceResolution: this.config.enableReferenceResolution,\r\n strictMode: this.config.strictMode\r\n }\r\n );\r\n\r\n console.error(` transformedBlock keys:`, Object.keys(transformedBlock));\r\n if (chartConfigType === 'graph' && transformedBlock.shapes) {\r\n console.error(` transformed shapes count:`, transformedBlock.shapes.length);\r\n }\r\n\r\n // 处理转换后的结构,确保 chartConfig 保持原始格式\r\n let transformedChartConfig;\r\n\r\n if (chartConfigType === 'geometryTransform' && transformedBlock.metadata && transformedBlock.metadata.config) {\r\n // 对于 geometryTransform 类型,保持原始的 metadata 结构\r\n // 不要重构,让 ContentRenderer 正常访问 metadata.config\r\n transformedChartConfig = transformedBlock;\r\n console.error(` geometryTransform preserved: metadata.config exists=${!!transformedChartConfig.metadata?.config}`);\r\n console.error(` geometryTransform preserved: step.title=${step.title}`);\r\n console.error(` geometryTransform preserved: config keys=`, Object.keys(transformedChartConfig.metadata?.config || {}));\r\n console.error(` geometryTransform preserved: config=`, transformedChartConfig.metadata?.config);\r\n } else if (chartConfigType === 'graph' && transformedBlock.boardConfig) {\r\n // 对于 explanation 中的 graph 类型,完全扁平化\r\n // 因为 ExplanationStep 和 SolveModule 都期望扁平结构\r\n const { boardConfig, ...rest } = transformedBlock;\r\n transformedChartConfig = {\r\n ...rest,\r\n // 将 boardConfig 的属性展开到顶层(不保留 boardConfig)\r\n ...boardConfig\r\n };\r\n console.error(` graph flattened: boundingBox=${transformedChartConfig.boundingBox}`);\r\n } else {\r\n transformedChartConfig = { ...transformedBlock };\r\n }\r\n\r\n // 返回更新后的步骤\r\n return {\r\n ...step,\r\n chartConfig: transformedChartConfig\r\n };\r\n } catch (error) {\r\n console.error(`❌ 转换解释步骤中的 chartConfig 失败:`, error);\r\n // 在非严格模式下,返回原始步骤\r\n if (this.config.strictMode) {\r\n throw error;\r\n }\r\n return step;\r\n }\r\n }\r\n\r\n /**\r\n * 转换答案\r\n */\r\n private transformAnswer(answerInfo: any): any {\r\n if (!answerInfo || typeof answerInfo !== 'object') {\r\n return {\r\n value: 0,\r\n unit: '',\r\n explanation: ''\r\n };\r\n }\r\n\r\n return {\r\n value: answerInfo.value || 0,\r\n unit: answerInfo.unit || '',\r\n explanation: answerInfo.explanation_text || ''\r\n };\r\n }\r\n\r\n /**\r\n * 转换答案信息(扩展)\r\n */\r\n private transformAnswerInfo(answerInfo: any): any {\r\n if (!answerInfo || typeof answerInfo !== 'object') {\r\n return undefined;\r\n }\r\n\r\n return {\r\n ...answerInfo,\r\n explanation_text: answerInfo.explanation_text || ''\r\n };\r\n }\r\n\r\n /**\r\n * 解析引用\r\n */\r\n private resolveReferences(data: any): any {\r\n // 提取所有引用\r\n const allRefs = this.resolverRegistry.extractAllRefs(data);\r\n this.performanceMonitor.setReferenceCount(allRefs.length);\r\n\r\n // 批量解析引用\r\n const _resolvedRefs = this.resolverRegistry.batchResolve(allRefs, this.referenceContext);\r\n\r\n // 替换引用\r\n return ReferenceUtils.replaceReferences(data, this.referenceContext, {\r\n strictMode: this.config.strictMode,\r\n onMissing: (ref) => {\r\n console.warn(`引用未找到: ${ref}`);\r\n return ref; // 保留原始引用\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * 转换场景内容\r\n */\r\n private transformScenes(data: any): any {\r\n const transformedData = { ...data };\r\n\r\n if (transformedData.scenes && typeof transformedData.scenes === 'object') {\r\n console.error('🔄 transformScenes: starting scene transformation');\r\n console.error(' - referenceContext.geometryPresets keys:', Object.keys(this.referenceContext.geometryPresets || {}));\r\n console.error(' - enableReferenceResolution:', this.config.enableReferenceResolution);\r\n\r\n transformedData.scenes = this.transformerRegistry.transformScenes(\r\n transformedData.scenes,\r\n this.referenceContext,\r\n {\r\n enableReferenceResolution: this.config.enableReferenceResolution,\r\n strictMode: this.config.strictMode\r\n }\r\n );\r\n\r\n console.error('✅ transformScenes: completed scene transformation');\r\n }\r\n\r\n return transformedData;\r\n }\r\n\r\n /**\r\n * 验证输出数据\r\n */\r\n private validateOutput(outputData: any): { isValid: boolean; errors: string[]; warnings: string[] } {\r\n return ValidationManager.validateOutput(outputData, {\r\n strictMode: this.config.strictMode || this.config.validationLevel === 'strict'\r\n });\r\n }\r\n\r\n /**\r\n * 构建结果\r\n */\r\n private buildResult(\r\n data: MathPracticeProblemData,\r\n meta: {\r\n inputValidation: { errors: string[]; warnings: string[] };\r\n outputValidation: { errors: string[]; warnings: string[] };\r\n inputWarnings: string[];\r\n outputWarnings: string[];\r\n },\r\n inputData?: RawTriangleProblemData\r\n ): AdapterResult {\r\n const performanceStats = this.performanceMonitor.getStats();\r\n const performanceCheck = this.performanceMonitor.checkPerformance();\r\n\r\n // 构建警告列表\r\n const warnings: AdapterWarning[] = [\r\n ...meta.inputValidation.warnings.map(msg => ({\r\n code: AdapterErrorCode.INVALID_INPUT,\r\n message: `输入验证警告: ${msg}`,\r\n suggestion: '检查输入数据格式'\r\n })),\r\n ...meta.outputValidation.warnings.map(msg => ({\r\n code: AdapterErrorCode.OUTPUT_VALIDATION_FAILED,\r\n message: `输出验证警告: ${msg}`,\r\n suggestion: '检查数据转换逻辑'\r\n })),\r\n ...performanceCheck.warnings.map(msg => ({\r\n code: AdapterErrorCode.TRANSFORMATION_FAILED,\r\n message: `性能警告: ${msg}`,\r\n suggestion: '优化数据转换性能'\r\n }))\r\n ];\r\n\r\n // 计算引用统计(如果启用引用解析)\r\n // 使用原始输入数据计算引用,以便统计所有原始引用\r\n const refSource = inputData || data;\r\n const allRefs = this.config.enableReferenceResolution\r\n ? this.resolverRegistry.extractAllRefs(refSource)\r\n : [];\r\n const referenceStats = ReferenceUtils.calculateReferenceStats(allRefs, this.referenceContext);\r\n\r\n return {\r\n data,\r\n warnings,\r\n performance: performanceStats,\r\n referenceStats: {\r\n total: referenceStats.total,\r\n resolved: referenceStats.resolved,\r\n failed: referenceStats.failed,\r\n byType: referenceStats.byType\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * 创建回退结果\r\n */\r\n private createFallbackResult(inputData: any, error: any): AdapterResult {\r\n const fallbackData = {\r\n ...DEFAULT_FALLBACK_DATA,\r\n id: inputData?.math_prob_id || DEFAULT_FALLBACK_DATA.id,\r\n title: inputData?.title || DEFAULT_FALLBACK_DATA.title\r\n };\r\n\r\n const warning: AdapterWarning = {\r\n code: AdapterErrorCode.TRANSFORMATION_FAILED,\r\n message: `适配失败,使用回退数据: ${error.message}`,\r\n suggestion: '检查输入数据格式和适配器配置'\r\n };\r\n\r\n return {\r\n data: fallbackData as unknown as MathPracticeProblemData,\r\n warnings: [warning],\r\n performance: this.performanceMonitor.getStats(),\r\n referenceStats: {\r\n total: 0,\r\n resolved: 0,\r\n failed: 0,\r\n byType: {}\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * 获取性能统计\r\n */\r\n getPerformanceStats() {\r\n return this.performanceMonitor.getStats();\r\n }\r\n\r\n /**\r\n * 重置适配器状态\r\n */\r\n reset() {\r\n this.performanceMonitor.reset();\r\n }\r\n}\r\n\r\n/**\r\n * 主适配器函数\r\n */\r\nexport function adaptTriangleDataSync(\r\n inputData: RawTriangleProblemData,\r\n config?: SyncAdapterConfig\r\n): MathPracticeProblemData {\r\n console.error('🔧 adaptTriangleDataSync called with inputData:', {\r\n math_prob_id: inputData?.math_prob_id,\r\n hasBasicInfo: !!inputData?.basic_info,\r\n basicInfo: inputData?.basic_info\r\n });\r\n const adapter = new SyncAdapterCore(config);\r\n const result = adapter.adapt(inputData);\r\n console.error('🔧 adaptTriangleDataSync result data:', {\r\n id: result.data.id,\r\n hasBasicInfo: !!result.data.basicInfo,\r\n basicInfo: result.data.basicInfo\r\n });\r\n return result.data;\r\n}\r\n\r\n/**\r\n * 创建适配器工厂函数\r\n */\r\nexport function createSyncAdapter(config?: SyncAdapterConfig) {\r\n const adapter = new SyncAdapterCore(config);\r\n return (inputData: RawTriangleProblemData) => adapter.adapt(inputData).data;\r\n}","/**\n * 几何适配器核心\n *\n * GeometryProblemAdapterV4 的主适配器函数实现\n * 基于 TriangleAdapterV3 重构,支持多种几何形状的 V4 格式数据。\n */\n\nimport type {\n GeometryProblemDataV4,\n MathPracticeProblemData,\n SyncAdapterConfig,\n AdapterResult,\n AdapterWarning,\n ReferenceContext\n} from './types';\n\nimport type {\n GeometryShapeDefinition,\n TransformDefinition,\n AnswerInfo,\n ExplanationData,\n ExplanationStep,\n AnimationConfigs,\n GeometryTransformConfig,\n SceneDefinition,\n ProblemMetadata,\n LayoutConfig\n} from './geometry-types';\n\nimport { AdapterErrorCode } from './types';\nimport { DEFAULT_SYNC_ADAPTER_CONFIG } from './types';\n\n// 注意:由于需要复用现有工具,我们可能需要从 TriangleAdapterV3 导入一些模块\n// 暂时导入,后续考虑重构为通用工具\nimport { DEFAULT_FALLBACK_DATA } from '../TriangleAdapterV3/constants';\nimport { getDefaultReferenceContext } from '../TriangleAdapterV3/config';\nimport { createDefaultResolverRegistry } from '../TriangleAdapterV3/resolvers';\nimport { createDefaultTransformerRegistry } from '../TriangleAdapterV3/transformers';\nimport { ValidationManager } from '../TriangleAdapterV3/validators';\nimport { ReferenceUtils, PerformanceMonitor } from '../TriangleAdapterV3/utils';\n\n// 导入专业同步适配器\nimport { SyncAdapterCore } from '../TriangleAdapterV3/core/syncAdapter';\nimport type { RawTriangleProblemData } from '../TriangleAdapterV3/types';\n\n/**\n * 同步适配器核心类\n */\nexport class GeometryAdapterCore {\n private config: SyncAdapterConfig;\n private referenceContext: ReferenceContext;\n private resolverRegistry: any;\n private transformerRegistry: any;\n private performanceMonitor: PerformanceMonitor;\n private syncAdapter: SyncAdapterCore;\n\n constructor(config: SyncAdapterConfig = {}) {\n this.config = { ...DEFAULT_SYNC_ADAPTER_CONFIG, ...config };\n this.referenceContext = getDefaultReferenceContext();\n this.resolverRegistry = createDefaultResolverRegistry();\n this.transformerRegistry = createDefaultTransformerRegistry();\n this.performanceMonitor = new PerformanceMonitor();\n // 创建专业同步适配器实例\n this.syncAdapter = new SyncAdapterCore(config);\n }\n\n /**\n * 主适配器函数\n * 使用专业的 TriangleAdapterV3 同步适配器处理几何问题数据\n */\n adapt(inputData: GeometryProblemDataV4): AdapterResult {\n if (this.config.enableLogging) {\n console.log('🔧 GeometryAdapter.adapt called with inputData (delegating to SyncAdapterCore):', {\n math_prob_id: inputData?.math_prob_id,\n schema_version: inputData?.schema_version,\n shape: inputData?.basic_info?.shape,\n hasGeometryShapes: !!inputData?.geometry_shapes,\n geometryShapeKeys: inputData?.geometry_shapes ? Object.keys(inputData.geometry_shapes) : [],\n hasScenes: !!inputData?.scenes,\n sceneKeys: inputData?.scenes ? Object.keys(inputData.scenes) : []\n });\n }\n\n this.performanceMonitor.markStart('total');\n\n try {\n // 将 GeometryProblemDataV4 转换为 RawTriangleProblemData(类型断言,字段兼容)\n const rawData = inputData as unknown as RawTriangleProblemData;\n\n // 使用专业的 SyncAdapterCore 进行适配\n const result = this.syncAdapter.adapt(rawData);\n\n this.performanceMonitor.markEnd('total');\n\n if (this.config.enableLogging) {\n console.log('✅ GeometryAdapter.adapt completed successfully:', {\n id: result.data.id,\n hasBasicInfo: !!result.data.basicInfo,\n warningCount: result.warnings.length,\n referenceStats: result.referenceStats\n });\n }\n\n return result;\n\n } catch (error) {\n this.performanceMonitor.markEnd('total');\n\n // 处理错误\n // 如果启用了严格模式,总是抛出错误\n if (this.config.strictMode) {\n throw error;\n }\n\n // 非严格模式下,根据fallbackOnError决定是否使用回退数据\n if (this.config.fallbackOnError) {\n console.warn('适配失败,使用回退数据:', error);\n return this.createFallbackResult(inputData, error);\n }\n\n throw error;\n }\n }\n\n /**\n * 验证输入数据\n */\n private _validateInput(inputData: any): { isValid: boolean; errors: string[]; warnings: string[] } {\n return ValidationManager.validateInput(inputData, {\n strictMode: this.config.strictMode || this.config.validationLevel === 'strict'\n });\n }\n\n /**\n * 从输入数据中提取几何定义到referenceContext\n */\n private extractGeometryDefinitionsFromInput(inputData: GeometryProblemDataV4): void {\n // 如果输入数据为空,直接返回\n if (!inputData) {\n if (this.config.enableLogging) {\n console.error('⚠️ extractGeometryDefinitionsFromInput: inputData is null or undefined');\n }\n return;\n }\n\n // 确保referenceContext有geometryPresets和transformDefinitions字段\n if (!this.referenceContext.geometryPresets) {\n this.referenceContext.geometryPresets = {};\n }\n if (!this.referenceContext.transformDefinitions) {\n this.referenceContext.transformDefinitions = {};\n }\n\n // 提取geometry_shapes(如果存在)\n if (inputData.geometry_shapes && typeof inputData.geometry_shapes === 'object') {\n if (this.config.enableLogging) {\n console.log(`📦 Extracting geometry_shapes:`, Object.keys(inputData.geometry_shapes));\n }\n // 合并几何形状预设\n Object.entries(inputData.geometry_shapes).forEach(([key, shape]) => {\n if (shape && typeof shape === 'object') {\n // 深度复制并转换坐标格式\n const processedShape = this.convertGeometryShapeCoordinates(shape as GeometryShapeDefinition);\n this.referenceContext.geometryPresets[key] = processedShape;\n }\n });\n if (this.config.enableLogging) {\n console.log(`✅ geometryPresets after extraction:`, Object.keys(this.referenceContext.geometryPresets));\n }\n } else if (this.config.enableLogging) {\n console.log(`⚠️ No geometry_shapes found in input data`);\n }\n\n // 提取transform_definitions(如果存在)\n if (inputData.transform_definitions && typeof inputData.transform_definitions === 'object') {\n // 合并变换定义\n if (!this.referenceContext.transformDefinitions) {\n this.referenceContext.transformDefinitions = {};\n }\n Object.entries(inputData.transform_definitions).forEach(([key, transform]) => {\n if (transform && typeof transform === 'object') {\n // 转换坐标格式\n const processedTransform = this.convertTransformDefinitionCoordinates(transform as TransformDefinition);\n this.referenceContext.transformDefinitions![key] = processedTransform;\n }\n });\n }\n\n // 提取点坐标信息:将原始JSON中的点定义提取为geometryRef引用\n // 这里复用现有逻辑,暂不修改\n }\n\n /**\n * 转换答案\n */\n private transformAnswer(answerInfo: AnswerInfo | undefined | null): { value: number; unit: string; explanation: string } {\n if (!answerInfo || typeof answerInfo !== 'object') {\n return {\n value: 0,\n unit: '',\n explanation: ''\n };\n }\n\n return {\n value: answerInfo.value || 0,\n unit: answerInfo.unit || '',\n explanation: answerInfo.explanation_text || ''\n };\n }\n\n /**\n * 转换答案信息(扩展)\n */\n private transformAnswerInfo(answerInfo: AnswerInfo | undefined | null): AnswerInfo | undefined {\n if (!answerInfo || typeof answerInfo !== 'object') {\n return undefined;\n }\n\n return {\n ...answerInfo,\n explanation_text: answerInfo.explanation_text || ''\n };\n }\n\n /**\n * 转换解释\n */\n private transformExplanation(explanation: ExplanationData | ExplanationStep[] | undefined | null): ExplanationData {\n if (this.config.enableLogging) {\n console.log(`🔄 transformExplanation called:`, {\n hasExplanation: !!explanation,\n isArray: Array.isArray(explanation),\n hasSteps: explanation && !Array.isArray(explanation) && explanation.steps && Array.isArray(explanation.steps),\n stepsCount: explanation ? (Array.isArray(explanation) ? explanation.length : (explanation.steps ? explanation.steps.length : 0)) : 0\n });\n }\n\n if (!explanation) {\n return { steps: [] };\n }\n\n // 如果已经是数组,直接使用\n if (Array.isArray(explanation)) {\n return { steps: explanation };\n }\n\n // 如果是对象且有 steps 字段\n if (explanation.steps && Array.isArray(explanation.steps)) {\n if (this.config.enableLogging) {\n console.log(`🔄 transformExplanation: processing ${explanation.steps.length} steps`);\n }\n // 转换每个步骤中的 chartConfig\n const transformedSteps = explanation.steps.map((step: ExplanationStep, index: number) => {\n if (this.config.enableLogging) {\n console.log(` Step ${index}: hasChartConfig=${!!step.chartConfig}`);\n }\n return this.transformExplanationStep(step);\n });\n return {\n ...explanation,\n steps: transformedSteps\n };\n }\n\n // 其他情况创建空解释\n return { steps: [] };\n }\n\n /**\n * 转换解释步骤中的 chartConfig\n */\n private transformExplanationStep(step: ExplanationStep): ExplanationStep {\n if (!step || !step.chartConfig) {\n return step;\n }\n\n const chartConfig = step.chartConfig;\n const chartConfigType = chartConfig.type;\n\n if (this.config.enableLogging) {\n console.log(`🔄 transformExplanationStep: step.title=${step.title}, chartConfigType=${chartConfigType}`);\n console.log(` chartConfig keys:`, Object.keys(chartConfig));\n }\n\n // 检查是否为支持的图表类型\n if (chartConfigType !== 'graph' && chartConfigType !== 'geometryTransform') {\n if (this.config.enableLogging) {\n console.warn(`⚠️ 不支持的 chartConfig 类型: ${chartConfigType},跳过转换`);\n }\n return step;\n }\n\n try {\n // 将 chartConfig 包装成标准内容块格式\n const contentBlock = {\n ...chartConfig,\n type: chartConfigType // 确保 type 使用 chartConfigType,覆盖 chartConfig 中的 type(如果有)\n };\n\n if (this.config.enableLogging) {\n console.log(` contentBlock keys:`, Object.keys(contentBlock));\n if (chartConfigType === 'graph' && contentBlock.shapes) {\n console.log(` shapes count:`, contentBlock.shapes.length);\n if (contentBlock.shapes.length > 0) {\n console.log(` first shape:`, contentBlock.shapes[0]);\n }\n }\n }\n\n // 调试:检查 referenceContext 中的 transformDefinitions\n if (this.config.enableLogging) {\n console.log(`🔍 transformExplanationStep: referenceContext.transformDefinitions =`, this.referenceContext.transformDefinitions);\n console.log(`🔍 transformExplanationStep: transformDefinitions keys =`, this.referenceContext.transformDefinitions ? Object.keys(this.referenceContext.transformDefinitions) : []);\n }\n\n // 使用 transformerRegistry 转换 chartConfig\n const transformedBlock = this.transformerRegistry.transform(\n contentBlock,\n this.referenceContext,\n {\n enableReferenceResolution: this.config.enableReferenceResolution,\n strictMode: this.config.strictMode\n }\n );\n\n if (this.config.enableLogging) {\n console.log(` transformedBlock keys:`, Object.keys(transformedBlock));\n if (chartConfigType === 'graph' && transformedBlock.shapes) {\n console.log(` transformed shapes count:`, transformedBlock.shapes.length);\n }\n }\n\n // 处理转换后的结构,确保 chartConfig 保持原始格式\n let transformedChartConfig;\n\n if (chartConfigType === 'geometryTransform' && transformedBlock.metadata && transformedBlock.metadata.config) {\n // 对于 geometryTransform 类型,保持原始的 metadata 结构\n // 不要重构,让 ContentRenderer 正常访问 metadata.config\n transformedChartConfig = transformedBlock;\n if (this.config.enableLogging) {\n console.log(` geometryTransform preserved: metadata.config exists=${!!transformedChartConfig.metadata?.config}`);\n console.log(` geometryTransform preserved: step.title=${step.title}`);\n console.log(` geometryTransform preserved: config keys=`, Object.keys(transformedChartConfig.metadata?.config || {}));\n console.log(` geometryTransform preserved: config=`, transformedChartConfig.metadata?.config);\n }\n } else if (chartConfigType === 'graph' && transformedBlock.boardConfig) {\n // 对于 explanation 中的 graph 类型,完全扁平化\n // 因为 ExplanationStep 和 SolveModule 都期望扁平结构\n const { boardConfig, ...rest } = transformedBlock;\n transformedChartConfig = {\n ...rest,\n // 将 boardConfig 的属性展开到顶层(不保留 boardConfig)\n ...boardConfig\n };\n if (this.config.enableLogging) {\n console.log(` graph flattened: boundingBox=${transformedChartConfig.boundingBox}`);\n }\n } else {\n transformedChartConfig = { ...transformedBlock };\n }\n\n // 返回更新后的步骤\n return {\n ...step,\n chartConfig: transformedChartConfig\n };\n } catch (error) {\n if (this.config.enableLogging) {\n console.error(`❌ 转换解释步骤中的 chartConfig 失败:`, error);\n }\n // 在非严格模式下,返回原始步骤\n if (this.config.strictMode) {\n throw error;\n }\n return step;\n }\n }\n\n /**\n * 转换几何形状中的坐标格式(数组转对象)\n */\n private convertGeometryShapeCoordinates(shape: GeometryShapeDefinition): GeometryShapeDefinition {\n if (!shape || typeof shape !== 'object') {\n return shape;\n }\n\n if (this.config.enableLogging) {\n console.log(`🔄 convertGeometryShapeCoordinates called for shape:`, {\n id: shape.id,\n type: shape.type,\n hasEndpoints: 'endpoints' in shape,\n endpoints: shape.endpoints,\n endpointsIsArray: Array.isArray(shape.endpoints),\n endpointsLength: shape.endpoints ? shape.endpoints.length : 0\n });\n }\n\n const processedShape = { ...shape };\n\n // 将 segment 类型转换为 line(兼容 MathGraph)\n if (processedShape.type === 'segment') {\n if (this.config.enableLogging) {\n console.log(`🔄 Converting segment to line for shape ${processedShape.id || 'unknown'}`);\n }\n processedShape.type = 'line';\n }\n\n // 转换 position 字段(数组 [x, y] -> 对象 {x, y})\n if (Array.isArray(processedShape.position) && processedShape.position.length >= 2) {\n processedShape.position = {\n x: processedShape.position[0],\n y: processedShape.position[1]\n };\n }\n\n // 转换 vertices 字段(数组的数组 -> 对象数组)\n if (Array.isArray(processedShape.vertices)) {\n processedShape.vertices = processedShape.vertices.map((vertex: any) => {\n if (Array.isArray(vertex) && vertex.length >= 2) {\n return {\n x: vertex[0],\n y: vertex[1]\n };\n }\n // 如果已经是对象格式,保持原样\n return vertex;\n });\n }\n\n // 转换 endpoints 字段(数组的数组 -> 对象数组)\n if (Array.isArray(processedShape.endpoints)) {\n if (this.config.enableLogging) {\n console.log(`🔄 Processing endpoints for shape ${processedShape.id || 'unknown'}:`, {\n endpointsLength: processedShape.endpoints.length,\n firstEndpoint: processedShape.endpoints[0],\n firstEndpointType: typeof processedShape.endpoints[0],\n firstEndpointIsArray: Array.isArray(processedShape.endpoints[0])\n });\n }\n processedShape.endpoints = processedShape.endpoints.map((endpoint: any, index: number) => {\n if (Array.isArray(endpoint) && endpoint.length >= 2) {\n return {\n x: endpoint[0],\n y: endpoint[1]\n };\n }\n if (this.config.enableLogging) {\n console.log(` Endpoint ${index} is not array:`, endpoint);\n }\n return endpoint;\n });\n\n // 特殊处理:将 segment 类型转换为 line,并创建 start/end 属性\n if (processedShape.type === 'line' && Array.isArray(processedShape.endpoints) && processedShape.endpoints.length === 2) {\n if (this.config.enableLogging) {\n console.log(`🔄 Converting segment to line for shape ${processedShape.id || 'unknown'}`);\n }\n processedShape.type = 'line';\n processedShape.start = processedShape.endpoints[0];\n processedShape.end = processedShape.endpoints[1];\n // 删除 endpoints 字段,因为 MathGraph 使用 start/end\n delete processedShape.endpoints;\n }\n } else if ('endpoints' in processedShape) {\n if (this.config.enableLogging) {\n console.log(`⚠️ Shape ${processedShape.id || 'unknown'} has endpoints but not array:`, {\n endpoints: processedShape.endpoints,\n endpointsType: typeof processedShape.endpoints\n });\n }\n }\n\n // 递归处理嵌套对象\n for (const [key, value] of Object.entries(processedShape)) {\n if (Array.isArray(value)) {\n processedShape[key] = value.map((item: any) => {\n // 检查是否为 $ref 引用对象,如果是则保持原样\n if (item && typeof item === 'object' && '$ref' in item) {\n return item; // 保留 $ref 引用,不进行转换\n }\n return typeof item === 'object' ? this.convertGeometryShapeCoordinates(item) : item;\n });\n } else if (value && typeof value === 'object') {\n // 检查是否为 $ref 引用对象,如果是则保持原样\n if ('$ref' in value) {\n processedShape[key] = value; // 保留 $ref 引用,不进行转换\n } else {\n processedShape[key] = this.convertGeometryShapeCoordinates(value);\n }\n }\n }\n\n if (this.config.enableLogging) {\n console.log(`✅ convertGeometryShapeCoordinates result for ${shape.id}:`, {\n type: processedShape.type,\n hasEndpoints: 'endpoints' in processedShape,\n endpoints: processedShape.endpoints,\n endpointsIsArray: Array.isArray(processedShape.endpoints),\n endpointsLength: processedShape.endpoints ? processedShape.endpoints.length : 0,\n keys: Object.keys(processedShape)\n });\n }\n\n return processedShape;\n }\n\n /**\n * 转换变换定义中的坐标格式\n */\n private convertTransformDefinitionCoordinates(transform: TransformDefinition): TransformDefinition {\n if (!transform || typeof transform !== 'object') {\n return transform;\n }\n\n const processedTransform: Record<string, any> = { ...transform };\n\n // 处理 config.center 字段 - 确保符合 GeometryTransform 的 RotationConfig 格式\n if (processedTransform.config && processedTransform.config.center) {\n const center = processedTransform.config.center;\n\n // 如果 center 是对象格式 {x, y},转换为数组 [x, y]\n if (center && typeof center === 'object' && 'x' in center && 'y' in center) {\n processedTransform.config.center = [center.x, center.y];\n }\n // 如果 center 是数组格式,保持原样(符合 RotationConfig 要求)\n // 如果 center 是字符串 'auto',保持原样\n }\n\n // 递归处理嵌套对象\n for (const [key, value] of Object.entries(processedTransform)) {\n if (Array.isArray(value)) {\n processedTransform[key] = value.map((item: any) => {\n if (typeof item === 'object' && item !== null) {\n // 检查是否为 TransformDefinition\n if ('id' in item && 'type' in item && 'config' in item) {\n return this.convertTransformDefinitionCoordinates(item as TransformDefinition);\n } else {\n // 普通对象,深拷贝\n return this.deepClone(item);\n }\n }\n return item;\n });\n } else if (value && typeof value === 'object') {\n // 递归处理嵌套对象,但需要检查是否为 TransformDefinition\n if ('id' in value && 'type' in value && 'config' in value) {\n processedTransform[key] = this.convertTransformDefinitionCoordinates(value as TransformDefinition);\n } else {\n // 普通对象,递归处理但不转换特定字段\n processedTransform[key] = this.deepClone(value); // 使用深拷贝代替递归转换\n }\n }\n }\n\n return processedTransform as TransformDefinition;\n }\n\n /**\n * 简单的深度克隆函数\n */\n private deepClone(obj: any): any {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => this.deepClone(item));\n }\n\n const cloned: Record<string, any> = {};\n for (const key in obj) {\n if (obj.hasOwnProperty(key)) {\n cloned[key] = this.deepClone(obj[key]);\n }\n }\n\n return cloned;\n }\n\n /**\n * 转换基础数据(snake_case → camelCase)\n */\n private _transformBaseData(inputData: GeometryProblemDataV4): any {\n // 提取几何定义到referenceContext\n this.extractGeometryDefinitionsFromInput(inputData);\n\n // 转换字段命名(snake_case → camelCase)\n const transformed = {\n // 转换基础字段\n id: inputData.math_prob_id,\n title: inputData.title,\n grade: parseInt(inputData.grade_id.replace('g', '')) || 5,\n unit: inputData.unit_name,\n lesson: inputData.lesson_name,\n skillDescription: inputData.skill_description,\n objective: inputData.objective,\n knowledgePoints: inputData.knowledge_points,\n difficulty: inputData.difficulty,\n description: inputData.description,\n metadata: inputData.metadata,\n\n // 转换basic_info\n basicInfo: {\n question: inputData.basic_info.question,\n answerUnit: inputData.basic_info.answerUnit || inputData.basic_info.areaUnit,\n shape: inputData.basic_info.shape,\n // 通用几何参数\n base: inputData.basic_info.base,\n height: inputData.basic_info.height,\n baseUnit: inputData.basic_info.baseUnit,\n heightUnit: inputData.basic_info.heightUnit,\n // 梯形特定参数\n topBase: inputData.basic_info.topBase,\n topBaseUnit: inputData.basic_info.topBaseUnit,\n // 平行四边形/矩形特定参数\n length: inputData.basic_info.length,\n width: inputData.basic_info.width,\n lengthUnit: inputData.basic_info.lengthUnit,\n widthUnit: inputData.basic_info.widthUnit,\n // 其他参数\n side: inputData.basic_info.side,\n sideUnit: inputData.basic_info.sideUnit,\n variables: inputData.basic_info.variables,\n score: inputData.basic_info.score,\n context: inputData.basic_info.context,\n },\n\n // 原始数据引用(用于后续处理)\n rawGeometryShapes: inputData.geometry_shapes,\n rawTransformDefinitions: inputData.transform_definitions,\n rawGeometryTransformConfigs: inputData.geometry_transform_configs,\n rawAnimationConfigs: inputData.animation_configs,\n rawScenes: inputData.scenes,\n rawExplanation: inputData.explanation,\n rawAnswerInfo: inputData.answer_info,\n\n // 转换后的答案和解释字段\n answer: this.transformAnswer(inputData.answer_info),\n answer_info: this.transformAnswerInfo(inputData.answer_info),\n explanation: this.transformExplanation(inputData.explanation),\n\n // 其他字段\n unitId: inputData.unit_id,\n lessonId: inputData.lesson_id,\n moduleId: inputData.module_id,\n skillItemId: inputData.skill_item_id,\n skillId: inputData.skill_id,\n createdAt: inputData.created_at,\n updatedAt: inputData.updated_at,\n layout: inputData.layout,\n };\n\n // 将basicInfo设置到referenceContext,供解析器使用\n this.referenceContext.basicInfo = transformed.basicInfo;\n\n // 设置几何变换配置\n if (inputData.geometry_transform_configs) {\n this.referenceContext.geometryTransformConfigs = inputData.geometry_transform_configs;\n }\n\n // 设置动画配置\n if (inputData.animation_configs) {\n this.referenceContext.animationConfigs = inputData.animation_configs;\n }\n\n return transformed;\n }\n\n /**\n * 解析引用\n */\n private _resolveReferences(data: any): any {\n // 提取所有引用\n const allRefs = this.resolverRegistry.extractAllRefs(data);\n this.performanceMonitor.setReferenceCount(allRefs.length);\n\n // 批量解析引用\n const _resolvedRefs = this.resolverRegistry.batchResolve(allRefs, this.referenceContext);\n\n // 替换引用\n return ReferenceUtils.replaceReferences(data, this.referenceContext, {\n strictMode: this.config.strictMode,\n onMissing: (ref) => {\n if (this.config.enableLogging) {\n console.warn(`引用未找到: ${ref}`);\n }\n return ref; // 保留原始引用\n }\n });\n }\n\n /**\n * 转换场景内容\n */\n private _transformScenes(data: any): any {\n const transformedData = { ...data };\n\n if (transformedData.scenes && typeof transformedData.scenes === 'object') {\n if (this.config.enableLogging) {\n console.log('🔄 transformScenes: starting scene transformation');\n }\n\n transformedData.scenes = this.transformerRegistry.transformScenes(\n transformedData.scenes,\n this.referenceContext,\n {\n enableReferenceResolution: this.config.enableReferenceResolution,\n strictMode: this.config.strictMode\n }\n );\n\n if (this.config.enableLogging) {\n console.log('✅ transformScenes: completed scene transformation');\n }\n }\n\n return transformedData;\n }\n\n /**\n * 验证输出数据\n */\n private _validateOutput(data: any): { isValid: boolean; errors: string[]; warnings: string[] } {\n return ValidationManager.validateOutput(data, {\n strictMode: this.config.strictMode || this.config.validationLevel === 'strict'\n });\n }\n\n /**\n * 构建结果对象\n */\n private buildResult(\n data: any,\n validationResults: any,\n inputData: GeometryProblemDataV4\n ): AdapterResult {\n const performanceStats = this.performanceMonitor.getStats();\n const referenceStats = this.resolverRegistry.getStats?.() || {\n total: 0,\n resolved: 0,\n failed: 0,\n byType: {}\n };\n\n // 收集所有警告\n const warnings: AdapterWarning[] = [\n ...(validationResults.inputWarnings || []).map((msg: string) => ({\n code: AdapterErrorCode.MISSING_REQUIRED_FIELD,\n message: msg,\n path: 'input'\n })),\n ...(validationResults.outputWarnings || []).map((msg: string) => ({\n code: AdapterErrorCode.OUTPUT_VALIDATION_FAILED,\n message: msg,\n path: 'output'\n }))\n ];\n\n return {\n data: data as unknown as MathPracticeProblemData,\n warnings,\n performance: this.config.enablePerformanceMonitoring ? performanceStats : undefined,\n referenceStats\n };\n }\n\n /**\n * 创建回退结果\n */\n private createFallbackResult(inputData: GeometryProblemDataV4, error: any): AdapterResult {\n // 创建简单的回退数据\n const fallbackData = {\n ...DEFAULT_FALLBACK_DATA,\n id: inputData?.math_prob_id || 'geometry-fallback',\n title: inputData?.title || '几何问题(回退)',\n basicInfo: {\n question: inputData?.basic_info?.question || '计算下面几何图形的面积:',\n answerUnit: inputData?.basic_info?.answerUnit || 'cm²',\n shape: inputData?.basic_info?.shape || 'triangle',\n base: inputData?.basic_info?.base || 6,\n height: inputData?.basic_info?.height || 4,\n baseUnit: inputData?.basic_info?.baseUnit || 'cm',\n heightUnit: inputData?.basic_info?.heightUnit || 'cm'\n }\n };\n\n return {\n data: fallbackData as unknown as MathPracticeProblemData,\n warnings: [{\n code: AdapterErrorCode.TRANSFORMATION_FAILED,\n message: `适配失败,使用回退数据: ${error instanceof Error ? error.message : error}`,\n suggestion: '检查输入数据格式是否符合V4规范'\n }],\n referenceStats: {\n total: 0,\n resolved: 0,\n failed: 0,\n byType: {}\n }\n };\n }\n\n /**\n * 适配器工厂方法\n */\n static create(config?: SyncAdapterConfig): GeometryAdapterCore {\n return new GeometryAdapterCore(config);\n }\n}","/**\n * GeometryProblemAdapterV4 - 统一几何问题适配器\n *\n * 基于 TriangleAdapterV3 重构的通用几何问题适配器。\n * 支持三角形、梯形、平行四边形等多种几何形状的 V4 格式数据。\n */\n\n// ============================================================================\n// 核心模块导出\n// ============================================================================\n\n// 同步适配器核心\nexport * from './GeometryAdapterCore';\n\n// 类型定义\nexport * from './types';\n\n// ============================================================================\n// 主适配器函数\n// ============================================================================\n\nimport { GeometryAdapterCore } from './GeometryAdapterCore';\nimport type { GeometryProblemDataV4, SyncAdapterConfig, AdapterResult } from './types';\nimport { ValidationManager } from '../TriangleAdapterV3/validators';\n\n/**\n * 同步适配几何问题数据(主函数)\n *\n * @param inputData 原始几何问题数据 (V4格式)\n * @param config 适配器配置\n * @returns 适配后的 MathPracticeProblemData\n */\nexport function adaptGeometryDataSync(\n inputData: GeometryProblemDataV4,\n config?: SyncAdapterConfig\n): AdapterResult {\n const adapter = new GeometryAdapterCore(config);\n return adapter.adapt(inputData);\n}\n\n/**\n * 异步适配几何问题数据(兼容接口)\n *\n * @param inputData 原始几何问题数据 (V4格式)\n * @param config 适配器配置\n * @returns Promise<AdapterResult>\n */\nexport async function adaptGeometryDataAsync(\n inputData: GeometryProblemDataV4,\n config?: SyncAdapterConfig\n): Promise<AdapterResult> {\n // 同步适配器已经足够快,直接返回Promise包装的结果\n return Promise.resolve(adaptGeometryDataSync(inputData, config));\n}\n\n// 别名:保持与现有代码兼容\nexport { adaptGeometryDataSync as adaptGeometryDataV4 };\nexport { adaptGeometryDataAsync as adaptGeometryData };\n\n// ============================================================================\n// 数据加载函数\n// ============================================================================\n\n/**\n * 同步加载几何问题数据\n */\nexport function loadGeometryProblemDataSync(\n dataSource: GeometryProblemDataV4 | (() => GeometryProblemDataV4),\n config?: SyncAdapterConfig\n): AdapterResult {\n const inputData = typeof dataSource === 'function' ? dataSource() : dataSource;\n return adaptGeometryDataSync(inputData, config);\n}\n\n/**\n * 异步加载几何问题数据(兼容接口)\n */\nexport async function loadGeometryProblemDataAsync(\n dataSource: GeometryProblemDataV4 | (() => GeometryProblemDataV4) | Promise<GeometryProblemDataV4>,\n config?: SyncAdapterConfig\n): Promise<AdapterResult> {\n const inputData = typeof dataSource === 'function'\n ? await dataSource()\n : dataSource instanceof Promise\n ? await dataSource\n : dataSource;\n\n return adaptGeometryDataSync(inputData, config);\n}\n\n// 别名:保持与现有代码兼容\nexport { loadGeometryProblemDataSync as loadGeometryProblemDataV4 };\nexport { loadGeometryProblemDataAsync as loadGeometryProblemData };\n\n// ============================================================================\n// 适配器工厂\n// ============================================================================\n\n/**\n * 创建同步适配器\n */\nexport function createSyncAdapter(config?: SyncAdapterConfig): GeometryAdapterCore {\n return new GeometryAdapterCore(config);\n}\n\n/**\n * 创建异步适配器(兼容接口)\n */\nexport function createAsyncAdapter(config?: SyncAdapterConfig): { adapt: (data: GeometryProblemDataV4) => Promise<AdapterResult> } {\n const syncAdapter = new GeometryAdapterCore(config);\n return {\n adapt: (data: GeometryProblemDataV4) => Promise.resolve(syncAdapter.adapt(data))\n };\n}\n\n// 别名:保持与现有代码兼容\nexport { createAsyncAdapter as createGeometryDataAdapter };\n\n// ============================================================================\n// 验证工具\n// ============================================================================\n\n// TODO: 从 TriangleAdapterV3 导入并包装验证工具\nexport { ValidationManager } from '../TriangleAdapterV3/validators';\n\n/**\n * 验证数据格式\n */\nexport function validateGeometryData(data: any, type: 'input' | 'output' = 'input'): { isValid: boolean; errors: string[]; warnings: string[] } {\n // 使用已导入的 ValidationManager\n if (type === 'input') {\n return ValidationManager.validateInput(data);\n } else {\n return ValidationManager.validateOutput(data);\n }\n}\n\n/**\n * 性能测试\n */\nexport function benchmarkAdapter(\n adapter: GeometryAdapterCore,\n testData: GeometryProblemDataV4,\n iterations: number = 100\n): { averageTime: number; minTime: number; maxTime: number; memoryUsage: number } {\n const times: number[] = [];\n\n for (let i = 0; i < iterations; i++) {\n const start = performance.now();\n adapter.adapt(testData);\n const end = performance.now();\n times.push(end - start);\n }\n\n const averageTime = times.reduce((sum, time) => sum + time, 0) / iterations;\n const minTime = Math.min(...times);\n const maxTime = Math.max(...times);\n\n // 简单内存使用估计(实际实现需要更精确)\n const memoryUsage = process.memoryUsage?.().heapUsed || 0;\n\n return { averageTime, minTime, maxTime, memoryUsage };\n}\n\n// ============================================================================\n// 默认导出\n// ============================================================================\n\n/**\n * 默认导出(兼容现有导入方式)\n */\nconst geometryAdapterV4 = {\n adapt: (data: GeometryProblemDataV4, config?: SyncAdapterConfig) =>\n adaptGeometryDataSync(data, config),\n adaptAsync: (data: GeometryProblemDataV4, config?: SyncAdapterConfig) =>\n adaptGeometryDataAsync(data, config),\n create: (config?: SyncAdapterConfig) => createSyncAdapter(config)\n};\n\nexport default geometryAdapterV4;\n\n// ============================================================================\n// 版本信息\n// ============================================================================\n\nexport const VERSION = '4.0.0';\nexport const SCHEMA_VERSION = '4.0.0';\n\n/**\n * 检查兼容性\n */\nexport function checkCompatibility(expectedVersion: string = '4.0.0'): boolean {\n return SCHEMA_VERSION >= expectedVersion;\n}\n\n/**\n * 检查是否为V4格式数据\n */\nexport function isV4Format(data: any): boolean {\n return data?.schema_version === '4.0.0' ||\n data?.schema_version?.startsWith('4.');\n}\n\n/**\n * 检查是否为几何问题数据\n */\nexport function isGeometryProblem(data: any): boolean {\n return isV4Format(data) &&\n (data.geometry_shapes ||\n data.transform_definitions ||\n (data.basic_info?.shape &&\n ['triangle', 'acute_triangle', 'right_triangle', 'obtuse_triangle',\n 'trapezoid', 'parallelogram', 'rectangle', 'square', 'rhombus'].includes(data.basic_info.shape)));\n}\n\n// ============================================================================\n// 类型重新导出(方便使用)\n// ============================================================================\n\nexport type {\n // 核心类型\n GeometryProblemDataV4,\n MathPracticeProblemData,\n SyncAdapterConfig,\n AdapterResult,\n AdapterError,\n AdapterWarning,\n AdapterErrorCode,\n GeometryShapeType,\n\n // 引用解析类型\n ReferenceContext,\n ReferenceType,\n ReferenceResolution,\n\n // 性能类型\n PerformanceMark,\n PerformanceStats\n} from './types';","/**\r\n * GeometryTransform 配置生成器 - 扩展类型定义\r\n *\r\n * 此文件定义了通用GeometryTransform配置生成器所需的扩展类型系统,\r\n * 支持动态配置生成、多变换策略和严格的类型验证。\r\n */\r\n\r\nimport type { GeometryTransformProps, TransformConfig, GeometryShape } from '../../../../components/GeometryTransform/types';\r\n\r\n// ========== 核心枚举类型 ==========\r\n\r\n/**\r\n * 三角形类型枚举\r\n * 支持直角三角形、锐角三角形、钝角三角形\r\n */\r\nexport type TriangleType = 'right_triangle' | 'acute_triangle' | 'obtuse_triangle';\r\n\r\n/**\r\n * 变换策略枚举\r\n * 根据三角形类型选择不同的变换策略\r\n */\r\nexport type TransformStrategy = 'single_rotation' | 'double_rotation' | 'cut_and_paste';\r\n\r\n/**\r\n * 配置生成模式\r\n * 控制配置生成的详细程度和验证级别\r\n */\r\nexport type ConfigGenerationMode = 'strict' | 'lenient' | 'compatibility';\r\n\r\n// ========== 配置生成选项接口 ==========\r\n\r\n/**\r\n * 三角形配置生成选项\r\n * 包含生成三角形几何变换配置所需的所有参数\r\n */\r\nexport interface TriangleConfigOptions {\r\n /** 三角形类型 */\r\n type: TriangleType;\r\n /** 底边长度 */\r\n base: number;\r\n /** 高度 */\r\n height: number;\r\n /** 原点X坐标(可选,默认0) */\r\n originX?: number;\r\n /** 原点的Y坐标(可选,默认0) */\r\n originY?: number;\r\n /** 长度单位(可选,默认'in') */\r\n unit?: string;\r\n /** 变换策略(可选,根据三角形类型自动选择) */\r\n strategy?: TransformStrategy;\r\n /** 配置生成模式(可选,默认'strict') */\r\n mode?: ConfigGenerationMode;\r\n /** 主题样式(可选) */\r\n theme?: 'light' | 'dark';\r\n /** 布局密度(可选) */\r\n layoutDensity?: 'default' | 'compact';\r\n}\r\n\r\n/**\r\n * 动态几何变换配置\r\n * 扩展GeometryTransformProps,支持多变换和策略标识\r\n */\r\nexport interface DynamicGeometryTransformConfig extends Omit<GeometryTransformProps, 'shapes' | 'transform'> {\r\n /** 形状定义(动态生成) */\r\n shapes: GeometryTransformProps['shapes'];\r\n /** 变换配置(支持单变换或多变换) */\r\n transform: TransformConfig | TransformConfig[];\r\n /** 变换策略标识 */\r\n strategy: string;\r\n /** UI配置(可选,向后兼容) */\r\n ui?: {\r\n layoutDensity?: 'default' | 'compact';\r\n boardHeight?: number;\r\n boardWidth?: number | string;\r\n };\r\n /** 底边单位(可选) */\r\n baseUnit?: string;\r\n /** 高度单位(可选) */\r\n heightUnit?: string;\r\n /** 原始配置选项(用于调试和验证) */\r\n metadata?: {\r\n triangleType: TriangleType;\r\n base: number;\r\n height: number;\r\n unit: string;\r\n originX: number;\r\n originY: number;\r\n strategy: TransformStrategy;\r\n generatedAt: string;\r\n };\r\n}\r\n\r\n// ========== 几何计算接口 ==========\r\n\r\n/**\r\n * 三角形顶点坐标\r\n * 表示三角形的三个顶点\r\n */\r\nexport interface TriangleVertices {\r\n x1: number;\r\n y1: number;\r\n x2: number;\r\n y2: number;\r\n x3: number;\r\n y3: number;\r\n}\r\n\r\n/**\r\n * 变换中心点配置\r\n * 定义旋转或缩放的中心点\r\n */\r\nexport interface TransformCenter {\r\n x: number;\r\n y: number;\r\n label?: string;\r\n}\r\n\r\n// ========== 验证结果接口 ==========\r\n\r\n/**\r\n * 配置验证结果\r\n * 包含验证状态、错误信息和修复建议\r\n */\r\nexport interface ConfigValidationResult {\r\n /** 验证是否通过 */\r\n isValid: boolean;\r\n /** 验证错误列表 */\r\n errors: ConfigValidationError[];\r\n /** 修复建议 */\r\n fixes: ConfigFixSuggestion[];\r\n /** 验证时间戳 */\r\n timestamp: string;\r\n}\r\n\r\n/**\r\n * 配置验证错误\r\n * 描述配置中的具体问题\r\n */\r\nexport interface ConfigValidationError {\r\n /** 错误代码 */\r\n code: ConfigValidationErrorCode;\r\n /** 错误消息 */\r\n message: string;\r\n /** 错误路径 */\r\n path: string;\r\n /** 错误值 */\r\n value?: any;\r\n /** 建议修复值 */\r\n suggestedValue?: any;\r\n}\r\n\r\n/**\r\n * 修复建议\r\n * 提供自动修复配置的建议\r\n */\r\nexport interface ConfigFixSuggestion {\r\n /** 修复动作 */\r\n action: 'replace' | 'add' | 'remove' | 'adjust';\r\n /** 修复路径 */\r\n path: string;\r\n /** 目标值 */\r\n value: any;\r\n /** 修复描述 */\r\n description: string;\r\n /** 自动修复是否安全 */\r\n isSafe: boolean;\r\n}\r\n\r\n/**\r\n * 配置验证错误代码\r\n */\r\nexport type ConfigValidationErrorCode =\r\n | 'INVALID_TRIANGLE_TYPE'\r\n | 'INVALID_BASE_VALUE'\r\n | 'INVALID_HEIGHT_VALUE'\r\n | 'INVALID_ORIGIN'\r\n | 'MISSING_SHAPES'\r\n | 'INVALID_SHAPE_VERTICES'\r\n | 'MISSING_TRANSFORM'\r\n | 'INVALID_TRANSFORM_CONFIG'\r\n | 'STRATEGY_MISMATCH'\r\n | 'UNIT_MISMATCH'\r\n | 'GEOMETRY_INCONSISTENCY';\r\n\r\n// ========== 错误处理接口 ==========\r\n\r\n/**\r\n * 配置生成错误\r\n * 表示配置生成过程中发生的错误\r\n */\r\nexport class ConfigGenerationError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly shapeType: string,\r\n public readonly options: any,\r\n public readonly innerError?: Error\r\n ) {\r\n super(`Failed to generate config for ${shapeType}: ${message}`);\r\n this.name = 'ConfigGenerationError';\r\n }\r\n}\r\n\r\n/**\r\n * 操作结果包装器\r\n * 用于处理可能失败的操作\r\n */\r\nexport interface Result<T, E = ConfigGenerationError> {\r\n /** 操作是否成功 */\r\n success: boolean;\r\n /** 成功时的数据 */\r\n data?: T;\r\n /** 失败时的错误 */\r\n error?: E;\r\n}\r\n\r\n/**\r\n * 配置生成器接口\r\n * 定义通用配置生成器的契约\r\n */\r\nexport interface GeometryConfigGenerator {\r\n /** 生成配置 */\r\n generate(options: any): Result<DynamicGeometryTransformConfig, ConfigGenerationError>;\r\n /** 验证输入选项 */\r\n validate(options: any): ConfigValidationResult;\r\n /** 获取支持的形状类型 */\r\n getSupportedShapes(): string[];\r\n /** 获取默认选项 */\r\n getDefaultOptions(): any;\r\n}\r\n\r\n// ========== 实用工具类型 ==========\r\n\r\n/**\r\n * 从基础信息对象推断配置选项\r\n */\r\nexport interface BasicInfoFields {\r\n shape: string;\r\n base: number;\r\n height: number;\r\n baseUnit?: string;\r\n heightUnit?: string;\r\n originX?: number;\r\n originY?: number;\r\n unit?: string;\r\n strategy?: string;\r\n}\r\n\r\n/**\r\n * 向后兼容包装器\r\n * 确保新旧配置格式的兼容性\r\n */\r\nexport interface CompatibilityWrapper {\r\n /** 原始配置(旧格式) */\r\n original: any;\r\n /** 转换后的配置(新格式) */\r\n converted: DynamicGeometryTransformConfig;\r\n /** 转换是否成功 */\r\n success: boolean;\r\n /** 转换警告 */\r\n warnings: string[];\r\n /** 自动修复的操作 */\r\n appliedFixes: ConfigFixSuggestion[];\r\n}\r\n\r\n// ========== 常量定义 ==========\r\n\r\n/**\r\n * 默认配置选项\r\n */\r\nexport const DEFAULT_TRIANGLE_CONFIG_OPTIONS: Partial<TriangleConfigOptions> = {\r\n originX: 0,\r\n originY: 0,\r\n unit: 'in',\r\n theme: 'light',\r\n layoutDensity: 'compact' as const,\r\n mode: 'strict' as const,\r\n};\r\n\r\n/**\r\n * 三角形类型到变换策略的映射\r\n */\r\nexport const TRIANGLE_TYPE_TO_STRATEGY: Record<TriangleType, TransformStrategy> = {\r\n right_triangle: 'single_rotation',\r\n acute_triangle: 'double_rotation',\r\n obtuse_triangle: 'cut_and_paste',\r\n};\r\n\r\n/**\r\n * 支持的三角形类型列表\r\n */\r\nexport const SUPPORTED_TRIANGLE_TYPES: TriangleType[] = [\r\n 'right_triangle',\r\n 'acute_triangle',\r\n 'obtuse_triangle',\r\n];\r\n\r\n/**\r\n * 支持的变换策略列表\r\n */\r\nexport const SUPPORTED_TRANSFORM_STRATEGIES: TransformStrategy[] = [\r\n 'single_rotation',\r\n 'double_rotation',\r\n 'cut_and_paste',\r\n];\r\n\r\n// ========== 类型守卫 ==========\r\n\r\n/**\r\n * 类型守卫:检查是否为有效的三角形类型\r\n */\r\nexport function isValidTriangleType(value: any): value is TriangleType {\r\n return SUPPORTED_TRIANGLE_TYPES.includes(value);\r\n}\r\n\r\n/**\r\n * 类型守卫:检查是否为有效的变换策略\r\n */\r\nexport function isValidTransformStrategy(value: any): value is TransformStrategy {\r\n return SUPPORTED_TRANSFORM_STRATEGIES.includes(value);\r\n}\r\n\r\n/**\r\n * 类型守卫:检查是否为有效的DynamicGeometryTransformConfig\r\n */\r\nexport function isDynamicGeometryTransformConfig(value: any): value is DynamicGeometryTransformConfig {\r\n return (\r\n value &&\r\n typeof value === 'object' &&\r\n 'shapes' in value &&\r\n 'transform' in value &&\r\n 'strategy' in value &&\r\n typeof value.strategy === 'string'\r\n );\r\n}\r\n\r\n/**\r\n * 类型守卫:检查是否为TransformConfig数组\r\n */\r\nexport function isTransformConfigArray(value: any): value is TransformConfig[] {\r\n return Array.isArray(value) && value.every(item => item && typeof item === 'object' && 'type' in item);\r\n}\r\n\r\n/**\r\n * 类型守卫:检查是否为有效的配置选项\r\n */\r\nexport function isValidTriangleConfigOptions(value: any): value is TriangleConfigOptions {\r\n return (\r\n value &&\r\n typeof value === 'object' &&\r\n 'type' in value &&\r\n isValidTriangleType(value.type) &&\r\n 'base' in value &&\r\n typeof value.base === 'number' &&\r\n value.base > 0 &&\r\n 'height' in value &&\r\n typeof value.height === 'number' &&\r\n value.height > 0\r\n );\r\n}","/**\r\n * GeometryTransform 配置验证工具\r\n *\r\n * 此模块提供了验证GeometryTransform配置的工具函数,\r\n * 包括配置完整性检查、类型验证、几何一致性验证等。\r\n *\r\n * @module configValidation\r\n */\r\n\r\nimport type {\r\n ConfigValidationResult,\r\n ConfigValidationError,\r\n ConfigValidationErrorCode,\r\n ConfigFixSuggestion,\r\n DynamicGeometryTransformConfig,\r\n TriangleConfigOptions,\r\n GeometryConfigGenerator,\r\n} from './types';\r\nimport type { GeometryTransformProps, GeometryShape, TransformConfig } from '../../../../components/GeometryTransform/types';\r\n\r\n// ========== 占位函数(TDD Red阶段) ==========\r\n\r\n/**\r\n * 验证动态几何变换配置是否有效\r\n *\r\n * @param config 动态几何变换配置\r\n * @returns 配置验证结果\r\n */\r\nexport function validateGeometryTransformConfig(config: any): ConfigValidationResult {\r\n const errors: ConfigValidationError[] = [];\r\n const fixes: ConfigFixSuggestion[] = [];\r\n\r\n // 检查必需字段\r\n if (!config.shapes) {\r\n errors.push(createValidationError(\r\n 'MISSING_SHAPES',\r\n '缺少形状定义',\r\n '$.shapes',\r\n undefined\r\n ));\r\n }\r\n\r\n if (!config.transform) {\r\n errors.push(createValidationError(\r\n 'MISSING_TRANSFORM',\r\n '缺少变换配置',\r\n '$.transform',\r\n undefined\r\n ));\r\n }\r\n\r\n if (!config.strategy) {\r\n errors.push(createValidationError(\r\n 'STRATEGY_MISMATCH',\r\n '缺少变换策略',\r\n '$.strategy',\r\n undefined\r\n ));\r\n }\r\n\r\n // 如果缺少必需字段,直接返回\r\n if (errors.length > 0) {\r\n return {\r\n isValid: false,\r\n errors,\r\n fixes: generateFixSuggestions(errors),\r\n timestamp: new Date().toISOString(),\r\n };\r\n }\r\n\r\n // 验证形状定义\r\n if (config.shapes) {\r\n errors.push(...validateShapes(config.shapes));\r\n }\r\n\r\n // 验证变换配置\r\n // 检查是否有动画形状具有形状专属transform\r\n let hasShapeSpecificTransform = false;\r\n if (config.shapes?.animated) {\r\n for (const shape of config.shapes.animated) {\r\n if (shape.transform) {\r\n hasShapeSpecificTransform = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // 验证全局transform(如果存在)\r\n if (config.transform) {\r\n errors.push(...validateTransform(config.transform));\r\n } else if (!hasShapeSpecificTransform) {\r\n // 如果没有全局transform且没有形状专属transform,报告错误\r\n errors.push(createValidationError(\r\n 'MISSING_TRANSFORM',\r\n '缺少变换配置:需要全局transform或形状专属transform',\r\n '$.transform',\r\n undefined,\r\n { type: 'rotation' }\r\n ));\r\n }\r\n\r\n // 验证策略匹配性\r\n errors.push(...validateStrategyMatch(config));\r\n\r\n // 验证单位一致性\r\n errors.push(...validateUnitConsistency(config));\r\n\r\n // 验证几何一致性\r\n errors.push(...validateGeometryConsistency(config));\r\n\r\n // 生成修复建议\r\n if (errors.length > 0) {\r\n fixes.push(...generateFixSuggestions(errors));\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n fixes,\r\n timestamp: new Date().toISOString(),\r\n };\r\n}\r\n\r\n/**\r\n * 创建配置验证器\r\n *\r\n * @param shapeType 形状类型\r\n * @returns 配置验证器实例\r\n */\r\nexport function createConfigValidator(shapeType: string): GeometryConfigGenerator {\r\n // 返回适当形状类型的验证器实例\r\n return new BaseValidator(shapeType);\r\n}\r\n\r\n/**\r\n * 验证变换配置是否有效\r\n *\r\n * @param transform 变换配置\r\n * @returns 是否有效\r\n */\r\nexport function isValidTransformConfig(transform: any): boolean {\r\n if (!transform || typeof transform !== 'object') {\r\n return false;\r\n }\r\n\r\n // 检查变换类型\r\n if (!transform.type || typeof transform.type !== 'string') {\r\n return false;\r\n }\r\n\r\n const validTransformTypes = ['rotation', 'translation', 'scale', 'composite'];\r\n if (!validTransformTypes.includes(transform.type)) {\r\n return false;\r\n }\r\n\r\n // 根据变换类型进行详细验证\r\n switch (transform.type) {\r\n case 'rotation':\r\n if (!transform.config || typeof transform.config !== 'object') {\r\n return false;\r\n }\r\n // 检查旋转中心:可以是数组 [number, number] 或字符串 'auto'\r\n const center = transform.config.center;\r\n if (center !== 'auto' && (!Array.isArray(center) || center.length !== 2)) {\r\n return false;\r\n }\r\n // 检查角度\r\n if (typeof transform.config.startAngle !== 'number' ||\r\n typeof transform.config.endAngle !== 'number') {\r\n return false;\r\n }\r\n // 检查方向\r\n if (transform.config.direction !== 'clockwise' &&\r\n transform.config.direction !== 'counterclockwise' &&\r\n transform.config.direction !== 'horizontal' &&\r\n transform.config.direction !== 'vertical') {\r\n return false;\r\n }\r\n break;\r\n\r\n case 'translation':\r\n if (!transform.config || typeof transform.config !== 'object') {\r\n return false;\r\n }\r\n // 检查方向:可以是数组 [number, number] 或字符串 'horizontal'/'vertical'\r\n const direction = transform.config.direction;\r\n if (Array.isArray(direction)) {\r\n // 数组形式:[number, number]\r\n if (direction.length !== 2) {\r\n return false;\r\n }\r\n if (typeof direction[0] !== 'number' || typeof direction[1] !== 'number') {\r\n return false;\r\n }\r\n } else if (typeof direction === 'string') {\r\n // 字符串形式:'horizontal' 或 'vertical'\r\n if (direction !== 'horizontal' && direction !== 'vertical') {\r\n return false;\r\n }\r\n } else {\r\n // 既不是数组也不是字符串\r\n return false;\r\n }\r\n // 检查距离\r\n if (typeof transform.config.distance !== 'number' ||\r\n transform.config.distance <= 0) {\r\n return false;\r\n }\r\n break;\r\n\r\n case 'scale':\r\n if (!transform.config || typeof transform.config !== 'object') {\r\n return false;\r\n }\r\n // 检查缩放中心:可以是数组 [number, number] 或字符串 'centroid'\r\n const scaleCenter = transform.config.center;\r\n if (scaleCenter !== 'centroid' && (!Array.isArray(scaleCenter) || scaleCenter.length !== 2)) {\r\n return false;\r\n }\r\n // 检查缩放比例\r\n if (typeof transform.config.startScale !== 'number' ||\r\n typeof transform.config.endScale !== 'number') {\r\n return false;\r\n }\r\n // 检查uniform字段\r\n if (typeof transform.config.uniform !== 'boolean') {\r\n return false;\r\n }\r\n break;\r\n\r\n case 'composite':\r\n // 检查transforms字段(允许空数组)\r\n if (!transform.transforms || !Array.isArray(transform.transforms)) {\r\n return false;\r\n }\r\n // 检查复合变换中的每个子变换\r\n for (const subTransform of transform.transforms) {\r\n if (!isValidTransformConfig(subTransform)) {\r\n return false;\r\n }\r\n }\r\n // 检查executionMode(可选)\r\n if (transform.executionMode !== undefined) {\r\n if (transform.executionMode !== 'sequential' && transform.executionMode !== 'parallel') {\r\n return false;\r\n }\r\n }\r\n break;\r\n }\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * 验证单个变换配置并返回错误列表\r\n * @param transform 变换配置\r\n * @param path 配置路径\r\n * @returns 验证错误列表\r\n */\r\nfunction validateSingleTransformConfig(transform: any, path: string): ConfigValidationError[] {\r\n const errors: ConfigValidationError[] = [];\r\n\r\n if (!transform || typeof transform !== 'object') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '变换配置必须是对象',\r\n path,\r\n transform,\r\n { type: 'rotation' }\r\n ));\r\n return errors;\r\n }\r\n\r\n // 检查变换类型\r\n if (!transform.type || typeof transform.type !== 'string') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '变换类型缺失或无效',\r\n `${path}.type`,\r\n transform.type,\r\n 'rotation'\r\n ));\r\n }\r\n\r\n const validTransformTypes = ['rotation', 'translation', 'scale', 'composite'];\r\n if (transform.type && !validTransformTypes.includes(transform.type)) {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n `无效的变换类型: ${transform.type}`,\r\n `${path}.type`,\r\n transform.type,\r\n 'rotation'\r\n ));\r\n }\r\n\r\n // 根据变换类型进行详细验证\r\n switch (transform.type) {\r\n case 'rotation':\r\n if (!transform.config || typeof transform.config !== 'object') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '旋转变换缺少配置',\r\n `${path}.config`,\r\n transform.config,\r\n { center: [0, 0], startAngle: 0, endAngle: Math.PI, direction: 'clockwise' }\r\n ));\r\n } else {\r\n // 检查旋转中心:可以是数组 [number, number] 或字符串 'auto'\r\n const center = transform.config.center;\r\n if (center !== 'auto' && (!Array.isArray(center) || center.length !== 2)) {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '旋转中心必须是包含两个数字的数组或字符串 \"auto\"',\r\n `${path}.config.center`,\r\n transform.config.center,\r\n [0, 0]\r\n ));\r\n }\r\n // 检查角度\r\n if (typeof transform.config.startAngle !== 'number' ||\r\n typeof transform.config.endAngle !== 'number') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '旋转起始角度和结束角度必须是数字',\r\n `${path}.config.startAngle`,\r\n transform.config,\r\n { startAngle: 0, endAngle: Math.PI }\r\n ));\r\n }\r\n // 检查方向\r\n if (transform.config.direction !== 'clockwise' &&\r\n transform.config.direction !== 'counterclockwise' &&\r\n transform.config.direction !== 'horizontal' &&\r\n transform.config.direction !== 'vertical') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '旋转方向必须是 clockwise、counterclockwise、horizontal 或 vertical',\r\n `${path}.config.direction`,\r\n transform.config.direction,\r\n 'clockwise'\r\n ));\r\n }\r\n }\r\n break;\r\n\r\n case 'translation':\r\n if (!transform.config || typeof transform.config !== 'object') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '平移变换缺少配置',\r\n `${path}.config`,\r\n transform.config,\r\n { direction: 'horizontal', distance: 1 }\r\n ));\r\n } else {\r\n // 检查方向:可以是数组 [number, number] 或字符串 'horizontal'/'vertical'\r\n const direction = transform.config.direction;\r\n if (Array.isArray(direction)) {\r\n // 数组形式:[number, number]\r\n if (direction.length !== 2) {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '平移方向数组必须包含两个数字',\r\n `${path}.config.direction`,\r\n direction,\r\n [1, 0]\r\n ));\r\n } else if (typeof direction[0] !== 'number' || typeof direction[1] !== 'number') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '平移方向数组必须包含数字',\r\n `${path}.config.direction`,\r\n direction,\r\n [1, 0]\r\n ));\r\n }\r\n } else if (typeof direction === 'string') {\r\n // 字符串形式:'horizontal' 或 'vertical'\r\n if (direction !== 'horizontal' && direction !== 'vertical') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '平移方向必须是 horizontal 或 vertical',\r\n `${path}.config.direction`,\r\n direction,\r\n 'horizontal'\r\n ));\r\n }\r\n } else {\r\n // 既不是数组也不是字符串\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '平移方向必须是数组 [number, number] 或字符串 horizontal/vertical',\r\n `${path}.config.direction`,\r\n direction,\r\n 'horizontal'\r\n ));\r\n }\r\n // 检查距离\r\n if (typeof transform.config.distance !== 'number' ||\r\n transform.config.distance <= 0) {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '平移距离必须是大于0的数字',\r\n `${path}.config.distance`,\r\n transform.config.distance,\r\n 1\r\n ));\r\n }\r\n }\r\n break;\r\n\r\n case 'scale':\r\n if (!transform.config || typeof transform.config !== 'object') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '缩放变换缺少配置',\r\n `${path}.config`,\r\n transform.config,\r\n { center: 'centroid', startScale: 1, endScale: 2, uniform: true }\r\n ));\r\n } else {\r\n // 检查缩放中心:可以是数组 [number, number] 或字符串 'centroid'\r\n const scaleCenter = transform.config.center;\r\n if (scaleCenter !== 'centroid' && (!Array.isArray(scaleCenter) || scaleCenter.length !== 2)) {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '缩放中心必须是包含两个数字的数组或字符串 \"centroid\"',\r\n `${path}.config.center`,\r\n transform.config.center,\r\n 'centroid'\r\n ));\r\n }\r\n // 检查缩放比例\r\n if (typeof transform.config.startScale !== 'number' ||\r\n typeof transform.config.endScale !== 'number') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '缩放起始比例和结束比例必须是数字',\r\n `${path}.config.startScale`,\r\n transform.config,\r\n { startScale: 1, endScale: 2 }\r\n ));\r\n }\r\n // 检查uniform字段\r\n if (typeof transform.config.uniform !== 'boolean') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '缩放uniform字段必须是布尔值',\r\n `${path}.config.uniform`,\r\n transform.config.uniform,\r\n true\r\n ));\r\n }\r\n }\r\n break;\r\n\r\n case 'composite':\r\n // 检查transforms字段(允许空数组)\r\n if (!transform.transforms || !Array.isArray(transform.transforms)) {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '复合变换transforms字段必须是数组',\r\n `${path}.transforms`,\r\n transform.transforms,\r\n []\r\n ));\r\n } else {\r\n // 检查复合变换中的每个子变换\r\n for (let i = 0; i < transform.transforms.length; i++) {\r\n const subErrors = validateSingleTransformConfig(\r\n transform.transforms[i],\r\n `${path}.transforms[${i}]`\r\n );\r\n errors.push(...subErrors);\r\n }\r\n }\r\n // 检查executionMode(可选)\r\n if (transform.executionMode !== undefined) {\r\n if (transform.executionMode !== 'sequential' && transform.executionMode !== 'parallel') {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '复合变换执行模式必须是 sequential 或 parallel',\r\n `${path}.executionMode`,\r\n transform.executionMode,\r\n 'sequential'\r\n ));\r\n }\r\n }\r\n break;\r\n }\r\n\r\n return errors;\r\n}\r\n\r\n/**\r\n * 验证三角形配置选项是否有效\r\n *\r\n * @param options 三角形配置选项\r\n * @returns 配置验证结果\r\n */\r\nexport function validateTriangleConfigOptions(options: TriangleConfigOptions): ConfigValidationResult {\r\n const errors: ConfigValidationError[] = [];\r\n const fixes: ConfigFixSuggestion[] = [];\r\n\r\n // 检查必需字段\r\n const requiredFields = ['type', 'base', 'height'];\r\n for (const field of requiredFields) {\r\n if (!(field in options)) {\r\n errors.push(createValidationError(\r\n field === 'type' ? 'INVALID_TRIANGLE_TYPE' :\r\n field === 'base' ? 'INVALID_BASE_VALUE' : 'INVALID_HEIGHT_VALUE',\r\n `缺少必需字段: ${field}`,\r\n `$.${field}`,\r\n undefined,\r\n field === 'type' ? 'right_triangle' : 1\r\n ));\r\n }\r\n }\r\n\r\n // 如果缺少必需字段,直接返回错误\r\n if (errors.length > 0) {\r\n return {\r\n isValid: false,\r\n errors,\r\n fixes,\r\n timestamp: new Date().toISOString(),\r\n };\r\n }\r\n\r\n // 检查三角形类型是否有效\r\n const validTriangleTypes = ['right_triangle', 'acute_triangle', 'obtuse_triangle'];\r\n if (!validTriangleTypes.includes(options.type)) {\r\n errors.push(createValidationError(\r\n 'INVALID_TRIANGLE_TYPE',\r\n `无效的三角形类型: ${options.type}`,\r\n '$.type',\r\n options.type,\r\n 'right_triangle'\r\n ));\r\n }\r\n\r\n // 检查底边是否为有效正数\r\n if (typeof options.base !== 'number' || options.base <= 0 || !isFinite(options.base)) {\r\n errors.push(createValidationError(\r\n 'INVALID_BASE_VALUE',\r\n `底边长度必须为正数: ${options.base}`,\r\n '$.base',\r\n options.base,\r\n 1\r\n ));\r\n }\r\n\r\n // 检查高度是否为有效正数\r\n if (typeof options.height !== 'number' || options.height <= 0 || !isFinite(options.height)) {\r\n errors.push(createValidationError(\r\n 'INVALID_HEIGHT_VALUE',\r\n `高度必须为正数: ${options.height}`,\r\n '$.height',\r\n options.height,\r\n 1\r\n ));\r\n }\r\n\r\n // 检查原点坐标(如果提供)\r\n if (options.originX !== undefined && (typeof options.originX !== 'number' || !isFinite(options.originX))) {\r\n errors.push(createValidationError(\r\n 'INVALID_ORIGIN',\r\n `原点X坐标无效: ${options.originX}`,\r\n '$.originX',\r\n options.originX,\r\n 0\r\n ));\r\n }\r\n\r\n if (options.originY !== undefined && (typeof options.originY !== 'number' || !isFinite(options.originY))) {\r\n errors.push(createValidationError(\r\n 'INVALID_ORIGIN',\r\n `原点Y坐标无效: ${options.originY}`,\r\n '$.originY',\r\n options.originY,\r\n 0\r\n ));\r\n }\r\n\r\n // 生成修复建议\r\n if (errors.length > 0) {\r\n fixes.push(...generateFixSuggestions(errors));\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n fixes,\r\n timestamp: new Date().toISOString(),\r\n };\r\n}\r\n\r\n/**\r\n * 创建验证错误对象\r\n *\r\n * @param code 错误代码\r\n * @param message 错误消息\r\n * @param path 错误路径\r\n * @param value 错误值\r\n * @param suggestedValue 建议值\r\n * @returns 验证错误对象\r\n */\r\nexport function createValidationError(\r\n code: ConfigValidationErrorCode,\r\n message: string,\r\n path: string,\r\n value?: any,\r\n suggestedValue?: any\r\n): ConfigValidationError {\r\n // 如果没有提供建议值,根据错误代码提供合理的默认值\r\n let finalSuggestedValue = suggestedValue;\r\n if (suggestedValue === undefined) {\r\n switch (code) {\r\n case 'INVALID_TRIANGLE_TYPE':\r\n finalSuggestedValue = 'right_triangle';\r\n break;\r\n case 'INVALID_BASE_VALUE':\r\n case 'INVALID_HEIGHT_VALUE':\r\n finalSuggestedValue = 1; // 最小正值\r\n break;\r\n case 'INVALID_ORIGIN':\r\n finalSuggestedValue = 0; // 默认原点\r\n break;\r\n case 'MISSING_SHAPES':\r\n finalSuggestedValue = { static: [], animated: [] };\r\n break;\r\n case 'MISSING_TRANSFORM':\r\n finalSuggestedValue = { type: 'rotation' };\r\n break;\r\n case 'STRATEGY_MISMATCH':\r\n finalSuggestedValue = 'single_rotation';\r\n break;\r\n case 'UNIT_MISMATCH':\r\n finalSuggestedValue = 'in'; // 默认单位\r\n break;\r\n default:\r\n finalSuggestedValue = undefined;\r\n }\r\n }\r\n\r\n return {\r\n code,\r\n message,\r\n path,\r\n value,\r\n suggestedValue: finalSuggestedValue,\r\n };\r\n}\r\n\r\n/**\r\n * 应用修复建议到配置\r\n *\r\n * @param config 原始配置\r\n * @param fixes 修复建议列表\r\n * @returns 修复后的配置\r\n */\r\nexport function applyConfigFixes(\r\n config: DynamicGeometryTransformConfig,\r\n fixes: ConfigFixSuggestion[]\r\n): DynamicGeometryTransformConfig {\r\n // 创建配置的深拷贝\r\n let fixedConfig = JSON.parse(JSON.stringify(config));\r\n\r\n // 只应用安全的修复建议\r\n const safeFixes = fixes.filter(fix => fix.isSafe);\r\n\r\n for (const fix of safeFixes) {\r\n try {\r\n fixedConfig = applyFix(fixedConfig, fix);\r\n } catch (error) {\r\n // 如果修复失败,记录错误但继续处理其他修复\r\n console.warn(`Failed to apply fix: ${fix.description}`, error);\r\n }\r\n }\r\n\r\n return fixedConfig;\r\n}\r\n\r\n/**\r\n * 应用单个修复建议\r\n */\r\nfunction applyFix(config: any, fix: ConfigFixSuggestion): any {\r\n const { action, path, value } = fix;\r\n\r\n // 解析路径\r\n const pathParts = path.replace('$.', '').split(/[\\.\\[\\]]/).filter(Boolean);\r\n\r\n let current = config;\r\n for (let i = 0; i < pathParts.length - 1; i++) {\r\n const part = pathParts[i];\r\n if (part === '' || current === undefined || current === null) {\r\n return config; // 路径无效,返回原始配置\r\n }\r\n\r\n // 处理数组索引\r\n if (!isNaN(Number(part)) && Array.isArray(current)) {\r\n current = current[Number(part)];\r\n } else {\r\n current = current[part];\r\n }\r\n }\r\n\r\n const lastPart = pathParts[pathParts.length - 1];\r\n if (current === undefined || current === null) {\r\n return config; // 路径无效,返回原始配置\r\n }\r\n\r\n // 根据动作类型应用修复\r\n switch (action) {\r\n case 'replace':\r\n // 处理数组索引\r\n if (!isNaN(Number(lastPart)) && Array.isArray(current)) {\r\n current[Number(lastPart)] = value;\r\n } else {\r\n current[lastPart] = value;\r\n }\r\n break;\r\n\r\n case 'add':\r\n if (!isNaN(Number(lastPart)) && Array.isArray(current)) {\r\n // 添加到数组\r\n current.splice(Number(lastPart), 0, value);\r\n } else {\r\n // 添加到对象\r\n current[lastPart] = value;\r\n }\r\n break;\r\n\r\n case 'remove':\r\n if (!isNaN(Number(lastPart)) && Array.isArray(current)) {\r\n // 从数组删除\r\n current.splice(Number(lastPart), 1);\r\n } else {\r\n // 从对象删除\r\n delete current[lastPart];\r\n }\r\n break;\r\n\r\n case 'adjust':\r\n // 调整值(例如增加/减少)\r\n const currentValue = !isNaN(Number(lastPart)) && Array.isArray(current)\r\n ? current[Number(lastPart)]\r\n : current[lastPart];\r\n\r\n if (typeof currentValue === 'number' && typeof value === 'number') {\r\n const adjustedValue = currentValue + value;\r\n if (!isNaN(Number(lastPart)) && Array.isArray(current)) {\r\n current[Number(lastPart)] = adjustedValue;\r\n } else {\r\n current[lastPart] = adjustedValue;\r\n }\r\n }\r\n break;\r\n }\r\n\r\n return config;\r\n}\r\n\r\n/**\r\n * 验证形状定义是否有效\r\n *\r\n * @param shapes 形状定义\r\n * @returns 验证错误列表\r\n */\r\nfunction validateShapes(shapes: any): ConfigValidationError[] {\r\n const errors: ConfigValidationError[] = [];\r\n\r\n if (!shapes || typeof shapes !== 'object') {\r\n errors.push(createValidationError(\r\n 'MISSING_SHAPES',\r\n '形状定义无效或缺失',\r\n '$.shapes',\r\n shapes\r\n ));\r\n return errors;\r\n }\r\n\r\n // 检查静态形状\r\n if (!Array.isArray(shapes.static)) {\r\n errors.push(createValidationError(\r\n 'INVALID_SHAPE_VERTICES',\r\n '静态形状必须是数组',\r\n '$.shapes.static',\r\n shapes.static\r\n ));\r\n } else {\r\n // 验证每个静态形状\r\n for (let i = 0; i < shapes.static.length; i++) {\r\n const shape = shapes.static[i];\r\n const shapeErrors = validateSingleShape(shape, `$.shapes.static[${i}]`);\r\n errors.push(...shapeErrors);\r\n }\r\n }\r\n\r\n // 检查动画形状\r\n if (!Array.isArray(shapes.animated)) {\r\n errors.push(createValidationError(\r\n 'INVALID_SHAPE_VERTICES',\r\n '动画形状必须是数组',\r\n '$.shapes.animated',\r\n shapes.animated\r\n ));\r\n } else {\r\n // 验证每个动画形状\r\n for (let i = 0; i < shapes.animated.length; i++) {\r\n const shape = shapes.animated[i];\r\n const shapeErrors = validateSingleShape(shape, `$.shapes.animated[${i}]`);\r\n errors.push(...shapeErrors);\r\n }\r\n }\r\n\r\n return errors;\r\n}\r\n\r\n/**\r\n * 验证单个形状\r\n */\r\nfunction validateSingleShape(shape: any, path: string): ConfigValidationError[] {\r\n const errors: ConfigValidationError[] = [];\r\n\r\n if (!shape || typeof shape !== 'object') {\r\n errors.push(createValidationError(\r\n 'INVALID_SHAPE_VERTICES',\r\n '形状定义必须是对象',\r\n path,\r\n shape\r\n ));\r\n return errors;\r\n }\r\n\r\n // 检查形状类型\r\n if (!shape.type || typeof shape.type !== 'string') {\r\n errors.push(createValidationError(\r\n 'INVALID_SHAPE_VERTICES',\r\n '形状类型缺失或无效',\r\n `${path}.type`,\r\n shape.type\r\n ));\r\n }\r\n\r\n // 检查顶点\r\n if (!Array.isArray(shape.vertices)) {\r\n errors.push(createValidationError(\r\n 'INVALID_SHAPE_VERTICES',\r\n '形状顶点必须是数组',\r\n `${path}.vertices`,\r\n shape.vertices\r\n ));\r\n } else if (shape.vertices.length === 0) {\r\n errors.push(createValidationError(\r\n 'INVALID_SHAPE_VERTICES',\r\n '形状顶点数组不能为空',\r\n `${path}.vertices`,\r\n shape.vertices\r\n ));\r\n } else {\r\n // 验证每个顶点\r\n for (let i = 0; i < shape.vertices.length; i++) {\r\n const vertex = shape.vertices[i];\r\n if (!Array.isArray(vertex) || vertex.length !== 2) {\r\n errors.push(createValidationError(\r\n 'INVALID_SHAPE_VERTICES',\r\n `顶点 ${i} 必须是包含两个数字的数组`,\r\n `${path}.vertices[${i}]`,\r\n vertex\r\n ));\r\n } else if (typeof vertex[0] !== 'number' || typeof vertex[1] !== 'number') {\r\n errors.push(createValidationError(\r\n 'INVALID_SHAPE_VERTICES',\r\n `顶点 ${i} 必须包含数字`,\r\n `${path}.vertices[${i}]`,\r\n vertex\r\n ));\r\n }\r\n }\r\n }\r\n\r\n // 验证形状专属transform(如果存在)\r\n if (shape.transform !== undefined) {\r\n const transformErrors = validateSingleTransformConfig(shape.transform, `${path}.transform`);\r\n errors.push(...transformErrors);\r\n }\r\n\r\n return errors;\r\n}\r\n\r\n/**\r\n * 验证变换配置是否有效\r\n *\r\n * @param transform 变换配置\r\n * @returns 验证错误列表\r\n */\r\nfunction validateTransform(transform: any): ConfigValidationError[] {\r\n const errors: ConfigValidationError[] = [];\r\n\r\n if (!transform) {\r\n errors.push(createValidationError(\r\n 'MISSING_TRANSFORM',\r\n '变换配置缺失',\r\n '$.transform',\r\n transform\r\n ));\r\n return errors;\r\n }\r\n\r\n // 检查是否为数组(多变换)或对象(单变换)\r\n const isArray = Array.isArray(transform);\r\n const transforms = isArray ? transform : [transform];\r\n const basePath = isArray ? '$.transform' : '$.transform';\r\n\r\n for (let i = 0; i < transforms.length; i++) {\r\n const currentTransform = transforms[i];\r\n const currentPath = isArray ? `${basePath}[${i}]` : basePath;\r\n\r\n if (!isValidTransformConfig(currentTransform)) {\r\n errors.push(createValidationError(\r\n 'INVALID_TRANSFORM_CONFIG',\r\n '变换配置无效',\r\n currentPath,\r\n currentTransform\r\n ));\r\n }\r\n }\r\n\r\n return errors;\r\n}\r\n\r\n/**\r\n * 验证策略匹配性\r\n *\r\n * @param config 配置对象\r\n * @returns 验证错误列表\r\n */\r\nfunction validateStrategyMatch(config: DynamicGeometryTransformConfig): ConfigValidationError[] {\r\n const errors: ConfigValidationError[] = [];\r\n\r\n if (!config.strategy) {\r\n return errors; // 策略已在其他验证中检查\r\n }\r\n\r\n const { strategy } = config;\r\n\r\n // 计算变换数量,考虑全局transform和形状专属transform\r\n let transformCount = 0;\r\n\r\n // 计算全局transform数量\r\n if (config.transform) {\r\n if (Array.isArray(config.transform)) {\r\n transformCount += config.transform.length;\r\n } else if (typeof config.transform === 'object') {\r\n // 检查是否为复合变换(具有transforms属性)\r\n if (config.transform && typeof config.transform === 'object' && 'transforms' in config.transform) {\r\n transformCount += (config.transform as any).transforms.length;\r\n } else {\r\n // 单个变换对象\r\n transformCount += 1;\r\n }\r\n }\r\n }\r\n\r\n // 计算形状专属transform数量\r\n if (config.shapes?.animated) {\r\n for (const shape of config.shapes.animated) {\r\n if (shape.transform) {\r\n transformCount += 1;\r\n }\r\n }\r\n }\r\n\r\n // 检查策略与变换数量的匹配性\r\n if (strategy.includes('single') && transformCount !== 1) {\r\n errors.push(createValidationError(\r\n 'STRATEGY_MISMATCH',\r\n `单旋转策略需要一个变换,但找到 ${transformCount} 个`,\r\n '$.strategy',\r\n strategy,\r\n transformCount === 0 ? 'single_rotation' : 'double_rotation'\r\n ));\r\n }\r\n\r\n if (strategy.includes('double') && transformCount !== 2) {\r\n errors.push(createValidationError(\r\n 'STRATEGY_MISMATCH',\r\n `双旋转策略需要两个变换,但找到 ${transformCount} 个`,\r\n '$.strategy',\r\n strategy,\r\n transformCount === 1 ? 'single_rotation' : 'double_rotation'\r\n ));\r\n }\r\n\r\n // 检查策略名称的有效性\r\n const validStrategies = ['single_rotation', 'double_rotation', 'cut_and_paste', 'rigid_rotation', 'double_rotation_visual_proof', 'fillcolor_swap'];\r\n if (!validStrategies.includes(strategy)) {\r\n errors.push(createValidationError(\r\n 'STRATEGY_MISMATCH',\r\n `无效的策略名称: ${strategy}`,\r\n '$.strategy',\r\n strategy,\r\n 'single_rotation'\r\n ));\r\n }\r\n\r\n return errors;\r\n}\r\n\r\n/**\r\n * 验证单位一致性\r\n *\r\n * @param config 配置对象\r\n * @returns 验证错误列表\r\n */\r\nfunction validateUnitConsistency(config: DynamicGeometryTransformConfig): ConfigValidationError[] {\r\n const errors: ConfigValidationError[] = [];\r\n\r\n // 检查单位字段\r\n if (config.unit && typeof config.unit !== 'string') {\r\n errors.push(createValidationError(\r\n 'UNIT_MISMATCH',\r\n '单位必须是字符串',\r\n '$.unit',\r\n config.unit,\r\n 'in'\r\n ));\r\n }\r\n\r\n // 检查底边和高度单位(如果提供)\r\n if (config.baseUnit && typeof config.baseUnit !== 'string') {\r\n errors.push(createValidationError(\r\n 'UNIT_MISMATCH',\r\n '底边单位必须是字符串',\r\n '$.baseUnit',\r\n config.baseUnit,\r\n config.unit || 'in'\r\n ));\r\n }\r\n\r\n if (config.heightUnit && typeof config.heightUnit !== 'string') {\r\n errors.push(createValidationError(\r\n 'UNIT_MISMATCH',\r\n '高度单位必须是字符串',\r\n '$.heightUnit',\r\n config.heightUnit,\r\n config.unit || 'in'\r\n ));\r\n }\r\n\r\n // 检查单位一致性:如果提供了baseUnit和heightUnit,它们应该与unit一致\r\n if (config.unit && config.baseUnit && config.baseUnit !== config.unit) {\r\n errors.push(createValidationError(\r\n 'UNIT_MISMATCH',\r\n `底边单位 (${config.baseUnit}) 与主单位 (${config.unit}) 不一致`,\r\n '$.baseUnit',\r\n config.baseUnit,\r\n config.unit\r\n ));\r\n }\r\n\r\n if (config.unit && config.heightUnit && config.heightUnit !== config.unit) {\r\n errors.push(createValidationError(\r\n 'UNIT_MISMATCH',\r\n `高度单位 (${config.heightUnit}) 与主单位 (${config.unit}) 不一致`,\r\n '$.heightUnit',\r\n config.heightUnit,\r\n config.unit\r\n ));\r\n }\r\n\r\n // 检查单位与值的合理性(启发式检查)\r\n// // 如果单位是厘米,但底边和高度值很小(可能是英寸值),则警告\r\n// if (config.unit === 'cm' && config.base && config.height) {\r\n// const typicalCmRange = { min: 2, max: 100 }; // 厘米的典型范围\r\n// const typicalInRange = { min: 0.5, max: 40 }; // 英寸的典型范围\r\n//\r\n// // 如果值在英寸范围内但单位是厘米,可能单位不一致\r\n// if (config.base >= typicalInRange.min && config.base <= typicalInRange.max &&\r\n// config.height >= typicalInRange.min && config.height <= typicalInRange.max) {\r\n// // 值在英寸范围内,但单位是厘米\r\n// errors.push(createValidationError(\r\n// 'UNIT_MISMATCH',\r\n// `底边(${config.base})和高度(${config.height})的值在英寸范围内,但单位设置为厘米`,\r\n// '$.unit',\r\n// config.unit,\r\n// 'in'\r\n// ));\r\n// }\r\n// }\r\n\r\n // 检查单位与边界框的合理性\r\n if (config.unit && config.boardConfig && config.boardConfig.boundingBox) {\r\n const [minX, maxY, maxX, minY] = config.boardConfig.boundingBox;\r\n const bboxWidth = maxX - minX;\r\n const bboxHeight = maxY - minY;\r\n\r\n // 根据单位检查边界框尺寸是否合理\r\n const reasonableSize = config.unit === 'cm' ? 50 : 20; // 厘米单位下边界框通常更大\r\n if (bboxWidth > reasonableSize * 5 || bboxHeight > reasonableSize * 5) {\r\n errors.push(createValidationError(\r\n 'UNIT_MISMATCH',\r\n `边界框尺寸(${bboxWidth.toFixed(1)}×${bboxHeight.toFixed(1)})与单位(${config.unit})不匹配`,\r\n '$.boardConfig.boundingBox',\r\n config.boardConfig.boundingBox,\r\n undefined\r\n ));\r\n }\r\n }\r\n\r\n return errors;\r\n}\r\n\r\n/**\r\n * 验证几何一致性\r\n *\r\n * @param config 配置对象\r\n * @returns 验证错误列表\r\n */\r\nfunction validateGeometryConsistency(config: DynamicGeometryTransformConfig): ConfigValidationError[] {\r\n const errors: ConfigValidationError[] = [];\r\n\r\n // 检查形状是否在画板边界内\r\n if (config.shapes && config.boardConfig && config.boardConfig.boundingBox) {\r\n const bbox = config.boardConfig.boundingBox;\r\n const [minX, maxY, maxX, minY] = bbox;\r\n\r\n // 检查所有形状的顶点是否在边界内\r\n const allShapes = [\r\n ...(config.shapes.static || []),\r\n ...(config.shapes.animated || [])\r\n ];\r\n\r\n for (let i = 0; i < allShapes.length; i++) {\r\n const shape = allShapes[i];\r\n if (shape && shape.vertices) {\r\n for (let j = 0; j < shape.vertices.length; j++) {\r\n const vertex = shape.vertices[j];\r\n if (Array.isArray(vertex) && vertex.length === 2) {\r\n const [x, y] = vertex;\r\n if (x < minX || x > maxX || y < minY || y > maxY) {\r\n errors.push(createValidationError(\r\n 'GEOMETRY_INCONSISTENCY',\r\n `形状 ${i} 的顶点 ${j} (${x}, ${y}) 超出画板边界`,\r\n `$.shapes.${i < (config.shapes.static?.length || 0) ? 'static' : 'animated'}[${i}].vertices[${j}]`,\r\n vertex,\r\n [Math.max(minX, Math.min(x, maxX)), Math.max(minY, Math.min(y, maxY))]\r\n ));\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // 检查底边和高度与三角形面积的一致性(如果提供了metadata)\r\n if (config.metadata && config.metadata.base && config.metadata.height) {\r\n const expectedArea = 0.5 * config.metadata.base * config.metadata.height;\r\n\r\n // 尝试从第一个静态形状计算面积\r\n if (config.shapes?.static?.[0]?.vertices) {\r\n const vertices = config.shapes.static[0].vertices;\r\n if (vertices.length === 3) {\r\n // 使用三角形面积公式:0.5 * |(x2-x1)*(y3-y1) - (x3-x1)*(y2-y1)|\r\n const [x1, y1] = vertices[0];\r\n const [x2, y2] = vertices[1];\r\n const [x3, y3] = vertices[2];\r\n const calculatedArea = 0.5 * Math.abs(\r\n (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)\r\n );\r\n\r\n // 允许一定的浮点误差\r\n const tolerance = 0.01;\r\n if (Math.abs(calculatedArea - expectedArea) > tolerance) {\r\n errors.push(createValidationError(\r\n 'GEOMETRY_INCONSISTENCY',\r\n `计算面积 (${calculatedArea.toFixed(2)}) 与预期面积 (${expectedArea.toFixed(2)}) 不一致`,\r\n '$.metadata',\r\n { base: config.metadata.base, height: config.metadata.height, calculatedArea, expectedArea }\r\n ));\r\n }\r\n }\r\n }\r\n }\r\n\r\n return errors;\r\n}\r\n\r\n/**\r\n * 生成修复建议\r\n *\r\n * @param errors 验证错误列表\r\n * @returns 修复建议列表\r\n */\r\nfunction generateFixSuggestions(errors: ConfigValidationError[]): ConfigFixSuggestion[] {\r\n const fixes: ConfigFixSuggestion[] = [];\r\n\r\n for (const error of errors) {\r\n switch (error.code) {\r\n case 'INVALID_TRIANGLE_TYPE':\r\n fixes.push({\r\n action: 'replace',\r\n path: error.path,\r\n value: error.suggestedValue || 'right_triangle',\r\n description: `将三角形类型修复为: ${error.suggestedValue || 'right_triangle'}`,\r\n isSafe: true,\r\n });\r\n break;\r\n\r\n case 'INVALID_BASE_VALUE':\r\n fixes.push({\r\n action: 'replace',\r\n path: error.path,\r\n value: error.suggestedValue || 1,\r\n description: `将底边长度修复为: ${error.suggestedValue || 1}`,\r\n isSafe: true,\r\n });\r\n break;\r\n\r\n case 'INVALID_HEIGHT_VALUE':\r\n fixes.push({\r\n action: 'replace',\r\n path: error.path,\r\n value: error.suggestedValue || 1,\r\n description: `将高度修复为: ${error.suggestedValue || 1}`,\r\n isSafe: true,\r\n });\r\n break;\r\n\r\n case 'INVALID_ORIGIN':\r\n fixes.push({\r\n action: 'replace',\r\n path: error.path,\r\n value: error.suggestedValue || 0,\r\n description: `将原点坐标修复为: ${error.suggestedValue || 0}`,\r\n isSafe: true,\r\n });\r\n break;\r\n\r\n case 'MISSING_TRANSFORM':\r\n fixes.push({\r\n action: 'add',\r\n path: error.path,\r\n value: { type: 'rotation' },\r\n description: '添加默认旋转变换配置',\r\n isSafe: false, // 添加变换可能不安全,需要用户确认\r\n });\r\n break;\r\n\r\n default:\r\n // 对于其他错误,提供通用修复建议\r\n if (error.suggestedValue !== undefined) {\r\n fixes.push({\r\n action: 'replace',\r\n path: error.path,\r\n value: error.suggestedValue,\r\n description: `修复 ${error.code} 错误`,\r\n isSafe: false,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return fixes;\r\n}\r\n\r\n// ========== 验证器类定义 ==========\r\n\r\n/**\r\n * 基础配置验证器\r\n * 实现 GeometryConfigGenerator 接口,提供配置验证功能\r\n */\r\nclass BaseValidator implements GeometryConfigGenerator {\r\n protected shapeType: string;\r\n\r\n constructor(shapeType: string) {\r\n this.shapeType = shapeType;\r\n }\r\n\r\n /**\r\n * 生成配置(占位实现)\r\n */\r\n generate(options: any): import('./types').Result<import('./types').DynamicGeometryTransformConfig, import('./types').ConfigGenerationError> {\r\n throw new Error('Method not implemented: generate');\r\n }\r\n\r\n /**\r\n * 验证配置\r\n */\r\n validate(options: any): ConfigValidationResult {\r\n // 根据形状类型调用相应的验证函数\r\n switch (this.shapeType) {\r\n case 'triangle':\r\n if (this.isTriangleConfig(options)) {\r\n return validateTriangleConfigOptions(options);\r\n } else if (this.isDynamicGeometryTransformConfig(options)) {\r\n return validateGeometryTransformConfig(options);\r\n }\r\n break;\r\n case 'parallelogram':\r\n // 平行四边形验证(待实现)\r\n return this.validateGenericConfig(options);\r\n default:\r\n return this.validateGenericConfig(options);\r\n }\r\n\r\n // 默认返回验证失败\r\n return {\r\n isValid: false,\r\n errors: [createValidationError(\r\n 'INVALID_SHAPE_VERTICES',\r\n `不支持的形状类型: ${this.shapeType}`,\r\n '$.type',\r\n this.shapeType,\r\n 'triangle'\r\n )],\r\n fixes: [],\r\n timestamp: new Date().toISOString(),\r\n };\r\n }\r\n\r\n /**\r\n * 获取支持的形状类型\r\n */\r\n getSupportedShapes(): string[] {\r\n switch (this.shapeType) {\r\n case 'triangle':\r\n return ['right_triangle', 'acute_triangle', 'obtuse_triangle'];\r\n case 'parallelogram':\r\n return ['parallelogram', 'rectangle', 'square'];\r\n default:\r\n return [this.shapeType];\r\n }\r\n }\r\n\r\n /**\r\n * 获取支持的检查类型(测试需要)\r\n */\r\n getSupportedChecks(): string[] {\r\n return ['shape_integrity', 'transform_consistency', 'strategy_match', 'unit_consistency'];\r\n }\r\n\r\n /**\r\n * 获取默认选项\r\n */\r\n getDefaultOptions(): any {\r\n switch (this.shapeType) {\r\n case 'triangle':\r\n return {\r\n type: 'right_triangle',\r\n base: 8,\r\n height: 6,\r\n originX: 0,\r\n originY: 0,\r\n unit: 'in'\r\n };\r\n case 'parallelogram':\r\n return {\r\n type: 'parallelogram',\r\n base: 6,\r\n height: 4,\r\n unit: 'cm'\r\n };\r\n default:\r\n return {};\r\n }\r\n }\r\n\r\n /**\r\n * 类型守卫:检查是否为三角形配置选项\r\n */\r\n private isTriangleConfig(value: any): value is TriangleConfigOptions {\r\n return value && typeof value === 'object' && 'type' in value && 'base' in value && 'height' in value;\r\n }\r\n\r\n /**\r\n * 类型守卫:检查是否为动态几何变换配置\r\n */\r\n private isDynamicGeometryTransformConfig(value: any): value is DynamicGeometryTransformConfig {\r\n return value && typeof value === 'object' && 'shapes' in value && 'transform' in value;\r\n }\r\n\r\n /**\r\n * 通用配置验证\r\n */\r\n private validateGenericConfig(config: any): ConfigValidationResult {\r\n const errors: ConfigValidationError[] = [];\r\n const fixes: ConfigFixSuggestion[] = [];\r\n\r\n // 基本验证\r\n if (!config || typeof config !== 'object') {\r\n errors.push(createValidationError(\r\n 'INVALID_SHAPE_VERTICES',\r\n '配置必须是一个对象',\r\n '$',\r\n config,\r\n {}\r\n ));\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n fixes,\r\n timestamp: new Date().toISOString(),\r\n };\r\n }\r\n}\r\n\r\n// ========== 导出占位函数 ==========\r\n\r\nexport default {\r\n validateGeometryTransformConfig,\r\n createConfigValidator,\r\n isValidTransformConfig,\r\n validateTriangleConfigOptions,\r\n createValidationError,\r\n applyConfigFixes,\r\n};","/**\r\n * 平行四边形几何变换配置生成器\r\n *\r\n * 此模块提供了根据平行四边形尺寸动态生成GeometryTransform配置的功能。\r\n * 支持平行四边形割补变换演示,用于平行四边形面积公式推导。\r\n *\r\n * @module parallelogramConfigGenerator\r\n */\r\n\r\nimport type {\r\n DynamicGeometryTransformConfig,\r\n ConfigValidationResult,\r\n} from './types';\r\nimport { ConfigGenerationError } from './types';\r\nimport { validateGeometryTransformConfig } from './configValidation';\r\n\r\n/**\r\n * 平行四边形配置选项\r\n */\r\nexport interface ParallelogramConfigOptions {\r\n /** 底边长度 */\r\n base: number;\r\n /** 高度 */\r\n height: number;\r\n /** 倾斜度(可选,默认 base/3) */\r\n skew?: number;\r\n /** 原点X坐标(可选,默认0) */\r\n originX?: number;\r\n /** 原点Y坐标(可选,默认0) */\r\n originY?: number;\r\n /** 长度单位(可选,默认'in') */\r\n unit?: string;\r\n /** 主题样式(可选) */\r\n theme?: 'light' | 'dark';\r\n /** 布局密度(可选) */\r\n layoutDensity?: 'default' | 'compact';\r\n}\r\n\r\n/**\r\n * 生成平行四边形几何变换配置\r\n *\r\n * @param options 平行四边形配置选项\r\n * @returns 动态几何变换配置\r\n * @throws {ConfigGenerationError} 当配置生成失败时抛出\r\n */\r\nexport function generateParallelogramConfig(options: ParallelogramConfigOptions): DynamicGeometryTransformConfig {\r\n // 验证输入选项\r\n if (!isValidParallelogramConfigOptions(options)) {\r\n throw new ConfigGenerationError(\r\n 'Invalid parallelogram config options',\r\n 'parallelogram',\r\n options\r\n );\r\n }\r\n\r\n const { base, height, unit = 'in', layoutDensity = 'compact', theme = 'light' } = options;\r\n const originX = options.originX ?? 0;\r\n const originY = options.originY ?? 0;\r\n const skew = options.skew ?? base / 3;\r\n\r\n try {\r\n // 生成各个配置部分\r\n const shapes = generateParallelogramShapes(base, height, skew, originX, originY, theme);\r\n const transform = generateTranslationTransform(base);\r\n const animation = generateAnimationConfig(layoutDensity);\r\n const boardConfig = generateBoardConfig(base, height, skew, originX, originY);\r\n\r\n // 构建完整配置\r\n return {\r\n ui: {\r\n layoutDensity,\r\n },\r\n base,\r\n height,\r\n unit,\r\n shapes,\r\n transform,\r\n animation,\r\n boardConfig,\r\n strategy: 'cut_and_paste', // 平行四边形使用割补策略\r\n theme,\r\n enableRigidityVerification: true,\r\n enableKeyboardNavigation: true,\r\n autoCompleteThreshold: 0.95,\r\n metadata: {\r\n triangleType: 'right_triangle' as any, // 临时使用right_triangle,虽然类型不正确\r\n base,\r\n height,\r\n unit,\r\n originX,\r\n originY,\r\n strategy: 'cut_and_paste',\r\n generatedAt: new Date().toISOString(),\r\n },\r\n };\r\n } catch (error) {\r\n // 如果已经是ConfigGenerationError,直接抛出\r\n if (error instanceof ConfigGenerationError) {\r\n throw error;\r\n }\r\n // 否则包装为ConfigGenerationError\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n throw new ConfigGenerationError(\r\n errorMessage,\r\n 'parallelogram',\r\n options,\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * 验证平行四边形配置选项是否有效\r\n *\r\n * @param options 配置选项\r\n * @returns 是否为有效的配置选项\r\n */\r\nexport function isValidParallelogramConfigOptions(options: any): boolean {\r\n // 检查基本结构\r\n if (!options || typeof options !== 'object') {\r\n return false;\r\n }\r\n\r\n // 检查必需字段\r\n const requiredFields = ['base', 'height'];\r\n for (const field of requiredFields) {\r\n if (!(field in options)) {\r\n return false;\r\n }\r\n }\r\n\r\n // 检查底边和高度是否为有效正数\r\n if (typeof options.base !== 'number' || options.base <= 0 ||\r\n typeof options.height !== 'number' || options.height <= 0) {\r\n return false;\r\n }\r\n\r\n // 检查倾斜度(如果提供)\r\n if (options.skew !== undefined && (typeof options.skew !== 'number' || options.skew < 0)) {\r\n return false;\r\n }\r\n\r\n // 检查原点坐标(如果提供)\r\n if (options.originX !== undefined && (typeof options.originX !== 'number' || !isFinite(options.originX))) {\r\n return false;\r\n }\r\n if (options.originY !== undefined && (typeof options.originY !== 'number' || !isFinite(options.originY))) {\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * 生成平行四边形形状定义\r\n */\r\nfunction generateParallelogramShapes(\r\n base: number,\r\n height: number,\r\n skew: number,\r\n originX: number,\r\n originY: number,\r\n theme: 'light' | 'dark'\r\n): any {\r\n // 根据主题选择颜色\r\n const getColors = () => {\r\n if (theme === 'dark') {\r\n return {\r\n staticFill: '#2a4365',\r\n staticStroke: '#1a365d',\r\n animatedFill: '#4c51bf',\r\n animatedStroke: '#434190',\r\n };\r\n }\r\n return {\r\n staticFill: '#8ec5fc',\r\n staticStroke: '#4a90e2',\r\n animatedFill: '#6a5acd',\r\n animatedStroke: '#483d8b',\r\n };\r\n };\r\n\r\n const colors = getColors();\r\n\r\n // 计算梯形顶点(静态部分)\r\n // 梯形:左下 -> 右下 -> 右上 -> 左上\r\n const trapezoidVertices = [\r\n [originX + skew, originY], // 左下\r\n [originX + base, originY], // 右下\r\n [originX + base + skew, originY + height], // 右上\r\n [originX + skew, originY + height], // 左上\r\n ];\r\n\r\n // 计算三角形顶点(动画部分)\r\n const triangleVertices = [\r\n [originX, originY], // 左下\r\n [originX + skew, originY], // 右下\r\n [originX + skew, originY + height], // 左上\r\n ];\r\n\r\n return {\r\n static: [\r\n {\r\n type: 'trapezoid' as const,\r\n vertices: trapezoidVertices,\r\n style: {\r\n fillColor: colors.staticFill,\r\n fillOpacity: 0.6,\r\n strokeColor: colors.staticStroke,\r\n strokeWidth: 2,\r\n },\r\n metadata: {\r\n id: 'static-trapezoid',\r\n label: '梯形部分',\r\n isStatic: true,\r\n },\r\n },\r\n ],\r\n animated: [\r\n {\r\n type: 'triangle' as const,\r\n vertices: triangleVertices,\r\n style: {\r\n fillColor: colors.animatedFill,\r\n fillOpacity: 0.7,\r\n strokeColor: colors.animatedStroke,\r\n strokeWidth: 2,\r\n },\r\n metadata: {\r\n id: 'animated-triangle',\r\n label: '移动三角形',\r\n isMovable: true,\r\n },\r\n },\r\n ],\r\n };\r\n}\r\n\r\n/**\r\n * 生成平移变换配置\r\n */\r\nfunction generateTranslationTransform(base: number): any {\r\n return {\r\n type: 'translation' as const,\r\n config: {\r\n direction: [1, 0] as [number, number], // 水平方向向量\r\n distance: base, // 向右平移底边长度\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 生成动画配置\r\n */\r\nfunction generateAnimationConfig(layoutDensity: 'default' | 'compact'): any {\r\n // 根据布局密度调整滑块位置\r\n const sliderPosition = layoutDensity === 'compact' ? [0, -5] : [0, -8];\r\n\r\n return {\r\n slider: {\r\n position: sliderPosition as [number, number],\r\n length: 10,\r\n orientation: 'horizontal' as const,\r\n min: 0,\r\n max: 1,\r\n step: 0.01,\r\n },\r\n progressIndicator: {\r\n enabled: false, // 平行四边形演示通常不使用阶段指示器\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 生成画板配置\r\n */\r\nfunction generateBoardConfig(\r\n base: number,\r\n height: number,\r\n skew: number,\r\n originX: number,\r\n originY: number\r\n): any {\r\n // 计算图形的边界框\r\n const minX = Math.min(originX, originX + skew, originX + base, originX + base + skew);\r\n const maxX = Math.max(originX, originX + skew, originX + base, originX + base + skew);\r\n const minY = Math.min(originY, originY + height);\r\n const maxY = Math.max(originY, originY + height);\r\n\r\n // 添加边距\r\n const margin = 3;\r\n const boundingBox: [number, number, number, number] = [\r\n minX - margin, // minX\r\n maxY + margin, // maxY\r\n maxX + margin, // maxX\r\n minY - margin, // minY\r\n ];\r\n\r\n return {\r\n boundingBox,\r\n keepAspectRatio: true,\r\n showGrid: true,\r\n showAxis: false,\r\n };\r\n}\r\n\r\n/**\r\n * 验证平行四边形配置是否有效\r\n *\r\n * @param config 几何变换配置\r\n * @returns 配置验证结果\r\n */\r\nexport function validateParallelogramConfig(config: any): ConfigValidationResult {\r\n // 使用通用的配置验证工具\r\n return validateGeometryTransformConfig(config);\r\n}\r\n\r\n// ========== 导出占位函数 ==========\r\n\r\nexport default {\r\n generateParallelogramConfig,\r\n isValidParallelogramConfigOptions,\r\n validateParallelogramConfig,\r\n};","import type { Explanation, ExplanationStep } from '../../../../components/MathCardV2/MathPracticeSessionTypes';\r\n\r\n/**\r\n * 转换snake_case字段名为camelCase\r\n */\r\nexport function convertSnakeCaseToCamelCase(obj: any): any {\r\n if (!obj || typeof obj !== 'object') return obj;\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(item => convertSnakeCaseToCamelCase(item));\r\n }\r\n\r\n const result: any = {};\r\n for (const [key, value] of Object.entries(obj)) {\r\n // 转换snake_case到camelCase\r\n const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\r\n\r\n // 递归处理嵌套对象\r\n result[camelKey] = convertSnakeCaseToCamelCase(value);\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * 标准化解释数据\r\n */\r\nexport function normalizeExplanation(explanation: any): Explanation | ExplanationStep[] {\r\n // 如果已经是数组格式,直接返回\r\n if (Array.isArray(explanation)) {\r\n return explanation;\r\n }\r\n\r\n // 如果是对象格式且有steps字段,返回对象\r\n if (explanation && explanation.steps) {\r\n return explanation as Explanation;\r\n }\r\n\r\n // 默认返回空解释\r\n return {\r\n steps: [],\r\n strategy: 'default',\r\n total_steps: 0,\r\n estimated_time: 0\r\n };\r\n}\r\n\r\n/**\r\n * 获取基础字段映射\r\n */\r\nexport function getBaseFieldMappings(jsonData: any) {\r\n return {\r\n // 核心标识字段\r\n id: jsonData.id || jsonData.math_prob_id,\r\n title: jsonData.title || '',\r\n\r\n // 教学元数据\r\n grade: jsonData.grade || 5,\r\n unit: jsonData.unit || jsonData.unit_name || '',\r\n lesson: jsonData.lesson || jsonData.lesson_name || '',\r\n skill: jsonData.skill || jsonData.skill_description || '',\r\n objective: jsonData.objective || '',\r\n\r\n // 转换后的字段\r\n knowledgePoints: Array.isArray(jsonData.knowledge_points)\r\n ? jsonData.knowledge_points\r\n : Array.isArray(jsonData.knowledgePoints)\r\n ? jsonData.knowledgePoints\r\n : [],\r\n\r\n difficulty: jsonData.difficulty || 1,\r\n description: jsonData.description || '',\r\n\r\n // 元数据\r\n metadata: jsonData.metadata || {\r\n topic: '',\r\n skill: '',\r\n tags: []\r\n },\r\n\r\n // 保留原始JSON中的其他字段\r\n math_prob_id: jsonData.math_prob_id,\r\n grade_id: jsonData.grade_id,\r\n unit_id: jsonData.unit_id,\r\n lesson_id: jsonData.lesson_id,\r\n module_id: jsonData.module_id,\r\n skill_item_id: jsonData.skill_item_id,\r\n skill_id: jsonData.skill_id,\r\n created_at: jsonData.created_at,\r\n updated_at: jsonData.updated_at,\r\n\r\n // 布局配置\r\n layout: jsonData.layout || {\r\n type: 'card',\r\n padding: '20px',\r\n theme: 'light'\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * 获取基础信息字段\r\n */\r\nexport function getBasicInfoFields(basicInfo: any) {\r\n const info = basicInfo || {};\r\n\r\n return {\r\n question: info.question || '',\r\n answerUnit: info.answerUnit || '',\r\n areaUnit: info.areaUnit || '',\r\n shape: info.shape || '',\r\n base: info.base || info.length || 0,\r\n height: info.height || info.width || 0,\r\n baseUnit: info.baseUnit || info.lengthUnit || '',\r\n heightUnit: info.heightUnit || info.widthUnit || '',\r\n // 向后兼容字段\r\n length: info.base || info.length || 0,\r\n width: info.height || info.width || 0,\r\n lengthUnit: info.baseUnit || info.lengthUnit || '',\r\n widthUnit: info.heightUnit || info.widthUnit || '',\r\n variables: info.variables || {},\r\n context: info.context || {}\r\n };\r\n}\r\n\r\n/**\r\n * 验证数据完整性\r\n */\r\nexport function validateProblemData(data: any): string[] {\r\n const errors: string[] = [];\r\n\r\n if (!data.id) {\r\n errors.push('缺少id字段');\r\n }\r\n\r\n if (!data.title) {\r\n errors.push('缺少title字段');\r\n }\r\n\r\n if (!data.basicInfo?.question) {\r\n errors.push('缺少basicInfo.question字段');\r\n }\r\n\r\n return errors;\r\n}\r\n\r\n/**\r\n * 创建默认答案信息\r\n */\r\nexport function createDefaultAnswerInfo(value: number, unit: string, explanation: string) {\r\n return {\r\n value,\r\n unit,\r\n type: 'numeric' as const,\r\n tolerance: 0.01,\r\n format: {\r\n decimal_places: 2,\r\n allow_fraction: true,\r\n allow_negative: false\r\n },\r\n validation_rules: {\r\n required: true,\r\n min_value: 0,\r\n max_value: 1000,\r\n exact_match: false\r\n },\r\n explanation_text: explanation\r\n };\r\n}\r\n\r\n/**\r\n * 从answer_info创建answer字段\r\n */\r\nexport function createAnswerFromAnswerInfo(answerInfo: any): any {\r\n if (!answerInfo) return null;\r\n\r\n return {\r\n value: answerInfo.value,\r\n unit: answerInfo.unit,\r\n explanation: answerInfo.explanation_text || answerInfo.explanation || '正确答案'\r\n };\r\n}\r\n\r\n/**\r\n * 获取兼容的答案字段(优先使用answer,如果没有则从answer_info创建)\r\n */\r\nexport function getCompatibleAnswer(jsonData: any): any {\r\n // 如果jsonData中有answer字段,直接使用\r\n if (jsonData.answer) return jsonData.answer;\r\n\r\n // 如果jsonData中有answer_info字段,从中创建answer\r\n if (jsonData.answer_info) {\r\n return createAnswerFromAnswerInfo(jsonData.answer_info);\r\n }\r\n\r\n // 如果两者都没有,返回null\r\n return null;\r\n}","import type { Explanation } from '../../../../components/MathCardV2/MathPracticeSessionTypes';\r\n\r\n/**\r\n * 获取默认的平行四边形场景配置\r\n */\r\nexport function getDefaultParallelogramScenes() {\r\n return {\r\n question: {\r\n content: [\r\n {\r\n type: 'text',\r\n content: 'What is the area of the parallelogram?',\r\n style: {\r\n fontSize: '1.5rem',\r\n color: '#1e293b',\r\n fontWeight: 'bold',\r\n textAlign: 'center',\r\n marginBottom: '20px'\r\n }\r\n }\r\n ],\r\n layout: {\r\n type: 'vertical',\r\n spacing: '20px',\r\n alignment: 'center'\r\n }\r\n },\r\n solve: {\r\n content: [\r\n {\r\n type: 'text',\r\n content: 'SOLVE',\r\n style: {\r\n fontSize: '1.25rem',\r\n fontWeight: 'bold',\r\n color: '#1e293b',\r\n marginBottom: '10px'\r\n }\r\n },\r\n {\r\n type: 'geometryTransform',\r\n content: '平行四边形割补演示',\r\n enabled: true,\r\n metadata: {\r\n componentType: 'geometry-transform'\r\n // config将在enrichScenesWithGeometryTransform中注入\r\n }\r\n }\r\n ],\r\n layout: {\r\n type: 'vertical',\r\n spacing: '20px',\r\n alignment: 'center',\r\n cardStyle: {\r\n backgroundColor: '#F0F9FF',\r\n borderColor: '#BAE6FD',\r\n borderWidth: '2px'\r\n }\r\n }\r\n },\r\n review: {\r\n content: [\r\n {\r\n type: 'text',\r\n content: 'Core Concept Review:',\r\n style: {\r\n fontSize: '1.25rem',\r\n fontWeight: 'bold',\r\n color: '#1e293b'\r\n }\r\n },\r\n {\r\n type: 'text',\r\n content: 'The area of a parallelogram is found by multiplying its base by its height.',\r\n style: {\r\n marginTop: '8px'\r\n }\r\n }\r\n ]\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * 获取默认的平行四边形解释\r\n */\r\nexport function getDefaultParallelogramExplanation(): Explanation {\r\n return {\r\n steps: [\r\n {\r\n id: 'exp-step-1',\r\n type: 'instructionalStep',\r\n title: '识别底和高',\r\n description: '确定平行四边形的底边长度 b = 9 inches 和对应的高度 h = 6 inches。'\r\n },\r\n {\r\n id: 'exp-step-2',\r\n type: 'instructionalStep',\r\n title: '割补法演示',\r\n description: '将平行四边形切割成三角形和梯形,然后将三角形移动到另一侧形成长方形。'\r\n },\r\n {\r\n id: 'exp-step-3',\r\n type: 'instructionalStep',\r\n title: '面积公式推导',\r\n description: '转换后的长方形面积 = b × h = 54 平方英寸,因此平行四边形面积 = b × h = 54 平方英寸。'\r\n }\r\n ],\r\n strategy: 'visual_transformation',\r\n total_steps: 3,\r\n estimated_time: 120\r\n };\r\n}\r\n\r\n/**\r\n * 平行四边形特定的normalizeExplanation函数\r\n */\r\nexport function normalizeParallelogramExplanation(explanation: any): Explanation | any[] {\r\n // 如果已经是数组格式,直接返回\r\n if (Array.isArray(explanation)) {\r\n return explanation;\r\n }\r\n\r\n // 如果是对象格式且有steps字段,返回对象\r\n if (explanation && explanation.steps) {\r\n return explanation as Explanation;\r\n }\r\n\r\n // 默认返回空解释,使用平行四边形特定策略\r\n return {\r\n steps: [],\r\n strategy: 'visual_transformation',\r\n total_steps: 0,\r\n estimated_time: 0\r\n };\r\n}","import type { MathPracticeProblemData } from '../../../../components/MathCardV2/MathPracticeSessionTypes';\r\nimport { generateParallelogramConfig } from '../config/parallelogramConfigGenerator';\r\nimport { validateGeometryTransformConfig } from '../config/configValidation';\r\nimport {\r\n getBaseFieldMappings,\r\n getBasicInfoFields,\r\n createDefaultAnswerInfo,\r\n getCompatibleAnswer\r\n} from './adapterUtils';\r\nimport {\r\n getDefaultParallelogramScenes,\r\n getDefaultParallelogramExplanation,\r\n normalizeParallelogramExplanation\r\n} from './parallelogramDefaults';\r\n\r\n/**\r\n * 转换平行四边形JSON数据中的字段命名:snake_case → camelCase\r\n * 并添加GeometryTransform配置\r\n */\r\nexport function adaptParallelogramData(jsonData: any): MathPracticeProblemData {\r\n // 获取基础字段映射\r\n const baseFields = getBaseFieldMappings(jsonData);\r\n\r\n // 获取基础信息字段\r\n const basicInfoFields = getBasicInfoFields(jsonData.basic_info || jsonData.basicInfo);\r\n\r\n // 默认知识点\r\n const defaultKnowledgePoints = [\r\n '平行四边形面积公式 A=bh',\r\n '平行四边形面积与矩形面积关系'\r\n ];\r\n\r\n // 使用baseFields作为基础,然后覆盖特定值\r\n const adaptedData: MathPracticeProblemData = {\r\n // 首先使用baseFields中的基础字段\r\n ...baseFields,\r\n\r\n // 覆盖默认值,确保必要的属性有值\r\n id: baseFields.id || 'parallelogram-area-001',\r\n title: baseFields.title || '平行四边形面积公式推导',\r\n grade: baseFields.grade || 5,\r\n unit: baseFields.unit || '多边形的面积',\r\n lesson: baseFields.lesson || '平行四边形的面积',\r\n skill: baseFields.skill || '已知平行四边形的底和高,求平行四边形面积',\r\n objective: baseFields.objective || '理解平行四边形面积公式 A=bh',\r\n\r\n // 知识点处理 - 如果baseFields中没有或为空,使用默认值\r\n knowledgePoints: baseFields.knowledgePoints?.length\r\n ? baseFields.knowledgePoints\r\n : defaultKnowledgePoints,\r\n\r\n // 其他基础字段 - 使用baseFields中的值或默认值\r\n difficulty: baseFields.difficulty || 1,\r\n description: baseFields.description || '通过割补变换演示理解平行四边形面积公式 A=bh',\r\n\r\n // 元数据 - 使用baseFields中的值或默认值\r\n metadata: baseFields.metadata || {\r\n topic: '面积计算',\r\n skill: '平行四边形面积公式的推导',\r\n tags: ['平行四边形', '割补变换', '面积', '公式推导', '几何变换']\r\n },\r\n\r\n // 基础信息(合并通用字段和平行四边形特定字段)\r\n basicInfo: {\r\n ...basicInfoFields,\r\n // 确保平行四边形特定默认值\r\n question: basicInfoFields.question || '计算下面平行四边形的面积:',\r\n answerUnit: basicInfoFields.answerUnit || '平方英寸',\r\n shape: basicInfoFields.shape || 'parallelogram',\r\n base: basicInfoFields.base || 9,\r\n height: basicInfoFields.height || 6,\r\n baseUnit: basicInfoFields.baseUnit || 'in',\r\n heightUnit: basicInfoFields.heightUnit || 'in',\r\n variables: basicInfoFields.variables || { b: 9, h: 6, unit: 'in' },\r\n context: basicInfoFields.context || {\r\n learning_objective: 'parallelogram_area_derivation',\r\n prerequisite_skills: ['rectangle_area', 'unit_conversion'],\r\n time_estimate: 300\r\n }\r\n },\r\n\r\n // 场景内容 - 注入GeometryTransform配置\r\n scenes: enrichScenesWithGeometryTransform(\r\n jsonData.scenes || getDefaultParallelogramScenes(),\r\n 'parallelogram',\r\n basicInfoFields\r\n ),\r\n\r\n // 解释数据标准化(使用平行四边形特定函数)\r\n explanation: normalizeParallelogramExplanation(jsonData.explanation || getDefaultParallelogramExplanation()),\r\n\r\n // 答案信息(兼容answer和answer_info两种格式)\r\n answer: getCompatibleAnswer(jsonData) || {\r\n value: 54,\r\n unit: 'square inches',\r\n explanation: '正确答案是54平方英寸。通过割补法,平行四边形可以转换为等面积的长方形,因此面积公式为:A = b × h = 9 × 6 = 54。'\r\n },\r\n\r\n // 扩展答案信息(优先使用jsonData中的answer_info,否则使用默认值)\r\n answer_info: jsonData.answer_info || createDefaultAnswerInfo(\r\n 54,\r\n 'square inches',\r\n '正确答案是54平方英寸。通过割补法,平行四边形可以转换为等面积的长方形,因此面积公式为:A = b × h = 9 × 6 = 54。'\r\n ),\r\n\r\n // 布局配置(覆盖默认值)\r\n layout: jsonData.layout || {\r\n type: 'card',\r\n padding: '20px',\r\n theme: 'light',\r\n renderer: {\r\n showFormulaSteps: true,\r\n interactiveAnimations: true,\r\n validateAnswers: true,\r\n auto_progress: true,\r\n hints_enabled: true\r\n }\r\n }\r\n };\r\n\r\n return adaptedData;\r\n}\r\n\r\n/**\r\n * 检查JSON配置是否完整有效\r\n */\r\nfunction hasValidJsonConfig(item: any): boolean {\r\n return item?.config && typeof item.config === 'object';\r\n}\r\n\r\n/**\r\n * 转换JSON配置格式为系统期望的格式\r\n * 平行四边形JSON格式可能包含 trapezoid, triangle 等字段\r\n * 需要转换为 static 和 animated 数组\r\n */\r\nfunction convertParallelogramJsonConfigToSystemFormat(jsonConfig: any): any {\r\n // 如果已经是系统格式,直接返回\r\n if (jsonConfig.shapes?.static && jsonConfig.shapes?.animated) {\r\n console.log('🔍 JSON config already in system format');\r\n return jsonConfig;\r\n }\r\n\r\n console.log('🔍 Converting parallelogram JSON config to system format');\r\n console.log('📦 Input JSON config transform:', {\r\n hasTransform: !!jsonConfig.transform,\r\n type: getTransformType(jsonConfig.transform),\r\n distance: getTranslationDistance(jsonConfig.transform),\r\n direction: getTranslationDirection(jsonConfig.transform)\r\n });\r\n\r\n try {\r\n const converted = { ...jsonConfig };\r\n\r\n // 转换shapes格式\r\n if (jsonConfig.shapes && typeof jsonConfig.shapes === 'object') {\r\n // 平行四边形配置可能有不同的结构\r\n // 尝试常见格式:trapezoid(静态部分),triangle(动画部分)\r\n const staticShapes: any[] = [];\r\n const animatedShapes: any[] = [];\r\n\r\n // 检查是否有 trapezoid 字段(静态梯形部分)\r\n if (jsonConfig.shapes.trapezoid) {\r\n const trapezoid = jsonConfig.shapes.trapezoid;\r\n if (Array.isArray(trapezoid)) {\r\n staticShapes.push(...trapezoid.map((shape: any) => ({\r\n ...shape,\r\n metadata: {\r\n ...shape.metadata,\r\n isStatic: true\r\n }\r\n })));\r\n } else if (typeof trapezoid === 'object') {\r\n staticShapes.push({\r\n ...trapezoid,\r\n metadata: {\r\n ...trapezoid.metadata,\r\n isStatic: true\r\n }\r\n });\r\n }\r\n }\r\n\r\n // 检查是否有 triangle 字段(动画三角形部分)\r\n if (jsonConfig.shapes.triangle) {\r\n const triangle = jsonConfig.shapes.triangle;\r\n if (Array.isArray(triangle)) {\r\n animatedShapes.push(...triangle.map((shape: any) => ({\r\n ...shape,\r\n metadata: {\r\n ...shape.metadata,\r\n isMovable: true\r\n }\r\n })));\r\n } else if (typeof triangle === 'object') {\r\n animatedShapes.push({\r\n ...triangle,\r\n metadata: {\r\n ...triangle.metadata,\r\n isMovable: true\r\n }\r\n });\r\n }\r\n }\r\n\r\n // 如果没有找到特定字段,尝试通用转换\r\n if (staticShapes.length === 0 || animatedShapes.length === 0) {\r\n // 尝试将 original/static 字段作为静态,animated/movable 字段作为动画\r\n Object.entries(jsonConfig.shapes).forEach(([key, shape]: [string, any]) => {\r\n const keyLower = key.toLowerCase();\r\n if (keyLower.includes('static') || keyLower.includes('original') || keyLower.includes('trapezoid')) {\r\n if (Array.isArray(shape)) {\r\n staticShapes.push(...shape);\r\n } else if (shape && typeof shape === 'object') {\r\n staticShapes.push(shape);\r\n }\r\n } else if (keyLower.includes('animated') || keyLower.includes('movable') || keyLower.includes('triangle')) {\r\n if (Array.isArray(shape)) {\r\n animatedShapes.push(...shape);\r\n } else if (shape && typeof shape === 'object') {\r\n animatedShapes.push(shape);\r\n }\r\n }\r\n });\r\n }\r\n\r\n converted.shapes = {\r\n static: staticShapes,\r\n animated: animatedShapes\r\n };\r\n }\r\n\r\n // 确保必要字段存在\r\n if (!converted.base && jsonConfig.base) {\r\n converted.base = jsonConfig.base;\r\n }\r\n\r\n if (!converted.height && jsonConfig.height) {\r\n converted.height = jsonConfig.height;\r\n }\r\n\r\n if (!converted.unit && jsonConfig.unit) {\r\n converted.unit = jsonConfig.unit;\r\n }\r\n\r\n // 转换transform格式(如果必要)\r\n const transformType = getTransformType(jsonConfig.transform);\r\n if (jsonConfig.transform && transformType === 'translation') {\r\n console.log('🔧 Processing translation transform from JSON');\r\n console.log('📐 JSON transform details:', {\r\n type: transformType,\r\n translation: jsonConfig.transform.translation,\r\n distance: getTranslationDistance(jsonConfig.transform),\r\n direction: getTranslationDirection(jsonConfig.transform)\r\n });\r\n\r\n // JSON格式的translation可能在transform.translation中\r\n if (jsonConfig.transform.translation) {\r\n converted.transform = {\r\n type: 'translation',\r\n translation: jsonConfig.transform.translation\r\n };\r\n console.log('✅ Set converted.transform with distance:',\r\n getTranslationDistance(jsonConfig.transform));\r\n }\r\n } else if (jsonConfig.transform) {\r\n console.log('⚠️ JSON has transform but not translation type:', getTransformType(jsonConfig.transform));\r\n } else {\r\n console.log('ℹ️ No transform found in JSON config');\r\n }\r\n\r\n // 确保animation配置存在\r\n if (!converted.animation) {\r\n converted.animation = {\r\n slider: {\r\n position: [0, -5],\r\n length: 10,\r\n orientation: 'horizontal',\r\n min: 0,\r\n max: 1,\r\n step: 0.01\r\n },\r\n progressIndicator: {\r\n enabled: false\r\n }\r\n };\r\n } else {\r\n // 确保animation有slider配置\r\n if (!converted.animation.slider) {\r\n converted.animation.slider = {\r\n position: [0, -5],\r\n length: 10,\r\n orientation: 'horizontal',\r\n min: 0,\r\n max: 1,\r\n step: 0.01\r\n };\r\n }\r\n // 确保progressIndicator存在\r\n if (!converted.animation.progressIndicator) {\r\n converted.animation.progressIndicator = {\r\n enabled: false\r\n };\r\n }\r\n }\r\n\r\n // 确保boardConfig存在\r\n if (!converted.boardConfig && jsonConfig.boardConfig) {\r\n converted.boardConfig = jsonConfig.boardConfig;\r\n }\r\n\r\n // 添加策略标识(如果缺失)\r\n if (!converted.strategy) {\r\n converted.strategy = 'cut_and_paste';\r\n }\r\n\r\n // 确保theme字段存在\r\n if (!converted.theme) {\r\n converted.theme = 'light';\r\n }\r\n\r\n // 确保layoutDensity字段存在\r\n if (!converted.layoutDensity) {\r\n converted.layoutDensity = 'compact';\r\n }\r\n\r\n // 确保ui字段存在\r\n if (!converted.ui) {\r\n converted.ui = {\r\n layoutDensity: converted.layoutDensity\r\n };\r\n }\r\n\r\n // 确保baseUnit和heightUnit字段存在\r\n if (!converted.baseUnit && converted.unit) {\r\n converted.baseUnit = converted.unit;\r\n }\r\n if (!converted.heightUnit && converted.unit) {\r\n converted.heightUnit = converted.unit;\r\n }\r\n\r\n // 添加metadata字段(如果缺失)\r\n if (!converted.metadata) {\r\n converted.metadata = {\r\n shapeType: 'parallelogram',\r\n base: converted.base,\r\n height: converted.height,\r\n unit: converted.unit,\r\n strategy: converted.strategy,\r\n generatedAt: new Date().toISOString()\r\n };\r\n }\r\n\r\n console.log('🎉 Conversion complete. Final converted config:');\r\n console.log('📊 Final transform:', {\r\n type: getTransformType(converted.transform),\r\n distance: getTranslationDistance(converted.transform),\r\n direction: getTranslationDirection(converted.transform)\r\n });\r\n console.log('📐 Final base:', converted.base, 'height:', converted.height);\r\n console.log('🏷️ Final strategy:', converted.strategy, 'theme:', converted.theme);\r\n\r\n return converted;\r\n } catch (error) {\r\n console.warn('Failed to convert parallelogram JSON config format:', error);\r\n // 转换失败,返回原始配置\r\n return jsonConfig;\r\n }\r\n}\r\n\r\n/**\r\n * 获取变换配置中的平移距离\r\n * 处理 TransformConfig | TransformConfig[] 类型\r\n */\r\nfunction getTranslationDistance(transform: any): string {\r\n if (!transform) return 'N/A';\r\n\r\n // 如果是数组,取第一个元素\r\n const config = Array.isArray(transform) ? transform[0] : transform;\r\n\r\n // 检查旧格式 { type: 'translation', translation: { distance, direction } }\r\n if (config?.translation?.distance !== undefined) {\r\n return String(config.translation.distance);\r\n }\r\n\r\n // 检查新格式 { type: 'translation', config: { distance, direction } }\r\n if (config?.config?.distance !== undefined) {\r\n return String(config.config.distance);\r\n }\r\n\r\n return 'N/A';\r\n}\r\n\r\n/**\r\n * 获取变换配置中的平移方向\r\n * 处理 TransformConfig | TransformConfig[] 类型\r\n */\r\nfunction getTranslationDirection(transform: any): any {\r\n if (!transform) return undefined;\r\n\r\n // 如果是数组,取第一个元素\r\n const config = Array.isArray(transform) ? transform[0] : transform;\r\n\r\n // 检查旧格式 { type: 'translation', translation: { distance, direction } }\r\n if (config?.translation?.direction !== undefined) {\r\n return config.translation.direction;\r\n }\r\n\r\n // 检查新格式 { type: 'translation', config: { distance, direction } }\r\n if (config?.config?.direction !== undefined) {\r\n return config.config.direction;\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n/**\r\n * 获取变换配置类型\r\n * 处理 TransformConfig | TransformConfig[] 类型\r\n */\r\nfunction getTransformType(transform: any): string {\r\n if (!transform) return 'N/A';\r\n\r\n // 如果是数组,取第一个元素\r\n const config = Array.isArray(transform) ? transform[0] : transform;\r\n\r\n // 返回变换类型\r\n return config?.type || 'N/A';\r\n}\r\n\r\n/**\r\n * 在场景中注入GeometryTransform配置\r\n */\r\nfunction enrichScenesWithGeometryTransform(scenes: any, problemType: string, basicInfo?: any): any {\r\n if (problemType !== 'parallelogram') return scenes;\r\n\r\n // 如果scenes中已经有solve场景,注入GeometryTransform配置\r\n if (scenes?.solve?.content) {\r\n const enrichedContent = scenes.solve.content.map((item: any) => {\r\n if (item.type === 'geometryTransform') {\r\n // 优先检查JSON中是否已提供配置\r\n if (hasValidJsonConfig(item)) {\r\n try {\r\n // 转换JSON配置为系统格式\r\n const jsonConfig = convertParallelogramJsonConfigToSystemFormat(item.config);\r\n\r\n // 验证配置有效性\r\n const validationResult = validateGeometryTransformConfig(jsonConfig);\r\n\r\n if (validationResult.isValid) {\r\n console.log('✅ Using JSON-provided parallelogram geometry transform configuration');\r\n console.log('📏 JSON transform distance:',\r\n getTranslationDistance(jsonConfig.transform));\r\n console.log('📐 JSON base:', jsonConfig.base, 'height:', jsonConfig.height);\r\n return {\r\n ...item,\r\n metadata: {\r\n ...item.metadata,\r\n config: jsonConfig,\r\n source: 'json', // 标记配置来源\r\n validationResult\r\n }\r\n };\r\n } else {\r\n console.warn('❌ JSON-provided parallelogram config validation failed:', validationResult.errors);\r\n console.log('📊 JSON config structure:', {\r\n hasShapes: !!jsonConfig.shapes,\r\n hasTransform: !!jsonConfig.transform,\r\n transformType: getTransformType(jsonConfig.transform),\r\n distance: getTranslationDistance(jsonConfig.transform),\r\n strategy: jsonConfig.strategy,\r\n theme: jsonConfig.theme\r\n });\r\n // 验证失败,继续动态生成\r\n }\r\n } catch (error) {\r\n console.warn('Failed to process JSON-provided parallelogram config:', error);\r\n // 处理失败,继续动态生成\r\n }\r\n }\r\n\r\n // 如果JSON中没有配置或配置无效,动态生成配置\r\n let dynamicConfig;\r\n try {\r\n // 动态生成平行四边形配置\r\n const dynamicBase = basicInfo?.base || 9;\r\n const dynamicHeight = basicInfo?.height || 6;\r\n console.log('🔄 Generating dynamic parallelogram config with base:', dynamicBase, 'height:', dynamicHeight);\r\n\r\n dynamicConfig = generateParallelogramConfig({\r\n base: dynamicBase,\r\n height: dynamicHeight,\r\n unit: basicInfo?.baseUnit || basicInfo?.unit || 'in',\r\n originX: basicInfo?.originX,\r\n originY: basicInfo?.originY,\r\n layoutDensity: 'compact' as const\r\n });\r\n\r\n console.log('📏 Dynamic transform distance:',\r\n getTranslationDistance(dynamicConfig.transform));\r\n } catch (error) {\r\n console.warn('Failed to generate dynamic parallelogram config:', error);\r\n // 使用默认配置作为回退\r\n console.log('🔄 Using fallback dynamic config with base: 9, height: 6');\r\n dynamicConfig = generateParallelogramConfig({\r\n base: 9,\r\n height: 6,\r\n unit: 'in',\r\n layoutDensity: 'compact' as const\r\n });\r\n console.log('📏 Fallback transform distance:',\r\n getTranslationDistance(dynamicConfig.transform));\r\n }\r\n\r\n console.log('🔧 Final config source: generated');\r\n console.log('📊 Final transform details:', {\r\n type: getTransformType(dynamicConfig.transform),\r\n direction: getTranslationDirection(dynamicConfig.transform),\r\n distance: getTranslationDistance(dynamicConfig.transform)\r\n });\r\n\r\n return {\r\n ...item,\r\n metadata: {\r\n ...item.metadata,\r\n config: dynamicConfig,\r\n source: 'generated' // 标记配置来源\r\n }\r\n };\r\n }\r\n return item;\r\n });\r\n\r\n return {\r\n ...scenes,\r\n solve: {\r\n ...scenes.solve,\r\n content: enrichedContent\r\n }\r\n };\r\n }\r\n\r\n // 如果scenes中没有solve场景,返回原始场景\r\n return scenes;\r\n}\r\n\r\n\r\n/**\r\n * 获取默认的平行四边形场景配置\r\n */\r\n\r\n/**\r\n * 获取默认的平行四边形解释\r\n */\r\n","/**\r\n * ⚠️⚠️⚠️ DEPRECATED ⚠️⚠️⚠️\r\n *\r\n * AreaGeometrySessionPage 数据加载模块 - 简化版 (已废弃)\r\n *\r\n * 此模块已废弃,将在 v2.0.0 版本中移除。\r\n *\r\n * 迁移到新的数据适配架构:\r\n * 1. 业务项目自己获取原始JSON数据(从API或静态文件)\r\n * 2. 使用 GeometryProblemAdapterV4 适配器将V4格式JSON转换为标准化格式\r\n * 3. 将转换后的 MathPracticeProblemData 直接传递给组件\r\n *\r\n * 替代方案:\r\n * - 几何问题(三角形、梯形):使用 src/data/GeometryProblemAdapterV4/index.ts\r\n * - 年龄问题:使用 src/pages/AreaGeometrySessionPage/data/adapters/ageProblemAdapter.ts\r\n * - 平行四边形:使用 src/pages/AreaGeometrySessionPage/data/adapters/parallelogramDataAdapter.ts\r\n *\r\n * 废弃原因:组件库不应包含数据加载逻辑,违反关注点分离原则\r\n * 废弃日期:2026-02-21\r\n * 预计移除版本:v2.0.0\r\n */\r\n\r\nimport type { MathPracticeProblemData } from '../../../components/MathCardV2/MathPracticeSessionTypes';\r\nimport type { GeometryProblemDataV4, SyncAdapterConfig, AdapterResult } from '../../../data/GeometryProblemAdapterV4/types';\r\n\r\n// 导入适配器函数 - 使用 GeometryProblemAdapterV4 作为主适配器\r\nimport { adaptGeometryDataSync, adaptGeometryDataAsync } from '../../../data/GeometryProblemAdapterV4';\r\n\r\n// 导入传统适配器(仅用于年龄和平行四边形问题)\r\nimport { adaptParallelogramData } from './adapters/parallelogramDataAdapter';\r\nimport { adaptAgeProblemData } from './adapters/ageProblemAdapter';\r\n\r\n// 导入JSON数据文件\r\n// 注意:这些JSON文件可能使用snake_case字段名,适配器会处理转换\r\nimport ageProblemJson from '../../../data/GeometryProblemAdapterV4/jsondata/age-problem-compatible.json';\r\nimport triangleAreaJson from '../../../data/GeometryProblemAdapterV4/jsondata/triangle-v4-final.json';\r\nimport parallelogramAreaJson from '../../../data/GeometryProblemAdapterV4/jsondata/parallelogram-revised.json';\r\nimport acuteTrianglePoolJson from '../../../../../prd/MathCardV2/triangleAreCalculateStories/refactor/Acute-Triangle-area-data-refactored.json';\r\nimport trapezoidAreaJson from '../../../data/GeometryProblemAdapterV4/jsondata/trapezoid-v4-final.json';\r\n\r\n/**\r\n * 问题类型定义\r\n */\r\nexport type ProblemType = 'triangle' | 'parallelogram' | 'age' | 'trapezoid';\r\n\r\n/**\r\n * 通用适配器配置\r\n */\r\nconst DEFAULT_ADAPTER_CONFIG: SyncAdapterConfig = {\r\n enableReferenceResolution: true,\r\n strictMode: false,\r\n fallbackOnError: true,\r\n validationLevel: 'basic' as const,\r\n enableLogging: false\r\n};\r\n\r\n/**\r\n * 加载锐角三角形问题数据(使用新的池化格式)(保持向后兼容)\r\n *\r\n * @deprecated 请使用 GeometryProblemAdapterV4 直接适配JSON数据\r\n */\r\nexport function loadTriangleProblemDataFromPool(): MathPracticeProblemData {\r\n // 显示弃用警告\r\n console.warn(`⚠️ DEPRECATION WARNING ⚠️\r\n函数 loadTriangleProblemDataFromPool() 已弃用。\r\n组件库不再包含数据加载逻辑。\r\n\r\n迁移方案:\r\n1. 获取池化格式JSON数据(如 Acute-Triangle-area-data-refactored.json)\r\n2. 直接使用 adaptGeometryDataSync(poolJsonData) 转换\r\n3. 将转换后的数据传递给组件\r\n\r\n调用栈:\r\n${new Error().stack?.split('\\n').slice(2, 6).join('\\n') || '无法获取调用栈'}\r\n`);\r\n\r\n // 直接使用 GeometryAdapterV4 适配池化数据\r\n const adaptedData = adaptGeometryDataSync(acuteTrianglePoolJson as unknown as GeometryProblemDataV4, DEFAULT_ADAPTER_CONFIG);\r\n console.log('锐角三角形池化数据加载成功 (GeometryAdapterV4):', adaptedData.data.id);\r\n return adaptedData.data;\r\n}\r\n\r\n/**\r\n * 加载锐角三角形V4外部化配置数据(保持向后兼容)\r\n *\r\n * @deprecated 请使用 GeometryProblemAdapterV4 直接适配JSON数据\r\n */\r\nexport async function loadAcuteTriangleV2Data(): Promise<MathPracticeProblemData> {\r\n // 显示弃用警告\r\n console.warn(`⚠️ DEPRECATION WARNING ⚠️\r\n函数 loadAcuteTriangleV2Data() 已弃用。\r\n组件库不再包含数据加载逻辑。\r\n\r\n迁移方案:\r\n1. 获取V4格式JSON数据(如 triangle-v4-final.json)\r\n2. 直接使用 adaptGeometryDataSync(triangleJsonData) 转换\r\n3. 将转换后的数据传递给组件\r\n\r\n调用栈:\r\n${new Error().stack?.split('\\n').slice(2, 6).join('\\n') || '无法获取调用栈'}\r\n`);\r\n\r\n // 直接使用同步适配器,V4数据应该能直接适配\r\n const result = adaptGeometryDataSync(triangleAreaJson as unknown as GeometryProblemDataV4, DEFAULT_ADAPTER_CONFIG);\r\n console.log('V4三角形数据适配成功 (GeometryAdapterV4):', result.data.id);\r\n return result.data;\r\n}\r\n\r\n/**\r\n * 加载梯形面积问题数据(保持向后兼容)\r\n *\r\n * @deprecated 请使用 GeometryProblemAdapterV4 直接适配JSON数据\r\n */\r\nexport async function loadTrapezoidProblemData(): Promise<MathPracticeProblemData> {\r\n // 显示弃用警告\r\n console.warn(`⚠️ DEPRECATION WARNING ⚠️\r\n函数 loadTrapezoidProblemData() 已弃用。\r\n组件库不再包含数据加载逻辑。\r\n\r\n迁移方案:\r\n1. 获取V4格式JSON数据(如 trapezoid-v4-final.json)\r\n2. 直接使用 adaptGeometryDataSync(trapezoidJsonData) 转换\r\n3. 将转换后的数据传递给组件\r\n\r\n调用栈:\r\n${new Error().stack?.split('\\n').slice(2, 6).join('\\n') || '无法获取调用栈'}\r\n`);\r\n\r\n try {\r\n const result = adaptGeometryDataSync(trapezoidAreaJson as unknown as GeometryProblemDataV4, DEFAULT_ADAPTER_CONFIG);\r\n console.log('梯形面积数据适配成功 (GeometryAdapterV4):', result.data.id);\r\n return result.data;\r\n } catch (error) {\r\n console.error('梯形数据适配失败:', error);\r\n // 返回默认数据作为回退\r\n return getDefaultTrapezoidProblemData();\r\n }\r\n}\r\n\r\n/**\r\n * 加载三角形问题数据(保持向后兼容)\r\n *\r\n * @deprecated 请使用 GeometryProblemAdapterV4 直接适配JSON数据\r\n */\r\nexport async function loadTriangleProblemData(): Promise<MathPracticeProblemData> {\r\n // 显示弃用警告\r\n console.warn(`⚠️ DEPRECATION WARNING ⚠️\r\n函数 loadTriangleProblemData() 已弃用。\r\n组件库不再包含数据加载逻辑。\r\n\r\n迁移方案:\r\n1. 获取三角形JSON数据(V4格式或池化格式)\r\n2. 直接使用 adaptGeometryDataSync(triangleJsonData) 转换\r\n3. 将转换后的数据传递给组件\r\n\r\n调用栈:\r\n${new Error().stack?.split('\\n').slice(2, 6).join('\\n') || '无法获取调用栈'}\r\n`);\r\n\r\n // 直接使用 V4 格式数据\r\n return loadAcuteTriangleV2Data();\r\n}\r\n\r\n/**\r\n * 加载平行四边形问题数据(保持向后兼容)\r\n *\r\n * @deprecated 请使用 parallelogramDataAdapter 直接适配JSON数据\r\n */\r\nexport async function loadParallelogramProblemData(): Promise<MathPracticeProblemData> {\r\n // 显示弃用警告\r\n console.warn(`⚠️ DEPRECATION WARNING ⚠️\r\n函数 loadParallelogramProblemData() 已弃用。\r\n组件库不再包含数据加载逻辑。\r\n\r\n迁移方案:\r\n1. 获取平行四边形JSON数据\r\n2. 直接使用 adaptParallelogramData(parallelogramJsonData) 转换\r\n3. 将转换后的数据传递给组件\r\n\r\n调用栈:\r\n${new Error().stack?.split('\\n').slice(2, 6).join('\\n') || '无法获取调用栈'}\r\n`);\r\n\r\n try {\r\n const adaptedData = adaptParallelogramData(parallelogramAreaJson);\r\n console.log('平行四边形数据加载成功 (传统适配器):', adaptedData.id);\r\n return adaptedData;\r\n } catch (error) {\r\n console.error('传统适配器失败:', error);\r\n // 返回默认数据作为回退\r\n return getDefaultParallelogramProblemData();\r\n }\r\n}\r\n\r\n/**\r\n * 加载年龄问题数据(保持向后兼容)\r\n *\r\n * @deprecated 请使用 ageProblemAdapter 直接适配JSON数据\r\n */\r\nexport async function loadAgeProblemData(): Promise<MathPracticeProblemData> {\r\n // 显示弃用警告\r\n console.warn(`⚠️ DEPRECATION WARNING ⚠️\r\n函数 loadAgeProblemData() 已弃用。\r\n组件库不再包含数据加载逻辑。\r\n\r\n迁移方案:\r\n1. 获取年龄问题JSON数据\r\n2. 直接使用 adaptAgeProblemData(ageJsonData) 转换\r\n3. 将转换后的数据传递给组件\r\n\r\n调用栈:\r\n${new Error().stack?.split('\\n').slice(2, 6).join('\\n') || '无法获取调用栈'}\r\n`);\r\n\r\n try {\r\n const adaptedData = adaptAgeProblemData(ageProblemJson);\r\n console.log('年龄问题数据加载成功 (传统适配器):', adaptedData.id);\r\n return adaptedData;\r\n } catch (error) {\r\n console.error('传统适配器失败:', error);\r\n // 返回默认数据作为回退\r\n return getDefaultAgeProblemData();\r\n }\r\n}\r\n\r\n/**\r\n * 根据问题类型加载数据\r\n *\r\n * @deprecated 组件库不应包含数据加载逻辑,请使用正确的架构模式\r\n */\r\nexport async function loadProblemData(problemType: ProblemType): Promise<MathPracticeProblemData> {\r\n // 显示弃用警告\r\n console.warn('⚠️ DEPRECATION WARNING ⚠️');\r\n console.warn('函数 loadProblemData() 已弃用,组件库不再包含硬编码API调用。');\r\n console.warn('组件库作为npm包使用时,请使用正确的架构模式:');\r\n console.warn('1. 业务项目自己调用API获取原始JSON数据');\r\n console.warn('2. 使用适配器函数将原始JSON转换为标准化格式');\r\n console.warn('3. 将转换后的数据传递给AreaGeometrySessionPage组件');\r\n console.warn('');\r\n console.warn('当前loadProblemData()将返回适配后的测试数据。');\r\n\r\n switch (problemType) {\r\n case 'triangle':\r\n return await loadTriangleProblemData();\r\n case 'parallelogram':\r\n return await loadParallelogramProblemData();\r\n case 'age':\r\n return await loadAgeProblemData();\r\n case 'trapezoid':\r\n return await loadTrapezoidProblemData();\r\n default:\r\n console.warn(`未知的问题类型: ${problemType},默认使用三角形数据`);\r\n return await loadTriangleProblemData();\r\n }\r\n}\r\n\r\n/**\r\n * 获取默认的三角形问题数据(回退用)\r\n */\r\nfunction getDefaultTriangleProblemData(): MathPracticeProblemData {\r\n // 创建V4格式的回退数据\r\n const fallbackData = {\r\n schema_version: \"4.0.0\",\r\n math_prob_id: 'triangle-area-fallback',\r\n title: '三角形面积公式推导(默认)',\r\n grade_id: 'g5',\r\n unit_name: '多边形的面积',\r\n basic_info: {\r\n question: '计算下面三角形的面积:',\r\n answerUnit: '平方英寸',\r\n shape: 'triangle',\r\n base: 8,\r\n height: 6,\r\n baseUnit: 'inch',\r\n heightUnit: 'inch'\r\n }\r\n };\r\n\r\n const result = adaptGeometryDataSync(fallbackData as unknown as GeometryProblemDataV4, {\r\n ...DEFAULT_ADAPTER_CONFIG,\r\n enableReferenceResolution: false\r\n });\r\n return result.data;\r\n}\r\n\r\n/**\r\n * 获取默认的平行四边形问题数据(回退用)\r\n */\r\nfunction getDefaultParallelogramProblemData(): MathPracticeProblemData {\r\n return adaptParallelogramData({\r\n id: 'parallelogram-area-fallback',\r\n title: '平行四边形面积公式推导(默认)',\r\n grade: 5,\r\n unit: '多边形的面积',\r\n basic_info: {\r\n question: '计算下面平行四边形的面积:',\r\n answerUnit: '平方英寸',\r\n base: 9,\r\n height: 6\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 获取默认的年龄问题数据(回退用)\r\n */\r\nfunction getDefaultAgeProblemData(): MathPracticeProblemData {\r\n return adaptAgeProblemData({\r\n id: 'age-problem-fallback',\r\n title: '年龄倍数问题(默认)',\r\n grade: 4,\r\n unit: '应用题',\r\n basicInfo: {\r\n question: '今年小明12岁,妈妈36岁。请问几年后,妈妈的年龄是小明的2倍?',\r\n answerUnit: '年后'\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 获取默认的梯形面积问题数据(回退用)\r\n */\r\nfunction getDefaultTrapezoidProblemData(): MathPracticeProblemData {\r\n // 创建一个简单的梯形V4格式数据,使用GeometryAdapterV4转换\r\n const simpleTrapezoidData = {\r\n schema_version: \"4.0.0\",\r\n math_prob_id: \"trapezoid-area-fallback\",\r\n title: \"梯形面积计算(默认)\",\r\n grade: 5,\r\n unit: \"多边形的面积\",\r\n basic_info: {\r\n question: \"图中梯形上底为 6 cm,下底为 10 cm,高为 5 cm。梯形面积是多少?\",\r\n answerUnit: \"cm²\",\r\n shape: \"trapezoid\",\r\n base: 10,\r\n topBase: 6,\r\n height: 5,\r\n baseUnit: \"cm\",\r\n heightUnit: \"cm\"\r\n }\r\n };\r\n\r\n const result = adaptGeometryDataSync(simpleTrapezoidData as unknown as GeometryProblemDataV4, {\r\n ...DEFAULT_ADAPTER_CONFIG,\r\n enableReferenceResolution: false\r\n });\r\n return result.data;\r\n}\r\n\r\n// 导出适配器函数供其他模块使用\r\nexport { adaptParallelogramData, adaptAgeProblemData };","import React, { useState, useMemo, useEffect } from 'react';\r\nimport {\r\n useCurrentScene,\r\n useUserAnswer,\r\n useAnswerFormVisibility,\r\n useValidationError,\r\n useSessionActions\r\n} from '../../components/MathCardV2/MathPracticeStoreHooks';\r\nimport { QuestionScene } from '../../components/MathCardV2/scenes/QuestionScene';\r\nimport { ExplanationScene } from '../../components/MathCardV2/scenes/ExplanationScene';\r\nimport { SuccessScene } from '../../components/MathCardV2/scenes/SuccessScene';\r\nimport type { MathPracticeSessionPageProps, MathPracticeProblemData } from '../../components/MathCardV2/MathPracticeSessionTypes';\r\n\r\n// 导入平行四边形面积数据(使用JSON数据源)\r\nimport { loadParallelogramProblemData } from '../AreaGeometrySessionPage/data';\r\n\r\n/**\r\n * 平行四边形面积计算会话主页面\r\n * 管理三场景流程:问题 → 解释/成功 → 重置\r\n * 专门用于展示平行四边形面积公式推导\r\n */\r\nexport const ParallelogramAreaCalculationSessionPage: React.FC<MathPracticeSessionPageProps> = ({\r\n className = '',\r\n problemData: externalProblemData\r\n}) => {\r\n // 状态管理 - 复用现有Store\r\n const currentScene = useCurrentScene();\r\n const userAnswer = useUserAnswer();\r\n const showAnswerForm = useAnswerFormVisibility();\r\n const validationError = useValidationError();\r\n const { updateUserAnswer, submitAnswer, nextQuestion, setProblemData } = useSessionActions();\r\n\r\n // 本地状态管理\r\n const [loading, setLoading] = useState(true);\r\n const [error, setError] = useState<string | null>(null);\r\n const [internalProblemData, setInternalProblemData] = useState<MathPracticeProblemData | null>(null);\r\n\r\n // 使用useMemo缓存外部问题数据\r\n const externalProblemDataMemo = useMemo(() => externalProblemData, [externalProblemData]);\r\n\r\n // 异步加载内部问题数据(当无外部数据时)\r\n useEffect(() => {\r\n if (externalProblemDataMemo) {\r\n // 有外部数据,直接使用,不需要加载\r\n setLoading(false);\r\n setError(null);\r\n setInternalProblemData(null); // 清空内部数据\r\n return;\r\n }\r\n\r\n const loadInternalData = async () => {\r\n try {\r\n setLoading(true);\r\n setError(null);\r\n const data = await loadParallelogramProblemData();\r\n setInternalProblemData(data);\r\n } catch (err) {\r\n const errorMessage = err instanceof Error ? err.message : '数据加载失败';\r\n setError(errorMessage);\r\n console.error('页面数据加载失败:', err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n loadInternalData();\r\n }, [externalProblemDataMemo]);\r\n\r\n // 合并问题数据:优先使用外部数据,其次是内部加载的数据\r\n const problemData = useMemo(() => {\r\n return externalProblemDataMemo || internalProblemData;\r\n }, [externalProblemDataMemo, internalProblemData]);\r\n\r\n // 初始化问题数据到 store\r\n useEffect(() => {\r\n if (problemData) {\r\n setProblemData(problemData);\r\n }\r\n }, [problemData, setProblemData]);\r\n\r\n // 渲染加载状态\r\n if (loading) {\r\n return (\r\n <div className=\"min-h-screen bg-cyan-50 flex flex-col items-center justify-center p-4 font-sans\">\r\n <div className=\"text-slate-500 text-sm font-medium mb-4 tracking-wide uppercase\">\r\n 加载中...\r\n </div>\r\n <div className=\"text-lg text-slate-700\">正在加载平行四边形面积数据...</div>\r\n </div>\r\n );\r\n }\r\n\r\n // 渲染错误状态\r\n if (error) {\r\n return (\r\n <div className=\"min-h-screen bg-cyan-50 flex flex-col items-center justify-center p-4 font-sans\">\r\n <div className=\"text-slate-500 text-sm font-medium mb-4 tracking-wide uppercase\">\r\n 数据加载失败\r\n </div>\r\n <div className=\"text-lg text-red-600 mb-4\">{error}</div>\r\n <div className=\"text-slate-700\">请检查网络连接或稍后重试。</div>\r\n </div>\r\n );\r\n }\r\n\r\n // 渲染主内容(确保problemData存在)\r\n if (!problemData) {\r\n return (\r\n <div className=\"min-h-screen bg-cyan-50 flex flex-col items-center justify-center p-4 font-sans\">\r\n <div className=\"text-slate-500 text-sm font-medium mb-4 tracking-wide uppercase\">\r\n 数据不可用\r\n </div>\r\n <div className=\"text-lg text-slate-700\">未能加载平行四边形面积数据。</div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"min-h-screen bg-cyan-50 flex flex-col items-center justify-center p-4 font-sans\">\r\n {/* 页面标题 */}\r\n <div className=\"text-slate-500 text-sm font-medium mb-4 tracking-wide uppercase\">\r\n {problemData.grade}年级 &bull; {problemData.unit}\r\n </div>\r\n\r\n {/* 主内容区域 - 三场景切换 */}\r\n <main className=\"bg-white border border-slate-200 rounded-lg shadow-sm\">\r\n {/* 问题场景 */}\r\n {currentScene === 'question' && (\r\n <QuestionScene\r\n problemData={problemData}\r\n userAnswer={userAnswer}\r\n showAnswerForm={showAnswerForm}\r\n onAnswerSubmit={submitAnswer}\r\n onAnswerChange={updateUserAnswer}\r\n validationError={validationError}\r\n />\r\n )}\r\n\r\n {/* 解释场景 */}\r\n {currentScene === 'explanation' && (\r\n <ExplanationScene\r\n problemData={problemData}\r\n userAnswer={userAnswer}\r\n onNextQuestion={nextQuestion}\r\n />\r\n )}\r\n\r\n {/* 成功场景 */}\r\n {currentScene === 'success' && (\r\n <SuccessScene\r\n problemData={problemData}\r\n onNextQuestion={nextQuestion}\r\n />\r\n )}\r\n </main>\r\n </div>\r\n );\r\n};","import React, { useState, useMemo, useEffect } from 'react';\r\nimport {\r\n useCurrentScene,\r\n useUserAnswer,\r\n useAnswerFormVisibility,\r\n useValidationError,\r\n useSessionActions\r\n} from '../../../components/MathCardV2/MathPracticeStoreHooks';\r\nimport { QuestionScene } from '../../../components/MathCardV2/scenes/QuestionScene';\r\nimport { ExplanationScene } from '../../../components/MathCardV2/scenes/ExplanationScene';\r\nimport { SuccessScene } from '../../../components/MathCardV2/scenes/SuccessScene';\r\nimport type { MathPracticeSessionPageProps, MathPracticeProblemData } from '../../../components/MathCardV2/MathPracticeSessionTypes';\r\n\r\n// 导入三角形面积数据(使用JSON数据源)\r\nimport { loadTriangleProblemData } from '../../AreaGeometrySessionPage/data';\r\n\r\n/**\r\n * 三角形面积计算会话主页面\r\n *\r\n * 基于MathCardV2组件系统,管理三场景流程:\r\n * 1. 问题场景 (question): 展示三角形图形和答案输入表单\r\n * 2. 解释场景 (explanation): 错误答案时的详细解释,包含GeometryTransform刚体旋转演示\r\n * 3. 成功场景 (success): 正确答案时的积极反馈和概念回顾\r\n *\r\n * 关键特性:\r\n * - 复用MathCardV2现有组件系统(QuestionScene, ExplanationScene, SuccessScene)\r\n * - 集成GeometryTransform组件,演示三角形旋转成矩形的面积公式推导\r\n * - 使用Zustand Store进行状态管理,支持场景切换和答案验证\r\n * - 数据驱动设计,支持外部传入问题数据覆盖默认配置\r\n *\r\n * @example\r\n * ```tsx\r\n * // 使用默认数据\r\n * <TriangleAreaCalculationSessionPage />\r\n *\r\n * // 使用自定义问题数据\r\n * <TriangleAreaCalculationSessionPage problemData={customTriangleData} />\r\n * ```\r\n *\r\n * @see {@link ParallelogramAreaCalculationSessionPage} 类似实现参考\r\n * @see {@link MathCardV2} 底层组件系统\r\n * @see {@link GeometryTransform} 几何变换演示组件\r\n */\r\nexport const TriangleAreaCalculationSessionPage: React.FC<MathPracticeSessionPageProps> = ({\r\n className = '',\r\n problemData: externalProblemData\r\n}) => {\r\n // 状态管理 - 复用现有Store\r\n const currentScene = useCurrentScene();\r\n const userAnswer = useUserAnswer();\r\n const showAnswerForm = useAnswerFormVisibility();\r\n const validationError = useValidationError();\r\n const { updateUserAnswer, submitAnswer, nextQuestion, setProblemData } = useSessionActions();\r\n\r\n // 本地状态管理\r\n const [loading, setLoading] = useState(true);\r\n const [error, setError] = useState<string | null>(null);\r\n const [internalProblemData, setInternalProblemData] = useState<MathPracticeProblemData | null>(null);\r\n\r\n // 使用useMemo缓存外部问题数据\r\n const externalProblemDataMemo = useMemo(() => externalProblemData, [externalProblemData]);\r\n\r\n // 异步加载内部问题数据(当无外部数据时)\r\n useEffect(() => {\r\n if (externalProblemDataMemo) {\r\n // 有外部数据,直接使用,不需要加载\r\n setLoading(false);\r\n setError(null);\r\n setInternalProblemData(null); // 清空内部数据\r\n return;\r\n }\r\n\r\n const loadInternalData = async () => {\r\n try {\r\n setLoading(true);\r\n setError(null);\r\n const data = await loadTriangleProblemData();\r\n setInternalProblemData(data);\r\n } catch (err) {\r\n const errorMessage = err instanceof Error ? err.message : '数据加载失败';\r\n setError(errorMessage);\r\n console.error('页面数据加载失败:', err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n loadInternalData();\r\n }, [externalProblemDataMemo]);\r\n\r\n // 合并问题数据:优先使用外部数据,其次是内部加载的数据\r\n const problemData = useMemo(() => {\r\n return externalProblemDataMemo || internalProblemData;\r\n }, [externalProblemDataMemo, internalProblemData]);\r\n\r\n // 初始化问题数据到 store\r\n useEffect(() => {\r\n if (problemData) {\r\n setProblemData(problemData);\r\n }\r\n }, [problemData, setProblemData]);\r\n\r\n // 渲染加载状态\r\n if (loading) {\r\n return (\r\n <div className=\"min-h-screen bg-cyan-50 flex flex-col items-center justify-center p-4 font-sans\">\r\n <div className=\"text-slate-500 text-sm font-medium mb-4 tracking-wide uppercase\">\r\n 加载中...\r\n </div>\r\n <div className=\"text-lg text-slate-700\">正在加载三角形面积数据...</div>\r\n </div>\r\n );\r\n }\r\n\r\n // 渲染错误状态\r\n if (error) {\r\n return (\r\n <div className=\"min-h-screen bg-cyan-50 flex flex-col items-center justify-center p-4 font-sans\">\r\n <div className=\"text-slate-500 text-sm font-medium mb-4 tracking-wide uppercase\">\r\n 数据加载失败\r\n </div>\r\n <div className=\"text-lg text-red-600 mb-4\">{error}</div>\r\n <div className=\"text-slate-700\">请检查网络连接或稍后重试。</div>\r\n </div>\r\n );\r\n }\r\n\r\n // 渲染主内容(确保problemData存在)\r\n if (!problemData) {\r\n return (\r\n <div className=\"min-h-screen bg-cyan-50 flex flex-col items-center justify-center p-4 font-sans\">\r\n <div className=\"text-slate-500 text-sm font-medium mb-4 tracking-wide uppercase\">\r\n 数据不可用\r\n </div>\r\n <div className=\"text-lg text-slate-700\">未能加载三角形面积数据。</div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"min-h-screen bg-cyan-50 flex flex-col items-center justify-center p-4 font-sans\">\r\n {/* 页面标题 */}\r\n <div className=\"text-slate-500 text-sm font-medium mb-4 tracking-wide uppercase\">\r\n {problemData.grade}年级 &bull; {problemData.unit}\r\n </div>\r\n\r\n {/* 主内容区域 - 三场景切换 */}\r\n <main className=\"bg-white border border-slate-200 rounded-lg shadow-sm\">\r\n {/* 问题场景 */}\r\n {currentScene === 'question' && (\r\n <QuestionScene\r\n problemData={problemData}\r\n userAnswer={userAnswer}\r\n showAnswerForm={showAnswerForm}\r\n onAnswerSubmit={submitAnswer}\r\n onAnswerChange={updateUserAnswer}\r\n validationError={validationError}\r\n />\r\n )}\r\n\r\n {/* 解释场景 */}\r\n {currentScene === 'explanation' && (\r\n <ExplanationScene\r\n problemData={problemData}\r\n userAnswer={userAnswer}\r\n onNextQuestion={nextQuestion}\r\n />\r\n )}\r\n\r\n {/* 成功场景 */}\r\n {currentScene === 'success' && (\r\n <SuccessScene\r\n problemData={problemData}\r\n onNextQuestion={nextQuestion}\r\n />\r\n )}\r\n </main>\r\n </div>\r\n );\r\n};","import React from 'react';\r\nimport type {\r\n MathProblemData,\r\n MathCardScene,\r\n SubmissionResult,\r\n MathCardConfig\r\n} from './MathCard.types';\r\n\r\nexport interface MathCardContextType {\r\n problemData?: MathProblemData;\r\n scene: MathCardScene;\r\n submissionResult?: SubmissionResult;\r\n config?: MathCardConfig;\r\n value?: string[];\r\n}\r\n\r\nexport const MathCardContext = React.createContext<MathCardContextType | undefined>(undefined);\r\n\r\nexport const useMathCardContext = () => {\r\n const context = React.useContext(MathCardContext);\r\n if (!context) {\r\n throw new Error('useMathCardContext must be used within a MathCard component');\r\n }\r\n return context;\r\n};","import React from 'react';\r\nimport EquationRender from '../../EquationRender/EquationRender';\r\nimport type { ContentBlock } from '../MathCard.types';\r\n\r\n/**\r\n * 解析复习模板中的占位符\r\n * @param template 模板字符串\r\n * @param correctAnswer 正确答案\r\n * @param userAnswer 用户答案\r\n * @returns 解析后的字符串\r\n */\r\nexport const parseTemplate = (\r\n template: string,\r\n correctAnswer: string[],\r\n userAnswer: string[]\r\n): string => {\r\n return template\r\n .replace(/{correctAnswer}/g, correctAnswer.join(', '))\r\n .replace(/{userAnswer}/g, userAnswer.join(', '));\r\n};\r\n\r\n/**\r\n * 渲染内容块\r\n * @param block 内容块\r\n * @returns 渲染后的React元素\r\n */\r\nexport const renderContentBlock = (block: ContentBlock): React.ReactNode => {\r\n if (block.type === 'formula') {\r\n // 使用 EquationRender 组件渲染公式\r\n return React.createElement(EquationRender, {\r\n key: block.content,\r\n parts: [block.content],\r\n children: null,\r\n displayMode: false,\r\n fontSize: '1em',\r\n color: '#333333'\r\n });\r\n }\r\n\r\n if (block.type === 'image') {\r\n return React.createElement('img', {\r\n src: block.content,\r\n alt: 'content',\r\n className: 'image',\r\n key: block.content\r\n });\r\n }\r\n\r\n return React.createElement('span', { key: block.content }, block.content);\r\n};\r\n\r\n/**\r\n * 渲染内容块数组\r\n * @param blocks 内容块数组\r\n * @returns 渲染后的React元素数组\r\n */\r\nexport const renderContentBlocks = (blocks: ContentBlock[]): React.ReactNode[] => {\r\n return blocks.map((block, index) =>\r\n React.createElement('div', {\r\n className: 'content-block',\r\n key: index\r\n }, renderContentBlock(block))\r\n );\r\n};\r\n\r\n/**\r\n * 获取场景对应的显示文本\r\n * @param scene 场景类型\r\n * @returns 场景显示文本\r\n */\r\nexport const getSceneText = (scene: 'question' | 'solve' | 'review'): string => {\r\n const sceneTexts = {\r\n question: '题目作答',\r\n solve: '官方解析',\r\n review: '用户复习'\r\n };\r\n\r\n return sceneTexts[scene];\r\n};\r\n\r\n/**\r\n * 获取难度等级对应的文本\r\n * @param level 难度等级\r\n * @returns 难度文本\r\n */\r\nexport const getDifficultyText = (level: 1 | 2 | 3 | 4 | 5): string => {\r\n const difficultyTexts = {\r\n 1: '非常简单',\r\n 2: '简单',\r\n 3: '中等',\r\n 4: '困难',\r\n 5: '非常困难'\r\n };\r\n\r\n return difficultyTexts[level];\r\n};\r\n\r\n/**\r\n * 验证问题数据格式\r\n * @param data 问题数据\r\n * @returns 验证结果\r\n */\r\nexport const validateProblemData = (data: any): { isValid: boolean; errors: string[] } => {\r\n const errors: string[] = [];\r\n\r\n if (!data) {\r\n errors.push('问题数据不能为空');\r\n return { isValid: false, errors };\r\n }\r\n\r\n if (!data.problemId) {\r\n errors.push('缺少问题ID');\r\n }\r\n\r\n if (!data.grade) {\r\n errors.push('缺少年级信息');\r\n }\r\n\r\n if (!data.unit) {\r\n errors.push('缺少单元信息');\r\n }\r\n\r\n if (!data.problemType) {\r\n errors.push('缺少问题类型');\r\n }\r\n\r\n if (!data.question || !Array.isArray(data.question) || data.question.length === 0) {\r\n errors.push('问题内容不能为空');\r\n }\r\n\r\n if (!data.answer || !data.answer.correctAnswer || !Array.isArray(data.answer.correctAnswer)) {\r\n errors.push('正确答案不能为空');\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n};\r\n\r\n/**\r\n * 解析模板字符串中的公式标记\r\n * @param template 模板字符串\r\n * @returns 解析后的 ContentBlock 数组\r\n */\r\nexport const parseTemplateWithFormulas = (template: string): ContentBlock[] => {\r\n const blocks: ContentBlock[] = [];\r\n let currentIndex = 0;\r\n\r\n // 正则表达式匹配 $...$ 和 $$...$$ 格式的公式\r\n const formulaRegex = /\\$\\$?[^$]+\\$\\$?/g;\r\n let match;\r\n\r\n while ((match = formulaRegex.exec(template)) !== null) {\r\n const matchStart = match.index;\r\n const matchEnd = match.index + match[0].length;\r\n\r\n // 添加匹配前的文本块\r\n if (matchStart > currentIndex) {\r\n const textContent = template.substring(currentIndex, matchStart);\r\n if (textContent.trim()) {\r\n blocks.push({\r\n type: 'text',\r\n content: textContent\r\n });\r\n }\r\n }\r\n\r\n // 添加公式块\r\n const formulaContent = match[0];\r\n // 移除公式标记($ 或 $$)\r\n const cleanFormula = formulaContent\r\n .replace(/^\\$\\$?/, '')\r\n .replace(/\\$\\$?$/, '');\r\n\r\n blocks.push({\r\n type: 'formula',\r\n content: cleanFormula\r\n });\r\n\r\n currentIndex = matchEnd;\r\n }\r\n\r\n // 添加剩余的文本块\r\n if (currentIndex < template.length) {\r\n const remainingText = template.substring(currentIndex);\r\n if (remainingText.trim()) {\r\n blocks.push({\r\n type: 'text',\r\n content: remainingText\r\n });\r\n }\r\n }\r\n\r\n return blocks;\r\n};\r\n\r\n/**\r\n * 渲染包含公式的模板字符串\r\n * @param template 模板字符串\r\n * @param correctAnswer 正确答案\r\n * @param userAnswer 用户答案\r\n * @returns 渲染后的React元素数组\r\n */\r\nexport const renderTemplateWithFormulas = (\r\n template: string,\r\n correctAnswer: string[],\r\n userAnswer: string[]\r\n): React.ReactNode[] => {\r\n // 先解析占位符\r\n const parsedTemplate = parseTemplate(template, correctAnswer, userAnswer);\r\n\r\n // 再解析公式\r\n const contentBlocks = parseTemplateWithFormulas(parsedTemplate);\r\n\r\n // 渲染内容块\r\n return renderContentBlocks(contentBlocks);\r\n};","import React from 'react';\r\nimport type { ExplanationStep, ExplanationStepType, ReviewStep } from '../MathCard.types';\r\nimport EquationRender from '../../EquationRender/EquationRender';\r\nimport { parseTemplate } from './templateParser';\r\n\r\n/**\r\n * 渲染解题步骤\r\n * @param step 解题步骤\r\n * @returns 渲染后的React元素\r\n */\r\nexport const renderExplanationStep = (step: ExplanationStep): React.ReactNode => {\r\n const { type, content, style = {} } = step;\r\n\r\n const baseStyle: React.CSSProperties = {\r\n marginBottom: '8px',\r\n lineHeight: '1.6',\r\n ...style\r\n };\r\n\r\n switch (type) {\r\n case 'instruction':\r\n return React.createElement('div', {\r\n key: step.id,\r\n style: {\r\n ...baseStyle,\r\n fontWeight: 'bold',\r\n color: '#4a6cf7'\r\n }\r\n }, content);\r\n\r\n case 'formula':\r\n // Use display mode for complex formulas that contain line breaks or special commands\r\n const isComplexFormula = content.includes('\\\\\\\\') || content.includes('\\\\downarrow') || content.includes('\\\\quad');\r\n return React.createElement(EquationRender, {\r\n key: step.id,\r\n parts: [content],\r\n children: null,\r\n displayMode: isComplexFormula,\r\n fontSize: '1.1em',\r\n color: '#333333'\r\n });\r\n\r\n case 'conclusion':\r\n return React.createElement('div', {\r\n key: step.id,\r\n style: {\r\n ...baseStyle,\r\n fontWeight: 'bold',\r\n color: '#22c55e',\r\n borderLeft: '3px solid #22c55e',\r\n paddingLeft: '12px'\r\n }\r\n }, content);\r\n\r\n case 'image':\r\n return React.createElement('div', {\r\n key: step.id,\r\n style: baseStyle\r\n }, React.createElement('img', {\r\n src: content,\r\n alt: '解题步骤',\r\n style: {\r\n maxWidth: '100%',\r\n height: 'auto',\r\n borderRadius: '4px'\r\n }\r\n }));\r\n\r\n case 'table':\r\n return React.createElement('div', {\r\n key: step.id,\r\n style: baseStyle\r\n }, React.createElement('div', {\r\n style: {\r\n border: '1px solid #e0e0e0',\r\n borderRadius: '4px',\r\n padding: '8px',\r\n backgroundColor: '#f8f9fa'\r\n }\r\n }, content));\r\n\r\n default:\r\n return React.createElement('div', {\r\n key: step.id,\r\n style: baseStyle\r\n }, content);\r\n }\r\n};\r\n\r\n/**\r\n * 渲染复习步骤\r\n * @param step 复习步骤\r\n * @param userAnswer 用户答案\r\n * @param correctAnswer 正确答案\r\n * @returns 渲染后的React元素\r\n */\r\nexport const renderReviewStep = (\r\n step: ReviewStep,\r\n userAnswer: string[],\r\n correctAnswer: string[]\r\n): React.ReactNode => {\r\n const { type, content, style = {} } = step;\r\n\r\n const baseStyle: React.CSSProperties = {\r\n marginBottom: '8px',\r\n lineHeight: '1.6',\r\n ...style\r\n };\r\n\r\n switch (type) {\r\n case 'instruction':\r\n return React.createElement('div', {\r\n key: step.id,\r\n style: {\r\n ...baseStyle,\r\n fontWeight: 'bold',\r\n color: '#4ade80'\r\n }\r\n }, content);\r\n\r\n case 'formula':\r\n // Use display mode for complex formulas that contain line breaks or special commands\r\n const isComplexFormula = content.includes('\\\\\\\\') || content.includes('\\\\downarrow') || content.includes('\\\\quad');\r\n return React.createElement(EquationRender, {\r\n key: step.id,\r\n parts: [content],\r\n children: null,\r\n displayMode: isComplexFormula,\r\n fontSize: '1.1em',\r\n color: '#333333'\r\n });\r\n\r\n case 'conclusion':\r\n // 解析模板中的占位符\r\n const parsedContent = parseTemplate(content, correctAnswer, userAnswer);\r\n return React.createElement('div', {\r\n key: step.id,\r\n style: {\r\n ...baseStyle,\r\n fontWeight: 'bold',\r\n color: '#4ade80',\r\n borderLeft: '3px solid #4ade80',\r\n paddingLeft: '12px'\r\n }\r\n }, parsedContent);\r\n\r\n default:\r\n return React.createElement('div', {\r\n key: step.id,\r\n style: baseStyle\r\n }, content);\r\n }\r\n};\r\n\r\n/**\r\n * 渲染解题步骤数组\r\n * @param steps 解题步骤数组\r\n * @returns 渲染后的React元素数组\r\n */\r\nexport const renderExplanationSteps = (steps: ExplanationStep[]): React.ReactNode[] => {\r\n return steps.map(renderExplanationStep);\r\n};\r\n\r\n/**\r\n * 渲染复习步骤数组\r\n * @param steps 复习步骤数组\r\n * @param userAnswer 用户答案\r\n * @param correctAnswer 正确答案\r\n * @returns 渲染后的React元素数组\r\n */\r\nexport const renderReviewSteps = (\r\n steps: ReviewStep[],\r\n userAnswer: string[],\r\n correctAnswer: string[]\r\n): React.ReactNode[] => {\r\n return steps.map(step => renderReviewStep(step, userAnswer, correctAnswer));\r\n};\r\n\r\n/**\r\n * 获取步骤类型图标\r\n * @param type 步骤类型\r\n * @returns 图标组件\r\n */\r\nexport const getStepIcon = (type: ExplanationStepType): string => {\r\n const icons: Record<ExplanationStepType, string> = {\r\n instruction: '📝',\r\n text: '📄',\r\n formula: '🧮',\r\n conclusion: '✅',\r\n image: '🖼️',\r\n table: '📊'\r\n };\r\n\r\n return icons[type];\r\n};\r\n\r\n/**\r\n * 格式化答案显示\r\n * @param answer 答案数组\r\n * @param problemType 问题类型\r\n * @returns 格式化后的答案字符串\r\n */\r\nexport const formatAnswer = (answer: string[], problemType: 'fill-in-the-blank' | 'multiple-choice' | 'calculation'): string => {\r\n if (problemType === 'multiple-choice') {\r\n return answer.map(a => `选项 ${a}`).join(', ');\r\n }\r\n\r\n return answer.join(', ');\r\n};","import React from 'react';\r\nimport type {\r\n MathCardProps,\r\n BannerProps,\r\n QuestionProps,\r\n AnswerInputProps,\r\n SubmitButtonProps,\r\n ExplanationProps,\r\n ReviewContentProps,\r\n LoadingStateProps,\r\n ErrorStateProps,\r\n DividerProps\r\n} from './MathCard.types';\r\nimport { MathCardContext, useMathCardContext } from './context';\r\nimport type { MathCardContextType } from './context';\r\nimport { renderContentBlocks, renderTemplateWithFormulas } from './utils/templateParser';\r\nimport { renderExplanationSteps, renderReviewSteps } from './utils/contentRenderer';\r\n\r\n// ========== 子组件实现 ==========\r\n\r\n// Banner 组件\r\nconst Banner: React.FC<BannerProps> = ({\r\n scene,\r\n position = 'header',\r\n size = 'medium',\r\n color,\r\n bgColor,\r\n hidden = false\r\n}) => {\r\n if (hidden) return null;\r\n\r\n const sceneTexts = {\r\n question: '题目作答',\r\n solve: '官方解析',\r\n review: '用户复习'\r\n };\r\n\r\n const getBannerStyle = (): React.CSSProperties => {\r\n const baseStyle: React.CSSProperties = {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontWeight: 600,\r\n textTransform: 'uppercase',\r\n letterSpacing: '0.5px'\r\n };\r\n\r\n // 背景色和文字色\r\n const sceneColors = {\r\n question: '#f97316',\r\n solve: '#4a6cf7',\r\n review: '#4ade80'\r\n };\r\n\r\n baseStyle.background = bgColor || sceneColors[scene];\r\n baseStyle.color = color || '#ffffff';\r\n\r\n // 位置样式\r\n if (position === 'header') {\r\n baseStyle.borderBottom = '1px solid #e0e0e0';\r\n } else if (position === 'sidebar') {\r\n baseStyle.borderRight = '1px solid #e0e0e0';\r\n baseStyle.writingMode = 'vertical-rl';\r\n baseStyle.textOrientation = 'mixed';\r\n }\r\n\r\n // 尺寸样式\r\n const sizeStyles = {\r\n small: { fontSize: '12px', padding: '8px 12px' },\r\n medium: { fontSize: '14px', padding: '12px 16px' },\r\n large: { fontSize: '16px', padding: '16px 20px' }\r\n };\r\n\r\n Object.assign(baseStyle, sizeStyles[size]);\r\n\r\n return baseStyle;\r\n };\r\n\r\n return (\r\n <div style={getBannerStyle()}>\r\n {sceneTexts[scene]}\r\n </div>\r\n );\r\n};\r\n\r\n// Question 组件\r\nconst Question: React.FC<QuestionProps> = ({ question }) => {\r\n const questionStyle: React.CSSProperties = {\r\n padding: '20px',\r\n lineHeight: '1.6',\r\n fontSize: '16px'\r\n };\r\n\r\n return (\r\n <div style={questionStyle}>\r\n {renderContentBlocks(question)}\r\n </div>\r\n );\r\n};\r\n\r\n// AnswerInput 组件\r\nconst AnswerInput: React.FC<AnswerInputProps> = ({\r\n problemType,\r\n options,\r\n value = [],\r\n onChange,\r\n placeholder = '请输入答案'\r\n}) => {\r\n const containerStyle: React.CSSProperties = {\r\n padding: '20px',\r\n borderTop: '1px solid #e0e0e0'\r\n };\r\n\r\n const inputStyle: React.CSSProperties = {\r\n width: '100%',\r\n padding: '12px 16px',\r\n border: '1px solid #e0e0e0',\r\n borderRadius: '4px',\r\n fontSize: '14px'\r\n };\r\n\r\n const optionsStyle: React.CSSProperties = {\r\n display: 'grid',\r\n gap: '12px'\r\n };\r\n\r\n const getOptionStyle = (isSelected: boolean): React.CSSProperties => ({\r\n padding: '12px 16px',\r\n border: '1px solid #e0e0e0',\r\n borderRadius: '4px',\r\n cursor: 'pointer',\r\n transition: 'all 0.2s ease',\r\n background: isSelected ? '#f97316' : 'transparent',\r\n color: isSelected ? '#ffffff' : 'inherit',\r\n borderColor: isSelected ? '#f97316' : '#e0e0e0'\r\n });\r\n\r\n const handleOptionClick = (optionId: string) => {\r\n if (!onChange) return;\r\n\r\n if (problemType === 'multiple-choice') {\r\n const newValue = value.includes(optionId)\r\n ? value.filter(id => id !== optionId)\r\n : [...value, optionId];\r\n onChange(newValue);\r\n } else {\r\n onChange([optionId]);\r\n }\r\n };\r\n\r\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n if (onChange) {\r\n onChange([e.target.value]);\r\n }\r\n };\r\n\r\n if (problemType === 'multiple-choice' && options) {\r\n return (\r\n <div style={containerStyle}>\r\n <div style={optionsStyle}>\r\n {options.map(option => (\r\n <div\r\n key={option.id}\r\n style={getOptionStyle(value.includes(option.id))}\r\n onClick={() => handleOptionClick(option.id)}\r\n >\r\n {renderContentBlocks(option.content)}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div style={containerStyle}>\r\n <input\r\n type=\"text\"\r\n style={inputStyle}\r\n placeholder={placeholder}\r\n value={value[0] || ''}\r\n onChange={handleInputChange}\r\n />\r\n </div>\r\n );\r\n};\r\n\r\n// SubmitButton 组件\r\nconst SubmitButton: React.FC<SubmitButtonProps> = ({\r\n onClick,\r\n children,\r\n disabled = false,\r\n loading = false\r\n}) => {\r\n const buttonStyle: React.CSSProperties = {\r\n padding: '12px 24px',\r\n background: '#f97316',\r\n color: 'white',\r\n border: 'none',\r\n borderRadius: '6px',\r\n fontSize: '14px',\r\n fontWeight: 600,\r\n cursor: disabled ? 'not-allowed' : 'pointer',\r\n opacity: disabled ? 0.6 : 1\r\n };\r\n\r\n return (\r\n <button\r\n style={buttonStyle}\r\n onClick={onClick}\r\n disabled={disabled || loading}\r\n >\r\n {loading ? '提交中...' : children}\r\n </button>\r\n );\r\n};\r\n\r\n// Explanation 组件\r\nconst Explanation: React.FC<ExplanationProps> = ({ steps, title = '解题步骤' }) => {\r\n const containerStyle: React.CSSProperties = {\r\n padding: '20px',\r\n borderTop: '1px solid #e0e0e0'\r\n };\r\n\r\n const titleStyle: React.CSSProperties = {\r\n fontSize: '18px',\r\n fontWeight: 600,\r\n marginBottom: '16px',\r\n color: '#4a6cf7'\r\n };\r\n\r\n const stepsStyle: React.CSSProperties = {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '12px'\r\n };\r\n\r\n const stepStyle: React.CSSProperties = {\r\n padding: '12px',\r\n borderLeft: '3px solid #4a6cf7',\r\n background: '#f8f9fa',\r\n borderRadius: '0 4px 4px 0',\r\n lineHeight: '1.6'\r\n };\r\n\r\n return (\r\n <div style={containerStyle}>\r\n <div style={titleStyle}>{title}</div>\r\n <div style={stepsStyle}>\r\n {renderExplanationSteps(steps).map((stepElement, index) => (\r\n <div key={steps[index].id} style={stepStyle}>\r\n {stepElement}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n// ReviewContent 组件\r\nconst ReviewContent: React.FC<ReviewContentProps> = ({\r\n reviewContent,\r\n userAnswer,\r\n correctAnswer\r\n}) => {\r\n const containerStyle: React.CSSProperties = {\r\n padding: '20px',\r\n borderTop: '1px solid #e0e0e0'\r\n };\r\n\r\n const titleStyle: React.CSSProperties = {\r\n fontSize: '18px',\r\n fontWeight: 600,\r\n marginBottom: '16px',\r\n color: '#4ade80'\r\n };\r\n\r\n const contentStyle: React.CSSProperties = {\r\n lineHeight: '1.6'\r\n };\r\n\r\n const templateStyle: React.CSSProperties = {\r\n padding: '12px',\r\n background: '#f0fdf4',\r\n border: '1px solid #bbf7d0',\r\n borderRadius: '4px',\r\n marginBottom: '16px'\r\n };\r\n\r\n const stepsStyle: React.CSSProperties = {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '12px'\r\n };\r\n\r\n const stepStyle: React.CSSProperties = {\r\n padding: '12px',\r\n borderLeft: '3px solid #4ade80',\r\n background: '#f8f9fa',\r\n borderRadius: '0 4px 4px 0',\r\n lineHeight: '1.6'\r\n };\r\n\r\n return (\r\n <div style={containerStyle}>\r\n <div style={titleStyle}>复习内容</div>\r\n <div style={contentStyle}>\r\n {reviewContent.reviewTemplate && (\r\n <div style={templateStyle}>\r\n {renderTemplateWithFormulas(\r\n reviewContent.reviewTemplate,\r\n correctAnswer,\r\n userAnswer\r\n )}\r\n </div>\r\n )}\r\n {reviewContent.reviewExplanation && (\r\n <div style={stepsStyle}>\r\n {renderReviewSteps(reviewContent.reviewExplanation, userAnswer, correctAnswer).map((stepElement, index) => (\r\n <div key={reviewContent.reviewExplanation![index].id} style={stepStyle}>\r\n {stepElement}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n// LoadingState 组件\r\nconst LoadingState: React.FC<LoadingStateProps> = ({ type = 'skeleton' }) => {\r\n const skeletonStyle: React.CSSProperties = {\r\n padding: '20px'\r\n };\r\n\r\n const skeletonLineStyle: React.CSSProperties = {\r\n height: '16px',\r\n background: 'linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%)',\r\n backgroundSize: '200% 100%',\r\n animation: 'loading 1.5s infinite',\r\n borderRadius: '4px',\r\n marginBottom: '12px'\r\n };\r\n\r\n const spinnerStyle: React.CSSProperties = {\r\n display: 'flex',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n padding: '24px'\r\n };\r\n\r\n const spinnerElementStyle: React.CSSProperties = {\r\n width: '40px',\r\n height: '40px',\r\n border: '4px solid #f0f0f0',\r\n borderTop: '4px solid #f97316',\r\n borderRadius: '50%',\r\n animation: 'spin 1s linear infinite'\r\n };\r\n\r\n if (type === 'spinner') {\r\n return (\r\n <div style={spinnerStyle}>\r\n <div style={spinnerElementStyle} />\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div style={skeletonStyle} data-testid=\"loading-skeleton\">\r\n <div style={{ ...skeletonLineStyle, width: '80%' }} />\r\n <div style={{ ...skeletonLineStyle, width: '60%' }} />\r\n <div style={{ ...skeletonLineStyle, width: '70%' }} />\r\n </div>\r\n );\r\n};\r\n\r\n// ErrorState 组件\r\nconst ErrorState: React.FC<ErrorStateProps> = ({ error, onRetry }) => {\r\n const errorStyle: React.CSSProperties = {\r\n padding: '24px',\r\n textAlign: 'center',\r\n color: '#ef4444'\r\n };\r\n\r\n const errorMessageStyle: React.CSSProperties = {\r\n marginBottom: '16px',\r\n fontSize: '16px'\r\n };\r\n\r\n const retryButtonStyle: React.CSSProperties = {\r\n padding: '12px 16px',\r\n background: '#ef4444',\r\n color: 'white',\r\n border: 'none',\r\n borderRadius: '6px',\r\n cursor: 'pointer',\r\n fontSize: '14px'\r\n };\r\n\r\n const errorMessage = typeof error === 'string' ? error : error.message;\r\n\r\n return (\r\n <div style={errorStyle}>\r\n <div style={errorMessageStyle}>{errorMessage}</div>\r\n {onRetry && (\r\n <button\r\n style={retryButtonStyle}\r\n onClick={() => onRetry(error)}\r\n >\r\n 重试\r\n </button>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// Divider 组件\r\nconst Divider: React.FC<DividerProps> = ({\r\n orientation = 'horizontal',\r\n size = 'medium'\r\n}) => {\r\n const dividerStyle: React.CSSProperties = {\r\n background: '#e0e0e0'\r\n };\r\n\r\n // 设置尺寸\r\n const sizeMap = {\r\n small: '12px',\r\n medium: '16px',\r\n large: '20px'\r\n };\r\n\r\n if (orientation === 'horizontal') {\r\n dividerStyle.height = '1px';\r\n dividerStyle.width = '100%';\r\n dividerStyle.margin = `${sizeMap[size]} 0`;\r\n } else {\r\n dividerStyle.width = '1px';\r\n dividerStyle.height = '100%';\r\n dividerStyle.margin = `0 ${sizeMap[size]}`;\r\n }\r\n\r\n return <div style={dividerStyle} />;\r\n};\r\n\r\n// ========== 默认布局组件 ==========\r\n\r\ninterface DefaultLayoutProps {\r\n onSubmit?: (currentAnswer?: string[]) => void;\r\n onNext?: (currentProblemId: string) => void;\r\n onRetry?: (problemId: string) => void;\r\n onAnswerChange?: (answer: string[], problemType: 'fill-in-the-blank' | 'multiple-choice' | 'calculation' | 'geometry') => void;\r\n onHintToggle?: (hintIndex: number, isExpanded: boolean) => void;\r\n value?: string[];\r\n}\r\n\r\nconst DefaultLayout: React.FC<DefaultLayoutProps> = ({\r\n onSubmit,\r\n onNext,\r\n onRetry,\r\n onAnswerChange,\r\n // onHintToggle,\r\n value\r\n}) => {\r\n const { problemData, scene, submissionResult, config } = useMathCardContext();\r\n\r\n if (!problemData) {\r\n return <ErrorState error=\"No problem data provided\" />;\r\n }\r\n\r\n const handleSubmit = () => {\r\n if (onSubmit) {\r\n onSubmit();\r\n }\r\n };\r\n\r\n const handleNext = () => {\r\n if (onNext) {\r\n onNext(problemData.problemId);\r\n }\r\n };\r\n\r\n const handleRetry = () => {\r\n if (onRetry) {\r\n onRetry(problemData.problemId);\r\n }\r\n };\r\n\r\n const handleAnswerChange = (answer: string[]) => {\r\n if (onAnswerChange) {\r\n onAnswerChange(answer, problemData.problemType);\r\n }\r\n };\r\n\r\n const cardStyle: React.CSSProperties = {\r\n background: config?.theme === 'dark' ? '#1a1a1a' : '#ffffff',\r\n borderRadius: '8px',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.1)',\r\n fontFamily: \"'Arial', sans-serif\",\r\n fontSize: '14px',\r\n overflow: 'hidden',\r\n color: config?.theme === 'dark' ? '#ffffff' : '#333333',\r\n width: '100%',\r\n maxWidth: '800px'\r\n };\r\n\r\n const buttonContainerStyle: React.CSSProperties = {\r\n padding: '20px',\r\n borderTop: '1px solid #e0e0e0',\r\n display: 'flex',\r\n gap: '12px'\r\n };\r\n\r\n return (\r\n <div\r\n style={cardStyle}\r\n data-testid=\"math-card\"\r\n data-theme={config?.theme}\r\n >\r\n {/* Banner */}\r\n {config?.showBanner !== false && (\r\n <Banner\r\n scene={scene}\r\n position={config?.bannerPosition}\r\n size={config?.bannerSize}\r\n color={config?.bannerCustomStyle?.color}\r\n bgColor={config?.bannerCustomStyle?.bgColor}\r\n />\r\n )}\r\n\r\n {/* 问题内容 */}\r\n <Question\r\n question={problemData.question}\r\n problemType={problemData.problemType}\r\n />\r\n\r\n {/* 根据场景渲染不同内容 */}\r\n {scene === 'question' && (\r\n <>\r\n {/* 答案输入 */}\r\n <AnswerInput\r\n problemType={problemData.problemType}\r\n options={problemData.answer.options}\r\n value={value}\r\n onChange={handleAnswerChange}\r\n placeholder={config?.inputPlaceholder}\r\n />\r\n\r\n {/* 提交按钮 */}\r\n <div style={buttonContainerStyle}>\r\n <SubmitButton\r\n onClick={handleSubmit}\r\n disabled={!onSubmit}\r\n >\r\n {config?.submitButtonText || '提交答案'}\r\n </SubmitButton>\r\n </div>\r\n </>\r\n )}\r\n\r\n {scene === 'solve' && problemData.explanation && (\r\n <Explanation\r\n steps={problemData.explanation}\r\n title=\"官方解析\"\r\n />\r\n )}\r\n\r\n {scene === 'review' && submissionResult && problemData.reviewContent && (\r\n <ReviewContent\r\n reviewContent={problemData.reviewContent}\r\n userAnswer={submissionResult.userAnswer}\r\n correctAnswer={problemData.answer.correctAnswer}\r\n />\r\n )}\r\n\r\n {/* 操作按钮 */}\r\n {(scene === 'solve' || scene === 'review') && (\r\n <div style={buttonContainerStyle}>\r\n {onNext && (\r\n <SubmitButton onClick={handleNext}>\r\n {config?.nextButtonText || '下一题'}\r\n </SubmitButton>\r\n )}\r\n {onRetry && (\r\n <SubmitButton onClick={handleRetry}>\r\n {config?.retryButtonText || '重新作答'}\r\n </SubmitButton>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// ========== 根组件 ==========\r\n\r\nexport const MathCard: React.FC<MathCardProps> & {\r\n Banner: React.FC<BannerProps>;\r\n Question: React.FC<QuestionProps>;\r\n AnswerInput: React.FC<AnswerInputProps>;\r\n SubmitButton: React.FC<SubmitButtonProps>;\r\n Explanation: React.FC<ExplanationProps>;\r\n ReviewContent: React.FC<ReviewContentProps>;\r\n LoadingState: React.FC<LoadingStateProps>;\r\n ErrorState: React.FC<ErrorStateProps>;\r\n Divider: React.FC<DividerProps>;\r\n} = ({\r\n problemData,\r\n scene,\r\n submissionResult,\r\n loading,\r\n error,\r\n config,\r\n children,\r\n onSubmit,\r\n onNext,\r\n onRetry,\r\n onErrorRetry,\r\n onAnswerChange,\r\n onHintToggle,\r\n value\r\n}) => {\r\n // 异步状态处理\r\n if (loading) {\r\n return <LoadingState type=\"skeleton\" />;\r\n }\r\n\r\n if (error) {\r\n return (\r\n <ErrorState\r\n error={error}\r\n onRetry={onErrorRetry}\r\n />\r\n );\r\n }\r\n\r\n if (!problemData) {\r\n return <ErrorState error=\"No problem data provided\" />;\r\n }\r\n\r\n // Context值(仅用于prop drilling)\r\n const contextValue: MathCardContextType = {\r\n problemData,\r\n scene,\r\n submissionResult,\r\n config,\r\n value\r\n };\r\n\r\n return (\r\n <MathCardContext.Provider value={contextValue}>\r\n {children || (\r\n <DefaultLayout\r\n onSubmit={onSubmit}\r\n onNext={onNext}\r\n onRetry={onRetry}\r\n onAnswerChange={onAnswerChange}\r\n onHintToggle={onHintToggle}\r\n value={value}\r\n />\r\n )}\r\n </MathCardContext.Provider>\r\n );\r\n};\r\n\r\n// 挂载子组件\r\nMathCard.Banner = Banner;\r\nMathCard.Question = Question;\r\nMathCard.AnswerInput = AnswerInput;\r\nMathCard.SubmitButton = SubmitButton;\r\nMathCard.Explanation = Explanation;\r\nMathCard.ReviewContent = ReviewContent;\r\nMathCard.LoadingState = LoadingState;\r\nMathCard.ErrorState = ErrorState;\r\nMathCard.Divider = Divider;","var isDevelopment = false;\n\n/*\n\nBased off glamor's StyleSheet, thanks Sunil ❤️\n\nhigh performance StyleSheet for css-in-js systems\n\n- uses multiple style tags behind the scenes for millions of rules\n- uses `insertRule` for appending in production for *much* faster performance\n\n// usage\n\nimport { StyleSheet } from '@emotion/sheet'\n\nlet styleSheet = new StyleSheet({ key: '', container: document.head })\n\nstyleSheet.insert('#box { border: 1px solid red; }')\n- appends a css rule into the stylesheet\n\nstyleSheet.flush()\n- empties the stylesheet of all its contents\n\n*/\n\nfunction sheetForTag(tag) {\n if (tag.sheet) {\n return tag.sheet;\n } // this weirdness brought to you by firefox\n\n /* istanbul ignore next */\n\n\n for (var i = 0; i < document.styleSheets.length; i++) {\n if (document.styleSheets[i].ownerNode === tag) {\n return document.styleSheets[i];\n }\n } // this function should always return with a value\n // TS can't understand it though so we make it stop complaining here\n\n\n return undefined;\n}\n\nfunction createStyleElement(options) {\n var tag = document.createElement('style');\n tag.setAttribute('data-emotion', options.key);\n\n if (options.nonce !== undefined) {\n tag.setAttribute('nonce', options.nonce);\n }\n\n tag.appendChild(document.createTextNode(''));\n tag.setAttribute('data-s', '');\n return tag;\n}\n\nvar StyleSheet = /*#__PURE__*/function () {\n // Using Node instead of HTMLElement since container may be a ShadowRoot\n function StyleSheet(options) {\n var _this = this;\n\n this._insertTag = function (tag) {\n var before;\n\n if (_this.tags.length === 0) {\n if (_this.insertionPoint) {\n before = _this.insertionPoint.nextSibling;\n } else if (_this.prepend) {\n before = _this.container.firstChild;\n } else {\n before = _this.before;\n }\n } else {\n before = _this.tags[_this.tags.length - 1].nextSibling;\n }\n\n _this.container.insertBefore(tag, before);\n\n _this.tags.push(tag);\n };\n\n this.isSpeedy = options.speedy === undefined ? !isDevelopment : options.speedy;\n this.tags = [];\n this.ctr = 0;\n this.nonce = options.nonce; // key is the value of the data-emotion attribute, it's used to identify different sheets\n\n this.key = options.key;\n this.container = options.container;\n this.prepend = options.prepend;\n this.insertionPoint = options.insertionPoint;\n this.before = null;\n }\n\n var _proto = StyleSheet.prototype;\n\n _proto.hydrate = function hydrate(nodes) {\n nodes.forEach(this._insertTag);\n };\n\n _proto.insert = function insert(rule) {\n // the max length is how many rules we have per style tag, it's 65000 in speedy mode\n // it's 1 in dev because we insert source maps that map a single rule to a location\n // and you can only have one source map per style tag\n if (this.ctr % (this.isSpeedy ? 65000 : 1) === 0) {\n this._insertTag(createStyleElement(this));\n }\n\n var tag = this.tags[this.tags.length - 1];\n\n if (this.isSpeedy) {\n var sheet = sheetForTag(tag);\n\n try {\n // this is the ultrafast version, works across browsers\n // the big drawback is that the css won't be editable in devtools\n sheet.insertRule(rule, sheet.cssRules.length);\n } catch (e) {\n }\n } else {\n tag.appendChild(document.createTextNode(rule));\n }\n\n this.ctr++;\n };\n\n _proto.flush = function flush() {\n this.tags.forEach(function (tag) {\n var _tag$parentNode;\n\n return (_tag$parentNode = tag.parentNode) == null ? void 0 : _tag$parentNode.removeChild(tag);\n });\n this.tags = [];\n this.ctr = 0;\n };\n\n return StyleSheet;\n}();\n\nexport { StyleSheet };\n","export var MS = '-ms-'\nexport var MOZ = '-moz-'\nexport var WEBKIT = '-webkit-'\n\nexport var COMMENT = 'comm'\nexport var RULESET = 'rule'\nexport var DECLARATION = 'decl'\n\nexport var PAGE = '@page'\nexport var MEDIA = '@media'\nexport var IMPORT = '@import'\nexport var CHARSET = '@charset'\nexport var VIEWPORT = '@viewport'\nexport var SUPPORTS = '@supports'\nexport var DOCUMENT = '@document'\nexport var NAMESPACE = '@namespace'\nexport var KEYFRAMES = '@keyframes'\nexport var FONT_FACE = '@font-face'\nexport var COUNTER_STYLE = '@counter-style'\nexport var FONT_FEATURE_VALUES = '@font-feature-values'\nexport var LAYER = '@layer'\n","/**\n * @param {number}\n * @return {number}\n */\nexport var abs = Math.abs\n\n/**\n * @param {number}\n * @return {string}\n */\nexport var from = String.fromCharCode\n\n/**\n * @param {object}\n * @return {object}\n */\nexport var assign = Object.assign\n\n/**\n * @param {string} value\n * @param {number} length\n * @return {number}\n */\nexport function hash (value, length) {\n\treturn charat(value, 0) ^ 45 ? (((((((length << 2) ^ charat(value, 0)) << 2) ^ charat(value, 1)) << 2) ^ charat(value, 2)) << 2) ^ charat(value, 3) : 0\n}\n\n/**\n * @param {string} value\n * @return {string}\n */\nexport function trim (value) {\n\treturn value.trim()\n}\n\n/**\n * @param {string} value\n * @param {RegExp} pattern\n * @return {string?}\n */\nexport function match (value, pattern) {\n\treturn (value = pattern.exec(value)) ? value[0] : value\n}\n\n/**\n * @param {string} value\n * @param {(string|RegExp)} pattern\n * @param {string} replacement\n * @return {string}\n */\nexport function replace (value, pattern, replacement) {\n\treturn value.replace(pattern, replacement)\n}\n\n/**\n * @param {string} value\n * @param {string} search\n * @return {number}\n */\nexport function indexof (value, search) {\n\treturn value.indexOf(search)\n}\n\n/**\n * @param {string} value\n * @param {number} index\n * @return {number}\n */\nexport function charat (value, index) {\n\treturn value.charCodeAt(index) | 0\n}\n\n/**\n * @param {string} value\n * @param {number} begin\n * @param {number} end\n * @return {string}\n */\nexport function substr (value, begin, end) {\n\treturn value.slice(begin, end)\n}\n\n/**\n * @param {string} value\n * @return {number}\n */\nexport function strlen (value) {\n\treturn value.length\n}\n\n/**\n * @param {any[]} value\n * @return {number}\n */\nexport function sizeof (value) {\n\treturn value.length\n}\n\n/**\n * @param {any} value\n * @param {any[]} array\n * @return {any}\n */\nexport function append (value, array) {\n\treturn array.push(value), value\n}\n\n/**\n * @param {string[]} array\n * @param {function} callback\n * @return {string}\n */\nexport function combine (array, callback) {\n\treturn array.map(callback).join('')\n}\n","import {from, trim, charat, strlen, substr, append, assign} from './Utility.js'\n\nexport var line = 1\nexport var column = 1\nexport var length = 0\nexport var position = 0\nexport var character = 0\nexport var characters = ''\n\n/**\n * @param {string} value\n * @param {object | null} root\n * @param {object | null} parent\n * @param {string} type\n * @param {string[] | string} props\n * @param {object[] | string} children\n * @param {number} length\n */\nexport function node (value, root, parent, type, props, children, length) {\n\treturn {value: value, root: root, parent: parent, type: type, props: props, children: children, line: line, column: column, length: length, return: ''}\n}\n\n/**\n * @param {object} root\n * @param {object} props\n * @return {object}\n */\nexport function copy (root, props) {\n\treturn assign(node('', null, null, '', null, null, 0), root, {length: -root.length}, props)\n}\n\n/**\n * @return {number}\n */\nexport function char () {\n\treturn character\n}\n\n/**\n * @return {number}\n */\nexport function prev () {\n\tcharacter = position > 0 ? charat(characters, --position) : 0\n\n\tif (column--, character === 10)\n\t\tcolumn = 1, line--\n\n\treturn character\n}\n\n/**\n * @return {number}\n */\nexport function next () {\n\tcharacter = position < length ? charat(characters, position++) : 0\n\n\tif (column++, character === 10)\n\t\tcolumn = 1, line++\n\n\treturn character\n}\n\n/**\n * @return {number}\n */\nexport function peek () {\n\treturn charat(characters, position)\n}\n\n/**\n * @return {number}\n */\nexport function caret () {\n\treturn position\n}\n\n/**\n * @param {number} begin\n * @param {number} end\n * @return {string}\n */\nexport function slice (begin, end) {\n\treturn substr(characters, begin, end)\n}\n\n/**\n * @param {number} type\n * @return {number}\n */\nexport function token (type) {\n\tswitch (type) {\n\t\t// \\0 \\t \\n \\r \\s whitespace token\n\t\tcase 0: case 9: case 10: case 13: case 32:\n\t\t\treturn 5\n\t\t// ! + , / > @ ~ isolate token\n\t\tcase 33: case 43: case 44: case 47: case 62: case 64: case 126:\n\t\t// ; { } breakpoint token\n\t\tcase 59: case 123: case 125:\n\t\t\treturn 4\n\t\t// : accompanied token\n\t\tcase 58:\n\t\t\treturn 3\n\t\t// \" ' ( [ opening delimit token\n\t\tcase 34: case 39: case 40: case 91:\n\t\t\treturn 2\n\t\t// ) ] closing delimit token\n\t\tcase 41: case 93:\n\t\t\treturn 1\n\t}\n\n\treturn 0\n}\n\n/**\n * @param {string} value\n * @return {any[]}\n */\nexport function alloc (value) {\n\treturn line = column = 1, length = strlen(characters = value), position = 0, []\n}\n\n/**\n * @param {any} value\n * @return {any}\n */\nexport function dealloc (value) {\n\treturn characters = '', value\n}\n\n/**\n * @param {number} type\n * @return {string}\n */\nexport function delimit (type) {\n\treturn trim(slice(position - 1, delimiter(type === 91 ? type + 2 : type === 40 ? type + 1 : type)))\n}\n\n/**\n * @param {string} value\n * @return {string[]}\n */\nexport function tokenize (value) {\n\treturn dealloc(tokenizer(alloc(value)))\n}\n\n/**\n * @param {number} type\n * @return {string}\n */\nexport function whitespace (type) {\n\twhile (character = peek())\n\t\tif (character < 33)\n\t\t\tnext()\n\t\telse\n\t\t\tbreak\n\n\treturn token(type) > 2 || token(character) > 3 ? '' : ' '\n}\n\n/**\n * @param {string[]} children\n * @return {string[]}\n */\nexport function tokenizer (children) {\n\twhile (next())\n\t\tswitch (token(character)) {\n\t\t\tcase 0: append(identifier(position - 1), children)\n\t\t\t\tbreak\n\t\t\tcase 2: append(delimit(character), children)\n\t\t\t\tbreak\n\t\t\tdefault: append(from(character), children)\n\t\t}\n\n\treturn children\n}\n\n/**\n * @param {number} index\n * @param {number} count\n * @return {string}\n */\nexport function escaping (index, count) {\n\twhile (--count && next())\n\t\t// not 0-9 A-F a-f\n\t\tif (character < 48 || character > 102 || (character > 57 && character < 65) || (character > 70 && character < 97))\n\t\t\tbreak\n\n\treturn slice(index, caret() + (count < 6 && peek() == 32 && next() == 32))\n}\n\n/**\n * @param {number} type\n * @return {number}\n */\nexport function delimiter (type) {\n\twhile (next())\n\t\tswitch (character) {\n\t\t\t// ] ) \" '\n\t\t\tcase type:\n\t\t\t\treturn position\n\t\t\t// \" '\n\t\t\tcase 34: case 39:\n\t\t\t\tif (type !== 34 && type !== 39)\n\t\t\t\t\tdelimiter(character)\n\t\t\t\tbreak\n\t\t\t// (\n\t\t\tcase 40:\n\t\t\t\tif (type === 41)\n\t\t\t\t\tdelimiter(type)\n\t\t\t\tbreak\n\t\t\t// \\\n\t\t\tcase 92:\n\t\t\t\tnext()\n\t\t\t\tbreak\n\t\t}\n\n\treturn position\n}\n\n/**\n * @param {number} type\n * @param {number} index\n * @return {number}\n */\nexport function commenter (type, index) {\n\twhile (next())\n\t\t// //\n\t\tif (type + character === 47 + 10)\n\t\t\tbreak\n\t\t// /*\n\t\telse if (type + character === 42 + 42 && peek() === 47)\n\t\t\tbreak\n\n\treturn '/*' + slice(index, position - 1) + '*' + from(type === 47 ? type : next())\n}\n\n/**\n * @param {number} index\n * @return {string}\n */\nexport function identifier (index) {\n\twhile (!token(peek()))\n\t\tnext()\n\n\treturn slice(index, position)\n}\n","import {COMMENT, RULESET, DECLARATION} from './Enum.js'\nimport {abs, charat, trim, from, sizeof, strlen, substr, append, replace, indexof} from './Utility.js'\nimport {node, char, prev, next, peek, caret, alloc, dealloc, delimit, whitespace, escaping, identifier, commenter} from './Tokenizer.js'\n\n/**\n * @param {string} value\n * @return {object[]}\n */\nexport function compile (value) {\n\treturn dealloc(parse('', null, null, null, [''], value = alloc(value), 0, [0], value))\n}\n\n/**\n * @param {string} value\n * @param {object} root\n * @param {object?} parent\n * @param {string[]} rule\n * @param {string[]} rules\n * @param {string[]} rulesets\n * @param {number[]} pseudo\n * @param {number[]} points\n * @param {string[]} declarations\n * @return {object}\n */\nexport function parse (value, root, parent, rule, rules, rulesets, pseudo, points, declarations) {\n\tvar index = 0\n\tvar offset = 0\n\tvar length = pseudo\n\tvar atrule = 0\n\tvar property = 0\n\tvar previous = 0\n\tvar variable = 1\n\tvar scanning = 1\n\tvar ampersand = 1\n\tvar character = 0\n\tvar type = ''\n\tvar props = rules\n\tvar children = rulesets\n\tvar reference = rule\n\tvar characters = type\n\n\twhile (scanning)\n\t\tswitch (previous = character, character = next()) {\n\t\t\t// (\n\t\t\tcase 40:\n\t\t\t\tif (previous != 108 && charat(characters, length - 1) == 58) {\n\t\t\t\t\tif (indexof(characters += replace(delimit(character), '&', '&\\f'), '&\\f') != -1)\n\t\t\t\t\t\tampersand = -1\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t// \" ' [\n\t\t\tcase 34: case 39: case 91:\n\t\t\t\tcharacters += delimit(character)\n\t\t\t\tbreak\n\t\t\t// \\t \\n \\r \\s\n\t\t\tcase 9: case 10: case 13: case 32:\n\t\t\t\tcharacters += whitespace(previous)\n\t\t\t\tbreak\n\t\t\t// \\\n\t\t\tcase 92:\n\t\t\t\tcharacters += escaping(caret() - 1, 7)\n\t\t\t\tcontinue\n\t\t\t// /\n\t\t\tcase 47:\n\t\t\t\tswitch (peek()) {\n\t\t\t\t\tcase 42: case 47:\n\t\t\t\t\t\tappend(comment(commenter(next(), caret()), root, parent), declarations)\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tcharacters += '/'\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t// {\n\t\t\tcase 123 * variable:\n\t\t\t\tpoints[index++] = strlen(characters) * ampersand\n\t\t\t// } ; \\0\n\t\t\tcase 125 * variable: case 59: case 0:\n\t\t\t\tswitch (character) {\n\t\t\t\t\t// \\0 }\n\t\t\t\t\tcase 0: case 125: scanning = 0\n\t\t\t\t\t// ;\n\t\t\t\t\tcase 59 + offset: if (ampersand == -1) characters = replace(characters, /\\f/g, '')\n\t\t\t\t\t\tif (property > 0 && (strlen(characters) - length))\n\t\t\t\t\t\t\tappend(property > 32 ? declaration(characters + ';', rule, parent, length - 1) : declaration(replace(characters, ' ', '') + ';', rule, parent, length - 2), declarations)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t// @ ;\n\t\t\t\t\tcase 59: characters += ';'\n\t\t\t\t\t// { rule/at-rule\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tappend(reference = ruleset(characters, root, parent, index, offset, rules, points, type, props = [], children = [], length), rulesets)\n\n\t\t\t\t\t\tif (character === 123)\n\t\t\t\t\t\t\tif (offset === 0)\n\t\t\t\t\t\t\t\tparse(characters, root, reference, reference, props, rulesets, length, points, children)\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tswitch (atrule === 99 && charat(characters, 3) === 110 ? 100 : atrule) {\n\t\t\t\t\t\t\t\t\t// d l m s\n\t\t\t\t\t\t\t\t\tcase 100: case 108: case 109: case 115:\n\t\t\t\t\t\t\t\t\t\tparse(value, reference, reference, rule && append(ruleset(value, reference, reference, 0, 0, rules, points, type, rules, props = [], length), children), rules, children, length, points, rule ? props : children)\n\t\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tparse(characters, reference, reference, reference, [''], children, 0, points, children)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tindex = offset = property = 0, variable = ampersand = 1, type = characters = '', length = pseudo\n\t\t\t\tbreak\n\t\t\t// :\n\t\t\tcase 58:\n\t\t\t\tlength = 1 + strlen(characters), property = previous\n\t\t\tdefault:\n\t\t\t\tif (variable < 1)\n\t\t\t\t\tif (character == 123)\n\t\t\t\t\t\t--variable\n\t\t\t\t\telse if (character == 125 && variable++ == 0 && prev() == 125)\n\t\t\t\t\t\tcontinue\n\n\t\t\t\tswitch (characters += from(character), character * variable) {\n\t\t\t\t\t// &\n\t\t\t\t\tcase 38:\n\t\t\t\t\t\tampersand = offset > 0 ? 1 : (characters += '\\f', -1)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t// ,\n\t\t\t\t\tcase 44:\n\t\t\t\t\t\tpoints[index++] = (strlen(characters) - 1) * ampersand, ampersand = 1\n\t\t\t\t\t\tbreak\n\t\t\t\t\t// @\n\t\t\t\t\tcase 64:\n\t\t\t\t\t\t// -\n\t\t\t\t\t\tif (peek() === 45)\n\t\t\t\t\t\t\tcharacters += delimit(next())\n\n\t\t\t\t\t\tatrule = peek(), offset = length = strlen(type = characters += identifier(caret())), character++\n\t\t\t\t\t\tbreak\n\t\t\t\t\t// -\n\t\t\t\t\tcase 45:\n\t\t\t\t\t\tif (previous === 45 && strlen(characters) == 2)\n\t\t\t\t\t\t\tvariable = 0\n\t\t\t\t}\n\t\t}\n\n\treturn rulesets\n}\n\n/**\n * @param {string} value\n * @param {object} root\n * @param {object?} parent\n * @param {number} index\n * @param {number} offset\n * @param {string[]} rules\n * @param {number[]} points\n * @param {string} type\n * @param {string[]} props\n * @param {string[]} children\n * @param {number} length\n * @return {object}\n */\nexport function ruleset (value, root, parent, index, offset, rules, points, type, props, children, length) {\n\tvar post = offset - 1\n\tvar rule = offset === 0 ? rules : ['']\n\tvar size = sizeof(rule)\n\n\tfor (var i = 0, j = 0, k = 0; i < index; ++i)\n\t\tfor (var x = 0, y = substr(value, post + 1, post = abs(j = points[i])), z = value; x < size; ++x)\n\t\t\tif (z = trim(j > 0 ? rule[x] + ' ' + y : replace(y, /&\\f/g, rule[x])))\n\t\t\t\tprops[k++] = z\n\n\treturn node(value, root, parent, offset === 0 ? RULESET : type, props, children, length)\n}\n\n/**\n * @param {number} value\n * @param {object} root\n * @param {object?} parent\n * @return {object}\n */\nexport function comment (value, root, parent) {\n\treturn node(value, root, parent, COMMENT, from(char()), substr(value, 2, -2), 0)\n}\n\n/**\n * @param {string} value\n * @param {object} root\n * @param {object?} parent\n * @param {number} length\n * @return {object}\n */\nexport function declaration (value, root, parent, length) {\n\treturn node(value, root, parent, DECLARATION, substr(value, 0, length), substr(value, length + 1, -1), length)\n}\n","import {IMPORT, LAYER, COMMENT, RULESET, DECLARATION, KEYFRAMES} from './Enum.js'\nimport {strlen, sizeof} from './Utility.js'\n\n/**\n * @param {object[]} children\n * @param {function} callback\n * @return {string}\n */\nexport function serialize (children, callback) {\n\tvar output = ''\n\tvar length = sizeof(children)\n\n\tfor (var i = 0; i < length; i++)\n\t\toutput += callback(children[i], i, children, callback) || ''\n\n\treturn output\n}\n\n/**\n * @param {object} element\n * @param {number} index\n * @param {object[]} children\n * @param {function} callback\n * @return {string}\n */\nexport function stringify (element, index, children, callback) {\n\tswitch (element.type) {\n\t\tcase LAYER: if (element.children.length) break\n\t\tcase IMPORT: case DECLARATION: return element.return = element.return || element.value\n\t\tcase COMMENT: return ''\n\t\tcase KEYFRAMES: return element.return = element.value + '{' + serialize(element.children, callback) + '}'\n\t\tcase RULESET: element.value = element.props.join(',')\n\t}\n\n\treturn strlen(children = serialize(element.children, callback)) ? element.return = element.value + '{' + children + '}' : ''\n}\n","import {MS, MOZ, WEBKIT, RULESET, KEYFRAMES, DECLARATION} from './Enum.js'\nimport {match, charat, substr, strlen, sizeof, replace, combine} from './Utility.js'\nimport {copy, tokenize} from './Tokenizer.js'\nimport {serialize} from './Serializer.js'\nimport {prefix} from './Prefixer.js'\n\n/**\n * @param {function[]} collection\n * @return {function}\n */\nexport function middleware (collection) {\n\tvar length = sizeof(collection)\n\n\treturn function (element, index, children, callback) {\n\t\tvar output = ''\n\n\t\tfor (var i = 0; i < length; i++)\n\t\t\toutput += collection[i](element, index, children, callback) || ''\n\n\t\treturn output\n\t}\n}\n\n/**\n * @param {function} callback\n * @return {function}\n */\nexport function rulesheet (callback) {\n\treturn function (element) {\n\t\tif (!element.root)\n\t\t\tif (element = element.return)\n\t\t\t\tcallback(element)\n\t}\n}\n\n/**\n * @param {object} element\n * @param {number} index\n * @param {object[]} children\n * @param {function} callback\n */\nexport function prefixer (element, index, children, callback) {\n\tif (element.length > -1)\n\t\tif (!element.return)\n\t\t\tswitch (element.type) {\n\t\t\t\tcase DECLARATION: element.return = prefix(element.value, element.length, children)\n\t\t\t\t\treturn\n\t\t\t\tcase KEYFRAMES:\n\t\t\t\t\treturn serialize([copy(element, {value: replace(element.value, '@', '@' + WEBKIT)})], callback)\n\t\t\t\tcase RULESET:\n\t\t\t\t\tif (element.length)\n\t\t\t\t\t\treturn combine(element.props, function (value) {\n\t\t\t\t\t\t\tswitch (match(value, /(::plac\\w+|:read-\\w+)/)) {\n\t\t\t\t\t\t\t\t// :read-(only|write)\n\t\t\t\t\t\t\t\tcase ':read-only': case ':read-write':\n\t\t\t\t\t\t\t\t\treturn serialize([copy(element, {props: [replace(value, /:(read-\\w+)/, ':' + MOZ + '$1')]})], callback)\n\t\t\t\t\t\t\t\t// :placeholder\n\t\t\t\t\t\t\t\tcase '::placeholder':\n\t\t\t\t\t\t\t\t\treturn serialize([\n\t\t\t\t\t\t\t\t\t\tcopy(element, {props: [replace(value, /:(plac\\w+)/, ':' + WEBKIT + 'input-$1')]}),\n\t\t\t\t\t\t\t\t\t\tcopy(element, {props: [replace(value, /:(plac\\w+)/, ':' + MOZ + '$1')]}),\n\t\t\t\t\t\t\t\t\t\tcopy(element, {props: [replace(value, /:(plac\\w+)/, MS + 'input-$1')]})\n\t\t\t\t\t\t\t\t\t], callback)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn ''\n\t\t\t\t\t\t})\n\t\t\t}\n}\n\n/**\n * @param {object} element\n * @param {number} index\n * @param {object[]} children\n */\nexport function namespace (element) {\n\tswitch (element.type) {\n\t\tcase RULESET:\n\t\t\telement.props = element.props.map(function (value) {\n\t\t\t\treturn combine(tokenize(value), function (value, index, children) {\n\t\t\t\t\tswitch (charat(value, 0)) {\n\t\t\t\t\t\t// \\f\n\t\t\t\t\t\tcase 12:\n\t\t\t\t\t\t\treturn substr(value, 1, strlen(value))\n\t\t\t\t\t\t// \\0 ( + > ~\n\t\t\t\t\t\tcase 0: case 40: case 43: case 62: case 126:\n\t\t\t\t\t\t\treturn value\n\t\t\t\t\t\t// :\n\t\t\t\t\t\tcase 58:\n\t\t\t\t\t\t\tif (children[++index] === 'global')\n\t\t\t\t\t\t\t\tchildren[index] = '', children[++index] = '\\f' + substr(children[index], index = 1, -1)\n\t\t\t\t\t\t// \\s\n\t\t\t\t\t\tcase 32:\n\t\t\t\t\t\t\treturn index === 1 ? '' : value\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tswitch (index) {\n\t\t\t\t\t\t\t\tcase 0: element = value\n\t\t\t\t\t\t\t\t\treturn sizeof(children) > 1 ? '' : value\n\t\t\t\t\t\t\t\tcase index = sizeof(children) - 1: case 2:\n\t\t\t\t\t\t\t\t\treturn index === 2 ? value + element + element : value + element\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\treturn value\n\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t}\n}\n","function memoize(fn) {\n var cache = Object.create(null);\n return function (arg) {\n if (cache[arg] === undefined) cache[arg] = fn(arg);\n return cache[arg];\n };\n}\n\nexport { memoize as default };\n","import { StyleSheet } from '@emotion/sheet';\nimport { dealloc, alloc, next, token, from, peek, delimit, slice, position, RULESET, combine, match, serialize, copy, replace, WEBKIT, MOZ, MS, KEYFRAMES, DECLARATION, hash, charat, strlen, indexof, stringify, rulesheet, middleware, compile } from 'stylis';\nimport '@emotion/weak-memoize';\nimport '@emotion/memoize';\n\nvar identifierWithPointTracking = function identifierWithPointTracking(begin, points, index) {\n var previous = 0;\n var character = 0;\n\n while (true) {\n previous = character;\n character = peek(); // &\\f\n\n if (previous === 38 && character === 12) {\n points[index] = 1;\n }\n\n if (token(character)) {\n break;\n }\n\n next();\n }\n\n return slice(begin, position);\n};\n\nvar toRules = function toRules(parsed, points) {\n // pretend we've started with a comma\n var index = -1;\n var character = 44;\n\n do {\n switch (token(character)) {\n case 0:\n // &\\f\n if (character === 38 && peek() === 12) {\n // this is not 100% correct, we don't account for literal sequences here - like for example quoted strings\n // stylis inserts \\f after & to know when & where it should replace this sequence with the context selector\n // and when it should just concatenate the outer and inner selectors\n // it's very unlikely for this sequence to actually appear in a different context, so we just leverage this fact here\n points[index] = 1;\n }\n\n parsed[index] += identifierWithPointTracking(position - 1, points, index);\n break;\n\n case 2:\n parsed[index] += delimit(character);\n break;\n\n case 4:\n // comma\n if (character === 44) {\n // colon\n parsed[++index] = peek() === 58 ? '&\\f' : '';\n points[index] = parsed[index].length;\n break;\n }\n\n // fallthrough\n\n default:\n parsed[index] += from(character);\n }\n } while (character = next());\n\n return parsed;\n};\n\nvar getRules = function getRules(value, points) {\n return dealloc(toRules(alloc(value), points));\n}; // WeakSet would be more appropriate, but only WeakMap is supported in IE11\n\n\nvar fixedElements = /* #__PURE__ */new WeakMap();\nvar compat = function compat(element) {\n if (element.type !== 'rule' || !element.parent || // positive .length indicates that this rule contains pseudo\n // negative .length indicates that this rule has been already prefixed\n element.length < 1) {\n return;\n }\n\n var value = element.value;\n var parent = element.parent;\n var isImplicitRule = element.column === parent.column && element.line === parent.line;\n\n while (parent.type !== 'rule') {\n parent = parent.parent;\n if (!parent) return;\n } // short-circuit for the simplest case\n\n\n if (element.props.length === 1 && value.charCodeAt(0) !== 58\n /* colon */\n && !fixedElements.get(parent)) {\n return;\n } // if this is an implicitly inserted rule (the one eagerly inserted at the each new nested level)\n // then the props has already been manipulated beforehand as they that array is shared between it and its \"rule parent\"\n\n\n if (isImplicitRule) {\n return;\n }\n\n fixedElements.set(element, true);\n var points = [];\n var rules = getRules(value, points);\n var parentRules = parent.props;\n\n for (var i = 0, k = 0; i < rules.length; i++) {\n for (var j = 0; j < parentRules.length; j++, k++) {\n element.props[k] = points[i] ? rules[i].replace(/&\\f/g, parentRules[j]) : parentRules[j] + \" \" + rules[i];\n }\n }\n};\nvar removeLabel = function removeLabel(element) {\n if (element.type === 'decl') {\n var value = element.value;\n\n if ( // charcode for l\n value.charCodeAt(0) === 108 && // charcode for b\n value.charCodeAt(2) === 98) {\n // this ignores label\n element[\"return\"] = '';\n element.value = '';\n }\n }\n};\n\n/* eslint-disable no-fallthrough */\n\nfunction prefix(value, length) {\n switch (hash(value, length)) {\n // color-adjust\n case 5103:\n return WEBKIT + 'print-' + value + value;\n // animation, animation-(delay|direction|duration|fill-mode|iteration-count|name|play-state|timing-function)\n\n case 5737:\n case 4201:\n case 3177:\n case 3433:\n case 1641:\n case 4457:\n case 2921: // text-decoration, filter, clip-path, backface-visibility, column, box-decoration-break\n\n case 5572:\n case 6356:\n case 5844:\n case 3191:\n case 6645:\n case 3005: // mask, mask-image, mask-(mode|clip|size), mask-(repeat|origin), mask-position, mask-composite,\n\n case 6391:\n case 5879:\n case 5623:\n case 6135:\n case 4599:\n case 4855: // background-clip, columns, column-(count|fill|gap|rule|rule-color|rule-style|rule-width|span|width)\n\n case 4215:\n case 6389:\n case 5109:\n case 5365:\n case 5621:\n case 3829:\n return WEBKIT + value + value;\n // appearance, user-select, transform, hyphens, text-size-adjust\n\n case 5349:\n case 4246:\n case 4810:\n case 6968:\n case 2756:\n return WEBKIT + value + MOZ + value + MS + value + value;\n // flex, flex-direction\n\n case 6828:\n case 4268:\n return WEBKIT + value + MS + value + value;\n // order\n\n case 6165:\n return WEBKIT + value + MS + 'flex-' + value + value;\n // align-items\n\n case 5187:\n return WEBKIT + value + replace(value, /(\\w+).+(:[^]+)/, WEBKIT + 'box-$1$2' + MS + 'flex-$1$2') + value;\n // align-self\n\n case 5443:\n return WEBKIT + value + MS + 'flex-item-' + replace(value, /flex-|-self/, '') + value;\n // align-content\n\n case 4675:\n return WEBKIT + value + MS + 'flex-line-pack' + replace(value, /align-content|flex-|-self/, '') + value;\n // flex-shrink\n\n case 5548:\n return WEBKIT + value + MS + replace(value, 'shrink', 'negative') + value;\n // flex-basis\n\n case 5292:\n return WEBKIT + value + MS + replace(value, 'basis', 'preferred-size') + value;\n // flex-grow\n\n case 6060:\n return WEBKIT + 'box-' + replace(value, '-grow', '') + WEBKIT + value + MS + replace(value, 'grow', 'positive') + value;\n // transition\n\n case 4554:\n return WEBKIT + replace(value, /([^-])(transform)/g, '$1' + WEBKIT + '$2') + value;\n // cursor\n\n case 6187:\n return replace(replace(replace(value, /(zoom-|grab)/, WEBKIT + '$1'), /(image-set)/, WEBKIT + '$1'), value, '') + value;\n // background, background-image\n\n case 5495:\n case 3959:\n return replace(value, /(image-set\\([^]*)/, WEBKIT + '$1' + '$`$1');\n // justify-content\n\n case 4968:\n return replace(replace(value, /(.+:)(flex-)?(.*)/, WEBKIT + 'box-pack:$3' + MS + 'flex-pack:$3'), /s.+-b[^;]+/, 'justify') + WEBKIT + value + value;\n // (margin|padding)-inline-(start|end)\n\n case 4095:\n case 3583:\n case 4068:\n case 2532:\n return replace(value, /(.+)-inline(.+)/, WEBKIT + '$1$2') + value;\n // (min|max)?(width|height|inline-size|block-size)\n\n case 8116:\n case 7059:\n case 5753:\n case 5535:\n case 5445:\n case 5701:\n case 4933:\n case 4677:\n case 5533:\n case 5789:\n case 5021:\n case 4765:\n // stretch, max-content, min-content, fill-available\n if (strlen(value) - 1 - length > 6) switch (charat(value, length + 1)) {\n // (m)ax-content, (m)in-content\n case 109:\n // -\n if (charat(value, length + 4) !== 45) break;\n // (f)ill-available, (f)it-content\n\n case 102:\n return replace(value, /(.+:)(.+)-([^]+)/, '$1' + WEBKIT + '$2-$3' + '$1' + MOZ + (charat(value, length + 3) == 108 ? '$3' : '$2-$3')) + value;\n // (s)tretch\n\n case 115:\n return ~indexof(value, 'stretch') ? prefix(replace(value, 'stretch', 'fill-available'), length) + value : value;\n }\n break;\n // position: sticky\n\n case 4949:\n // (s)ticky?\n if (charat(value, length + 1) !== 115) break;\n // display: (flex|inline-flex)\n\n case 6444:\n switch (charat(value, strlen(value) - 3 - (~indexof(value, '!important') && 10))) {\n // stic(k)y\n case 107:\n return replace(value, ':', ':' + WEBKIT) + value;\n // (inline-)?fl(e)x\n\n case 101:\n return replace(value, /(.+:)([^;!]+)(;|!.+)?/, '$1' + WEBKIT + (charat(value, 14) === 45 ? 'inline-' : '') + 'box$3' + '$1' + WEBKIT + '$2$3' + '$1' + MS + '$2box$3') + value;\n }\n\n break;\n // writing-mode\n\n case 5936:\n switch (charat(value, length + 11)) {\n // vertical-l(r)\n case 114:\n return WEBKIT + value + MS + replace(value, /[svh]\\w+-[tblr]{2}/, 'tb') + value;\n // vertical-r(l)\n\n case 108:\n return WEBKIT + value + MS + replace(value, /[svh]\\w+-[tblr]{2}/, 'tb-rl') + value;\n // horizontal(-)tb\n\n case 45:\n return WEBKIT + value + MS + replace(value, /[svh]\\w+-[tblr]{2}/, 'lr') + value;\n }\n\n return WEBKIT + value + MS + value + value;\n }\n\n return value;\n}\n\nvar prefixer = function prefixer(element, index, children, callback) {\n if (element.length > -1) if (!element[\"return\"]) switch (element.type) {\n case DECLARATION:\n element[\"return\"] = prefix(element.value, element.length);\n break;\n\n case KEYFRAMES:\n return serialize([copy(element, {\n value: replace(element.value, '@', '@' + WEBKIT)\n })], callback);\n\n case RULESET:\n if (element.length) return combine(element.props, function (value) {\n switch (match(value, /(::plac\\w+|:read-\\w+)/)) {\n // :read-(only|write)\n case ':read-only':\n case ':read-write':\n return serialize([copy(element, {\n props: [replace(value, /:(read-\\w+)/, ':' + MOZ + '$1')]\n })], callback);\n // :placeholder\n\n case '::placeholder':\n return serialize([copy(element, {\n props: [replace(value, /:(plac\\w+)/, ':' + WEBKIT + 'input-$1')]\n }), copy(element, {\n props: [replace(value, /:(plac\\w+)/, ':' + MOZ + '$1')]\n }), copy(element, {\n props: [replace(value, /:(plac\\w+)/, MS + 'input-$1')]\n })], callback);\n }\n\n return '';\n });\n }\n};\n\nvar defaultStylisPlugins = [prefixer];\n\nvar createCache = function createCache(options) {\n var key = options.key;\n\n if (key === 'css') {\n var ssrStyles = document.querySelectorAll(\"style[data-emotion]:not([data-s])\"); // get SSRed styles out of the way of React's hydration\n // document.head is a safe place to move them to(though note document.head is not necessarily the last place they will be)\n // note this very very intentionally targets all style elements regardless of the key to ensure\n // that creating a cache works inside of render of a React component\n\n Array.prototype.forEach.call(ssrStyles, function (node) {\n // we want to only move elements which have a space in the data-emotion attribute value\n // because that indicates that it is an Emotion 11 server-side rendered style elements\n // while we will already ignore Emotion 11 client-side inserted styles because of the :not([data-s]) part in the selector\n // Emotion 10 client-side inserted styles did not have data-s (but importantly did not have a space in their data-emotion attributes)\n // so checking for the space ensures that loading Emotion 11 after Emotion 10 has inserted some styles\n // will not result in the Emotion 10 styles being destroyed\n var dataEmotionAttribute = node.getAttribute('data-emotion');\n\n if (dataEmotionAttribute.indexOf(' ') === -1) {\n return;\n }\n\n document.head.appendChild(node);\n node.setAttribute('data-s', '');\n });\n }\n\n var stylisPlugins = options.stylisPlugins || defaultStylisPlugins;\n\n var inserted = {};\n var container;\n var nodesToHydrate = [];\n\n {\n container = options.container || document.head;\n Array.prototype.forEach.call( // this means we will ignore elements which don't have a space in them which\n // means that the style elements we're looking at are only Emotion 11 server-rendered style elements\n document.querySelectorAll(\"style[data-emotion^=\\\"\" + key + \" \\\"]\"), function (node) {\n var attrib = node.getAttribute(\"data-emotion\").split(' ');\n\n for (var i = 1; i < attrib.length; i++) {\n inserted[attrib[i]] = true;\n }\n\n nodesToHydrate.push(node);\n });\n }\n\n var _insert;\n\n var omnipresentPlugins = [compat, removeLabel];\n\n {\n var currentSheet;\n var finalizingPlugins = [stringify, rulesheet(function (rule) {\n currentSheet.insert(rule);\n })];\n var serializer = middleware(omnipresentPlugins.concat(stylisPlugins, finalizingPlugins));\n\n var stylis = function stylis(styles) {\n return serialize(compile(styles), serializer);\n };\n\n _insert = function insert(selector, serialized, sheet, shouldCache) {\n currentSheet = sheet;\n\n stylis(selector ? selector + \"{\" + serialized.styles + \"}\" : serialized.styles);\n\n if (shouldCache) {\n cache.inserted[serialized.name] = true;\n }\n };\n }\n\n var cache = {\n key: key,\n sheet: new StyleSheet({\n key: key,\n container: container,\n nonce: options.nonce,\n speedy: options.speedy,\n prepend: options.prepend,\n insertionPoint: options.insertionPoint\n }),\n nonce: options.nonce,\n inserted: inserted,\n registered: {},\n insert: _insert\n };\n cache.sheet.hydrate(nodesToHydrate);\n return cache;\n};\n\nexport { createCache as default };\n","/** @license React v16.13.1\n * react-is.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';var b=\"function\"===typeof Symbol&&Symbol.for,c=b?Symbol.for(\"react.element\"):60103,d=b?Symbol.for(\"react.portal\"):60106,e=b?Symbol.for(\"react.fragment\"):60107,f=b?Symbol.for(\"react.strict_mode\"):60108,g=b?Symbol.for(\"react.profiler\"):60114,h=b?Symbol.for(\"react.provider\"):60109,k=b?Symbol.for(\"react.context\"):60110,l=b?Symbol.for(\"react.async_mode\"):60111,m=b?Symbol.for(\"react.concurrent_mode\"):60111,n=b?Symbol.for(\"react.forward_ref\"):60112,p=b?Symbol.for(\"react.suspense\"):60113,q=b?\nSymbol.for(\"react.suspense_list\"):60120,r=b?Symbol.for(\"react.memo\"):60115,t=b?Symbol.for(\"react.lazy\"):60116,v=b?Symbol.for(\"react.block\"):60121,w=b?Symbol.for(\"react.fundamental\"):60117,x=b?Symbol.for(\"react.responder\"):60118,y=b?Symbol.for(\"react.scope\"):60119;\nfunction z(a){if(\"object\"===typeof a&&null!==a){var u=a.$$typeof;switch(u){case c:switch(a=a.type,a){case l:case m:case e:case g:case f:case p:return a;default:switch(a=a&&a.$$typeof,a){case k:case n:case t:case r:case h:return a;default:return u}}case d:return u}}}function A(a){return z(a)===m}exports.AsyncMode=l;exports.ConcurrentMode=m;exports.ContextConsumer=k;exports.ContextProvider=h;exports.Element=c;exports.ForwardRef=n;exports.Fragment=e;exports.Lazy=t;exports.Memo=r;exports.Portal=d;\nexports.Profiler=g;exports.StrictMode=f;exports.Suspense=p;exports.isAsyncMode=function(a){return A(a)||z(a)===l};exports.isConcurrentMode=A;exports.isContextConsumer=function(a){return z(a)===k};exports.isContextProvider=function(a){return z(a)===h};exports.isElement=function(a){return\"object\"===typeof a&&null!==a&&a.$$typeof===c};exports.isForwardRef=function(a){return z(a)===n};exports.isFragment=function(a){return z(a)===e};exports.isLazy=function(a){return z(a)===t};\nexports.isMemo=function(a){return z(a)===r};exports.isPortal=function(a){return z(a)===d};exports.isProfiler=function(a){return z(a)===g};exports.isStrictMode=function(a){return z(a)===f};exports.isSuspense=function(a){return z(a)===p};\nexports.isValidElementType=function(a){return\"string\"===typeof a||\"function\"===typeof a||a===e||a===m||a===g||a===f||a===p||a===q||\"object\"===typeof a&&null!==a&&(a.$$typeof===t||a.$$typeof===r||a.$$typeof===h||a.$$typeof===k||a.$$typeof===n||a.$$typeof===w||a.$$typeof===x||a.$$typeof===y||a.$$typeof===v)};exports.typeOf=z;\n","/** @license React v16.13.1\n * react-is.development.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n\n\nif (process.env.NODE_ENV !== \"production\") {\n (function() {\n'use strict';\n\n// The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar hasSymbol = typeof Symbol === 'function' && Symbol.for;\nvar REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;\nvar REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca;\nvar REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;\nvar REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;\nvar REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2;\nvar REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd;\nvar REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary\n// (unstable) APIs that have been removed. Can we remove the symbols?\n\nvar REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf;\nvar REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf;\nvar REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;\nvar REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1;\nvar REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8;\nvar REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;\nvar REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4;\nvar REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9;\nvar REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for('react.fundamental') : 0xead5;\nvar REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for('react.responder') : 0xead6;\nvar REACT_SCOPE_TYPE = hasSymbol ? Symbol.for('react.scope') : 0xead7;\n\nfunction isValidElementType(type) {\n return typeof type === 'string' || typeof type === 'function' || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.\n type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE);\n}\n\nfunction typeOf(object) {\n if (typeof object === 'object' && object !== null) {\n var $$typeof = object.$$typeof;\n\n switch ($$typeof) {\n case REACT_ELEMENT_TYPE:\n var type = object.type;\n\n switch (type) {\n case REACT_ASYNC_MODE_TYPE:\n case REACT_CONCURRENT_MODE_TYPE:\n case REACT_FRAGMENT_TYPE:\n case REACT_PROFILER_TYPE:\n case REACT_STRICT_MODE_TYPE:\n case REACT_SUSPENSE_TYPE:\n return type;\n\n default:\n var $$typeofType = type && type.$$typeof;\n\n switch ($$typeofType) {\n case REACT_CONTEXT_TYPE:\n case REACT_FORWARD_REF_TYPE:\n case REACT_LAZY_TYPE:\n case REACT_MEMO_TYPE:\n case REACT_PROVIDER_TYPE:\n return $$typeofType;\n\n default:\n return $$typeof;\n }\n\n }\n\n case REACT_PORTAL_TYPE:\n return $$typeof;\n }\n }\n\n return undefined;\n} // AsyncMode is deprecated along with isAsyncMode\n\nvar AsyncMode = REACT_ASYNC_MODE_TYPE;\nvar ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;\nvar ContextConsumer = REACT_CONTEXT_TYPE;\nvar ContextProvider = REACT_PROVIDER_TYPE;\nvar Element = REACT_ELEMENT_TYPE;\nvar ForwardRef = REACT_FORWARD_REF_TYPE;\nvar Fragment = REACT_FRAGMENT_TYPE;\nvar Lazy = REACT_LAZY_TYPE;\nvar Memo = REACT_MEMO_TYPE;\nvar Portal = REACT_PORTAL_TYPE;\nvar Profiler = REACT_PROFILER_TYPE;\nvar StrictMode = REACT_STRICT_MODE_TYPE;\nvar Suspense = REACT_SUSPENSE_TYPE;\nvar hasWarnedAboutDeprecatedIsAsyncMode = false; // AsyncMode should be deprecated\n\nfunction isAsyncMode(object) {\n {\n if (!hasWarnedAboutDeprecatedIsAsyncMode) {\n hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint\n\n console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 17+. Update your code to use ' + 'ReactIs.isConcurrentMode() instead. It has the exact same API.');\n }\n }\n\n return isConcurrentMode(object) || typeOf(object) === REACT_ASYNC_MODE_TYPE;\n}\nfunction isConcurrentMode(object) {\n return typeOf(object) === REACT_CONCURRENT_MODE_TYPE;\n}\nfunction isContextConsumer(object) {\n return typeOf(object) === REACT_CONTEXT_TYPE;\n}\nfunction isContextProvider(object) {\n return typeOf(object) === REACT_PROVIDER_TYPE;\n}\nfunction isElement(object) {\n return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n}\nfunction isForwardRef(object) {\n return typeOf(object) === REACT_FORWARD_REF_TYPE;\n}\nfunction isFragment(object) {\n return typeOf(object) === REACT_FRAGMENT_TYPE;\n}\nfunction isLazy(object) {\n return typeOf(object) === REACT_LAZY_TYPE;\n}\nfunction isMemo(object) {\n return typeOf(object) === REACT_MEMO_TYPE;\n}\nfunction isPortal(object) {\n return typeOf(object) === REACT_PORTAL_TYPE;\n}\nfunction isProfiler(object) {\n return typeOf(object) === REACT_PROFILER_TYPE;\n}\nfunction isStrictMode(object) {\n return typeOf(object) === REACT_STRICT_MODE_TYPE;\n}\nfunction isSuspense(object) {\n return typeOf(object) === REACT_SUSPENSE_TYPE;\n}\n\nexports.AsyncMode = AsyncMode;\nexports.ConcurrentMode = ConcurrentMode;\nexports.ContextConsumer = ContextConsumer;\nexports.ContextProvider = ContextProvider;\nexports.Element = Element;\nexports.ForwardRef = ForwardRef;\nexports.Fragment = Fragment;\nexports.Lazy = Lazy;\nexports.Memo = Memo;\nexports.Portal = Portal;\nexports.Profiler = Profiler;\nexports.StrictMode = StrictMode;\nexports.Suspense = Suspense;\nexports.isAsyncMode = isAsyncMode;\nexports.isConcurrentMode = isConcurrentMode;\nexports.isContextConsumer = isContextConsumer;\nexports.isContextProvider = isContextProvider;\nexports.isElement = isElement;\nexports.isForwardRef = isForwardRef;\nexports.isFragment = isFragment;\nexports.isLazy = isLazy;\nexports.isMemo = isMemo;\nexports.isPortal = isPortal;\nexports.isProfiler = isProfiler;\nexports.isStrictMode = isStrictMode;\nexports.isSuspense = isSuspense;\nexports.isValidElementType = isValidElementType;\nexports.typeOf = typeOf;\n })();\n}\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-is.production.min.js');\n} else {\n module.exports = require('./cjs/react-is.development.js');\n}\n","'use strict';\n\nvar reactIs = require('react-is');\n\n/**\n * Copyright 2015, Yahoo! Inc.\n * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.\n */\nvar REACT_STATICS = {\n childContextTypes: true,\n contextType: true,\n contextTypes: true,\n defaultProps: true,\n displayName: true,\n getDefaultProps: true,\n getDerivedStateFromError: true,\n getDerivedStateFromProps: true,\n mixins: true,\n propTypes: true,\n type: true\n};\nvar KNOWN_STATICS = {\n name: true,\n length: true,\n prototype: true,\n caller: true,\n callee: true,\n arguments: true,\n arity: true\n};\nvar FORWARD_REF_STATICS = {\n '$$typeof': true,\n render: true,\n defaultProps: true,\n displayName: true,\n propTypes: true\n};\nvar MEMO_STATICS = {\n '$$typeof': true,\n compare: true,\n defaultProps: true,\n displayName: true,\n propTypes: true,\n type: true\n};\nvar TYPE_STATICS = {};\nTYPE_STATICS[reactIs.ForwardRef] = FORWARD_REF_STATICS;\nTYPE_STATICS[reactIs.Memo] = MEMO_STATICS;\n\nfunction getStatics(component) {\n // React v16.11 and below\n if (reactIs.isMemo(component)) {\n return MEMO_STATICS;\n } // React v16.12 and above\n\n\n return TYPE_STATICS[component['$$typeof']] || REACT_STATICS;\n}\n\nvar defineProperty = Object.defineProperty;\nvar getOwnPropertyNames = Object.getOwnPropertyNames;\nvar getOwnPropertySymbols = Object.getOwnPropertySymbols;\nvar getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\nvar getPrototypeOf = Object.getPrototypeOf;\nvar objectPrototype = Object.prototype;\nfunction hoistNonReactStatics(targetComponent, sourceComponent, blacklist) {\n if (typeof sourceComponent !== 'string') {\n // don't hoist over string (html) components\n if (objectPrototype) {\n var inheritedComponent = getPrototypeOf(sourceComponent);\n\n if (inheritedComponent && inheritedComponent !== objectPrototype) {\n hoistNonReactStatics(targetComponent, inheritedComponent, blacklist);\n }\n }\n\n var keys = getOwnPropertyNames(sourceComponent);\n\n if (getOwnPropertySymbols) {\n keys = keys.concat(getOwnPropertySymbols(sourceComponent));\n }\n\n var targetStatics = getStatics(targetComponent);\n var sourceStatics = getStatics(sourceComponent);\n\n for (var i = 0; i < keys.length; ++i) {\n var key = keys[i];\n\n if (!KNOWN_STATICS[key] && !(blacklist && blacklist[key]) && !(sourceStatics && sourceStatics[key]) && !(targetStatics && targetStatics[key])) {\n var descriptor = getOwnPropertyDescriptor(sourceComponent, key);\n\n try {\n // Avoid failures from read-only properties\n defineProperty(targetComponent, key, descriptor);\n } catch (e) {}\n }\n }\n }\n\n return targetComponent;\n}\n\nmodule.exports = hoistNonReactStatics;\n","var isBrowser = true;\n\nfunction getRegisteredStyles(registered, registeredStyles, classNames) {\n var rawClassName = '';\n classNames.split(' ').forEach(function (className) {\n if (registered[className] !== undefined) {\n registeredStyles.push(registered[className] + \";\");\n } else if (className) {\n rawClassName += className + \" \";\n }\n });\n return rawClassName;\n}\nvar registerStyles = function registerStyles(cache, serialized, isStringTag) {\n var className = cache.key + \"-\" + serialized.name;\n\n if ( // we only need to add the styles to the registered cache if the\n // class name could be used further down\n // the tree but if it's a string tag, we know it won't\n // so we don't have to add it to registered cache.\n // this improves memory usage since we can avoid storing the whole style string\n (isStringTag === false || // we need to always store it if we're in compat mode and\n // in node since emotion-server relies on whether a style is in\n // the registered cache to know whether a style is global or not\n // also, note that this check will be dead code eliminated in the browser\n isBrowser === false ) && cache.registered[className] === undefined) {\n cache.registered[className] = serialized.styles;\n }\n};\nvar insertStyles = function insertStyles(cache, serialized, isStringTag) {\n registerStyles(cache, serialized, isStringTag);\n var className = cache.key + \"-\" + serialized.name;\n\n if (cache.inserted[serialized.name] === undefined) {\n var current = serialized;\n\n do {\n cache.insert(serialized === current ? \".\" + className : '', current, cache.sheet, true);\n\n current = current.next;\n } while (current !== undefined);\n }\n};\n\nexport { getRegisteredStyles, insertStyles, registerStyles };\n","/* eslint-disable */\n// Inspired by https://github.com/garycourt/murmurhash-js\n// Ported from https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash2.cpp#L37-L86\nfunction murmur2(str) {\n // 'm' and 'r' are mixing constants generated offline.\n // They're not really 'magic', they just happen to work well.\n // const m = 0x5bd1e995;\n // const r = 24;\n // Initialize the hash\n var h = 0; // Mix 4 bytes at a time into the hash\n\n var k,\n i = 0,\n len = str.length;\n\n for (; len >= 4; ++i, len -= 4) {\n k = str.charCodeAt(i) & 0xff | (str.charCodeAt(++i) & 0xff) << 8 | (str.charCodeAt(++i) & 0xff) << 16 | (str.charCodeAt(++i) & 0xff) << 24;\n k =\n /* Math.imul(k, m): */\n (k & 0xffff) * 0x5bd1e995 + ((k >>> 16) * 0xe995 << 16);\n k ^=\n /* k >>> r: */\n k >>> 24;\n h =\n /* Math.imul(k, m): */\n (k & 0xffff) * 0x5bd1e995 + ((k >>> 16) * 0xe995 << 16) ^\n /* Math.imul(h, m): */\n (h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);\n } // Handle the last few bytes of the input array\n\n\n switch (len) {\n case 3:\n h ^= (str.charCodeAt(i + 2) & 0xff) << 16;\n\n case 2:\n h ^= (str.charCodeAt(i + 1) & 0xff) << 8;\n\n case 1:\n h ^= str.charCodeAt(i) & 0xff;\n h =\n /* Math.imul(h, m): */\n (h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);\n } // Do a few final mixes of the hash to ensure the last few\n // bytes are well-incorporated.\n\n\n h ^= h >>> 13;\n h =\n /* Math.imul(h, m): */\n (h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);\n return ((h ^ h >>> 15) >>> 0).toString(36);\n}\n\nexport { murmur2 as default };\n","var unitlessKeys = {\n animationIterationCount: 1,\n aspectRatio: 1,\n borderImageOutset: 1,\n borderImageSlice: 1,\n borderImageWidth: 1,\n boxFlex: 1,\n boxFlexGroup: 1,\n boxOrdinalGroup: 1,\n columnCount: 1,\n columns: 1,\n flex: 1,\n flexGrow: 1,\n flexPositive: 1,\n flexShrink: 1,\n flexNegative: 1,\n flexOrder: 1,\n gridRow: 1,\n gridRowEnd: 1,\n gridRowSpan: 1,\n gridRowStart: 1,\n gridColumn: 1,\n gridColumnEnd: 1,\n gridColumnSpan: 1,\n gridColumnStart: 1,\n msGridRow: 1,\n msGridRowSpan: 1,\n msGridColumn: 1,\n msGridColumnSpan: 1,\n fontWeight: 1,\n lineHeight: 1,\n opacity: 1,\n order: 1,\n orphans: 1,\n scale: 1,\n tabSize: 1,\n widows: 1,\n zIndex: 1,\n zoom: 1,\n WebkitLineClamp: 1,\n // SVG-related properties\n fillOpacity: 1,\n floodOpacity: 1,\n stopOpacity: 1,\n strokeDasharray: 1,\n strokeDashoffset: 1,\n strokeMiterlimit: 1,\n strokeOpacity: 1,\n strokeWidth: 1\n};\n\nexport { unitlessKeys as default };\n","import hashString from '@emotion/hash';\nimport unitless from '@emotion/unitless';\nimport memoize from '@emotion/memoize';\n\nvar isDevelopment = false;\n\nvar hyphenateRegex = /[A-Z]|^ms/g;\nvar animationRegex = /_EMO_([^_]+?)_([^]*?)_EMO_/g;\n\nvar isCustomProperty = function isCustomProperty(property) {\n return property.charCodeAt(1) === 45;\n};\n\nvar isProcessableValue = function isProcessableValue(value) {\n return value != null && typeof value !== 'boolean';\n};\n\nvar processStyleName = /* #__PURE__ */memoize(function (styleName) {\n return isCustomProperty(styleName) ? styleName : styleName.replace(hyphenateRegex, '-$&').toLowerCase();\n});\n\nvar processStyleValue = function processStyleValue(key, value) {\n switch (key) {\n case 'animation':\n case 'animationName':\n {\n if (typeof value === 'string') {\n return value.replace(animationRegex, function (match, p1, p2) {\n cursor = {\n name: p1,\n styles: p2,\n next: cursor\n };\n return p1;\n });\n }\n }\n }\n\n if (unitless[key] !== 1 && !isCustomProperty(key) && typeof value === 'number' && value !== 0) {\n return value + 'px';\n }\n\n return value;\n};\n\nvar noComponentSelectorMessage = 'Component selectors can only be used in conjunction with ' + '@emotion/babel-plugin, the swc Emotion plugin, or another Emotion-aware ' + 'compiler transform.';\n\nfunction handleInterpolation(mergedProps, registered, interpolation) {\n if (interpolation == null) {\n return '';\n }\n\n var componentSelector = interpolation;\n\n if (componentSelector.__emotion_styles !== undefined) {\n\n return componentSelector;\n }\n\n switch (typeof interpolation) {\n case 'boolean':\n {\n return '';\n }\n\n case 'object':\n {\n var keyframes = interpolation;\n\n if (keyframes.anim === 1) {\n cursor = {\n name: keyframes.name,\n styles: keyframes.styles,\n next: cursor\n };\n return keyframes.name;\n }\n\n var serializedStyles = interpolation;\n\n if (serializedStyles.styles !== undefined) {\n var next = serializedStyles.next;\n\n if (next !== undefined) {\n // not the most efficient thing ever but this is a pretty rare case\n // and there will be very few iterations of this generally\n while (next !== undefined) {\n cursor = {\n name: next.name,\n styles: next.styles,\n next: cursor\n };\n next = next.next;\n }\n }\n\n var styles = serializedStyles.styles + \";\";\n return styles;\n }\n\n return createStringFromObject(mergedProps, registered, interpolation);\n }\n\n case 'function':\n {\n if (mergedProps !== undefined) {\n var previousCursor = cursor;\n var result = interpolation(mergedProps);\n cursor = previousCursor;\n return handleInterpolation(mergedProps, registered, result);\n }\n\n break;\n }\n } // finalize string values (regular strings and functions interpolated into css calls)\n\n\n var asString = interpolation;\n\n if (registered == null) {\n return asString;\n }\n\n var cached = registered[asString];\n return cached !== undefined ? cached : asString;\n}\n\nfunction createStringFromObject(mergedProps, registered, obj) {\n var string = '';\n\n if (Array.isArray(obj)) {\n for (var i = 0; i < obj.length; i++) {\n string += handleInterpolation(mergedProps, registered, obj[i]) + \";\";\n }\n } else {\n for (var key in obj) {\n var value = obj[key];\n\n if (typeof value !== 'object') {\n var asString = value;\n\n if (registered != null && registered[asString] !== undefined) {\n string += key + \"{\" + registered[asString] + \"}\";\n } else if (isProcessableValue(asString)) {\n string += processStyleName(key) + \":\" + processStyleValue(key, asString) + \";\";\n }\n } else {\n if (key === 'NO_COMPONENT_SELECTOR' && isDevelopment) {\n throw new Error(noComponentSelectorMessage);\n }\n\n if (Array.isArray(value) && typeof value[0] === 'string' && (registered == null || registered[value[0]] === undefined)) {\n for (var _i = 0; _i < value.length; _i++) {\n if (isProcessableValue(value[_i])) {\n string += processStyleName(key) + \":\" + processStyleValue(key, value[_i]) + \";\";\n }\n }\n } else {\n var interpolated = handleInterpolation(mergedProps, registered, value);\n\n switch (key) {\n case 'animation':\n case 'animationName':\n {\n string += processStyleName(key) + \":\" + interpolated + \";\";\n break;\n }\n\n default:\n {\n\n string += key + \"{\" + interpolated + \"}\";\n }\n }\n }\n }\n }\n }\n\n return string;\n}\n\nvar labelPattern = /label:\\s*([^\\s;{]+)\\s*(;|$)/g; // this is the cursor for keyframes\n// keyframes are stored on the SerializedStyles object as a linked list\n\nvar cursor;\nfunction serializeStyles(args, registered, mergedProps) {\n if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && args[0].styles !== undefined) {\n return args[0];\n }\n\n var stringMode = true;\n var styles = '';\n cursor = undefined;\n var strings = args[0];\n\n if (strings == null || strings.raw === undefined) {\n stringMode = false;\n styles += handleInterpolation(mergedProps, registered, strings);\n } else {\n var asTemplateStringsArr = strings;\n\n styles += asTemplateStringsArr[0];\n } // we start at 1 since we've already handled the first arg\n\n\n for (var i = 1; i < args.length; i++) {\n styles += handleInterpolation(mergedProps, registered, args[i]);\n\n if (stringMode) {\n var templateStringsArr = strings;\n\n styles += templateStringsArr[i];\n }\n } // using a global regex with .exec is stateful so lastIndex has to be reset each time\n\n\n labelPattern.lastIndex = 0;\n var identifierName = '';\n var match; // https://esbench.com/bench/5b809c2cf2949800a0f61fb5\n\n while ((match = labelPattern.exec(styles)) !== null) {\n identifierName += '-' + match[1];\n }\n\n var name = hashString(styles) + identifierName;\n\n return {\n name: name,\n styles: styles,\n next: cursor\n };\n}\n\nexport { serializeStyles };\n","import * as React from 'react';\n\nvar syncFallback = function syncFallback(create) {\n return create();\n};\n\nvar useInsertionEffect = React['useInsertion' + 'Effect'] ? React['useInsertion' + 'Effect'] : false;\nvar useInsertionEffectAlwaysWithSyncFallback = useInsertionEffect || syncFallback;\nvar useInsertionEffectWithLayoutFallback = useInsertionEffect || React.useLayoutEffect;\n\nexport { useInsertionEffectAlwaysWithSyncFallback, useInsertionEffectWithLayoutFallback };\n","import * as React from 'react';\nimport { useContext, forwardRef } from 'react';\nimport createCache from '@emotion/cache';\nimport _extends from '@babel/runtime/helpers/esm/extends';\nimport weakMemoize from '@emotion/weak-memoize';\nimport hoistNonReactStatics from '../_isolated-hnrs/dist/emotion-react-_isolated-hnrs.browser.esm.js';\nimport { getRegisteredStyles, registerStyles, insertStyles } from '@emotion/utils';\nimport { serializeStyles } from '@emotion/serialize';\nimport { useInsertionEffectAlwaysWithSyncFallback } from '@emotion/use-insertion-effect-with-fallbacks';\n\nvar isDevelopment = false;\n\nvar EmotionCacheContext = /* #__PURE__ */React.createContext( // we're doing this to avoid preconstruct's dead code elimination in this one case\n// because this module is primarily intended for the browser and node\n// but it's also required in react native and similar environments sometimes\n// and we could have a special build just for that\n// but this is much easier and the native packages\n// might use a different theme context in the future anyway\ntypeof HTMLElement !== 'undefined' ? /* #__PURE__ */createCache({\n key: 'css'\n}) : null);\n\nvar CacheProvider = EmotionCacheContext.Provider;\nvar __unsafe_useEmotionCache = function useEmotionCache() {\n return useContext(EmotionCacheContext);\n};\n\nvar withEmotionCache = function withEmotionCache(func) {\n return /*#__PURE__*/forwardRef(function (props, ref) {\n // the cache will never be null in the browser\n var cache = useContext(EmotionCacheContext);\n return func(props, cache, ref);\n });\n};\n\nvar ThemeContext = /* #__PURE__ */React.createContext({});\n\nvar useTheme = function useTheme() {\n return React.useContext(ThemeContext);\n};\n\nvar getTheme = function getTheme(outerTheme, theme) {\n if (typeof theme === 'function') {\n var mergedTheme = theme(outerTheme);\n\n return mergedTheme;\n }\n\n return _extends({}, outerTheme, theme);\n};\n\nvar createCacheWithTheme = /* #__PURE__ */weakMemoize(function (outerTheme) {\n return weakMemoize(function (theme) {\n return getTheme(outerTheme, theme);\n });\n});\nvar ThemeProvider = function ThemeProvider(props) {\n var theme = React.useContext(ThemeContext);\n\n if (props.theme !== theme) {\n theme = createCacheWithTheme(theme)(props.theme);\n }\n\n return /*#__PURE__*/React.createElement(ThemeContext.Provider, {\n value: theme\n }, props.children);\n};\nfunction withTheme(Component) {\n var componentName = Component.displayName || Component.name || 'Component';\n var WithTheme = /*#__PURE__*/React.forwardRef(function render(props, ref) {\n var theme = React.useContext(ThemeContext);\n return /*#__PURE__*/React.createElement(Component, _extends({\n theme: theme,\n ref: ref\n }, props));\n });\n WithTheme.displayName = \"WithTheme(\" + componentName + \")\";\n return hoistNonReactStatics(WithTheme, Component);\n}\n\nvar hasOwn = {}.hasOwnProperty;\n\nvar typePropName = '__EMOTION_TYPE_PLEASE_DO_NOT_USE__';\nvar createEmotionProps = function createEmotionProps(type, props) {\n\n var newProps = {};\n\n for (var _key in props) {\n if (hasOwn.call(props, _key)) {\n newProps[_key] = props[_key];\n }\n }\n\n newProps[typePropName] = type; // Runtime labeling is an opt-in feature because:\n\n return newProps;\n};\n\nvar Insertion = function Insertion(_ref) {\n var cache = _ref.cache,\n serialized = _ref.serialized,\n isStringTag = _ref.isStringTag;\n registerStyles(cache, serialized, isStringTag);\n useInsertionEffectAlwaysWithSyncFallback(function () {\n return insertStyles(cache, serialized, isStringTag);\n });\n\n return null;\n};\n\nvar Emotion = /* #__PURE__ */withEmotionCache(function (props, cache, ref) {\n var cssProp = props.css; // so that using `css` from `emotion` and passing the result to the css prop works\n // not passing the registered cache to serializeStyles because it would\n // make certain babel optimisations not possible\n\n if (typeof cssProp === 'string' && cache.registered[cssProp] !== undefined) {\n cssProp = cache.registered[cssProp];\n }\n\n var WrappedComponent = props[typePropName];\n var registeredStyles = [cssProp];\n var className = '';\n\n if (typeof props.className === 'string') {\n className = getRegisteredStyles(cache.registered, registeredStyles, props.className);\n } else if (props.className != null) {\n className = props.className + \" \";\n }\n\n var serialized = serializeStyles(registeredStyles, undefined, React.useContext(ThemeContext));\n\n className += cache.key + \"-\" + serialized.name;\n var newProps = {};\n\n for (var _key2 in props) {\n if (hasOwn.call(props, _key2) && _key2 !== 'css' && _key2 !== typePropName && (!isDevelopment )) {\n newProps[_key2] = props[_key2];\n }\n }\n\n newProps.className = className;\n\n if (ref) {\n newProps.ref = ref;\n }\n\n return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Insertion, {\n cache: cache,\n serialized: serialized,\n isStringTag: typeof WrappedComponent === 'string'\n }), /*#__PURE__*/React.createElement(WrappedComponent, newProps));\n});\n\nvar Emotion$1 = Emotion;\n\nexport { CacheProvider as C, Emotion$1 as E, ThemeContext as T, __unsafe_useEmotionCache as _, ThemeProvider as a, withTheme as b, createEmotionProps as c, hasOwn as h, isDevelopment as i, useTheme as u, withEmotionCache as w };\n","import { h as hasOwn, E as Emotion, c as createEmotionProps, w as withEmotionCache, T as ThemeContext, i as isDevelopment } from './emotion-element-f0de968e.browser.esm.js';\nexport { C as CacheProvider, T as ThemeContext, a as ThemeProvider, _ as __unsafe_useEmotionCache, u as useTheme, w as withEmotionCache, b as withTheme } from './emotion-element-f0de968e.browser.esm.js';\nimport * as React from 'react';\nimport { insertStyles, registerStyles, getRegisteredStyles } from '@emotion/utils';\nimport { useInsertionEffectWithLayoutFallback, useInsertionEffectAlwaysWithSyncFallback } from '@emotion/use-insertion-effect-with-fallbacks';\nimport { serializeStyles } from '@emotion/serialize';\nimport '@emotion/cache';\nimport '@babel/runtime/helpers/extends';\nimport '@emotion/weak-memoize';\nimport '../_isolated-hnrs/dist/emotion-react-_isolated-hnrs.browser.esm.js';\nimport 'hoist-non-react-statics';\n\nvar jsx = function jsx(type, props) {\n // eslint-disable-next-line prefer-rest-params\n var args = arguments;\n\n if (props == null || !hasOwn.call(props, 'css')) {\n return React.createElement.apply(undefined, args);\n }\n\n var argsLength = args.length;\n var createElementArgArray = new Array(argsLength);\n createElementArgArray[0] = Emotion;\n createElementArgArray[1] = createEmotionProps(type, props);\n\n for (var i = 2; i < argsLength; i++) {\n createElementArgArray[i] = args[i];\n }\n\n return React.createElement.apply(null, createElementArgArray);\n};\n\n(function (_jsx) {\n var JSX;\n\n (function (_JSX) {})(JSX || (JSX = _jsx.JSX || (_jsx.JSX = {})));\n})(jsx || (jsx = {}));\n\n// initial render from browser, insertBefore context.sheet.tags[0] or if a style hasn't been inserted there yet, appendChild\n// initial client-side render from SSR, use place of hydrating tag\n\nvar Global = /* #__PURE__ */withEmotionCache(function (props, cache) {\n\n var styles = props.styles;\n var serialized = serializeStyles([styles], undefined, React.useContext(ThemeContext));\n // but it is based on a constant that will never change at runtime\n // it's effectively like having two implementations and switching them out\n // so it's not actually breaking anything\n\n\n var sheetRef = React.useRef();\n useInsertionEffectWithLayoutFallback(function () {\n var key = cache.key + \"-global\"; // use case of https://github.com/emotion-js/emotion/issues/2675\n\n var sheet = new cache.sheet.constructor({\n key: key,\n nonce: cache.sheet.nonce,\n container: cache.sheet.container,\n speedy: cache.sheet.isSpeedy\n });\n var rehydrating = false;\n var node = document.querySelector(\"style[data-emotion=\\\"\" + key + \" \" + serialized.name + \"\\\"]\");\n\n if (cache.sheet.tags.length) {\n sheet.before = cache.sheet.tags[0];\n }\n\n if (node !== null) {\n rehydrating = true; // clear the hash so this node won't be recognizable as rehydratable by other <Global/>s\n\n node.setAttribute('data-emotion', key);\n sheet.hydrate([node]);\n }\n\n sheetRef.current = [sheet, rehydrating];\n return function () {\n sheet.flush();\n };\n }, [cache]);\n useInsertionEffectWithLayoutFallback(function () {\n var sheetRefCurrent = sheetRef.current;\n var sheet = sheetRefCurrent[0],\n rehydrating = sheetRefCurrent[1];\n\n if (rehydrating) {\n sheetRefCurrent[1] = false;\n return;\n }\n\n if (serialized.next !== undefined) {\n // insert keyframes\n insertStyles(cache, serialized.next, true);\n }\n\n if (sheet.tags.length) {\n // if this doesn't exist then it will be null so the style element will be appended\n var element = sheet.tags[sheet.tags.length - 1].nextElementSibling;\n sheet.before = element;\n sheet.flush();\n }\n\n cache.insert(\"\", serialized, sheet, false);\n }, [cache, serialized.name]);\n return null;\n});\n\nfunction css() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n return serializeStyles(args);\n}\n\nfunction keyframes() {\n var insertable = css.apply(void 0, arguments);\n var name = \"animation-\" + insertable.name;\n return {\n name: name,\n styles: \"@keyframes \" + name + \"{\" + insertable.styles + \"}\",\n anim: 1,\n toString: function toString() {\n return \"_EMO_\" + this.name + \"_\" + this.styles + \"_EMO_\";\n }\n };\n}\n\nvar classnames = function classnames(args) {\n var len = args.length;\n var i = 0;\n var cls = '';\n\n for (; i < len; i++) {\n var arg = args[i];\n if (arg == null) continue;\n var toAdd = void 0;\n\n switch (typeof arg) {\n case 'boolean':\n break;\n\n case 'object':\n {\n if (Array.isArray(arg)) {\n toAdd = classnames(arg);\n } else {\n\n toAdd = '';\n\n for (var k in arg) {\n if (arg[k] && k) {\n toAdd && (toAdd += ' ');\n toAdd += k;\n }\n }\n }\n\n break;\n }\n\n default:\n {\n toAdd = arg;\n }\n }\n\n if (toAdd) {\n cls && (cls += ' ');\n cls += toAdd;\n }\n }\n\n return cls;\n};\n\nfunction merge(registered, css, className) {\n var registeredStyles = [];\n var rawClassName = getRegisteredStyles(registered, registeredStyles, className);\n\n if (registeredStyles.length < 2) {\n return className;\n }\n\n return rawClassName + css(registeredStyles);\n}\n\nvar Insertion = function Insertion(_ref) {\n var cache = _ref.cache,\n serializedArr = _ref.serializedArr;\n useInsertionEffectAlwaysWithSyncFallback(function () {\n\n for (var i = 0; i < serializedArr.length; i++) {\n insertStyles(cache, serializedArr[i], false);\n }\n });\n\n return null;\n};\n\nvar ClassNames = /* #__PURE__ */withEmotionCache(function (props, cache) {\n var hasRendered = false;\n var serializedArr = [];\n\n var css = function css() {\n if (hasRendered && isDevelopment) {\n throw new Error('css can only be used during render');\n }\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n var serialized = serializeStyles(args, cache.registered);\n serializedArr.push(serialized); // registration has to happen here as the result of this might get consumed by `cx`\n\n registerStyles(cache, serialized, false);\n return cache.key + \"-\" + serialized.name;\n };\n\n var cx = function cx() {\n if (hasRendered && isDevelopment) {\n throw new Error('cx can only be used during render');\n }\n\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n\n return merge(cache.registered, css, classnames(args));\n };\n\n var content = {\n css: css,\n cx: cx,\n theme: React.useContext(ThemeContext)\n };\n var ele = props.children(content);\n hasRendered = true;\n return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Insertion, {\n cache: cache,\n serializedArr: serializedArr\n }), ele);\n});\n\nexport { ClassNames, Global, jsx as createElement, css, jsx, keyframes };\n","import { css } from '@emotion/react';\r\n\r\n// Design Tokens\r\nexport const tokens = {\r\n colors: {\r\n text: { primary: '#333333', secondary: '#666666', light: '#ffffff' },\r\n background: { card: '#ffffff', feedbackCorrect: '#f0fdf4', feedbackIncorrect: '#fef2f2' },\r\n border: { default: '#e0e0e0' },\r\n scene: { solve: '#4a6cf7', review: '#4ade80', question: '#f97316' }\r\n },\r\n typography: {\r\n fontFamily: \"'Arial', sans-serif\",\r\n fontSizeBase: '14px',\r\n fontSizeLarge: '16px',\r\n fontSizeSmall: '12px'\r\n },\r\n spacing: { sm: '12px', md: '16px', lg: '20px', xl: '24px' },\r\n borderRadius: { card: '8px', button: '6px', input: '4px' },\r\n shadows: { card: '0 2px 8px rgba(0,0,0,0.1)', button: '0 1px 3px rgba(0,0,0,0.12)' }\r\n};\r\n\r\n// 基础卡片样式\r\nexport const StyledCard = css`\r\n background: ${tokens.colors.background.card};\r\n border-radius: ${tokens.borderRadius.card};\r\n box-shadow: ${tokens.shadows.card};\r\n font-family: ${tokens.typography.fontFamily};\r\n font-size: ${tokens.typography.fontSizeBase};\r\n overflow: hidden;\r\n\r\n &[data-theme=\"dark\"] {\r\n background: #1a1a1a;\r\n color: #ffffff;\r\n }\r\n`;\r\n\r\n// Banner 样式\r\nexport const bannerStyles = {\r\n base: css`\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: ${tokens.spacing.sm} ${tokens.spacing.md};\r\n font-weight: 600;\r\n text-transform: uppercase;\r\n letter-spacing: 0.5px;\r\n `,\r\n sizes: {\r\n small: css`\r\n font-size: ${tokens.typography.fontSizeSmall};\r\n padding: 8px ${tokens.spacing.sm};\r\n `,\r\n medium: css`\r\n font-size: ${tokens.typography.fontSizeBase};\r\n padding: ${tokens.spacing.sm} ${tokens.spacing.md};\r\n `,\r\n large: css`\r\n font-size: ${tokens.typography.fontSizeLarge};\r\n padding: ${tokens.spacing.md} ${tokens.spacing.lg};\r\n `\r\n },\r\n positions: {\r\n header: css`\r\n border-bottom: 1px solid ${tokens.colors.border.default};\r\n `,\r\n sidebar: css`\r\n border-right: 1px solid ${tokens.colors.border.default};\r\n writing-mode: vertical-rl;\r\n text-orientation: mixed;\r\n `\r\n },\r\n scenes: {\r\n question: css`\r\n background: ${tokens.colors.scene.question};\r\n color: ${tokens.colors.text.light};\r\n `,\r\n solve: css`\r\n background: ${tokens.colors.scene.solve};\r\n color: ${tokens.colors.text.light};\r\n `,\r\n review: css`\r\n background: ${tokens.colors.scene.review};\r\n color: ${tokens.colors.text.light};\r\n `\r\n }\r\n};\r\n\r\n// 问题内容样式\r\nexport const questionStyles = css`\r\n padding: ${tokens.spacing.lg};\r\n line-height: 1.6;\r\n\r\n .content-block {\r\n margin-bottom: ${tokens.spacing.sm};\r\n\r\n &:last-child {\r\n margin-bottom: 0;\r\n }\r\n }\r\n\r\n .formula {\r\n display: inline-block;\r\n margin: 0 2px;\r\n vertical-align: middle;\r\n }\r\n\r\n .image {\r\n max-width: 100%;\r\n height: auto;\r\n border-radius: ${tokens.borderRadius.input};\r\n }\r\n`;\r\n\r\n// 答案输入样式\r\nexport const answerInputStyles = {\r\n container: css`\r\n padding: ${tokens.spacing.lg};\r\n border-top: 1px solid ${tokens.colors.border.default};\r\n `,\r\n input: css`\r\n width: 100%;\r\n padding: ${tokens.spacing.sm} ${tokens.spacing.md};\r\n border: 1px solid ${tokens.colors.border.default};\r\n border-radius: ${tokens.borderRadius.input};\r\n font-size: ${tokens.typography.fontSizeBase};\r\n\r\n &:focus {\r\n outline: none;\r\n border-color: ${tokens.colors.scene.question};\r\n }\r\n `,\r\n options: css`\r\n display: grid;\r\n gap: ${tokens.spacing.sm};\r\n `,\r\n option: css`\r\n padding: ${tokens.spacing.sm} ${tokens.spacing.md};\r\n border: 1px solid ${tokens.colors.border.default};\r\n border-radius: ${tokens.borderRadius.input};\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n\r\n &:hover {\r\n border-color: ${tokens.colors.scene.question};\r\n }\r\n\r\n &[data-selected=\"true\"] {\r\n background: ${tokens.colors.scene.question};\r\n color: ${tokens.colors.text.light};\r\n border-color: ${tokens.colors.scene.question};\r\n }\r\n `\r\n};\r\n\r\n// 反馈样式\r\nexport const feedbackStyles = {\r\n container: css`\r\n padding: ${tokens.spacing.lg};\r\n border-radius: ${tokens.borderRadius.card};\r\n margin: ${tokens.spacing.md} 0;\r\n `,\r\n correct: css`\r\n background: ${tokens.colors.background.feedbackCorrect};\r\n border: 1px solid #22c55e;\r\n `,\r\n incorrect: css`\r\n background: ${tokens.colors.background.feedbackIncorrect};\r\n border: 1px solid #ef4444;\r\n `\r\n};\r\n\r\n// 加载状态样式\r\nexport const loadingStyles = {\r\n skeleton: css`\r\n padding: ${tokens.spacing.lg};\r\n\r\n .skeleton-line {\r\n height: 16px;\r\n background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);\r\n background-size: 200% 100%;\r\n animation: loading 1.5s infinite;\r\n border-radius: 4px;\r\n margin-bottom: ${tokens.spacing.sm};\r\n\r\n &:last-child {\r\n margin-bottom: 0;\r\n }\r\n }\r\n\r\n @keyframes loading {\r\n 0% { background-position: 200% 0; }\r\n 100% { background-position: -200% 0; }\r\n }\r\n `,\r\n spinner: css`\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n padding: ${tokens.spacing.xl};\r\n\r\n .spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid #f0f0f0;\r\n border-top: 4px solid ${tokens.colors.scene.question};\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n }\r\n\r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n `\r\n};\r\n\r\n// 错误状态样式\r\nexport const errorStyles = css`\r\n padding: ${tokens.spacing.xl};\r\n text-align: center;\r\n color: #ef4444;\r\n\r\n .error-message {\r\n margin-bottom: ${tokens.spacing.md};\r\n font-size: ${tokens.typography.fontSizeLarge};\r\n }\r\n\r\n .retry-button {\r\n padding: ${tokens.spacing.sm} ${tokens.spacing.md};\r\n background: #ef4444;\r\n color: white;\r\n border: none;\r\n border-radius: ${tokens.borderRadius.button};\r\n cursor: pointer;\r\n font-size: ${tokens.typography.fontSizeBase};\r\n\r\n &:hover {\r\n background: #dc2626;\r\n }\r\n }\r\n`;\r\n\r\n// 分割线样式\r\nexport const dividerStyles = {\r\n horizontal: css`\r\n height: 1px;\r\n background: ${tokens.colors.border.default};\r\n margin: ${tokens.spacing.md} 0;\r\n\r\n &[data-size=\"small\"] {\r\n margin: ${tokens.spacing.sm} 0;\r\n }\r\n\r\n &[data-size=\"large\"] {\r\n margin: ${tokens.spacing.lg} 0;\r\n }\r\n `,\r\n vertical: css`\r\n width: 1px;\r\n background: ${tokens.colors.border.default};\r\n margin: 0 ${tokens.spacing.md};\r\n\r\n &[data-size=\"small\"] {\r\n margin: 0 ${tokens.spacing.sm};\r\n }\r\n\r\n &[data-size=\"large\"] {\r\n margin: 0 ${tokens.spacing.lg};\r\n }\r\n `\r\n};","import { create } from 'zustand';\r\nimport { devtools } from 'zustand/middleware';\r\nimport type { MathProblemData, MathCardScene, SubmissionResult } from '../components/MathCard/MathCard.types';\r\nimport type { Shape, Point } from '../components/MathGraph/types';\r\n\r\n// ===== 常量定义 =====\r\n\r\n// API 配置\r\nconst API_BASE_URL = '/api/v1/content';\r\nconst MOCK_JWT_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c2VyLTAwMSIsIm5hbWUiOiLlsI_mmI4iLCJsZXZlbCI6NSwiYXZhdGFyIjoiaHR0cHM6Ly9pLnByYXZhdGFyLmNjLzQwP3U9c3R1ZGVudDEiLCJiYWRnZXMiOlsi8J-SoiIsIvCfjZUiLCLwn5KbIl0sImlhdCI6MTY5MTYwMDAwMCwiZXhwIjoxNzIzMTM2MDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';\r\n\r\n// 默认配置\r\nconst DEFAULT_QUESTION_COUNT = 10;\r\nconst INITIAL_SCENE: MathCardScene = 'question';\r\n\r\n// ===== 类型定义 =====\r\n\r\nexport interface MathSessionState {\r\n // 会话标识\r\n sessionId: string | null;\r\n\r\n // 题目数据\r\n problems: MathProblemData[];\r\n totalProblems: number;\r\n\r\n // 当前状态\r\n currentProblemIndex: number;\r\n currentScene: MathCardScene;\r\n\r\n // 用户交互数据\r\n userAnswers: Record<string, string[]>;\r\n submissionResults: Record<string, SubmissionResult>;\r\n\r\n // 几何图形数据\r\n geometryShapes: Record<string, Shape[]>;\r\n selectedShapeId: string | null;\r\n geometryMode: 'view' | 'edit';\r\n\r\n // 异步状态\r\n loading: boolean;\r\n error: string | null;\r\n\r\n // 会话统计\r\n timeSpent: number;\r\n startTime: number | null;\r\n sessionComplete: boolean;\r\n}\r\n\r\nexport interface MathSessionActions {\r\n // === API 相关 ===\r\n loadQuestions: (sessionId: string, options: {\r\n gradeLevel: number;\r\n unitId: string;\r\n lessonId: string;\r\n count?: number;\r\n }) => Promise<void>;\r\n\r\n // === 导航控制 ===\r\n goToNextProblem: () => void;\r\n goToPreviousProblem: () => void;\r\n goToProblem: (index: number) => void;\r\n\r\n // === 场景切换 ===\r\n switchScene: (scene: MathCardScene) => void;\r\n\r\n // === 答案处理 ===\r\n submitAnswer: (problemId: string, answer: string[]) => Promise<void>;\r\n updateUserAnswer: (problemId: string, answer: string[]) => void;\r\n\r\n // === 几何图形操作 ===\r\n updateShape: (problemId: string, shapeId: string, newPosition: Point) => void;\r\n selectShape: (problemId: string, shapeId: string | null) => void;\r\n setGeometryMode: (problemId: string, mode: 'view' | 'edit') => void;\r\n\r\n // === 计时器 ===\r\n startTimer: () => void;\r\n stopTimer: () => void;\r\n\r\n // === 会话控制 ===\r\n reset: () => void;\r\n\r\n // === 选择器 ===\r\n getCurrentProblem: () => MathProblemData | null;\r\n getProgress: () => { current: number; total: number; percentage: number };\r\n getSessionResults: () => SessionResults;\r\n}\r\n\r\nexport interface SessionResults {\r\n sessionId: string;\r\n totalProblems: number;\r\n correctAnswers: number;\r\n accuracy: number;\r\n timeSpent: number;\r\n averageTime: number;\r\n answers: Array<{\r\n problemId: string;\r\n userAnswer: string[];\r\n isCorrect: boolean;\r\n timeSpent: number;\r\n }>;\r\n}\r\n\r\nexport type MathSessionStore = MathSessionState & MathSessionActions;\r\n\r\n// ===== Store 实现 =====\r\n\r\nexport const useSessionStore = create<MathSessionStore>()(\r\n devtools(\r\n (set, get) => ({\r\n // ===== 初始状态 =====\r\n sessionId: null,\r\n problems: [],\r\n totalProblems: 0,\r\n currentProblemIndex: 0,\r\n currentScene: 'question',\r\n userAnswers: {},\r\n submissionResults: {},\r\n geometryShapes: {},\r\n selectedShapeId: null,\r\n geometryMode: 'view',\r\n loading: false,\r\n error: null,\r\n timeSpent: 0,\r\n startTime: null,\r\n sessionComplete: false,\r\n\r\n // ===== API Actions =====\r\n loadQuestions: async (sessionId, options) => {\r\n set({ loading: true, sessionId });\r\n\r\n try {\r\n const { gradeLevel, unitId, lessonId, count = DEFAULT_QUESTION_COUNT } = options;\r\n\r\n // 构建 API 端点\r\n const url = `${API_BASE_URL}/grades/${gradeLevel}/units/${unitId}/lessons/${lessonId}/sessions/${sessionId}/questions`;\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${MOCK_JWT_TOKEN}`\r\n },\r\n body: JSON.stringify({ count })\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to load questions: ${response.status} ${response.statusText}`);\r\n }\r\n\r\n const data = await response.json();\r\n const questions = data.questions || [];\r\n\r\n // 从问题数据中提取几何图形\r\n const geometryShapes: Record<string, Shape[]> = {};\r\n questions.forEach((question: any) => {\r\n if (question.geometryShapes && Array.isArray(question.geometryShapes)) {\r\n geometryShapes[question.problemId] = question.geometryShapes;\r\n }\r\n });\r\n\r\n set({\r\n problems: questions,\r\n totalProblems: questions.length,\r\n currentProblemIndex: 0,\r\n currentScene: INITIAL_SCENE,\r\n geometryShapes,\r\n loading: false,\r\n error: null,\r\n startTime: Date.now()\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\r\n set({\r\n error: errorMessage,\r\n loading: false\r\n });\r\n // 重新抛出错误,让页面组件能够捕获\r\n throw error;\r\n }\r\n },\r\n\r\n // ===== 导航 Actions =====\r\n goToNextProblem: () => {\r\n const { currentProblemIndex, problems, currentScene } = get();\r\n\r\n // 业务规则:只在 question 场景允许导航\r\n if (currentScene !== INITIAL_SCENE) {\r\n console.warn('Cannot navigate during review/solve scene');\r\n return;\r\n }\r\n\r\n if (currentProblemIndex < problems.length - 1) {\r\n set({\r\n currentProblemIndex: currentProblemIndex + 1,\r\n currentScene: INITIAL_SCENE\r\n });\r\n } else {\r\n // 最后一题,标记会话完成\r\n set({ sessionComplete: true });\r\n }\r\n },\r\n\r\n goToPreviousProblem: () => {\r\n const { currentProblemIndex, currentScene } = get();\r\n\r\n if (currentScene !== INITIAL_SCENE) return;\r\n\r\n if (currentProblemIndex > 0) {\r\n set({\r\n currentProblemIndex: currentProblemIndex - 1,\r\n currentScene: INITIAL_SCENE\r\n });\r\n }\r\n },\r\n\r\n goToProblem: (index) => {\r\n const { problems, currentScene } = get();\r\n\r\n if (currentScene !== INITIAL_SCENE) return;\r\n if (index < 0 || index >= problems.length) return;\r\n\r\n set({\r\n currentProblemIndex: index,\r\n currentScene: INITIAL_SCENE\r\n });\r\n },\r\n\r\n // ===== 场景切换 =====\r\n switchScene: (scene) => {\r\n set({ currentScene: scene });\r\n },\r\n\r\n // ===== 答案处理 =====\r\n submitAnswer: async (problemId, answer) => {\r\n const { problems, currentProblemIndex } = get();\r\n const currentProblem = problems[currentProblemIndex];\r\n\r\n set({ loading: true });\r\n\r\n try {\r\n // 本地验证答案\r\n const correctAnswer = currentProblem?.answer.correctAnswer || [];\r\n const isCorrect = answer.length > 0 && answer[0] === correctAnswer[0];\r\n\r\n const result: SubmissionResult = {\r\n userAnswer: answer,\r\n isCorrect,\r\n feedback: isCorrect\r\n ? '🎉 Great job! Your answer is correct!'\r\n : '❌ Sorry, that\\'s not correct.'\r\n };\r\n\r\n set(state => ({\r\n userAnswers: { ...state.userAnswers, [problemId]: answer },\r\n submissionResults: { ...state.submissionResults, [problemId]: result },\r\n loading: false,\r\n currentScene: isCorrect ? 'review' : 'solve'\r\n }));\r\n } catch (error) {\r\n set({\r\n error: error instanceof Error ? error.message : 'Submission error',\r\n loading: false\r\n });\r\n }\r\n },\r\n\r\n updateUserAnswer: (problemId, answer) => {\r\n set(state => ({\r\n userAnswers: { ...state.userAnswers, [problemId]: answer }\r\n }));\r\n },\r\n\r\n // ===== 几何图形操作 =====\r\n updateShape: (problemId, shapeId, newPosition) => {\r\n set(state => {\r\n const currentShapes = state.geometryShapes[problemId] || [];\r\n const updatedShapes = currentShapes.map(shape => {\r\n if (shape.id === shapeId && shape.type === 'point') {\r\n return {\r\n ...shape,\r\n position: newPosition\r\n };\r\n }\r\n return shape;\r\n });\r\n\r\n return {\r\n geometryShapes: {\r\n ...state.geometryShapes,\r\n [problemId]: updatedShapes\r\n }\r\n };\r\n });\r\n },\r\n\r\n selectShape: (_problemId, shapeId) => {\r\n set({\r\n selectedShapeId: shapeId\r\n });\r\n },\r\n\r\n setGeometryMode: (_problemId, mode) => {\r\n set({\r\n geometryMode: mode\r\n });\r\n },\r\n\r\n // ===== 计时器 =====\r\n startTimer: () => {\r\n set({ startTime: Date.now() });\r\n },\r\n\r\n stopTimer: () => {\r\n const { startTime } = get();\r\n if (startTime) {\r\n const elapsed = Math.floor((Date.now() - startTime) / 1000);\r\n set(state => ({\r\n timeSpent: state.timeSpent + elapsed,\r\n startTime: null\r\n }));\r\n }\r\n },\r\n\r\n // ===== 重置 =====\r\n reset: () => {\r\n set({\r\n sessionId: null,\r\n problems: [],\r\n totalProblems: 0,\r\n currentProblemIndex: 0,\r\n currentScene: INITIAL_SCENE,\r\n userAnswers: {},\r\n submissionResults: {},\r\n geometryShapes: {},\r\n selectedShapeId: null,\r\n geometryMode: 'view',\r\n loading: false,\r\n error: null,\r\n timeSpent: 0,\r\n startTime: null,\r\n sessionComplete: false\r\n });\r\n },\r\n\r\n // ===== 选择器 =====\r\n getCurrentProblem: () => {\r\n const { problems, currentProblemIndex } = get();\r\n return problems[currentProblemIndex] || null;\r\n },\r\n\r\n getProgress: () => {\r\n const { currentProblemIndex, totalProblems } = get();\r\n return {\r\n current: currentProblemIndex + 1,\r\n total: totalProblems,\r\n percentage: totalProblems > 0\r\n ? ((currentProblemIndex + 1) / totalProblems) * 100\r\n : 0\r\n };\r\n },\r\n\r\n getSessionResults: () => {\r\n const { sessionId, problems, submissionResults, timeSpent } = get();\r\n const answers = problems.map(p => ({\r\n problemId: p.problemId,\r\n userAnswer: submissionResults[p.problemId]?.userAnswer || [],\r\n isCorrect: submissionResults[p.problemId]?.isCorrect || false,\r\n timeSpent: 0 // TODO: 记录每题用时\r\n }));\r\n\r\n const correctAnswers = answers.filter(a => a.isCorrect).length;\r\n\r\n return {\r\n sessionId: sessionId || '',\r\n totalProblems: problems.length,\r\n correctAnswers,\r\n accuracy: problems.length > 0 ? correctAnswers / problems.length : 0,\r\n timeSpent,\r\n averageTime: problems.length > 0 ? timeSpent / problems.length : 0,\r\n answers\r\n };\r\n }\r\n }),\r\n { name: 'MathSessionStore' }\r\n )\r\n);","import { useMemo } from 'react';\r\nimport type { MathProblemData, MathCardScene } from '../../MathCard/MathCard.types';\r\nimport type { MathSessionConfig } from '../MathSessionContainer.types';\r\n\r\n/**\r\n * 会话业务规则计算 Hook\r\n * 职责:计算应该显示/禁用什么,纯计算逻辑(无副作用)\r\n * \r\n * 包含:\r\n * - 导航控制逻辑(上一题/下一题禁用状态)\r\n * - MathGraph 渲染判断(根据题型/数据/配置)\r\n */\r\nexport const useSessionCalculations = (\r\n currentIndex: number,\r\n problems: MathProblemData[],\r\n currentScene: MathCardScene,\r\n currentProblem: MathProblemData | null,\r\n currentProblemId: string,\r\n geometryShapes: Record<string, any[]>,\r\n config?: MathSessionConfig\r\n) => {\r\n // ===== 导航控制 =====\r\n const canNavigate = useMemo(\r\n () => currentScene === 'question',\r\n [currentScene]\r\n );\r\n\r\n const canGoNext = useMemo(\r\n () => currentIndex < problems.length - 1,\r\n [currentIndex, problems.length]\r\n );\r\n\r\n const canGoPrevious = useMemo(\r\n () => currentIndex > 0,\r\n [currentIndex]\r\n );\r\n\r\n // ===== MathGraph 渲染判断 =====\r\n const shouldRenderMathGraph = useMemo(() => {\r\n if (!currentProblem || !currentProblemId) return false;\r\n\r\n // 方式1:根据题型判断(如 problemType 包含 'geometry')\r\n if (currentProblem.problemType?.includes('geometry')) return true;\r\n\r\n // 方式2:检查是否有几何图形数据\r\n const hasGeometryShapes = geometryShapes &&\r\n geometryShapes[currentProblemId] &&\r\n geometryShapes[currentProblemId].length > 0;\r\n if (hasGeometryShapes) return true;\r\n\r\n // 方式3:根据 config 参数(可选,由外部控制)\r\n if (config?.enableMathGraph !== undefined) return config.enableMathGraph;\r\n\r\n return false;\r\n }, [currentProblem, currentProblemId, geometryShapes, config?.enableMathGraph]);\r\n\r\n return {\r\n canNavigate,\r\n canGoNext,\r\n canGoPrevious,\r\n shouldRenderMathGraph\r\n };\r\n};\r\n","import { useEffect, useCallback, useMemo } from 'react';\r\nimport { useSessionStore } from '../../../stores/mathSessionStore';\r\nimport type { MathCardScene } from '../../MathCard/MathCard.types';\r\n\r\n/**\r\n * 几何图形管理 Hook\r\n * 职责:管理 MathGraph 的状态、模式切换、回调处理\r\n * \r\n * 包含:\r\n * - 获取当前题目的几何图形数据\r\n * - 场景驱动的几何模式管理(question→edit, solve/review→view)\r\n * - 处理形状变化和选择事件\r\n */\r\nexport const useGeometryManagement = (\r\n currentScene: MathCardScene,\r\n currentProblemId: string,\r\n shouldRenderMathGraph: boolean,\r\n geometryShapes: Record<string, any[]>,\r\n geometryMode: 'view' | 'edit'\r\n) => {\r\n const selectShape = useSessionStore(s => s.selectShape);\r\n const setGeometryMode = useSessionStore(s => s.setGeometryMode);\r\n\r\n // ===== 获取当前题目的几何图形数据 =====\r\n const currentGeometryShapes = useMemo(() => {\r\n if (!currentProblemId || !geometryShapes) return [];\r\n return geometryShapes[currentProblemId] || [];\r\n }, [geometryShapes, currentProblemId]);\r\n\r\n // ===== 场景驱动的几何模式管理 =====\r\n useEffect(() => {\r\n if (!currentProblemId || !shouldRenderMathGraph) return;\r\n\r\n // 根据场景自动设置几何模式\r\n let newMode: 'view' | 'edit' = 'view';\r\n\r\n switch (currentScene) {\r\n case 'question':\r\n newMode = 'edit'; // 答题阶段可编辑\r\n break;\r\n case 'solve':\r\n case 'review':\r\n newMode = 'view'; // 解题/复习阶段只读\r\n break;\r\n default:\r\n newMode = 'view';\r\n }\r\n\r\n if (geometryMode !== newMode) {\r\n setGeometryMode(currentProblemId, newMode);\r\n }\r\n }, [currentScene, currentProblemId, geometryMode, setGeometryMode, shouldRenderMathGraph]);\r\n\r\n // ===== 处理几何图形变化 =====\r\n const handleShapeChange = useCallback((updatedShapes: any[]) => {\r\n if (currentProblemId) {\r\n // MathGraph 返回整个更新后的 shapes 数组\r\n // 直接更新到 store 的 geometryShapes 中\r\n useSessionStore.setState(state => ({\r\n geometryShapes: {\r\n ...state.geometryShapes,\r\n [currentProblemId]: updatedShapes\r\n }\r\n }));\r\n }\r\n }, [currentProblemId]);\r\n\r\n // ===== 处理几何图形选择 =====\r\n const handleSelectionChange = useCallback((selectedIds: string[]) => {\r\n if (currentProblemId) {\r\n // MathGraph 返回选中的 shape IDs 数组\r\n // 我们只取第一个作为当前选中的 shape(简化处理)\r\n const selectedId = selectedIds.length > 0 ? selectedIds[0] : null;\r\n selectShape(currentProblemId, selectedId);\r\n }\r\n }, [currentProblemId, selectShape]);\r\n\r\n return {\r\n currentGeometryShapes,\r\n geometryMode,\r\n handleShapeChange,\r\n handleSelectionChange\r\n };\r\n};\r\n","import { useCallback } from 'react';\r\nimport { useSessionStore } from '../../../stores/mathSessionStore';\r\n\r\n/**\r\n * 会话事件处理 Hook\r\n * 职责:处理所有用户交互事件的回调函数\r\n * \r\n * 包含:\r\n * - 答案变更事件\r\n * - 答案提交事件\r\n * - 题目导航事件(上一题、下一题、分页)\r\n */\r\nexport const useSessionEventHandlers = (\r\n currentProblemId: string,\r\n currentIndex: number,\r\n userAnswers: Record<string, string[]>\r\n) => {\r\n const updateUserAnswer = useSessionStore(s => s.updateUserAnswer);\r\n const submitAnswer = useSessionStore(s => s.submitAnswer);\r\n const goToNextProblem = useSessionStore(s => s.goToNextProblem);\r\n const goToPreviousProblem = useSessionStore(s => s.goToPreviousProblem);\r\n const goToProblem = useSessionStore(s => s.goToProblem);\r\n\r\n // ===== 答案变更 =====\r\n const handleAnswerChange = useCallback(\r\n (answer: string[]) => {\r\n if (currentProblemId) {\r\n updateUserAnswer(currentProblemId, answer);\r\n }\r\n },\r\n [currentProblemId, updateUserAnswer]\r\n );\r\n\r\n // ===== 答案提交 =====\r\n const handleSubmit = useCallback(() => {\r\n if (currentProblemId && userAnswers[currentProblemId]) {\r\n submitAnswer(currentProblemId, userAnswers[currentProblemId]);\r\n }\r\n }, [currentProblemId, userAnswers, submitAnswer]);\r\n\r\n // ===== 下一题 =====\r\n const handleNext = useCallback(\r\n (onProblemChange?: (problemId: string, index: number) => void) => {\r\n goToNextProblem();\r\n onProblemChange?.(currentProblemId, currentIndex + 1);\r\n },\r\n [goToNextProblem, currentProblemId, currentIndex]\r\n );\r\n\r\n // ===== 上一题 =====\r\n const handlePrevious = useCallback(\r\n (onProblemChange?: (problemId: string, index: number) => void) => {\r\n goToPreviousProblem();\r\n onProblemChange?.(currentProblemId, currentIndex - 1);\r\n },\r\n [goToPreviousProblem, currentProblemId, currentIndex]\r\n );\r\n\r\n // ===== 分页跳转 =====\r\n const handlePagination = useCallback(\r\n (page: number, onProblemChange?: (problemId: string, index: number) => void) => {\r\n goToProblem(page - 1);\r\n onProblemChange?.(currentProblemId, page - 1);\r\n },\r\n [goToProblem, currentProblemId]\r\n );\r\n\r\n return {\r\n handleAnswerChange,\r\n handleSubmit,\r\n handleNext,\r\n handlePrevious,\r\n handlePagination\r\n };\r\n};\r\n","import React, { useEffect, useMemo } from 'react';\r\nimport { MathCard } from '../MathCard';\r\nimport { MathGraph } from '../MathGraph';\r\nimport { Pagination } from '@heroui/react';\r\nimport { useSessionStore } from '../../stores/mathSessionStore';\r\nimport { useSessionCalculations } from './hooks/useSessionCalculations';\r\nimport { useGeometryManagement } from './hooks/useGeometryManagement';\r\nimport { useSessionEventHandlers } from './hooks/useSessionEventHandlers';\r\nimport type { MathSessionContainerProps } from './MathSessionContainer.types';\r\n\r\n/**\r\n * MathSessionContainer - 会话容器组件\r\n *\r\n * 职责:\r\n * - 协调所有子组件的交互\r\n * - 负责整体渲染和布局\r\n * - 使用自定义 hooks 管理复杂逻辑\r\n *\r\n * 职责分离:\r\n * - useSessionCalculations: 业务规则计算\r\n * - useGeometryManagement: 几何图形管理\r\n * - useSessionEventHandlers: 事件处理\r\n */\r\nconst MathSessionContainer: React.FC<MathSessionContainerProps> = ({\r\n config = {},\r\n onSessionComplete,\r\n onSessionExit,\r\n onProblemChange,\r\n className = '',\r\n style\r\n}) => {\r\n // ===== 从 Store 读取会话状态 =====\r\n const problems = useSessionStore(s => s.problems);\r\n const currentIndex = useSessionStore(s => s.currentProblemIndex);\r\n const currentScene = useSessionStore(s => s.currentScene);\r\n const loading = useSessionStore(s => s.loading);\r\n const error = useSessionStore(s => s.error);\r\n const sessionComplete = useSessionStore(s => s.sessionComplete);\r\n const submissionResults = useSessionStore(s => s.submissionResults);\r\n const userAnswers = useSessionStore(s => s.userAnswers);\r\n const geometryShapes = useSessionStore(s => s.geometryShapes);\r\n const geometryMode = useSessionStore(s => s.geometryMode);\r\n const getSessionResults = useSessionStore(s => s.getSessionResults);\r\n\r\n // ===== 计算当前题目 =====\r\n const currentProblem = useMemo(() => problems[currentIndex] ?? null, [problems, currentIndex]);\r\n const currentProblemId = useMemo(() => currentProblem?.problemId ?? '', [currentProblem]);\r\n\r\n // ===== 使用自定义 hooks =====\r\n const { canNavigate, canGoNext, canGoPrevious, shouldRenderMathGraph } =\r\n useSessionCalculations(currentIndex, problems, currentScene, currentProblem, currentProblemId, geometryShapes, config);\r\n\r\n const { currentGeometryShapes, handleShapeChange, handleSelectionChange } =\r\n useGeometryManagement(currentScene, currentProblemId, shouldRenderMathGraph, geometryShapes, geometryMode);\r\n\r\n const { handleAnswerChange, handleSubmit, handleNext, handlePrevious, handlePagination } =\r\n useSessionEventHandlers(currentProblemId, currentIndex, userAnswers);\r\n\r\n // ===== 会话完成监听 =====\r\n useEffect(() => {\r\n if (sessionComplete && typeof getSessionResults === 'function') {\r\n const results = getSessionResults();\r\n onSessionComplete?.(results);\r\n }\r\n }, [sessionComplete, getSessionResults, onSessionComplete]);\r\n\r\n // ===== 工具函数 =====\r\n const formatErrorMessage = (error: unknown): string => {\r\n if (typeof error === 'string') return error;\r\n if (error instanceof Error) return error.message;\r\n return String(error);\r\n };\r\n\r\n // ===== Loading 状态 =====\r\n if (loading && problems.length === 0) {\r\n return (\r\n <div className=\"flex items-center justify-center p-12\" data-testid=\"math-session-loading\">\r\n <div className=\"text-center\">\r\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4\" />\r\n <p className=\"text-gray-600\">Loading questions...</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // ===== Error 状态 =====\r\n if (error && error !== null) {\r\n return (\r\n <div className=\"flex items-center justify-center p-12\" data-testid=\"math-session-error\">\r\n <div className=\"text-center text-red-600\">\r\n <p className=\"text-lg font-semibold mb-2\">Error</p>\r\n <p>{formatErrorMessage(error)}</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // ===== 无数据 =====\r\n if (!currentProblem) {\r\n return (\r\n <div className=\"flex items-center justify-center p-12\" data-testid=\"math-session-empty\">\r\n <p className=\"text-gray-600\">No problems available</p>\r\n </div>\r\n );\r\n }\r\n\r\n // ===== 主渲染 =====\r\n return (\r\n <div\r\n className={`flex flex-col max-w-4xl mx-auto p-6 ${className}`}\r\n style={style}\r\n data-testid=\"math-session-container\"\r\n role=\"region\"\r\n aria-label=\"数学练习会话\"\r\n >\r\n {/* Pagination - 进度指示器 */}\r\n <div className=\"mb-6\">\r\n <Pagination\r\n total={problems.length}\r\n page={currentIndex + 1}\r\n onChange={(page) => handlePagination(page, onProblemChange)}\r\n isDisabled={!canNavigate}\r\n showControls={false}\r\n color=\"primary\"\r\n size=\"lg\"\r\n className=\"justify-center\"\r\n />\r\n </div>\r\n\r\n {/* MathCard - 题目展示 */}\r\n <MathCard\r\n problemData={currentProblem}\r\n scene={currentScene}\r\n submissionResult={submissionResults[currentProblemId]}\r\n loading={loading}\r\n error={error ? formatErrorMessage(error) : undefined}\r\n value={userAnswers[currentProblemId]}\r\n onAnswerChange={handleAnswerChange}\r\n onSubmit={handleSubmit}\r\n onNext={() => handleNext(onProblemChange)}\r\n config={{\r\n theme: config.theme ?? 'light',\r\n submitButtonText: '提交答案',\r\n nextButtonText: currentScene === 'solve' ? 'Got it!' : '下一题',\r\n showHints: config.enableHints\r\n }}\r\n />\r\n\r\n {/* MathGraph - 几何图形(条件渲染,与 MathCard 平级) */}\r\n {shouldRenderMathGraph && (\r\n <div className=\"mt-4 w-full max-w-4xl mx-auto\" data-testid=\"mathgraph-container\">\r\n <MathGraph\r\n shapes={currentGeometryShapes}\r\n mode={geometryMode}\r\n onShapeChange={handleShapeChange}\r\n onSelectionChange={handleSelectionChange}\r\n // 使用自动边界框计算,不再需要手动设置 boundingBox\r\n showGrid={true}\r\n showAxis={true}\r\n width={800}\r\n height={500}\r\n boundingBoxOptions={{\r\n padding: 0.5, // 50% 边距(进一步增加确保图形完全在边界内)\r\n margin: 2.0, // 固定边距(增加固定边距)\r\n minSize: 8 // 最小尺寸(增加最小尺寸)\r\n }}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* 底部导航按钮 */}\r\n {config.showProgress && (\r\n <div className=\"mt-6 flex justify-between items-center\">\r\n <button\r\n onClick={() => handlePrevious(onProblemChange)}\r\n disabled={!canGoPrevious}\r\n className=\"px-4 py-2 text-sm border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n 上一题\r\n </button>\r\n\r\n <div className=\"text-sm text-gray-600\">\r\n {currentIndex + 1} / {problems.length}\r\n </div>\r\n\r\n <button\r\n onClick={() => handleNext(onProblemChange)}\r\n disabled={!canGoNext || !canNavigate}\r\n className=\"px-4 py-2 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n 下一题\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* 退出按钮 */}\r\n {onSessionExit && (\r\n <div className=\"mt-4 flex justify-center\">\r\n <button\r\n onClick={onSessionExit}\r\n className=\"px-4 py-2 text-sm text-gray-600 hover:text-gray-900 transition-colors\"\r\n >\r\n 退出练习\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport default MathSessionContainer;","import React, { useEffect, useState, useCallback, useRef } from 'react';\r\nimport { MathSessionContainer } from '../../components/MathSessionContainer';\r\nimport { useSessionStore } from '../../stores/mathSessionStore';\r\nimport type { MathSessionPageProps, MathSessionPageState } from './types';\r\nimport './MathSessionPage.css';\r\n\r\n/**\r\n * MathSessionPage - 数学练习会话页面组件\r\n *\r\n * 职责:\r\n * - 页面级布局和初始化\r\n * - 调用 Store.loadQuestions() 触发 API 请求\r\n * - 处理页面级状态管理\r\n * - 提供完整的用户会话体验\r\n *\r\n * 架构定位:\r\n * - 页面组件(Page Component)\r\n * - 负责数据初始化和页面布局\r\n * - 不包含业务逻辑,只协调子组件\r\n */\r\nconst MathSessionPage: React.FC<MathSessionPageProps> = ({\r\n sessionId,\r\n gradeId,\r\n unitId,\r\n lessonId,\r\n userId,\r\n config = {},\r\n className = '',\r\n onSessionComplete,\r\n onSessionExit\r\n}) => {\r\n // ===== 页面级状态 =====\r\n const [pageState, setPageState] = useState<MathSessionPageState>({\r\n loading: false,\r\n error: null,\r\n initialized: false\r\n });\r\n const [retryCount, setRetryCount] = useState(0);\r\n\r\n // ===== 可访问性状态 =====\r\n const [announcement, setAnnouncement] = useState<string>('');\r\n const mainContentRef = useRef<HTMLElement>(null);\r\n const loadingRef = useRef<HTMLDivElement>(null);\r\n const errorRef = useRef<HTMLDivElement>(null);\r\n\r\n // ===== Store Actions =====\r\n const loadQuestions = useSessionStore(s => s.loadQuestions);\r\n const reset = useSessionStore(s => s.reset);\r\n\r\n // ===== 页面初始化 =====\r\n useEffect(() => {\r\n const initializeSession = async () => {\r\n try {\r\n setPageState(prev => ({ ...prev, loading: true, error: null }));\r\n\r\n console.log('🎯 MathSessionPage: 开始初始化会话', {\r\n sessionId,\r\n gradeId,\r\n unitId,\r\n lessonId,\r\n userId\r\n });\r\n\r\n // 调用 Store.loadQuestions() 触发 API 请求\r\n await loadQuestions(sessionId, {\r\n gradeLevel: parseInt(gradeId.replace('g', '')) || 5,\r\n unitId,\r\n lessonId,\r\n count: config.questionCount || 10\r\n });\r\n\r\n setPageState(prev => ({ ...prev, loading: false, initialized: true }));\r\n console.log('✅ MathSessionPage: 会话初始化完成');\r\n\r\n } catch (err) {\r\n const errorMessage = err instanceof Error ? err.message : 'Failed to initialize session';\r\n setPageState(prev => ({\r\n ...prev,\r\n loading: false,\r\n error: errorMessage,\r\n initialized: false\r\n }));\r\n console.error('❌ MathSessionPage: 会话初始化失败', err);\r\n }\r\n };\r\n\r\n // 只有在必要参数存在时才初始化\r\n if (sessionId && gradeId && unitId && lessonId && !pageState.initialized) {\r\n initializeSession();\r\n }\r\n }, [sessionId, gradeId, unitId, lessonId, loadQuestions, config.questionCount, pageState.initialized, retryCount]);\r\n\r\n // ===== 可访问性效果 =====\r\n useEffect(() => {\r\n // 页面状态变化时向屏幕阅读器发出公告\r\n if (pageState.loading && !pageState.initialized) {\r\n setAnnouncement('正在加载数学练习内容,请稍候...');\r\n } else if (pageState.error) {\r\n setAnnouncement(`加载失败:${pageState.error},请点击重试按钮重新加载`);\r\n } else if (pageState.initialized) {\r\n setAnnouncement('数学练习内容已加载完成,可以开始练习');\r\n }\r\n }, [pageState.loading, pageState.error, pageState.initialized]);\r\n\r\n useEffect(() => {\r\n // 自动聚焦到主要内容区域\r\n if (pageState.initialized && mainContentRef.current) {\r\n mainContentRef.current.focus();\r\n }\r\n }, [pageState.initialized]);\r\n\r\n useEffect(() => {\r\n // 自动聚焦到错误状态\r\n if (pageState.error && errorRef.current) {\r\n errorRef.current.focus();\r\n }\r\n }, [pageState.error]);\r\n\r\n useEffect(() => {\r\n // 自动聚焦到加载状态\r\n if (pageState.loading && loadingRef.current) {\r\n loadingRef.current.focus();\r\n }\r\n }, [pageState.loading]);\r\n\r\n // ===== 清理函数 =====\r\n useEffect(() => {\r\n return () => {\r\n console.log('🧹 MathSessionPage: 清理会话状态');\r\n reset();\r\n };\r\n }, [reset]);\r\n\r\n // ===== 事件处理 =====\r\n const handleSessionComplete = useCallback((results: any) => {\r\n console.log('🎉 MathSessionPage: 会话完成', results);\r\n onSessionComplete?.(results);\r\n }, [onSessionComplete]);\r\n\r\n const handleSessionExit = useCallback(() => {\r\n console.log('🚪 MathSessionPage: 退出会话');\r\n onSessionExit?.();\r\n }, [onSessionExit]);\r\n\r\n const handleProblemChange = useCallback((problemId: string, index: number) => {\r\n console.log(`📝 MathSessionPage: 切换到题目 ${index + 1}`, problemId);\r\n }, []);\r\n\r\n // ===== 键盘事件处理 =====\r\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\r\n // 支持 ESC 键退出会话\r\n if (event.key === 'Escape') {\r\n event.preventDefault();\r\n handleSessionExit();\r\n }\r\n // 支持 Enter 键重试\r\n if (event.key === 'Enter' && pageState.error && event.target === errorRef.current) {\r\n event.preventDefault();\r\n setPageState({ loading: false, error: null, initialized: false });\r\n setRetryCount(prev => prev + 1);\r\n }\r\n }, [handleSessionExit, pageState.error]);\r\n\r\n // ===== 渲染逻辑 =====\r\n\r\n // 页面级加载状态\r\n if (pageState.loading && !pageState.initialized) {\r\n return (\r\n <div\r\n className={`math-session-page loading ${className}`}\r\n data-testid=\"math-session-page\"\r\n role=\"main\"\r\n aria-label=\"数学练习页面\"\r\n onKeyDown={handleKeyDown}\r\n tabIndex={-1}\r\n ref={loadingRef}\r\n >\r\n {/* 屏幕阅读器公告区域 */}\r\n <div\r\n aria-live=\"assertive\"\r\n aria-atomic=\"true\"\r\n className=\"sr-only\"\r\n >\r\n {announcement}\r\n </div>\r\n\r\n <div className=\"page-loading-container\">\r\n <div\r\n className=\"loading-spinner\"\r\n data-testid=\"page-loading-spinner\"\r\n role=\"status\"\r\n aria-label=\"正在加载练习内容\"\r\n >\r\n <div\r\n className=\"spinner\"\r\n aria-hidden=\"true\"\r\n ></div>\r\n <p className=\"loading-text\">正在加载练习内容...</p>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // 页面级错误状态\r\n if (pageState.error) {\r\n return (\r\n <div\r\n className={`math-session-page error ${className}`}\r\n data-testid=\"math-session-page\"\r\n role=\"main\"\r\n aria-label=\"数学练习页面 - 错误状态\"\r\n onKeyDown={handleKeyDown}\r\n tabIndex={-1}\r\n ref={errorRef}\r\n >\r\n {/* 屏幕阅读器公告区域 */}\r\n <div\r\n aria-live=\"assertive\"\r\n aria-atomic=\"true\"\r\n className=\"sr-only\"\r\n >\r\n {announcement}\r\n </div>\r\n\r\n <div className=\"error-container\">\r\n <div\r\n className=\"error-icon\"\r\n role=\"img\"\r\n aria-label=\"警告图标\"\r\n >\r\n ⚠️\r\n </div>\r\n <h3 className=\"error-title\">加载失败</h3>\r\n <p className=\"error-message\">{pageState.error}</p>\r\n <button\r\n onClick={() => {\r\n setPageState({ loading: false, error: null, initialized: false });\r\n setRetryCount(prev => prev + 1);\r\n }}\r\n className=\"retry-button\"\r\n data-testid=\"retry-button\"\r\n aria-label=\"重新加载练习内容\"\r\n >\r\n 重试\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // 主页面渲染\r\n return (\r\n <div\r\n className={`math-session-page ${className}`}\r\n data-testid=\"math-session-page\"\r\n role=\"main\"\r\n aria-label=\"数学练习页面\"\r\n onKeyDown={handleKeyDown}\r\n >\r\n {/* 屏幕阅读器公告区域 */}\r\n <div\r\n aria-live=\"polite\"\r\n aria-atomic=\"true\"\r\n className=\"sr-only\"\r\n >\r\n {announcement}\r\n </div>\r\n\r\n {/* 页面头部(可选) */}\r\n {config.layout?.showHeader && (\r\n <header className=\"page-header\" role=\"banner\">\r\n <div className=\"header-content\">\r\n <h1 className=\"page-title\">数学练习</h1>\r\n <div className=\"session-info\" aria-label=\"会话信息\">\r\n <span className=\"session-id\">会话: {sessionId}</span>\r\n <span className=\"grade-info\">年级: {gradeId}</span>\r\n </div>\r\n </div>\r\n </header>\r\n )}\r\n\r\n {/* 主内容区域 */}\r\n <main\r\n className=\"page-main\"\r\n ref={mainContentRef}\r\n tabIndex={-1}\r\n aria-label=\"数学练习主要内容区域\"\r\n >\r\n <MathSessionContainer\r\n config={{\r\n showProgress: config.showProgress ?? true,\r\n enableHints: config.enableHints ?? false,\r\n autoAdvance: config.autoAdvance ?? false,\r\n theme: config.theme ?? 'light'\r\n }}\r\n onSessionComplete={handleSessionComplete}\r\n onSessionExit={handleSessionExit}\r\n onProblemChange={handleProblemChange}\r\n />\r\n </main>\r\n\r\n {/* 页面底部(可选) */}\r\n {config.layout?.showFooter && (\r\n <footer className=\"page-footer\" role=\"contentinfo\">\r\n <div className=\"footer-content\">\r\n <p className=\"footer-text\">\r\n © 2024 MathWiz - 小学数学益智教育平台\r\n </p>\r\n </div>\r\n </footer>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// 使用 React.memo 包装组件,避免不必要的重渲染\r\nexport default React.memo(MathSessionPage);","import React from 'react';\r\nimport { ReviewModule, SolveModule } from '../../modules';\r\nimport type { ExplanationSceneProps } from '../../MathPracticeSessionTypes';\r\nimport './DecimalNumberExplanationScene.css';\r\n\r\n/**\r\n * 小数认识解释场景组件\r\n * 错误答案的详细解释,仅包含两个学习模块(根据demo分析,不需要记忆模块)\r\n */\r\nexport const DecimalNumberExplanationScene: React.FC<ExplanationSceneProps> = ({\r\n problemData,\r\n userAnswer,\r\n onNextQuestion\r\n}) => {\r\n return (\r\n <div>\r\n {/* 顶部错误提示栏 */}\r\n <div className=\"decimal-error-banner\">\r\n <div>\r\n <h3 className=\"decimal-error-title\">抱歉,答案不正确...</h3>\r\n <p className=\"decimal-error-description\">\r\n 正确答案是: <strong>\r\n {problemData.answer.value}\r\n </strong>\r\n </p>\r\n </div>\r\n <button\r\n onClick={onNextQuestion}\r\n className=\"decimal-understand-button\"\r\n >\r\n 明白了\r\n </button>\r\n </div>\r\n\r\n {/* 解释内容 - 两个学习模块(根据demo分析,不需要记忆模块) */}\r\n <div className=\"decimal-content-area\">\r\n {/* 复习模块 */}\r\n <ReviewModule\r\n problemData={problemData}\r\n userAnswer={userAnswer}\r\n />\r\n\r\n {/* 解题模块 */}\r\n <SolveModule\r\n problemData={problemData}\r\n />\r\n </div>\r\n\r\n {/* 底部按钮 */}\r\n <div className=\"decimal-bottom-area\">\r\n <button\r\n onClick={onNextQuestion}\r\n className=\"decimal-bottom-button\"\r\n >\r\n 明白了\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n};","import React, { useMemo } from 'react';\r\nimport {\r\n useCurrentScene,\r\n useUserAnswer,\r\n useAnswerFormVisibility,\r\n useSessionActions\r\n} from './MathPracticeSessionStore';\r\nimport { QuestionScene } from './scenes/QuestionScene';\r\nimport { ExplanationScene } from './scenes/ExplanationScene';\r\nimport { SuccessScene } from './scenes/SuccessScene';\r\nimport type { MathPracticeSessionPageProps, MathPracticeProblemData } from './MathPracticeSessionTypes';\r\n\r\n// 导入问题数据\r\nimport areaProblemData from '../../../../prd/MathCardV2/areaProblemData.json';\r\n\r\n/**\r\n * 数学练习会话主页面\r\n * 管理三场景流程:问题 → 解释/成功 → 重置\r\n */\r\nexport const MathPracticeSessionPage: React.FC<MathPracticeSessionPageProps> = ({\r\n className = ''\r\n}) => {\r\n // 状态管理\r\n const currentScene = useCurrentScene();\r\n const userAnswer = useUserAnswer();\r\n const showAnswerForm = useAnswerFormVisibility();\r\n const { updateUserAnswer, submitAnswer, nextQuestion } = useSessionActions();\r\n\r\n // 数据转换:确保数据符合 MathPracticeProblemData 接口\r\n const normalizeProblemData = (data: any): MathPracticeProblemData => {\r\n if (!data) return data;\r\n\r\n // 深度复制数据避免修改原始对象\r\n const normalized = JSON.parse(JSON.stringify(data));\r\n\r\n // 添加缺失的必需属性\r\n if (!normalized.lesson) normalized.lesson = '面积计算';\r\n if (!normalized.skill) normalized.skill = '面积公式应用';\r\n if (!normalized.objective) normalized.objective = '掌握面积计算方法';\r\n if (!normalized.knowledgePoints || !Array.isArray(normalized.knowledgePoints)) {\r\n normalized.knowledgePoints = ['面积公式', '几何变换'];\r\n }\r\n if (!normalized.difficulty) normalized.difficulty = 2;\r\n if (!normalized.metadata) {\r\n normalized.metadata = {\r\n topic: '几何',\r\n skill: '面积计算',\r\n tags: ['面积', '公式']\r\n };\r\n }\r\n\r\n // 确保每个场景都有 items 属性\r\n const sceneTypes = ['question', 'solve', 'review', 'remember'] as const;\r\n sceneTypes.forEach(sceneType => {\r\n if (normalized.scenes?.[sceneType]) {\r\n const scene = normalized.scenes[sceneType];\r\n // 如果 items 不存在但 content 存在,将 content 复制到 items\r\n if (!scene.items && scene.content) {\r\n scene.items = scene.content;\r\n }\r\n // 确保 items 是数组\r\n if (!Array.isArray(scene.items)) {\r\n scene.items = [];\r\n }\r\n }\r\n });\r\n\r\n return normalized as MathPracticeProblemData;\r\n };\r\n\r\n // 稳定化问题数据引用,避免 getSnapshot 警告\r\n const stableProblemData = useMemo(() => {\r\n return normalizeProblemData(areaProblemData);\r\n }, []);\r\n\r\n return (\r\n <div className={`max-w-4xl mx-auto p-4 md:p-8 bg-slate-50 min-h-screen ${className}`}>\r\n {/* 页面标题 */}\r\n <header className=\"mb-8\">\r\n <h1 className=\"text-2xl font-bold text-slate-800\">数学练习</h1>\r\n <p className=\"text-slate-600 mt-2\">\r\n {stableProblemData.grade}年级 - {stableProblemData.unit}\r\n </p>\r\n </header>\r\n\r\n {/* 主内容区域 */}\r\n <main className=\"bg-white border border-slate-200 rounded-lg shadow-sm\">\r\n {/* 问题场景 */}\r\n {currentScene === 'question' && (\r\n <QuestionScene\r\n problemData={stableProblemData}\r\n userAnswer={userAnswer}\r\n showAnswerForm={showAnswerForm}\r\n onAnswerSubmit={submitAnswer}\r\n onAnswerChange={updateUserAnswer}\r\n />\r\n )}\r\n\r\n {/* 解释场景 */}\r\n {currentScene === 'explanation' && (\r\n <ExplanationScene\r\n problemData={stableProblemData}\r\n userAnswer={userAnswer}\r\n onNextQuestion={nextQuestion}\r\n />\r\n )}\r\n\r\n {/* 成功场景 */}\r\n {currentScene === 'success' && (\r\n <SuccessScene\r\n problemData={stableProblemData}\r\n onNextQuestion={nextQuestion}\r\n />\r\n )}\r\n </main>\r\n </div>\r\n );\r\n};","import { create } from 'zustand';\r\nimport { useShallow } from 'zustand/react/shallow';\r\nimport type { MathPracticeSessionStore } from './MathPracticeSessionTypes';\r\n\r\n/**\r\n * 小数认识练习会话状态管理 Store\r\n * 扩展基础 MathPracticeSessionStore,专门处理小数答案验证\r\n */\r\nexport const useDecimalNumberRecognitionSessionStore = create<MathPracticeSessionStore>((set) => ({\r\n // 初始状态\r\n currentScene: 'question',\r\n userAnswer: '',\r\n isCorrect: null,\r\n showAnswerForm: true,\r\n problemData: null,\r\n validationError: null,\r\n\r\n // 设置问题数据\r\n setProblemData: (problemData) => {\r\n set({\r\n problemData,\r\n currentScene: 'question',\r\n userAnswer: '',\r\n isCorrect: null,\r\n showAnswerForm: true,\r\n validationError: null\r\n });\r\n },\r\n\r\n // 更新用户答案(输入时)\r\n updateUserAnswer: (answer: string) => {\r\n set({\r\n userAnswer: answer,\r\n validationError: null // 清除之前的错误信息\r\n });\r\n },\r\n\r\n // 提交答案 - 专门处理小数答案验证\r\n submitAnswer: (answer: string) => {\r\n const state = useDecimalNumberRecognitionSessionStore.getState();\r\n\r\n // 检查是否有问题数据\r\n if (!state.problemData) {\r\n set({\r\n validationError: '问题数据未加载,请刷新页面重试'\r\n });\r\n return;\r\n }\r\n\r\n // 获取正确答案\r\n const correctAnswer = state.problemData.answer.value.toString();\r\n\r\n // 处理小数答案验证,允许不同的格式\r\n const normalizedAnswer = answer.trim();\r\n const normalizedCorrect = correctAnswer.trim();\r\n\r\n // 验证答案(支持 0.12 或 .12 格式)\r\n let isCorrect = false;\r\n if (normalizedAnswer === normalizedCorrect) {\r\n isCorrect = true;\r\n } else if (normalizedAnswer === '.12' && normalizedCorrect === '0.12') {\r\n isCorrect = true;\r\n } else if (normalizedAnswer === '0,12' && normalizedCorrect === '0.12') {\r\n isCorrect = true; // 支持逗号分隔符\r\n }\r\n\r\n set({\r\n userAnswer: answer,\r\n isCorrect,\r\n showAnswerForm: false,\r\n validationError: null,\r\n currentScene: isCorrect ? 'success' : 'explanation'\r\n });\r\n },\r\n\r\n // 下一题\r\n nextQuestion: () => {\r\n set({\r\n currentScene: 'question',\r\n userAnswer: '',\r\n isCorrect: null,\r\n showAnswerForm: true,\r\n validationError: null\r\n });\r\n },\r\n\r\n // 重置会话\r\n resetSession: () => {\r\n set({\r\n currentScene: 'question',\r\n userAnswer: '',\r\n isCorrect: null,\r\n showAnswerForm: true,\r\n validationError: null\r\n });\r\n }\r\n}));\r\n\r\n/**\r\n * 自定义 Hook - 获取当前场景的状态\r\n */\r\nexport const useDecimalCurrentScene = () => {\r\n return useDecimalNumberRecognitionSessionStore((state) => state.currentScene);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取用户答案\r\n */\r\nexport const useDecimalUserAnswer = () => {\r\n return useDecimalNumberRecognitionSessionStore((state) => state.userAnswer);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取答案正确性\r\n */\r\nexport const useDecimalAnswerCorrectness = () => {\r\n return useDecimalNumberRecognitionSessionStore((state) => state.isCorrect);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取答案表单显示状态\r\n */\r\nexport const useDecimalAnswerFormVisibility = () => {\r\n return useDecimalNumberRecognitionSessionStore((state) => state.showAnswerForm);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取验证错误信息\r\n */\r\nexport const useDecimalValidationError = () => {\r\n return useDecimalNumberRecognitionSessionStore((state) => state.validationError);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取问题数据\r\n */\r\nexport const useDecimalProblemData = () => {\r\n return useDecimalNumberRecognitionSessionStore((state) => state.problemData);\r\n};\r\n\r\n/**\r\n * 自定义 Hook - 获取会话操作方法\r\n * 在 Zustand 中,action 函数是稳定引用,直接选择它们不会导致重渲染\r\n */\r\nexport const useDecimalSessionActions = () =>\r\n useDecimalNumberRecognitionSessionStore(\r\n useShallow<MathPracticeSessionStore, Pick<\r\n MathPracticeSessionStore,\r\n 'updateUserAnswer' | 'submitAnswer' | 'nextQuestion' | 'resetSession' | 'setProblemData'\r\n >>((state) => ({\r\n updateUserAnswer: state.updateUserAnswer,\r\n submitAnswer: state.submitAnswer,\r\n nextQuestion: state.nextQuestion,\r\n resetSession: state.resetSession,\r\n setProblemData: state.setProblemData\r\n }))\r\n );","import type { MathPracticeProblemData } from '../MathPracticeSessionTypes';\r\nimport type { HundredGridContentBlock, PlaceValueChartContentBlock } from '../MathCardV2.types';\r\n\r\n/**\r\n * 小数认识问题数据适配器\r\n * 将 decimalnumberRecognize.json 数据转换为 MathPracticeProblemData 接口\r\n */\r\nexport const decimalNumberRecognitionData: MathPracticeProblemData = {\r\n id: 'decimal-grid-problem-001',\r\n title: '百格图识别小数',\r\n grade: 4,\r\n unit: '小数的认识',\r\n lesson: '小数认识',\r\n skill: '百格图识别小数',\r\n objective: '理解百分位和小数的关系',\r\n knowledgePoints: [\r\n '小数表示',\r\n '百分位概念',\r\n '百格图模型'\r\n ],\r\n difficulty: 1,\r\n metadata: {\r\n topic: '小数',\r\n skill: '小数识别',\r\n tags: ['百格图', '百分位', '小数表示']\r\n },\r\n description: '通过百格图模型理解百分位和小数的关系。',\r\n basicInfo: {\r\n question: 'What decimal number does the model represent?',\r\n answerUnit: ''\r\n },\r\n scenes: {\r\n question: {\r\n content: [\r\n {\r\n type: 'text',\r\n content: 'What decimal number does the model represent?',\r\n style: {\r\n fontSize: '1.5rem',\r\n color: '#1e293b',\r\n fontWeight: 'bold'\r\n }\r\n },\r\n {\r\n type: 'text',\r\n content: 'The large square represents 1 whole.',\r\n style: {\r\n fontSize: '1rem',\r\n color: '#475569',\r\n marginTop: '4px'\r\n }\r\n },\r\n {\r\n type: 'hundredGrid',\r\n content: '',\r\n props: {\r\n value: 0.12,\r\n mode: 'readonly',\r\n rows: 10,\r\n cols: 10,\r\n cellSize: 12,\r\n fillColor: '#a5b4fc',\r\n baseColor: '#e2e8f0',\r\n strokeColor: '#d1d5db',\r\n shadingDirection: 'ltr',\r\n hasShadow: true\r\n }\r\n } as HundredGridContentBlock\r\n ],\r\n items: [\r\n {\r\n type: 'text',\r\n content: 'What decimal number does the model represent?',\r\n style: {\r\n fontSize: '1.5rem',\r\n color: '#1e293b',\r\n fontWeight: 'bold'\r\n }\r\n },\r\n {\r\n type: 'text',\r\n content: 'The large square represents 1 whole.',\r\n style: {\r\n fontSize: '1rem',\r\n color: '#475569',\r\n marginTop: '4px'\r\n }\r\n },\r\n {\r\n type: 'hundredGrid',\r\n content: '',\r\n props: {\r\n value: 0.12,\r\n mode: 'readonly',\r\n rows: 10,\r\n cols: 10,\r\n cellSize: 12,\r\n fillColor: '#a5b4fc',\r\n baseColor: '#e2e8f0',\r\n strokeColor: '#d1d5db',\r\n shadingDirection: 'ltr',\r\n hasShadow: true\r\n }\r\n } as HundredGridContentBlock\r\n ]\r\n },\r\n solve: {\r\n content: [\r\n {\r\n type: 'text',\r\n content: '解题步骤:',\r\n style: {\r\n fontSize: '1.25rem',\r\n fontWeight: 'bold',\r\n color: '#1e293b'\r\n }\r\n },\r\n {\r\n type: 'text',\r\n content: '1. 在模型中, 100个小方格中有12个被涂色。这代表 12/100 或者\"一百分之十二\"。'\r\n },\r\n {\r\n type: 'text',\r\n content: '2. 你可以使用数位表将\"一百分之十二\"写作小数。'\r\n },\r\n {\r\n type: 'placeValueChart',\r\n content: '',\r\n props: {\r\n headers: ['ones (个位)', 'tenths (十分位)', 'hundredths (百分位)'],\r\n values: ['0', '1', '2'],\r\n colors: {\r\n headerBg: '#f1f5f9',\r\n valueBg: '#ffffff',\r\n borderColor: '#e2e8f0'\r\n }\r\n }\r\n } as PlaceValueChartContentBlock,\r\n {\r\n type: 'text',\r\n content: '所以, 这个模型代表的小数是 <strong>0.12</strong>。',\r\n style: {\r\n marginTop: '1rem'\r\n }\r\n }\r\n ],\r\n items: [\r\n {\r\n type: 'text',\r\n content: '解题步骤:',\r\n style: {\r\n fontSize: '1.25rem',\r\n fontWeight: 'bold',\r\n color: '#1e293b'\r\n }\r\n },\r\n {\r\n type: 'text',\r\n content: '1. 在模型中, 100个小方格中有12个被涂色。这代表 12/100 或者\"一百分之十二\"。'\r\n },\r\n {\r\n type: 'text',\r\n content: '2. 你可以使用数位表将\"一百分之十二\"写作小数。'\r\n },\r\n {\r\n type: 'placeValueChart',\r\n content: '',\r\n props: {\r\n headers: ['ones (个位)', 'tenths (十分位)', 'hundredths (百分位)'],\r\n values: ['0', '1', '2'],\r\n colors: {\r\n headerBg: '#f1f5f9',\r\n valueBg: '#ffffff',\r\n borderColor: '#e2e8f0'\r\n }\r\n }\r\n } as PlaceValueChartContentBlock,\r\n {\r\n type: 'text',\r\n content: '所以, 这个模型代表的小数是 <strong>0.12</strong>。',\r\n style: {\r\n marginTop: '1rem'\r\n }\r\n }\r\n ]\r\n },\r\n review: {\r\n content: [\r\n {\r\n type: 'text',\r\n content: '回顾问题:',\r\n style: {\r\n fontSize: '1.25rem',\r\n fontWeight: 'bold',\r\n color: '#1e293b'\r\n }\r\n },\r\n {\r\n type: 'text',\r\n content: 'What decimal number does the model represent?\\nThe large square represents 1 whole.'\r\n },\r\n {\r\n type: 'hundredGrid',\r\n content: '',\r\n props: {\r\n value: 0.12,\r\n mode: 'readonly',\r\n rows: 10,\r\n cols: 10,\r\n cellSize: 12,\r\n fillColor: '#a5b4fc',\r\n baseColor: '#e2e8f0',\r\n strokeColor: '#d1d5db',\r\n shadingDirection: 'ltr',\r\n hasShadow: true\r\n }\r\n } as HundredGridContentBlock\r\n ],\r\n items: [\r\n {\r\n type: 'text',\r\n content: '回顾问题:',\r\n style: {\r\n fontSize: '1.25rem',\r\n fontWeight: 'bold',\r\n color: '#1e293b'\r\n }\r\n },\r\n {\r\n type: 'text',\r\n content: 'What decimal number does the model represent?\\nThe large square represents 1 whole.'\r\n },\r\n {\r\n type: 'hundredGrid',\r\n content: '',\r\n props: {\r\n value: 0.12,\r\n mode: 'readonly',\r\n rows: 10,\r\n cols: 10,\r\n cellSize: 12,\r\n fillColor: '#a5b4fc',\r\n baseColor: '#e2e8f0',\r\n strokeColor: '#d1d5db',\r\n shadingDirection: 'ltr',\r\n hasShadow: true\r\n }\r\n } as HundredGridContentBlock\r\n ]\r\n }\r\n },\r\n explanation: [], // 空数组,表示没有额外的解释步骤\r\n answer: {\r\n value: 0.12,\r\n unit: '',\r\n explanation: '模型中100个方格有12个被涂色,代表12/100,即0.12。'\r\n }\r\n};\r\n\r\nexport default decimalNumberRecognitionData;","import React, { useMemo, useEffect } from 'react';\r\nimport {\r\n useDecimalCurrentScene,\r\n useDecimalUserAnswer,\r\n useDecimalAnswerFormVisibility,\r\n useDecimalValidationError,\r\n useDecimalSessionActions\r\n} from './DecimalNumberRecognitionSessionStore';\r\nimport { QuestionScene } from './scenes/QuestionScene';\r\nimport { DecimalNumberExplanationScene } from './scenes/DecimalNumberExplanationScene';\r\nimport { SuccessScene } from './scenes/SuccessScene';\r\nimport type { MathPracticeSessionPageProps } from './MathPracticeSessionTypes';\r\n\r\n// 导入小数认识问题数据\r\nimport decimalNumberRecognitionData from './data/decimalNumberRecognitionData';\r\n\r\n/**\r\n * 小数认识练习会话主页面\r\n * 管理三场景流程:问题 → 解释/成功 → 重置\r\n * 专门用于展示百格图小数认识问题\r\n */\r\nexport const DecimalNumberRecognitionSessionPage: React.FC<MathPracticeSessionPageProps> = ({\r\n className = '',\r\n problemData: externalProblemData\r\n}) => {\r\n // 状态管理 - 使用专门的小数认识会话 Store\r\n const currentScene = useDecimalCurrentScene();\r\n const userAnswer = useDecimalUserAnswer();\r\n const showAnswerForm = useDecimalAnswerFormVisibility();\r\n const validationError = useDecimalValidationError();\r\n const { updateUserAnswer, submitAnswer, nextQuestion, setProblemData } = useDecimalSessionActions();\r\n\r\n // 使用外部传入的问题数据或默认的小数认识数据\r\n const stableProblemData = useMemo(() => {\r\n return externalProblemData || decimalNumberRecognitionData;\r\n }, [externalProblemData]);\r\n\r\n // 初始化问题数据到 store\r\n useEffect(() => {\r\n setProblemData(stableProblemData);\r\n }, [stableProblemData, setProblemData]);\r\n\r\n return (\r\n <div className={`max-w-4xl mx-auto p-4 md:p-8 bg-slate-50 min-h-screen ${className}`}>\r\n {/* 页面标题 */}\r\n <header className=\"mb-8\">\r\n <h1 className=\"text-2xl font-bold text-slate-800\">小数认识练习</h1>\r\n <p className=\"text-slate-600 mt-2\">\r\n {stableProblemData.grade}年级 - {stableProblemData.unit}\r\n </p>\r\n <p className=\"text-slate-500 text-sm mt-1\">\r\n 通过百格图模型理解百分位和小数的关系\r\n </p>\r\n </header>\r\n\r\n {/* 主内容区域 */}\r\n <main className=\"bg-white border border-slate-200 rounded-lg shadow-sm\">\r\n {/* 问题场景 */}\r\n {currentScene === 'question' && (\r\n <QuestionScene\r\n problemData={stableProblemData}\r\n userAnswer={userAnswer}\r\n showAnswerForm={showAnswerForm}\r\n onAnswerSubmit={submitAnswer}\r\n onAnswerChange={updateUserAnswer}\r\n validationError={validationError}\r\n />\r\n )}\r\n\r\n {/* 解释场景 */}\r\n {currentScene === 'explanation' && (\r\n <DecimalNumberExplanationScene\r\n problemData={stableProblemData}\r\n userAnswer={userAnswer}\r\n onNextQuestion={nextQuestion}\r\n />\r\n )}\r\n\r\n {/* 成功场景 */}\r\n {currentScene === 'success' && (\r\n <SuccessScene\r\n problemData={stableProblemData}\r\n onNextQuestion={nextQuestion}\r\n />\r\n )}\r\n </main>\r\n\r\n {/* 会话状态指示器 */}\r\n <div className=\"mt-4 text-center text-sm text-slate-500\">\r\n {currentScene === 'question' && '请识别百格图代表的小数'}\r\n {currentScene === 'explanation' && '查看详细解释'}\r\n {currentScene === 'success' && '恭喜!答案正确'}\r\n </div>\r\n </div>\r\n );\r\n};","/**\r\n * 几何核心工具函数 \r\n * 专注于三角形寻宝游戏的几何计算、坐标处理和三角形验证\r\n */\r\n\r\n// ==================== 基础几何计算 ====================\r\n\r\n/**\r\n * 计算线段上指定比例的点\r\n * @param {Object} p1 - 起点 {x, y}\r\n * @param {Object} p2 - 终点 {x, y}\r\n * @param {number} ratio - 比例 (0-1)\r\n * @returns {Object} 计算出的点 {x, y}\r\n */\r\nexport const pointOnLine = (p1, p2, ratio) => ({\r\n x: p1.x + (p2.x - p1.x) * ratio,\r\n y: p1.y + (p2.y - p1.y) * ratio\r\n});\r\n\r\n\r\n// ==================== 几何数据导入 ====================\r\n\r\n/**\r\n * 🔧 架构修复:从单一数据源导入几何数据\r\n * \r\n * ✅ 职责:提供纯工具函数 (符合utils层职责)\r\n * \r\n * 数据源:\r\n * - 统一从 data/geometryDefinitions.js 获取\r\n * - 实现真正的单一数据源架构\r\n * - 支持依赖注入和数据源切换\r\n */\r\n\r\n/**\r\n * 计算标准化的三角形分割点坐标 - 重构版本\r\n */\r\nexport const calculateGamePoints = () => {\r\n\r\n // 基础三角形顶点(归一化坐标)\r\n const A = { x: 0.5, y: 0.1, name: 'A' };\r\n const B = { x: 0.1, y: 0.75, name: 'B' };\r\n const C = { x: 0.9, y: 0.75, name: 'C' };\r\n\r\n // 第一层分割线(距离顶点A的1/3处)\r\n const D = { ...pointOnLine(A, B, 1 / 3), name: 'D' };\r\n const E = { ...pointOnLine(A, C, 1 / 3), name: 'E' };\r\n\r\n // 第二层分割线(距离顶点A的2/3处)\r\n const M = { ...pointOnLine(A, B, 2 / 3), name: 'M' };\r\n const N = { ...pointOnLine(A, C, 2 / 3), name: 'N' };\r\n\r\n // 底边BC上的分割点\r\n const P = { ...pointOnLine(B, C, 1 / 3), name: 'P' };\r\n const Q = { ...pointOnLine(B, C, 2 / 3), name: 'Q' };\r\n\r\n // DE线上的分割点\r\n const U = { ...pointOnLine(D, E, 1 / 3), name: 'U' };\r\n const S = { ...pointOnLine(D, E, 2 / 3), name: 'S' };\r\n\r\n // MN线上的分割点\r\n const K = { ...pointOnLine(M, N, 1 / 3), name: 'K' };\r\n const L = { ...pointOnLine(M, N, 2 / 3), name: 'L' };\r\n\r\n return { A, B, C, D, E, M, N, P, Q, U, S, K, L };\r\n};\r\n\r\n/**\r\n * 将归一化坐标转换为绝对像素坐标\r\n * @param {Object} normalizedPoints - 归一化坐标点集\r\n * @param {number} width - 画布宽度\r\n * @param {number} height - 画布高度\r\n * @returns {Object} 绝对坐标点集\r\n */\r\nexport const toPixelCoordinates = (normalizedPoints, width, height) => {\r\n const pixelPoints = {};\r\n\r\n for (const [name, point] of Object.entries(normalizedPoints)) {\r\n pixelPoints[name] = {\r\n ...point,\r\n x: point.x * width,\r\n y: point.y * height\r\n };\r\n }\r\n\r\n return pixelPoints;\r\n};\r\n\r\n\r\n\r\n/**\r\n * 使用重心坐标判断点是否在三角形内 - 来自 gameUtils.js\r\n * @param {Object} point - 待检测的点 {x, y}\r\n * @param {Array} triangle - 三角形的三个顶点\r\n * @returns {boolean} 点是否在三角形内\r\n */\r\nexport const isPointInTriangle = (point, triangle) => {\r\n const [p1, p2, p3] = triangle;\r\n const { x, y } = point;\r\n\r\n // 使用重心坐标系\r\n const denominator = ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));\r\n\r\n if (Math.abs(denominator) < 0.0001) return false; // 退化三角形\r\n\r\n const a = ((p2.y - p3.y) * (x - p3.x) + (p3.x - p2.x) * (y - p3.y)) / denominator;\r\n const b = ((p3.y - p1.y) * (x - p3.x) + (p1.x - p3.x) * (y - p3.y)) / denominator;\r\n const c = 1 - a - b;\r\n\r\n // 点在三角形内当且仅当所有重心坐标都非负\r\n return a >= -0.001 && b >= -0.001 && c >= -0.001;\r\n};\r\n\r\n/**\r\n * 检查两个三角形是否匹配 (顶点相同,顺序可能不同) - 来自 gameUtils.js\r\n * @param {Array} triangle1 - 第一个三角形的顶点数组\r\n * @param {Array} triangle2 - 第二个三角形的顶点数组\r\n * @returns {boolean} 是否匹配\r\n */\r\nexport const trianglesMatch = (triangle1, triangle2) => {\r\n if (!triangle1 || !triangle2) return false;\r\n if (triangle1.length !== 3 || triangle2.length !== 3) return false;\r\n\r\n const names1 = triangle1.map(p => p.name).sort();\r\n const names2 = triangle2.map(p => p.name).sort();\r\n\r\n return names1.every((name, index) => name === names2[index]);\r\n};\r\n\r\n/**\r\n * 比较两个点数组是否包含相同的点(忽略顺序)\r\n * @param {Array} points1 - 第一组点\r\n * @param {Array} points2 - 第二组点\r\n * @returns {boolean} 是否匹配\r\n */\r\nexport const comparePointArrays = (points1, points2) => {\r\n if (!points1 || !points2 || points1.length !== points2.length) {\r\n return false;\r\n }\r\n\r\n const names1 = points1.map(p => p.name).sort();\r\n const names2 = points2.map(p => p.name).sort();\r\n\r\n return names1.join('') === names2.join('');\r\n};\r\n\r\n\r\n\r\n/**\r\n * 获取标准化的三角形连线定义\r\n * @returns {Array} 连线数组\r\n */\r\nexport const getBasicLineDefinitions = () => [\r\n // 大三角形边\r\n { from: 'A', to: 'B' },\r\n { from: 'A', to: 'C' },\r\n { from: 'B', to: 'C' },\r\n \r\n // 第一层分割线\r\n { from: 'D', to: 'E' },\r\n \r\n // 第二层分割线\r\n { from: 'M', to: 'N' },\r\n \r\n // 底边分割线\r\n { from: 'P', to: 'Q' },\r\n \r\n // 连接到顶点的线段\r\n { from: 'A', to: 'D' },\r\n { from: 'A', to: 'E' },\r\n { from: 'A', to: 'M' },\r\n { from: 'A', to: 'N' },\r\n { from: 'A', to: 'P' },\r\n { from: 'A', to: 'Q' },\r\n \r\n // 内部连接线段\r\n { from: 'D', to: 'U' },\r\n { from: 'U', to: 'S' },\r\n { from: 'S', to: 'E' },\r\n { from: 'M', to: 'K' },\r\n { from: 'K', to: 'L' },\r\n { from: 'L', to: 'N' },\r\n \r\n // 到底边的连接\r\n { from: 'B', to: 'P' },\r\n { from: 'P', to: 'Q' },\r\n { from: 'Q', to: 'C' }\r\n];\r\n\r\n/**\r\n * 获取18个宝石的基础定义 - MVP版本\r\n * @returns {Array} 宝石数组\r\n */\r\nexport const getBasicGemDefinitions = () => [\r\n // 大三角形系列(3个)\r\n { id: 'gem_1', vertices: ['A', 'B', 'P'], points: 10, category: 'basic' },\r\n { id: 'gem_2', vertices: ['A', 'P', 'Q'], points: 10, category: 'basic' },\r\n { id: 'gem_3', vertices: ['A', 'Q', 'C'], points: 10, category: 'basic' },\r\n\r\n // 中等三角形系列(3个)\r\n { id: 'gem_4', vertices: ['A', 'B', 'Q'], points: 15, category: 'medium' },\r\n { id: 'gem_5', vertices: ['A', 'P', 'C'], points: 15, category: 'medium' },\r\n { id: 'gem_6', vertices: ['A', 'B', 'C'], points: 20, category: 'large' },\r\n\r\n // ADE区域系列(6个)\r\n { id: 'gem_7', vertices: ['A', 'D', 'U'], points: 12, category: 'ade_small' },\r\n { id: 'gem_8', vertices: ['A', 'U', 'S'], points: 12, category: 'ade_small' },\r\n { id: 'gem_9', vertices: ['A', 'S', 'E'], points: 12, category: 'ade_small' },\r\n { id: 'gem_10', vertices: ['A', 'D', 'S'], points: 18, category: 'ade_medium' },\r\n { id: 'gem_11', vertices: ['A', 'U', 'E'], points: 18, category: 'ade_medium' },\r\n { id: 'gem_12', vertices: ['A', 'D', 'E'], points: 25, category: 'ade_large' },\r\n\r\n // AMN区域系列(6个)\r\n { id: 'gem_13', vertices: ['A', 'M', 'K'], points: 14, category: 'amn_small' },\r\n { id: 'gem_14', vertices: ['A', 'K', 'L'], points: 14, category: 'amn_small' },\r\n { id: 'gem_15', vertices: ['A', 'L', 'N'], points: 14, category: 'amn_small' },\r\n { id: 'gem_16', vertices: ['A', 'M', 'L'], points: 20, category: 'amn_medium' },\r\n { id: 'gem_17', vertices: ['A', 'K', 'N'], points: 20, category: 'amn_medium' },\r\n { id: 'gem_18', vertices: ['A', 'M', 'N'], points: 30, category: 'amn_large' }\r\n];\r\n\r\n// ==================== 几何配置和默认导出 ====================\r\n\r\n/**\r\n * 几何配置常量 - 整合版本\r\n */\r\nexport const GEOMETRY_CONFIG = {\r\n TOTAL_GEMS: 18,\r\n CANVAS_RATIO: 4 / 3,\r\n DEFAULT_VIEWBOX: { width: 700, height: 600 },\r\n POINT_RADIUS: { default: 6, selected: 9 },\r\n TOLERANCE: 0.001,\r\n\r\n // 新增:几何计算相关常量\r\n MIN_TRIANGLE_AREA: 0.001,\r\n COORDINATE_PRECISION: 0.0001,\r\n BARYCENTRIC_TOLERANCE: -0.001\r\n};\r\n\r\n/**\r\n * 默认导出 - 包含所有几何工具函数\r\n */\r\nexport default {\r\n // 基础几何计算\r\n pointOnLine,\r\n calculateGamePoints,\r\n toPixelCoordinates,\r\n\r\n // 三角形验证和分析\r\n isPointInTriangle,\r\n trianglesMatch,\r\n comparePointArrays,\r\n\r\n // 数据和配置 (重新导出数据层接口)\r\n getBasicGemDefinitions,\r\n getBasicLineDefinitions,\r\n GEOMETRY_CONFIG,\r\n\r\n // 🔧 新增:单一数据源访问接口\r\n // getStandardGeometryPoints: calculateGamePoints // 暂时注释掉,需要时再实现\r\n}; ","import { MOCK_USER_DATA, MOCK_JWT_TOKEN } from './mockData';\r\nimport { courseData } from './courseData';\r\n\r\nexport interface UserLessonProgress {\r\n lessonId: string;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n progressPercentage: number;\r\n lastAccessed?: string;\r\n timeSpent?: number; // 分钟\r\n score?: number; // 分数 0-100\r\n attempts?: number; // 尝试次数\r\n}\r\n\r\nexport interface UserUnitProgress {\r\n unitId: string;\r\n userId: string;\r\n totalLessons: number;\r\n completedLessons: number;\r\n progressPercentage: number;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n lastAccessed?: string;\r\n lessons: UserLessonProgress[];\r\n}\r\n\r\nexport interface UserCourseProgress {\r\n courseId: string;\r\n userId: string;\r\n totalUnits: number;\r\n completedUnits: number;\r\n progressPercentage: number;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n lastAccessed?: string;\r\n units: UserUnitProgress[];\r\n}\r\n\r\n// 生成模拟的用户课程进度数据\r\nexport const generateMockUserCourseProgress = (userId: string = MOCK_USER_DATA.id): UserCourseProgress => {\r\n const unitsProgress: UserUnitProgress[] = courseData.units.map((unit, index) => {\r\n // 模拟进度数据 - 根据单元索引设置不同的进度\r\n const baseProgress = Math.min(100, Math.max(0, index * 15 + Math.random() * 20));\r\n const completedLessons = Math.floor((unit.lessons.length * baseProgress) / 100);\r\n\r\n const lessonsProgress: UserLessonProgress[] = unit.lessons.map((lesson, lessonIndex) => {\r\n const lessonProgress = Math.min(100, Math.max(0, baseProgress - (lessonIndex * 10) + Math.random() * 30));\r\n\r\n return {\r\n lessonId: lesson.id,\r\n status: lessonProgress >= 100 ? 'completed' : lessonProgress > 0 ? 'in-progress' : 'not-started',\r\n progressPercentage: Math.round(lessonProgress),\r\n lastAccessed: lessonProgress > 0 ? new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000).toISOString() : undefined,\r\n timeSpent: lessonProgress > 0 ? Math.floor(Math.random() * 120 + 10) : undefined,\r\n score: lessonProgress >= 100 ? Math.floor(Math.random() * 21 + 80) : undefined,\r\n attempts: lessonProgress > 0 ? Math.floor(Math.random() * 3 + 1) : undefined\r\n };\r\n });\r\n\r\n return {\r\n unitId: unit.id,\r\n userId,\r\n totalLessons: unit.lessons.length,\r\n completedLessons,\r\n progressPercentage: Math.round(baseProgress),\r\n status: baseProgress >= 100 ? 'completed' : baseProgress > 0 ? 'in-progress' : 'not-started',\r\n lastAccessed: baseProgress > 0 ? new Date(Date.now() - Math.random() * 14 * 24 * 60 * 60 * 1000).toISOString() : undefined,\r\n lessons: lessonsProgress\r\n };\r\n });\r\n\r\n const totalProgress = unitsProgress.reduce((sum, unit) => sum + unit.progressPercentage, 0) / unitsProgress.length;\r\n const completedUnits = unitsProgress.filter(unit => unit.status === 'completed').length;\r\n\r\n return {\r\n courseId: courseData.id,\r\n userId,\r\n totalUnits: unitsProgress.length,\r\n completedUnits,\r\n progressPercentage: Math.round(totalProgress),\r\n status: totalProgress >= 100 ? 'completed' : totalProgress > 0 ? 'in-progress' : 'not-started',\r\n lastAccessed: new Date(Date.now() - Math.random() * 3 * 24 * 60 * 60 * 1000).toISOString(),\r\n units: unitsProgress\r\n };\r\n};\r\n\r\n// 模拟用户课程进度数据\r\nexport const MOCK_USER_COURSE_PROGRESS: UserCourseProgress = generateMockUserCourseProgress();\r\n\r\n// 获取用户课程进度\r\nexport const getUserCourseProgress = (userId: string, courseId: string): UserCourseProgress | null => {\r\n if (userId === MOCK_USER_DATA.id && courseId === courseData.id) {\r\n return MOCK_USER_COURSE_PROGRESS;\r\n }\r\n return null;\r\n};\r\n\r\n// 获取特定单元的进度\r\nexport const getUserUnitProgress = (userId: string, courseId: string, unitId: string): UserUnitProgress | null => {\r\n const courseProgress = getUserCourseProgress(userId, courseId);\r\n if (!courseProgress) return null;\r\n\r\n return courseProgress.units.find(unit => unit.unitId === unitId) || null;\r\n};\r\n\r\n// 获取特定课时的进度\r\nexport const getUserLessonProgress = (userId: string, courseId: string, unitId: string, lessonId: string): UserLessonProgress | null => {\r\n const unitProgress = getUserUnitProgress(userId, courseId, unitId);\r\n if (!unitProgress) return null;\r\n\r\n return unitProgress.lessons.find(lesson => lesson.lessonId === lessonId) || null;\r\n};\r\n\r\n// 更新课时进度\r\nexport const updateUserLessonProgress = (\r\n userId: string,\r\n courseId: string,\r\n unitId: string,\r\n lessonId: string,\r\n progress: Partial<UserLessonProgress>\r\n): boolean => {\r\n // 在实际应用中,这里会调用API更新数据库\r\n // 这里只是模拟更新操作\r\n console.log('Updating lesson progress:', { userId, courseId, unitId, lessonId, progress });\r\n return true;\r\n};","import { MOCK_USER_DATA, MOCK_JWT_TOKEN } from './mockData';\r\nimport { courseData } from './courseData';\r\nimport { getUserCourseProgress } from './userCourseProgress';\r\nimport type { UserUnitProgress } from './userCourseProgress';\r\n\r\nexport interface UserGradeUnitNavItem {\r\n unitId: string;\r\n title: string;\r\n description: string;\r\n moduleCategory: string;\r\n estimatedDuration: string;\r\n totalLessons: number;\r\n completedLessons: number;\r\n progressPercentage: number;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n lastAccessed?: string;\r\n isActive: boolean;\r\n route: string;\r\n icon?: string;\r\n}\r\n\r\nexport interface UserGradeUnitsNav {\r\n userId: string;\r\n courseId: string;\r\n courseTitle: string;\r\n courseLevel: number;\r\n totalUnits: number;\r\n completedUnits: number;\r\n overallProgress: number;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n lastAccessed?: string;\r\n units: UserGradeUnitNavItem[];\r\n}\r\n\r\n// 获取用户年级单元导航数据\r\nexport const getUserGradeUnitsNav = (userId: string, courseId: string): UserGradeUnitsNav | null => {\r\n const userProgress = getUserCourseProgress(userId, courseId);\r\n if (!userProgress) return null;\r\n\r\n const unitsNav: UserGradeUnitNavItem[] = courseData.units.map((unit, index) => {\r\n const unitProgress = userProgress.units.find(up => up.unitId === unit.id);\r\n\r\n return {\r\n unitId: unit.id,\r\n title: unit.title,\r\n description: unit.description,\r\n moduleCategory: unit.moduleCategory,\r\n estimatedDuration: unit.estimatedDuration,\r\n totalLessons: unit.lessons.length,\r\n completedLessons: unitProgress?.completedLessons || 0,\r\n progressPercentage: unitProgress?.progressPercentage || 0,\r\n status: unitProgress?.status || 'not-started',\r\n lastAccessed: unitProgress?.lastAccessed,\r\n isActive: index === 0, // 默认第一个单元为活跃状态\r\n route: `/math/grade-${courseData.level}/unit/${unit.id}`\r\n };\r\n });\r\n\r\n return {\r\n userId,\r\n courseId: courseData.id,\r\n courseTitle: courseData.title,\r\n courseLevel: courseData.level,\r\n totalUnits: unitsNav.length,\r\n completedUnits: unitsNav.filter(unit => unit.status === 'completed').length,\r\n overallProgress: userProgress.progressPercentage,\r\n status: userProgress.status,\r\n lastAccessed: userProgress.lastAccessed,\r\n units: unitsNav\r\n };\r\n};\r\n\r\n// 获取特定单元的导航项\r\nexport const getUnitNavItem = (userId: string, courseId: string, unitId: string): UserGradeUnitNavItem | null => {\r\n const navData = getUserGradeUnitsNav(userId, courseId);\r\n if (!navData) return null;\r\n\r\n return navData.units.find(unit => unit.unitId === unitId) || null;\r\n};\r\n\r\n// 更新单元活跃状态\r\nexport const updateUnitActiveStatus = (userId: string, courseId: string, unitId: string, isActive: boolean): boolean => {\r\n // 在实际应用中,这里会更新用户的学习状态\r\n // 这里只是模拟操作\r\n console.log('Updating unit active status:', { userId, courseId, unitId, isActive });\r\n return true;\r\n};\r\n\r\n// 模拟用户年级单元导航数据\r\nexport const MOCK_USER_GRADE_UNITS_NAV: UserGradeUnitsNav = getUserGradeUnitsNav(MOCK_USER_DATA.id, courseData.id)!;","// 用户年级单元进度数据 - 用于 Sidebar 展示组件\r\nimport { MOCK_USER_DATA } from './mockData';\r\nimport { courseData } from './courseData';\r\n\r\nexport interface UnitProgressData {\r\n unitId: string;\r\n title: string;\r\n description: string;\r\n moduleCategory: string;\r\n estimatedDuration: string;\r\n totalLessons: number;\r\n completedLessons: number;\r\n progressPercentage: number;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n lastAccessed?: string;\r\n isActive: boolean;\r\n route: string;\r\n icon?: string;\r\n}\r\n\r\nexport interface UserGradeUnitsProgressData {\r\n userId: string;\r\n courseId: string;\r\n courseTitle: string;\r\n courseLevel: number;\r\n totalUnits: number;\r\n completedUnits: number;\r\n overallProgress: number;\r\n status: 'not-started' | 'in-progress' | 'completed';\r\n lastAccessed?: string;\r\n units: UnitProgressData[];\r\n}\r\n\r\n// 模拟用户年级单元进度数据 - 用于 Sidebar 展示组件\r\n// 此数据仅用于展示,不包含任何业务逻辑或API调用\r\n\r\nexport const MOCK_USER_GRADE_UNITS_PROGRESS: UserGradeUnitsProgressData = {\r\n userId: MOCK_USER_DATA.id,\r\n courseId: courseData.id,\r\n courseTitle: courseData.title,\r\n courseLevel: courseData.level,\r\n totalUnits: courseData.units.length,\r\n completedUnits: 3,\r\n overallProgress: 45,\r\n status: 'in-progress',\r\n lastAccessed: '2024-01-15T10:30:00Z',\r\n units: [\r\n {\r\n unitId: 'unit_1',\r\n title: '小数乘法',\r\n description: '学习小数乘法的计算方法及应用',\r\n moduleCategory: 'Arithmetic and Algebra',\r\n estimatedDuration: '3周',\r\n totalLessons: 10,\r\n completedLessons: 8,\r\n progressPercentage: 80,\r\n status: 'completed',\r\n lastAccessed: '2024-01-10T14:20:00Z',\r\n isActive: false,\r\n route: '/math/grade-5/unit/unit_1',\r\n icon: '🔢'\r\n },\r\n {\r\n unitId: 'unit_2',\r\n title: '小数除法',\r\n description: '学习小数除法的计算方法及应用',\r\n moduleCategory: 'Arithmetic and Algebra',\r\n estimatedDuration: '3周',\r\n totalLessons: 12,\r\n completedLessons: 6,\r\n progressPercentage: 50,\r\n status: 'in-progress',\r\n lastAccessed: '2024-01-15T10:30:00Z',\r\n isActive: true,\r\n route: '/math/grade-5/unit/unit_2',\r\n icon: '➗'\r\n },\r\n {\r\n unitId: 'unit_3',\r\n title: '简易方程',\r\n description: '学习用字母表示数和解简易方程',\r\n moduleCategory: 'Arithmetic and Algebra',\r\n estimatedDuration: '4周',\r\n totalLessons: 14,\r\n completedLessons: 2,\r\n progressPercentage: 14,\r\n status: 'in-progress',\r\n lastAccessed: '2024-01-12T16:45:00Z',\r\n isActive: false,\r\n route: '/math/grade-5/unit/unit_3',\r\n icon: '📝'\r\n },\r\n {\r\n unitId: 'unit_4',\r\n title: '多边形的面积',\r\n description: '学习平行四边形、三角形、梯形和组合图形的面积计算',\r\n moduleCategory: 'Graphics and Geometry',\r\n estimatedDuration: '3周',\r\n totalLessons: 12,\r\n completedLessons: 0,\r\n progressPercentage: 0,\r\n status: 'not-started',\r\n isActive: false,\r\n route: '/math/grade-5/unit/unit_4',\r\n icon: '📐'\r\n },\r\n {\r\n unitId: 'unit_5',\r\n title: '因数与倍数',\r\n description: '学习因数、倍数、质数、合数等概念',\r\n moduleCategory: 'Arithmetic and Algebra',\r\n estimatedDuration: '3周',\r\n totalLessons: 10,\r\n completedLessons: 0,\r\n progressPercentage: 0,\r\n status: 'not-started',\r\n isActive: false,\r\n route: '/math/grade-5/unit/unit_5',\r\n icon: '🔢'\r\n },\r\n {\r\n unitId: 'unit_6',\r\n title: '长方体和正方体',\r\n description: '学习长方体和正方体的特征、表面积和体积计算',\r\n moduleCategory: 'Graphics and Geometry',\r\n estimatedDuration: '4周',\r\n totalLessons: 14,\r\n completedLessons: 0,\r\n progressPercentage: 0,\r\n status: 'not-started',\r\n isActive: false,\r\n route: '/math/grade-5/unit/unit_6',\r\n icon: '📦'\r\n },\r\n {\r\n unitId: 'unit_7',\r\n title: '分数的意义和性质',\r\n description: '学习分数的意义、性质和约分、通分等方法',\r\n moduleCategory: 'Arithmetic and Algebra',\r\n estimatedDuration: '4周',\r\n totalLessons: 16,\r\n completedLessons: 0,\r\n progressPercentage: 0,\r\n status: 'not-started',\r\n isActive: false,\r\n route: '/math/grade-5/unit/unit_7',\r\n icon: '½'\r\n },\r\n {\r\n unitId: 'unit_8',\r\n title: '分数的加法和减法',\r\n description: '学习同分母分数、异分母分数的加法和减法',\r\n moduleCategory: 'Arithmetic and Algebra',\r\n estimatedDuration: '3周',\r\n totalLessons: 12,\r\n completedLessons: 0,\r\n progressPercentage: 0,\r\n status: 'not-started',\r\n isActive: false,\r\n route: '/math/grade-5/unit/unit_8',\r\n icon: '➕'\r\n },\r\n {\r\n unitId: 'unit_9',\r\n title: '折线统计图',\r\n description: '学习单式折线统计图和复式折线统计图的认识和制作',\r\n moduleCategory: 'Probability and Statistics',\r\n estimatedDuration: '2周',\r\n totalLessons: 6,\r\n completedLessons: 0,\r\n progressPercentage: 0,\r\n status: 'not-started',\r\n isActive: false,\r\n route: '/math/grade-5/unit/unit_9',\r\n icon: '📊'\r\n }\r\n ]\r\n};","import React, { useState, useEffect } from 'react';\r\nimport {\r\n useCurrentScene,\r\n useUserAnswer,\r\n useAnswerFormVisibility,\r\n useValidationError,\r\n useSessionActions,\r\n} from '../../components/MathCardV2/MathPracticeStoreHooks';\r\nimport { QuestionScene } from '../../components/MathCardV2/scenes/QuestionScene';\r\nimport { ExplanationScene } from '../../components/MathCardV2/scenes/ExplanationScene';\r\nimport { SuccessScene } from '../../components/MathCardV2/scenes/SuccessScene';\r\n// import type { MathPracticeSessionPageProps, MathPracticeProblemData } from '../../components/MathCardV2/MathPracticeSessionTypes';\r\nimport type { AreaGeometrySessionPageProps } from './types';\r\n\r\n/**\r\n * AreaGeometrySessionPage - 几何与年龄问题统一会话页面(纯容器组件)\r\n *\r\n * 这是一个纯粹的容器组件,负责:\r\n * 1. 连接MathPracticeSessionStore状态管理\r\n * 2. 根据currentScene路由到对应场景组件\r\n * 3. 初始化store中的问题数据\r\n *\r\n * 页面复用MathCardV2组件系统的三场景架构:\r\n * - 问题场景 (question): 展示问题和答案输入表单\r\n * - 解释场景 (explanation): 错误答案时的详细解释\r\n * - 成功场景 (success): 正确答案时的积极反馈\r\n *\r\n * @example\r\n * ```tsx\r\n * // 必需:传入适配后的问题数据\r\n * import { adaptGeometryDataSync } from '../data/GeometryProblemAdapterV4';\r\n * import triangleJson from './triangle-data.json';\r\n *\r\n * const problemData = adaptGeometryDataSync(triangleJson).data;\r\n * <AreaGeometrySessionPage problemData={problemData} />\r\n * ```\r\n */\r\nexport const AreaGeometrySessionPage: React.FC<AreaGeometrySessionPageProps> = ({\r\n className = '',\r\n problemData,\r\n children,\r\n}) => {\r\n // 状态管理 - 复用现有Store\r\n const currentScene = useCurrentScene();\r\n const userAnswer = useUserAnswer();\r\n const showAnswerForm = useAnswerFormVisibility();\r\n const validationError = useValidationError();\r\n const { updateUserAnswer, submitAnswer, nextQuestion, setProblemData } = useSessionActions();\r\n\r\n // 问题数据已通过props传入,无需本地状态\r\n\r\n // 初始化store数据\r\n useEffect(() => {\r\n if (problemData) {\r\n setProblemData(problemData);\r\n }\r\n }, [problemData, setProblemData]);\r\n\r\n // 问题数据通过props传入\r\n\r\n // 基于problemData元数据的样式函数\r\n const getPageStyle = () => {\r\n // 从problemData中提取shape信息决定样式\r\n const shape = problemData?.basicInfo?.shape;\r\n switch (shape) {\r\n case 'triangle':\r\n return { titleColor: 'text-cyan-600', label: '三角形面积' };\r\n case 'parallelogram':\r\n return { titleColor: 'text-blue-600', label: '平行四边形面积' };\r\n case 'trapezoid':\r\n return { titleColor: 'text-green-600', label: '梯形面积' };\r\n default:\r\n // 年龄问题或其他类型\r\n const isAgeProblem = problemData?.title?.includes('年龄') ||\r\n problemData?.basicInfo?.question?.includes('年龄');\r\n return isAgeProblem\r\n ? { titleColor: 'text-purple-600', label: '年龄问题' }\r\n : { titleColor: 'text-slate-600', label: '数学问题' };\r\n }\r\n };\r\n\r\n const pageStyle = getPageStyle();\r\n\r\n return (\r\n <div className=\"min-h-screen bg-gradient-to-br from-slate-50 to-cyan-50 flex flex-col items-center justify-center p-4 font-sans\">\r\n {/* 页面标题区域 */}\r\n <header className=\"w-full max-w-4xl mb-8\">\r\n <div className=\"flex flex-col md:flex-row md:items-center md:justify-between\">\r\n <div>\r\n <h1 className={`text-2xl md:text-3xl font-bold ${pageStyle.titleColor}`}>\r\n {problemData?.title || '数学问题练习'}\r\n </h1>\r\n <p className=\"text-slate-600 mt-2\">\r\n {problemData?.grade || 5}年级 · {problemData?.unit || '数学'}\r\n {problemData?.lesson && ` · ${problemData.lesson}`}\r\n </p>\r\n </div>\r\n\r\n {/* 问题类型标签 */}\r\n <div className=\"mt-4 md:mt-0\">\r\n <span className=\"inline-block px-3 py-1 text-sm font-medium rounded-full bg-white border border-slate-200 text-slate-700\">\r\n {pageStyle.label}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n {problemData?.description && (\r\n <p className=\"mt-4 text-slate-700 bg-white/50 p-3 rounded-lg border border-slate-200\">\r\n {problemData.description}\r\n </p>\r\n )}\r\n </header>\r\n\r\n {/* 主内容区域 */}\r\n <main className=\"w-full max-w-4xl bg-white border border-slate-200 rounded-xl shadow-sm overflow-hidden\">\r\n {!problemData ? (\r\n <div className=\"p-8 text-center\">\r\n <div className=\"text-red-500 text-4xl mb-4\">⚠️</div>\r\n <h3 className=\"text-xl font-semibold text-slate-800 mb-2\">缺少问题数据</h3>\r\n <p className=\"text-slate-600\">请提供有效的problemData prop</p>\r\n </div>\r\n ) : (\r\n <>\r\n {/* 场景切换逻辑 */}\r\n {currentScene === 'question' && (\r\n <QuestionScene\r\n problemData={problemData}\r\n userAnswer={userAnswer}\r\n showAnswerForm={showAnswerForm}\r\n onAnswerSubmit={submitAnswer}\r\n onAnswerChange={updateUserAnswer}\r\n validationError={validationError}\r\n />\r\n )}\r\n\r\n {currentScene === 'explanation' && (\r\n <ExplanationScene\r\n problemData={problemData}\r\n userAnswer={userAnswer}\r\n onNextQuestion={nextQuestion}\r\n />\r\n )}\r\n\r\n {currentScene === 'success' && (\r\n <SuccessScene\r\n problemData={problemData}\r\n onNextQuestion={nextQuestion}\r\n />\r\n )}\r\n </>\r\n )}\r\n </main>\r\n\r\n {/* 页脚信息 */}\r\n <footer className=\"w-full max-w-4xl mt-8 text-center text-slate-500 text-sm\">\r\n <div className=\"flex flex-col md:flex-row md:justify-between items-center\">\r\n <div className=\"mb-4 md:mb-0\">\r\n <p>使用MathCardV2组件系统 · 三场景交互设计</p>\r\n </div>\r\n <div>\r\n <p>数据源: {problemData?.id || '未知'}</p>\r\n </div>\r\n </div>\r\n </footer>\r\n\r\n {/* 子元素(可选) */}\r\n {children && (\r\n <div className=\"w-full max-w-4xl mt-8\">\r\n {children}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// 默认导出\r\nexport default AreaGeometrySessionPage;","// 组件库主入口文件\r\nimport './styles/index.css';\r\n\r\n// ==================== 基础UI组件 ====================\r\nexport { Button } from './components/Button';\r\nexport type { ButtonProps } from './components/Button';\r\n\r\nexport { ContentAccordion } from './components/ContentAccordion';\r\nexport type { ContentAccordionProps } from './components/ContentAccordion';\r\n\r\nexport { Sidebar } from './components/Sidebar';\r\nexport type { SidebarProps } from './components/Sidebar';\r\n\r\nexport { MathWizHeader } from './components/MathWizHeader';\r\nexport type { MathWizHeaderProps, ExploreItem } from './components/MathWizHeader';\r\n\r\nexport { default as Submenu } from './components/Submenu/Submenu';\r\nexport type { SubmenuItem, SubmenuProps } from './components/Submenu/Submenu';\r\n\r\nexport { default as UserProfile } from './components/UserProfile/UserProfile';\r\nexport type { UserProfileProps, ApiConfig } from './components/UserProfile/UserProfile';\r\n\r\n// 数学相关组件\r\nexport { default as EquationRender } from './components/EquationRender';\r\nexport type { EquationRenderProps } from './components/EquationRender/types';\r\n\r\nexport { default as GeometryTransform } from './components/GeometryTransform';\r\nexport type * from './components/GeometryTransform/types';\r\n\r\nexport { HundredChart } from './components/HundredChart';\r\nexport type {\r\n HundredChartProps,\r\n CellData,\r\n DragState,\r\n FillAlgorithmConfig,\r\n FillAlgorithmResult\r\n} from './components/HundredChart/HundredChart.types';\r\nexport {\r\n useHundredChartStore,\r\n useHundredChartValue,\r\n useHundredChartDrag\r\n} from './components/HundredChart/HundredChart.store';\r\nexport {\r\n calculateFilledCells,\r\n generateCellData,\r\n calculateDragRange,\r\n calculateValueFromDrag,\r\n validateValue,\r\n formatPercentage\r\n} from './components/HundredChart/HundredChart.utils';\r\n\r\nexport { IXLStyleCard } from './components/IXLStyleCard';\r\nexport type {\r\n IXLStyleCardProps,\r\n IXLCardConfig,\r\n IXLCardType,\r\n IXLColorMap,\r\n IXLStyleHookReturn,\r\n ResponsiveHookReturn,\r\n ResponsiveConfig\r\n} from './components/IXLStyleCard/IXLStyleCard.types';\r\nexport {\r\n DEFAULT_IXL_CONFIG,\r\n IXL_COLORS,\r\n IXL_LABELS\r\n} from './components/IXLStyleCard/IXLStyleCard.types';\r\nexport { useIXLStyle, useResponsive } from './components/IXLStyleCard';\r\n\r\nexport { GradeNavigation } from './components/GradeNavigation';\r\nexport type { GradeNavigationProps } from './components/GradeNavigation';\r\n\r\n// Radar Ability 相关组件\r\nexport { default as RadarChart } from './components/radarAbility/RadarChart/RadarChart';\r\n// export type { RadarChartProps } from './components/radarAbility/RadarChart/RadarChart';\r\n\r\nexport { default as AbilityAssessmentDashboard } from './components/radarAbility/AbilityAssessmentDashboard/AbilityAssessmentDashboard';\r\n// export type { AbilityAssessmentDashboardProps } from './components/radarAbility/AbilityAssessmentDashboard/AbilityAssessmentDashboard';\r\n\r\nexport { default as AbilityProgressBar } from './components/radarAbility/AbilityProgressBar/AbilityProgressBar';\r\n// export type { AbilityProgressBarProps } from './components/radarAbility/AbilityProgressBar/AbilityProgressBar';\r\n\r\nexport { default as PersonalizedAdvicePanel } from './components/radarAbility/PersonalizedAdvicePanel/PersonalizedAdvicePanel';\r\n// export type { PersonalizedAdvicePanelProps } from './components/radarAbility/PersonalizedAdvicePanel/PersonalizedAdvicePanel';\r\n\r\nexport { default as RecommendationCard } from './components/radarAbility/RecommendationCard/RecommendationCard';\r\n// export type { RecommendationCardProps } from './components/radarAbility/RecommendationCard/RecommendationCard';\r\n\r\n// ==================== 页面级组件 ====================\r\nexport { GradeUnitBrowserPage } from './pages/GradeUnitBrowserPage';\r\nexport type { GradeUnitBrowserPageProps } from './pages/GradeUnitBrowserPage';\r\n\r\nexport { GradeUnitBrowserProvider, useGradeUnitBrowser } from './pages/GradeUnitBrowserPage/GradeUnitBrowserContext';\r\nexport type { GradeUnitBrowserContextType } from './pages/GradeUnitBrowserPage/types';\r\n\r\n// 面积计算会话页面\r\nexport { ParallelogramAreaCalculationSessionPage } from './pages/AreaCalculationSessionPage';\r\nexport { TriangleAreaCalculationSessionPage } from './pages/AreaCalculationSessionPage/TriangleAreaCalculationSessionPage';\r\n\r\n// ==================== 数学练习组件 ====================\r\nexport { MathSessionPage } from './pages/MathSessionPage';\r\nexport type { MathSessionPageProps, MathSessionPageConfig, SessionResults } from './pages/MathSessionPage';\r\n\r\nexport { MathSessionContainer } from './components/MathSessionContainer';\r\nexport type { MathSessionContainerProps, MathSessionConfig } from './components/MathSessionContainer';\r\n\r\n// MathCard component has been deprecated and replaced by MathCardV2\r\n// export { MathCard } from './components/MathCard';\r\n// export type {\r\n// MathCardProps,\r\n// MathProblemData,\r\n// MathCardScene,\r\n// ProblemType,\r\n// ContentType,\r\n// MathCardConfig\r\n// } from './components/MathCard';\r\n\r\n// ==================== 废弃组件兼容性导出(带警告) ====================\r\n// @ts-ignore\r\nexport const MathCard = new Proxy({}, {\r\n get() {\r\n throw new Error('⚠️ MathCard 已废弃!请使用 MathCardV2 代替。\\n更改: import { MathCard } from \\'@mathwiz/ui-components\\' → import { MathCardV2 as MathCard } from \\'@mathwiz/ui-components\\'');\r\n }\r\n});\r\n\r\n// ==================== MathCardV2 下一代数学卡片组件 ====================\r\nexport { MathCardV2, useDataAdapter } from \"./components/MathCardV2\";\r\nexport type {\r\n MathCardV2Props,\r\n MathProblemDocument,\r\n ContentBlock,\r\n FormulaContentBlock,\r\n GraphContentBlock,\r\n InteractiveContentBlock,\r\n LayoutConfig,\r\n RendererConfig,\r\n MathCardV2Scene,\r\n ContentType as MathCardV2ContentType,\r\n LayoutType,\r\n RenderMode,\r\n MathCardV2ContextType,\r\n CardLayoutProps,\r\n GridLayoutProps,\r\n FlowLayoutProps,\r\n TextContentProps,\r\n FormulaContentProps,\r\n GraphContentProps\r\n} from './components/MathCardV2';\r\n\r\nexport { MathGraph, GraphContainer } from './components/MathGraph';\r\nexport type {\r\n MathGraphProps,\r\n Shape,\r\n Point,\r\n PointRef,\r\n BaseShape,\r\n PointShape,\r\n LineShape,\r\n CircleShape\r\n} from './components/MathGraph';\r\n\r\n// 数学练习相关的Store和Hooks\r\nexport { useSessionStore } from './stores/mathSessionStore';\r\nexport type { MathSessionStore } from './stores/mathSessionStore';\r\n\r\n// MathCardV2 数学练习会话组件\r\nexport {\r\n useMathPracticeSessionStore,\r\n useCurrentScene,\r\n useUserAnswer,\r\n useAnswerCorrectness,\r\n useAnswerFormVisibility,\r\n useValidationError,\r\n useProblemData,\r\n useSessionActions,\r\n ReviewModule,\r\n RememberModule,\r\n SolveModule,\r\n QuestionScene,\r\n ExplanationScene,\r\n SuccessScene,\r\n MathPracticeSessionPage\r\n} from './components/MathCardV2';\r\nexport type {\r\n MathPracticeScene,\r\n MathPracticeSessionState,\r\n MathPracticeSessionActions,\r\n MathPracticeSessionStore,\r\n MathPracticeProblemData,\r\n ReviewModuleProps,\r\n RememberModuleProps,\r\n SolveModuleProps,\r\n QuestionSceneProps,\r\n ExplanationSceneProps,\r\n SuccessSceneProps,\r\n MathPracticeSessionPageProps,\r\n AnswerValidationResult,\r\n // 新增缺失类型导出\r\n Explanation,\r\n ExplanationStep,\r\n AnswerInfo,\r\n ProblemMetadata,\r\n Hint\r\n} from './components/MathCardV2';\r\n\r\n// 数学练习相关的工具函数\r\nexport { calculateBoundingBox } from './components/MathGraph/utils/boundingBoxCalculator';\r\nexport type { BoundingBoxOptions, CalculatedBoundingBox } from './components/MathGraph/utils/boundingBoxCalculator';\r\n\r\n// 数学练习相关的自定义Hooks\r\nexport {\r\n useSessionCalculations,\r\n useGeometryManagement,\r\n useSessionEventHandlers\r\n} from './components/MathSessionContainer/hooks';\r\n\r\n// ==================== 数据与工具 ====================\r\n// 导出数据类型\r\nexport * from './types';\r\n\r\n// 导出工具函数\r\nexport * from './utils/geometryCore';\r\n\r\n// 导出数据验证器(修复构建产物路径错误)\r\nexport * from './data/TriangleAdapterV3/validators';\r\n// 明确导出 ValidationManager 到主命名空间\r\nexport { ValidationManager } from './data/TriangleAdapterV3/validators';\r\n\r\n// 导出数据配置(选择性导出重要数据)\r\nexport * from './data/courseData';\r\nexport * from './data/userCourseProgress';\r\nexport * from './data/usergradeuintsnav';\r\nexport * from './data/usergradeunitsProgressData';\r\n\r\n// ==================== 服务层(选择性导出) ====================\r\n// 只导出稳定、通用的服务\r\n// 注:服务导出需要确保文件存在,如果不存在请注释掉\r\n// export { apiService } from './services/apiService';\r\n// export { authService } from './services/authService';\r\n\r\n// ==================== 不导出的内容说明 ====================\r\n// src/store - 状态管理内部实现,不导出\r\n// src/mocks - 测试模拟数据,不导出\r\n// src/test - 测试文件,不导出\r\n// src/stories - Storybook文档,不导出\r\n\r\n// 小数认识练习会话组件\r\nexport { DecimalNumberRecognitionSessionPage } from './components/MathCardV2';\r\nexport {\r\n useDecimalCurrentScene,\r\n useDecimalUserAnswer,\r\n useDecimalAnswerFormVisibility,\r\n useDecimalSessionActions\r\n} from './components/MathCardV2';\r\n\r\n// ==================== 几何与年龄问题会话页面 (纯容器组件) ====================\r\nexport { AreaGeometrySessionPage } from './pages/AreaGeometrySessionPage';\r\nexport type { AreaGeometrySessionPageProps, ProblemType } from './pages/AreaGeometrySessionPage'; // ProblemType已废弃\r\n\r\n// ==================== 几何问题数据适配器 (V4标准) ====================\r\n// 用于将 V4 格式的几何问题 JSON 数据转换为标准化格式\r\n// 支持三角形、梯形等几何形状的 V4 标准数据适配\r\nexport {\r\n // 同步适配器函数\r\n adaptGeometryDataSync,\r\n adaptGeometryDataAsync,\r\n adaptGeometryDataV4,\r\n adaptGeometryData,\r\n\r\n // 数据加载函数\r\n loadGeometryProblemDataSync,\r\n loadGeometryProblemDataAsync,\r\n loadGeometryProblemDataV4,\r\n loadGeometryProblemData,\r\n\r\n // 适配器工厂\r\n createSyncAdapter,\r\n createAsyncAdapter,\r\n createGeometryDataAdapter,\r\n\r\n // 验证工具\r\n validateGeometryData,\r\n benchmarkAdapter,\r\n\r\n // 版本信息\r\n VERSION,\r\n SCHEMA_VERSION,\r\n checkCompatibility,\r\n isV4Format,\r\n isGeometryProblem,\r\n\r\n // 默认导出\r\n default as GeometryProblemAdapterV4\r\n} from './data/GeometryProblemAdapterV4';\r\n\r\n// 导出类型定义\r\nexport type {\r\n GeometryProblemDataV4,\r\n SyncAdapterConfig,\r\n AdapterResult,\r\n AdapterError,\r\n AdapterWarning,\r\n AdapterErrorCode\r\n} from './data/GeometryProblemAdapterV4';"],"names":["REACT_ELEMENT_TYPE","REACT_FRAGMENT_TYPE","jsxProd","type","config","maybeKey","key","propName","reactJsxRuntime_production","getComponentNameFromType","REACT_CLIENT_REFERENCE","REACT_PROFILER_TYPE","REACT_STRICT_MODE_TYPE","REACT_SUSPENSE_TYPE","REACT_SUSPENSE_LIST_TYPE","REACT_ACTIVITY_TYPE","REACT_PORTAL_TYPE","REACT_CONTEXT_TYPE","REACT_CONSUMER_TYPE","REACT_FORWARD_REF_TYPE","innerType","REACT_MEMO_TYPE","REACT_LAZY_TYPE","testStringCoercion","value","checkKeyStringCoercion","JSCompiler_inline_result","JSCompiler_temp_const","JSCompiler_inline_result$jscomp$0","getTaskName","name","getOwner","dispatcher","ReactSharedInternals","UnknownOwner","hasValidKey","hasOwnProperty","getter","defineKeyPropWarningGetter","props","displayName","warnAboutAccessingKey","specialPropKeyWarningShown","elementRefGetterWithDeprecationWarning","componentName","didWarnAboutElementRef","ReactElement","owner","debugStack","debugTask","refProp","jsxDEVImpl","isStaticChildren","children","isArrayImpl","validateChildKeys","keys","didWarnAboutKeySpread","node","isValidElement","object","React","require$$0","createTask","callStackForError","unknownOwnerDebugStack","unknownOwnerDebugTask","reactJsxRuntime_development","trackActualOwner","jsxRuntimeModule","require$$1","Button","progress","variant","size","radius","className","loading","colorClass","buttonClasses","jsx","getButtonText","calculateLessonProgress","knowledgeItems","totalProgress","sum","item","KnowledgeCard","knowledgeItem","onLearnAction","handleLearnClick","jsxs","Card","CardBody","CardFooter","Progress","LessonItem","lesson","isExpanded","onToggle","handleToggle","lessonProgress","ChevronDown","ChevronRight","ContentAccordion","unit","activeLessonIds","onToggleLesson","emptyState","getProgressColor","status","Sidebar","data","error","collapsed","onToggleCollapse","activeUnitId","onUnitSelect","renderUnitItem","unitItemClassName","style","unitItemStyle","handleUnitSelect","unitId","event","handleToggleCollapse","renderDefaultUnitItem","e","renderContent","Fragment","Submenu","trigger","items","position","alignment","openDelay","closeDelay","onOpen","onClose","renderItem","itemConfig","menuClassName","itemClassName","isOpen","setIsOpen","openTimeoutRef","closeTimeoutRef","clearTimeouts","handleMouseEnter","handleMouseLeave","handleItemClick","defaultRenderItem","getPanelClasses","classes","bind","fn","thisArg","toString","getPrototypeOf","iterator","toStringTag","kindOf","cache","thing","str","kindOfTest","typeOfTest","isArray","isUndefined","isBuffer","val","isFunction","isArrayBuffer","isArrayBufferView","result","isString","isNumber","isObject","isBoolean","isPlainObject","prototype","isEmptyObject","isDate","isFile","isBlob","isFileList","isStream","isFormData","kind","isURLSearchParams","isReadableStream","isRequest","isResponse","isHeaders","trim","forEach","obj","allOwnKeys","i","l","len","findKey","_key","_global","isContextDefined","context","merge","caseless","skipUndefined","assignValue","targetKey","extend","a","b","stripBOM","content","inherits","constructor","superConstructor","descriptors","toFlatObject","sourceObj","destObj","filter","propFilter","prop","merged","endsWith","searchString","lastIndex","toArray","arr","isTypedArray","TypedArray","forEachEntry","_iterator","pair","matchAll","regExp","matches","isHTMLForm","toCamelCase","m","p1","p2","isRegExp","reduceDescriptors","reducer","reducedDescriptors","descriptor","ret","freezeMethods","toObjectSet","arrayOrString","delimiter","define","noop","toFiniteNumber","defaultValue","isSpecCompliantForm","toJSONObject","stack","visit","source","target","reducedValue","isAsyncFn","isThenable","_setImmediate","setImmediateSupported","postMessageSupported","token","callbacks","cb","asap","isIterable","utils$1","AxiosError","code","request","response","customProps","axiosError","message","utils","httpAdapter","isVisitable","removeBrackets","renderKey","path","dots","isFlatArray","predicates","toFormData","formData","options","option","metaTokens","visitor","defaultVisitor","indexes","useBlob","convertValue","el","index","exposedHelpers","build","encode","charMap","match","AxiosURLSearchParams","params","encoder","_encode","buildURL","url","_options","serializeFn","serializedParams","hashmarkIndex","InterceptorManager","fulfilled","rejected","id","h","transitionalDefaults","URLSearchParams$1","FormData$1","Blob$1","platform$1","URLSearchParams","FormData","Blob","hasBrowserEnv","_navigator","hasStandardBrowserEnv","hasStandardBrowserWebWorkerEnv","origin","platform","toURLEncodedForm","helpers","parsePropPath","arrayToObject","formDataToJSON","buildPath","isNumericKey","isLast","stringifySafely","rawValue","parser","defaults","headers","contentType","hasJSONContentType","isObjectPayload","_FormData","transitional","forcedJSONParsing","JSONRequested","strictJSONParsing","method","ignoreDuplicateOf","parseHeaders","rawHeaders","parsed","line","$internals","normalizeHeader","header","normalizeValue","parseTokens","tokens","tokensRE","isValidHeaderName","matchHeaderValue","isHeaderNameFilter","formatHeader","w","char","buildAccessors","accessorName","methodName","arg1","arg2","arg3","AxiosHeaders$1","valueOrRewrite","rewrite","self","setHeader","_value","_header","_rewrite","lHeader","setHeaders","dest","entry","matcher","deleted","deleteHeader","format","normalized","targets","asStrings","first","computed","accessors","defineAccessor","AxiosHeaders","mapped","headerValue","transformData","fns","isCancel","settle","resolve","reject","validateStatus","parseProtocol","speedometer","samplesCount","min","bytes","timestamps","head","tail","firstSampleTS","chunkLength","now","startedAt","bytesCount","passed","throttle","freq","timestamp","threshold","lastArgs","timer","invoke","args","progressEventReducer","listener","isDownloadStream","bytesNotified","_speedometer","loaded","total","progressBytes","rate","inRange","progressEventDecorator","throttled","lengthComputable","asyncDecorator","isURLSameOrigin","isMSIE","cookies","expires","domain","secure","sameSite","cookie","isAbsoluteURL","combineURLs","baseURL","relativeURL","buildFullPath","requestedURL","allowAbsoluteUrls","isRelativeUrl","headersToObject","mergeConfig","config1","config2","getMergedValue","mergeDeepProperties","valueFromConfig2","defaultToConfig2","mergeDirectKeys","mergeMap","configValue","resolveConfig","newConfig","withXSRFToken","xsrfHeaderName","xsrfCookieName","auth","formHeaders","allowedHeaders","xsrfValue","isXHRAdapterSupported","xhrAdapter","_config","requestData","requestHeaders","responseType","onUploadProgress","onDownloadProgress","onCanceled","uploadThrottled","downloadThrottled","flushUpload","flushDownload","done","onloadend","responseHeaders","err","msg","timeoutErrorMessage","cancel","CanceledError","protocol","composeSignals","signals","timeout","length","controller","aborted","onabort","reason","unsubscribe","signal","streamChunk","chunk","chunkSize","pos","end","readBytes","iterable","readStream","stream","reader","trackStream","onProgress","onFinish","_onFinish","loadedBytes","DEFAULT_CHUNK_SIZE","globalFetchAPI","Request","Response","ReadableStream","TextEncoder","test","factory","env","envFetch","isFetchSupported","isRequestSupported","isResponseSupported","isReadableStreamSupported","encodeText","supportsRequestStream","duplexAccessed","hasContentType","supportsResponseStream","resolvers","res","getBodyLength","body","resolveBodyLength","cancelToken","withCredentials","fetchOptions","_fetch","composedSignal","requestContentLength","_request","contentTypeHeader","flush","isCredentialsSupported","resolvedOptions","isStreamResponse","responseContentLength","responseData","seedCache","getFetch","fetch","seeds","seed","map","knownAdapters","fetchAdapter.getFetch","renderReason","isResolvedHandle","adapter","getAdapter","adapters","nameOrAdapter","rejectedReasons","reasons","state","s","throwIfCancellationRequested","dispatchRequest","VERSION","validators","deprecatedWarnings","validator","version","formatMessage","opt","desc","opts","correctSpelling","assertOptions","schema","allowUnknown","Axios$1","instanceConfig","configOrUrl","dummy","paramsSerializer","contextHeaders","requestInterceptorChain","synchronousRequestInterceptors","interceptor","responseInterceptorChain","promise","chain","onFulfilled","onRejected","fullPath","Axios","generateHTTPMethod","isForm","CancelToken$1","CancelToken","executor","resolvePromise","onfulfilled","_resolve","abort","c","spread","callback","isAxiosError","payload","HttpStatusCode","createInstance","defaultConfig","instance","axios","promises","all","Cancel","formToJSON","UserIcon","SettingsIcon","HelpIcon","LogoutIcon","DEFAULT_MENU_ITEMS","UserProfile","userId","initialUserName","initialUserAvatar","apiConfig","menuItems","avatarSize","isLoading","avatarClassName","userNameClassName","containerClassName","onMenuOpen","onMenuClose","onMenuItemClick","onLogout","renderMenuItem","renderUserInfo","userData","setUserData","setLoading","errorState","setErrorState","fetchUserData","endpoint","handleMenuItemClick","handleMenuOpen","handleMenuClose","renderDefaultUserInfo","Avatar","_renderDefaultMenuItem","defaultRenderExploreItem","_ExploreTrigger","MathWizHeader","logoHref","logoText","onLogoClick","exploreItems","exploreMenuOpen","onExploreMenuToggle","onExploreItemClick","renderExploreItem","userMenuItems","onUserMenuItemClick","headerClassName","logoClassName","exploreClassName","userProfileClassName","color","background","height","gradientFrom","gradientTo","gradientVia","logoColor","logoSize","exploreButtonVariant","exploreButtonColor","ariaLabel","ariaLabelledBy","restProps","preparedExploreItems","headerClassNames","logoClassNames","exploreButtonClassNames","headerStyles","prevProps","nextProps","EquationRender","parts","fontSize","displayMode","useEffect","sheet","renderedParts","useMemo","part","renderToString","RootElement","childrenArray","renderedPart","isSingleTransform","isCompositeTransform","createDefaultTransform","convertLegacyTransformConfig","legacyConfig","transform","oldConfig","_index","calculateCentroid","vertices","sumX","sumY","x","y","validateSingleTransformConfig","scaleConfig","compositeConfig","subConfig","validateGeometryConfig","base","shapes","globalTransformError","shape","newShapeTransform","shapeTransformError","vertex","newTransform","errorMessage","validateGeometry","validateAnimationConfig","animation","slider","validateBoardConfig","boardConfig","left","top","right","bottom","validateAllConfigs","geometryError","animationError","boardError","BaseTransformExecutor","fieldName","max","isValid","errors","warnings","xError","yError","calculateTranslation","directionVector","offsetX","offsetY","calculateRotation","center","cx","cy","angleRange","direction","currentAngle","dx","dy","cos","sin","calculateScale","scaleRange","currentScale","shouldAutoComplete","currentProgress","TranslationExecutor","directionError","distanceError","offsetError","startOffset","effectiveProgress","RotationExecutor","centerError","startAngleError","endAngleError","minX","maxX","minY","maxY","ScaleExecutor","startScaleError","endScaleError","scaleRatio","bounds","originalWidth","originalHeight","originalArea","scaleFactor","newWidth","newHeight","newArea","hexToRgb","hex","cleanHex","ch","r","g","rgbToHex","clamp","rHex","gHex","bHex","parseColor","trimmed","rgbMatch","colorMap","lowerColor","isValidColor","interpolateColor","from","to","fromRgb","toRgb","interpolateColorWithEasing","easing","easedProgress","FillColorSetExecutor","_progress","startAtError","endAtError","easingError","currentColor","fromColor","targetColor","startAt","endAt","TransformExecutorRegistry","validationResult","transforms","defaultRegistry","getDefaultRegistry","GroupMatcher","shapeMetadata","groupMatch","fallbackGroup","metadata","targetGroup","metadataField","groupId","pattern","strategy","caseSensitive","wildcardPattern","p","fields","field","filterTransformsByGroup","t","TransformCompositor","registry","filteredTransforms","transformError","ids","uniqueIds","types","groups","group","filterTransformsByGroupFn","transformedResults","transformed","vertexArrays","array","TransformPipeline","globalTransform","effectiveTransform","shapeGroup","useTransformProgress","debounceTimerRef","useRef","handleProgressChange","useCallback","newProgress","debounceMs","getProgressLabel","stages","percentage","resetProgress","useKeyboardNavigation","handleKeyDown","step","getNavigationInstructions","JXG","JSXGraph","GeometryTransform","layoutDensity","boardHeight","theme","enableRigidityVerification","enableKeyboardNavigation","autoCompleteThreshold","boardWidth","onTransformStart","onTransformChange","onTransformComplete","onError","setProgress","useState","setError","_currentStage","setCurrentStage","board","setBoard","containerSize","setContainerSize","transformPipeline","newTransformConfig","boardContainerRef","shapeElementsRef","outerContainerRef","handleProgressChangeDebounced","updateSize","clientWidth","bbox","bboxWidth","bboxHeight","calculatedHeight","resizeObserver","boardSizeStyle","computeDynamicAppearance","dynamicAppearance","baseStyle","transformColor","colorConfig","startColor","computeVisibilityValue","startValue","endValue","fadeProgress","resultStyle","visible","visibilityValue","labelVisibilityValue","labelVisible","opacity","opacityValue","rangeProgress","createShape","isStatic","minVertices","computedStyle","element","shouldShowLabel","labelText","radiusPoint","validationError","defaultBoundingBox","isDark","newBoard","axisColor","gridColor","jsxgraphError","renderError","convertedShape","transformedVertices","transformedShape","progressStages","newStage","handleSliderChange","progressValue","debouncedValue","handleGlobalKeyDown","handleRetry","Slider","MemoizedGeometryTransform","prevConfig","nextConfig","useHundredChartStore","create","set","get","startIndex","currentIndex","dragState","startRow","startCol","currentRow","currentCol","useHundredChartValue","useShallow","useHundredChartDrag","calculateFilledCells","totalCells","fillRatio","rows","cols","filledCount","filledCells","row","col","generateCellData","cellSize","cells","calculateDragRange","_rows","range","calculateValueFromDrag","dragRange","validateValue","formatPercentage","HundredChart","mode","onChange","fillColor","baseColor","strokeColor","shadingDirection","hasShadow","internalValue","setInternalValue","isDragging","startDrag","updateDrag","endDrag","isControlled","currentValue","initialized","setInitialized","cellData","handleCellClick","cellIndex","newValue","handleMouseDown","handleMouseUp","svgWidth","svgHeight","containerClasses","fillPercentage","cell","isFilled","isInDragRange","isActive","MathCardV2Context","useDataAdapter","scene","sceneData","CardLayout","padding","shadow","border","themeClass","shadowClass","borderClass","GridLayout","columns","gap","responsive","responsiveClass","FlowLayout","wrap","directionClass","wrapClass","TextContent","onInteraction","FormulaContent","MathGraphErrorBoundary","info","parseFunctionString","fnStr","cleanStr","arrowMatch","expression","createSafeMathFunction","expr","numberPattern","numberMatch","multiplier","piMultiplierPattern","piMultiplierMatch","constantPattern","constantMatch","evalExpr","evaluateExpression","cleanExpr","evaluate","innerValue","mdMatch","op","asMatch","isFunctionString","evalParamValue","param","getJSXGraphParams","control","xParam","yParam","scaleXParam","scaleYParam","shearX","shearY","resolveDynamicParams","rawParams","resolved","GraphContainer","containerRef","setShapeElements","shapesReady","setShapesReady","transformsRef","controlRef","sliderListenersRef","handleShapeChange","_shapeId","_newPosition","handleSelectionChange","shapeId","boundingBox","controlConfig","endX","allObjects","sliderInList","isUpdating","normalizedValue","glider","newTransforms","usesControl","triggerUpdate","controlValue","k","transformId","targetElements","newShapeElements","createShapeWithEvents","onShapeChange","onSelectionChange","isEditMode","point","startPoint","resolvePointRef","endPoint","centerPoint","circle","throughPoint","vertexConfig","resolvePointRefWithConfig","v","polygonConfig","jsxgraphVerticesConfig","labelConfig","hasLabelConfig","polygon","ref","referencedPoint","coords","calculateBoundingBox","margin","minSize","allPoints","resolvePoint","textWidth","textHeight","centerX","centerY","width","canvasAspectRatio","currentRatio","paddedWidth","paddedHeight","finalBoundingBox","outsidePoints","debugBoundingBox","label","MathGraph","showGrid","showAxis","autoBoundingBox","boundingBoxOptions","animationProgress","onAnimationChange","_showAnimationControls","calculatedBoundingBox","containerStyle","GraphContent","showAnimationControls","clientHeight","GeometryTransformContent","effectiveLayoutDensity","effectiveBoardHeight","effectiveBoardWidth","handleTransformChange","handleTransformComplete","handleError","PlaceValueChart","values","colors","headerBg","valueBg","borderColor","ContentRenderer","renderContentBlock","block","contentId","handleInteraction","interaction","formulaBlock","graphBlock","hundredGridBlock","placeValueChartBlock","geometryTransformBlock","MathCardV2","layout","renderer","onContentInteraction","adaptedData","contextValue","currentLayout","LayoutComponent","layoutProps","baseProps","useIXLStyle","ixlConfig","enableIXLStyle","isMobile","tagText","tagColor","defaultColors","tagTextColor","tagStyle","contentStyle","debounce","func","wait","useResponsive","breakpoint","enabled","viewportWidth","setViewportWidth","setIsMobile","listenersRef","updateViewport","newIsMobile","debouncedUpdateViewport","addResizeListener","removeResizeListener","IXLStyleCard","cardProps","wrapperMode","mobileBreakpoint","onResponsiveChange","ixlStyle","mathCardClassName","DEFAULT_IXL_CONFIG","IXL_COLORS","IXL_LABELS","GradeNavigation","grades","onGradeSelect","selectedGrade","grade","RadarChart","abilities","calculateRadarPoints","ability","angle","calculateAxisEndPoints","x2","y2","calculateLabelPosition","textAnchor","_","mockRadarAbilityData","RadarAbilityService","feedback","useRadarAbilityStore","radarData","AbilityProgressBar","PersonalizedAdvicePanel","generalRecommendation","RecommendationCard","customLinkTexts","getLinkText","abilityName","defaultLinkTexts","ArrowRight","AbilityAssessmentDashboard","fetchData","styles","categoryIcons","statusMapping","statusColors","MOCK_USER_DATA","MOCK_EXPLORE_ITEMS","MOCK_JWT_TOKEN","courseData","CourseService","courseId","gradeId","progressUpdates","lessonId","courseService","DataSourceError","originalError","ApiDataSource","operation","lastError","attempt","ms","MockDataSource","update","lessonsData","DataSourceFactory","customDataSourceClass","instanceKey","dataSource","isBrowser","isDevelopment","isTest","useMock","createDefaultDataSource","createGradeUnitBrowserConfig","fallbackStrategy","errorHandling","performance","debug","enableDevTools","mergeConfigs","baseConfig","overrideConfig","GradeUnitBrowserContext","createContext","useGradeUnitBrowser","useContext","GradeUnitBrowserProvider","providedConfig","setConfig","userInfo","setUserInfo","exploreMenu","setExploreMenu","unitsData","setUnitsData","lessons","setLessons","setActiveUnitId","setActiveLessonIds","loadPageData","userProfile","exploreMenuData","mockUnitsData","toggleLesson","prev","setActiveUnit","updateConfig","updates","activeUnit","defaultActiveUnit","GradeUnitBrowserPageContent","propUserInfo","propExploreMenu","contextUserInfo","contextExploreMenu","activeUnitNav","debugActiveUnit","GradeUnitBrowserPage","validateAnswer","userAnswer","correctAnswer","tolerance","userAnswerNum","isCorrect","createMathPracticeStore","problemData","answer","correctAnswerNum","useMathPracticeSessionStore","useCurrentScene","useUserAnswer","useAnswerCorrectness","useAnswerFormVisibility","useValidationError","useProblemData","useSessionActions","MathPracticeStoreContext","useMathPracticeStore","store","useCurrentSceneFromStore","selector","useUserAnswerFromStore","useAnswerFormVisibilityFromStore","useValidationErrorFromStore","useSessionActionsFromStore","useGlobalCurrentScene","useGlobalUserAnswer","useGlobalAnswerFormVisibility","useGlobalValidationError","useGlobalSessionActions","QuestionScene","showAnswerForm","onAnswerSubmit","onAnswerChange","handleSubmit","handleAnswerChange","RememberModule","reviewContent","reviewItems","rememberItems","rememberContent","emptyContent","contentArea","contentBlock","ReviewModule","getStepStyle","ExplanationStep","stepNumber","title","description","chartConfig","hasChartConfig","styleVars","descriptionContent","isExplanationObject","explanation","normalizeExplanation","firstStep","steps","SolveModule","showDetailedSteps","setShowDetailedSteps","solveContent","hasSolve","normalizedExplanation","hasExplanations","adaptedExplanationSteps","ExplanationScene","onNextQuestion","SuccessScene","AdapterErrorCode","DEFAULT_SYNC_ADAPTER_CONFIG","ReferenceType","AdapterError","details","DEFAULT_FALLBACK_DATA","ERROR_MESSAGES","PERFORMANCE_THRESHOLDS","REQUIRED_FIELDS","SCENE_NAMES","REFERENCE_PATTERNS","CONTENT_BLOCK_TYPES","EMBEDDED_DESIGN_TOKENS","EMBEDDED_STYLE_PRESETS","EMBEDDED_GEOMETRY_PRESETS","EMBEDDED_LAYOUT_PRESETS","EMBEDDED_TRANSFORM_DEFINITIONS","EMBEDDED_ANIMATION_DEFINITIONS","EMBEDDED_BOARD_DEFINITIONS","GLOBAL_REFERENCE_CONTEXT","getDefaultReferenceContext","sliderDefinitions","DesignTokenResolver","current","refs","results","traverse","onMissing","replace","tokenRegex","createDesignTokenResolver","GeometryRefResolver","geometryName","refName","geometry","geometryCopy","createGeometryRefResolver","TransformRefResolver","transformName","defaultTransforms","ox","oy","rad","factor","createTransformRefResolver","StyleRefResolver","styleName","stylePreset","resolvedStyle","createStyleRefResolver","LayoutRefResolver","layoutName","layoutPreset","defaultLayouts","resolvedLayout","sceneConfig","scenes","createLayoutRefResolver","AnimationRefResolver","animationConfigId","rawConfig","animationId","_context","shapeIndex","resolvedParams","resolvedConfig","validation","createAnimationRefResolver","SliderRefResolver","sliderConfigId","DEFAULT_SLIDER_CONFIG","sliderId","requiredFields","createSliderRefResolver","GeometryTransformRefResolver","override","configId","overrides","blocks","createGeometryTransformRefResolver","REFERENCE_FIELD_MAP","ReferenceExtractor","seen","combined","regex","fieldCounts","countFields","ResolverRegistry","resolver","eligibleResolvers","createDefaultResolverRegistry","GraphTransformer","enableReferenceResolution","strictMode","refWithPrefix","animationConfig","originalType","originalContent","beforeMerge","geometryType","hasRequiredGeometry","originalGeometry","pointDefinition","styleId","styleWithoutId","pointRef","processedShape","resolvedPosition","verticesConfig","resolvedVertex","unifiedConfig","mergedConfig","resolvedEndpoint","resolvedCenter","resolvedStart","resolvedEnd","transformedTransform","transformDef","transformedLabel","boardRef","fallbackConfigs","contentBlocks","createGraphTransformer","GeometryTransformTransformer","sliderConfig","configOptions","transformedConfig","geometryRefToShapeId","resolvedTransform","transformItem","enhancedContext","configWithoutType","originalTargetGroup","mappedShapeId","matchingRef","refParts","targetParts","transformedGeometry","resolvedGeometry","transformedStyle","animationRef","fallbackConfig","fallbackPresets","createGeometryTransformTransformer","TextTransformer","text","tokenRegex2","fullMatch","createTextTransformer","createFormulaTransformer","TransformerRegistry","transformer","sceneContent","transformedContent","transformedLayout","layoutRefString","layoutRef","otherProps","transformedScenes","sceneName","createDefaultTransformerRegistry","InputValidator","input","skipOptionalFields","requiredScenes","sceneObj","basicInfo","answerInfo","criticalFields","removeInvalidFields","cleanedData","OutputValidator","output","checkSceneContent","contentItems","ValidationManager","inputStrictMode","outputStrictMode","inputResult","outputResult","allErrors","allWarnings","overall","warning","ReferenceUtils","categorized","resolverRegistry","maxDepth","RESERVED_REF_FIELDS","depth","parentKey","stats","PerformanceMonitor","mark","endTime","duration","memoryEnd","count","CommonUtils","aKeys","bKeys","pathArray","arrayMatch","nextArrayMatch","lastKey","lastArrayMatch","prefix","delay","lastCall","timeoutId","decimals","dm","sizes","visited","calculate","SyncAdapterCore","inputData","inputValidation","baseData","resolvedData","transformedData","outputValidation","processedTransform","pointId","sceneItems","transformedSteps","chartConfigType","transformedBlock","transformedChartConfig","rest","allRefs","outputData","meta","performanceStats","performanceCheck","refSource","referenceStats","fallbackData","GeometryAdapterCore","rawData","cloned","validationResults","adaptGeometryDataSync","adaptGeometryDataAsync","loadGeometryProblemDataSync","loadGeometryProblemDataAsync","createSyncAdapter","createAsyncAdapter","syncAdapter","validateGeometryData","benchmarkAdapter","testData","iterations","times","start","averageTime","time","minTime","maxTime","memoryUsage","geometryAdapterV4","SCHEMA_VERSION","checkCompatibility","expectedVersion","isV4Format","isGeometryProblem","ConfigGenerationError","shapeType","innerError","validateGeometryTransformConfig","fixes","createValidationError","generateFixSuggestions","validateShapes","hasShapeSpecificTransform","validateTransform","validateStrategyMatch","validateUnitConsistency","validateGeometryConsistency","isValidTransformConfig","scaleCenter","subTransform","validTransformTypes","subErrors","suggestedValue","finalSuggestedValue","shapeErrors","validateSingleShape","transformErrors","basePath","currentTransform","currentPath","transformCount","reasonableSize","allShapes","j","expectedArea","x1","y1","x3","y3","calculatedArea","generateParallelogramConfig","isValidParallelogramConfigOptions","originX","originY","skew","generateParallelogramShapes","generateTranslationTransform","generateAnimationConfig","generateBoardConfig","trapezoidVertices","triangleVertices","getBaseFieldMappings","jsonData","getBasicInfoFields","createDefaultAnswerInfo","createAnswerFromAnswerInfo","getCompatibleAnswer","getDefaultParallelogramScenes","getDefaultParallelogramExplanation","normalizeParallelogramExplanation","adaptParallelogramData","baseFields","basicInfoFields","defaultKnowledgePoints","enrichScenesWithGeometryTransform","hasValidJsonConfig","convertParallelogramJsonConfigToSystemFormat","jsonConfig","getTransformType","getTranslationDistance","getTranslationDirection","converted","staticShapes","animatedShapes","trapezoid","triangle","keyLower","transformType","problemType","enrichedContent","dynamicConfig","dynamicBase","dynamicHeight","DEFAULT_ADAPTER_CONFIG","loadAcuteTriangleV2Data","triangleAreaJson","loadTriangleProblemData","loadParallelogramProblemData","parallelogramAreaJson","getDefaultParallelogramProblemData","ParallelogramAreaCalculationSessionPage","externalProblemData","currentScene","updateUserAnswer","submitAnswer","nextQuestion","setProblemData","internalProblemData","setInternalProblemData","externalProblemDataMemo","TriangleAreaCalculationSessionPage","MathCardContext","useMathCardContext","parseTemplate","template","renderContentBlocks","parseTemplateWithFormulas","formulaRegex","matchStart","matchEnd","textContent","cleanFormula","remainingText","renderTemplateWithFormulas","parsedTemplate","renderExplanationStep","isComplexFormula","renderReviewStep","parsedContent","renderExplanationSteps","renderReviewSteps","Banner","bgColor","hidden","sceneTexts","getBannerStyle","sceneColors","Question","question","questionStyle","AnswerInput","placeholder","inputStyle","optionsStyle","getOptionStyle","isSelected","handleOptionClick","optionId","handleInputChange","SubmitButton","onClick","disabled","buttonStyle","Explanation","titleStyle","stepsStyle","stepStyle","stepElement","ReviewContent","templateStyle","LoadingState","skeletonStyle","skeletonLineStyle","spinnerStyle","spinnerElementStyle","ErrorState","onRetry","errorStyle","errorMessageStyle","retryButtonStyle","Divider","orientation","dividerStyle","sizeMap","DefaultLayout","onSubmit","onNext","submissionResult","handleNext","cardStyle","buttonContainerStyle","MathCard","onErrorRetry","onHintToggle","sheetForTag","tag","createStyleElement","StyleSheet","_this","before","_proto","nodes","rule","_tag$parentNode","MS","MOZ","WEBKIT","COMMENT","RULESET","DECLARATION","IMPORT","KEYFRAMES","LAYER","abs","assign","hash","charat","replacement","indexof","search","substr","begin","strlen","sizeof","append","combine","column","character","characters","root","parent","copy","next","peek","caret","slice","alloc","dealloc","delimit","whitespace","escaping","commenter","identifier","compile","parse","rules","rulesets","pseudo","points","declarations","offset","atrule","property","previous","variable","scanning","ampersand","reference","comment","declaration","ruleset","post","z","serialize","stringify","middleware","collection","rulesheet","memoize","arg","identifierWithPointTracking","toRules","getRules","fixedElements","compat","isImplicitRule","parentRules","removeLabel","prefixer","defaultStylisPlugins","createCache","ssrStyles","dataEmotionAttribute","stylisPlugins","inserted","container","nodesToHydrate","attrib","_insert","omnipresentPlugins","currentSheet","finalizingPlugins","serializer","stylis","serialized","shouldCache","d","f","n","q","u","A","reactIs_production_min","hasSymbol","REACT_PROVIDER_TYPE","REACT_ASYNC_MODE_TYPE","REACT_CONCURRENT_MODE_TYPE","REACT_BLOCK_TYPE","REACT_FUNDAMENTAL_TYPE","REACT_RESPONDER_TYPE","REACT_SCOPE_TYPE","isValidElementType","typeOf","$$typeof","$$typeofType","AsyncMode","ConcurrentMode","ContextConsumer","ContextProvider","Element","ForwardRef","Lazy","Memo","Portal","Profiler","StrictMode","Suspense","hasWarnedAboutDeprecatedIsAsyncMode","isAsyncMode","isConcurrentMode","isContextConsumer","isContextProvider","isElement","isForwardRef","isFragment","isLazy","isMemo","isPortal","isProfiler","isStrictMode","isSuspense","reactIs_development","reactIsModule","reactIs","REACT_STATICS","KNOWN_STATICS","FORWARD_REF_STATICS","MEMO_STATICS","TYPE_STATICS","getStatics","component","defineProperty","getOwnPropertyNames","getOwnPropertySymbols","getOwnPropertyDescriptor","objectPrototype","hoistNonReactStatics","targetComponent","sourceComponent","blacklist","inheritedComponent","targetStatics","sourceStatics","hoistNonReactStatics_cjs","getRegisteredStyles","registered","registeredStyles","classNames","rawClassName","registerStyles","isStringTag","insertStyles","murmur2","unitlessKeys","hyphenateRegex","animationRegex","isCustomProperty","isProcessableValue","processStyleName","processStyleValue","cursor","unitless","handleInterpolation","mergedProps","interpolation","componentSelector","keyframes","serializedStyles","createStringFromObject","previousCursor","asString","string","_i","interpolated","labelPattern","serializeStyles","stringMode","strings","asTemplateStringsArr","templateStringsArr","identifierName","hashString","syncFallback","useInsertionEffect","useInsertionEffectAlwaysWithSyncFallback","EmotionCacheContext","withEmotionCache","forwardRef","ThemeContext","hasOwn","typePropName","createEmotionProps","newProps","Insertion","_ref","Emotion","cssProp","WrappedComponent","_key2","Emotion$1","argsLength","createElementArgArray","_jsx","JSX","css","_len","API_BASE_URL","DEFAULT_QUESTION_COUNT","INITIAL_SCENE","useSessionStore","devtools","sessionId","gradeLevel","questions","geometryShapes","currentProblemIndex","problems","problemId","currentProblem","newPosition","updatedShapes","_problemId","startTime","elapsed","totalProblems","submissionResults","timeSpent","answers","correctAnswers","useSessionCalculations","currentProblemId","canNavigate","canGoNext","canGoPrevious","shouldRenderMathGraph","useGeometryManagement","geometryMode","selectShape","setGeometryMode","currentGeometryShapes","newMode","selectedIds","selectedId","useSessionEventHandlers","userAnswers","goToNextProblem","goToPreviousProblem","goToProblem","onProblemChange","handlePrevious","handlePagination","page","MathSessionContainer","onSessionComplete","onSessionExit","sessionComplete","getSessionResults","formatErrorMessage","Pagination","MathSessionPage","pageState","setPageState","retryCount","setRetryCount","announcement","setAnnouncement","mainContentRef","loadingRef","errorRef","loadQuestions","reset","initializeSession","handleSessionComplete","handleSessionExit","handleProblemChange","MathSessionPage_default","DecimalNumberExplanationScene","MathPracticeSessionPage","normalizeProblemData","sceneType","stableProblemData","areaProblemData","useDecimalNumberRecognitionSessionStore","normalizedAnswer","normalizedCorrect","useDecimalCurrentScene","useDecimalUserAnswer","useDecimalAnswerFormVisibility","useDecimalValidationError","useDecimalSessionActions","decimalNumberRecognitionData","DecimalNumberRecognitionSessionPage","pointOnLine","ratio","calculateGamePoints","B","C","D","E","M","N","P","Q","U","S","K","L","toPixelCoordinates","normalizedPoints","pixelPoints","isPointInTriangle","p3","denominator","trianglesMatch","triangle1","triangle2","names1","names2","comparePointArrays","points1","points2","getBasicLineDefinitions","getBasicGemDefinitions","GEOMETRY_CONFIG","generateMockUserCourseProgress","unitsProgress","baseProgress","completedLessons","lessonsProgress","lessonIndex","completedUnits","MOCK_USER_COURSE_PROGRESS","getUserCourseProgress","getUserUnitProgress","courseProgress","getUserLessonProgress","unitProgress","updateUserLessonProgress","getUserGradeUnitsNav","userProgress","unitsNav","up","getUnitNavItem","navData","updateUnitActiveStatus","MOCK_USER_GRADE_UNITS_NAV","MOCK_USER_GRADE_UNITS_PROGRESS","AreaGeometrySessionPage","pageStyle"],"mappings":"+tBAWA,IAAIA,EAAqB,OAAO,IAAI,4BAA4B,EAC9DC,EAAsB,OAAO,IAAI,gBAAgB,EACnD,SAASC,EAAQC,EAAMC,EAAQC,EAAU,CACvC,IAAIC,EAAM,KAGV,GAFWD,IAAX,SAAwBC,EAAM,GAAKD,GACxBD,EAAO,MAAlB,SAA0BE,EAAM,GAAKF,EAAO,KACxC,QAASA,EAAQ,CACnBC,EAAW,CAAA,EACX,QAASE,KAAYH,EACTG,IAAV,QAAuBF,EAASE,CAAQ,EAAIH,EAAOG,CAAQ,EACjE,MAASF,EAAWD,EAClB,OAAAA,EAASC,EAAS,IACX,CACL,SAAUL,EACV,KAAMG,EACN,IAAKG,EACL,IAAgBF,IAAX,OAAoBA,EAAS,KAClC,MAAOC,EAEX,CACA,OAAAG,GAAA,SAAmBP,EACnBO,GAAA,IAAcN,EACdM,GAAA,KAAeN,qDCtBE,QAAQ,IAAI,WAA7B,eACG,UAAY,CACX,SAASO,EAAyBN,EAAM,CACtC,GAAYA,GAAR,KAAc,OAAO,KACzB,GAAmB,OAAOA,GAAtB,WACF,OAAOA,EAAK,WAAaO,EACrB,KACAP,EAAK,aAAeA,EAAK,MAAQ,KACvC,GAAiB,OAAOA,GAApB,SAA0B,OAAOA,EACrC,OAAQA,EAAI,CACV,KAAKF,EACH,MAAO,WACT,KAAKU,EACH,MAAO,WACT,KAAKC,EACH,MAAO,aACT,KAAKC,EACH,MAAO,WACT,KAAKC,EACH,MAAO,eACT,KAAKC,EACH,MAAO,UACjB,CACM,GAAiB,OAAOZ,GAApB,SACF,OACgB,OAAOA,EAAK,KAAzB,UACC,QAAQ,MACN,qHAEJA,EAAK,SACf,CACU,KAAKa,EACH,MAAO,SACT,KAAKC,EACH,OAAOd,EAAK,aAAe,UAC7B,KAAKe,EACH,OAAQf,EAAK,SAAS,aAAe,WAAa,YACpD,KAAKgB,EACH,IAAIC,EAAYjB,EAAK,OACrB,OAAAA,EAAOA,EAAK,YACZA,IACIA,EAAOiB,EAAU,aAAeA,EAAU,MAAQ,GACnDjB,EAAcA,IAAP,GAAc,cAAgBA,EAAO,IAAM,cAC9CA,EACT,KAAKkB,EACH,OACGD,EAAYjB,EAAK,aAAe,KACxBiB,IAAT,KACIA,EACAX,EAAyBN,EAAK,IAAI,GAAK,OAE/C,KAAKmB,EACHF,EAAYjB,EAAK,SACjBA,EAAOA,EAAK,MACZ,GAAI,CACF,OAAOM,EAAyBN,EAAKiB,CAAS,CAAC,CAC7D,MAAwB,CAAA,CACxB,CACM,OAAO,IACb,CACI,SAASG,EAAmBC,EAAO,CACjC,MAAO,GAAKA,CAClB,CACI,SAASC,EAAuBD,EAAO,CACrC,GAAI,CACFD,EAAmBC,CAAK,EACxB,IAAIE,EAA2B,EACvC,MAAkB,CACVA,EAA2B,EACnC,CACM,GAAIA,EAA0B,CAC5BA,EAA2B,QAC3B,IAAIC,EAAwBD,EAAyB,MACjDE,GACc,OAAO,QAAtB,YACC,OAAO,aACPJ,EAAM,OAAO,WAAW,GAC1BA,EAAM,YAAY,MAClB,SACF,OAAAG,EAAsB,KACpBD,EACA,2GACAE,IAEKL,EAAmBC,CAAK,CACvC,CACA,CACI,SAASK,EAAY1B,EAAM,CACzB,GAAIA,IAASF,EAAqB,MAAO,KACzC,GACe,OAAOE,GAApB,UACSA,IAAT,MACAA,EAAK,WAAamB,EAElB,MAAO,QACT,GAAI,CACF,IAAIQ,EAAOrB,EAAyBN,CAAI,EACxC,OAAO2B,EAAO,IAAMA,EAAO,IAAM,OACzC,MAAkB,CACV,MAAO,OACf,CACA,CACI,SAASC,GAAW,CAClB,IAAIC,EAAaC,EAAqB,EACtC,OAAgBD,IAAT,KAAsB,KAAOA,EAAW,SAAQ,CAC7D,CACI,SAASE,GAAe,CACtB,OAAO,MAAM,uBAAuB,CAC1C,CACI,SAASC,EAAY/B,EAAQ,CAC3B,GAAIgC,EAAe,KAAKhC,EAAQ,KAAK,EAAG,CACtC,IAAIiC,EAAS,OAAO,yBAAyBjC,EAAQ,KAAK,EAAE,IAC5D,GAAIiC,GAAUA,EAAO,eAAgB,MAAO,EACpD,CACM,OAAkBjC,EAAO,MAAlB,MACb,CACI,SAASkC,EAA2BC,EAAOC,EAAa,CACtD,SAASC,GAAwB,CAC/BC,IACIA,EAA6B,GAC/B,QAAQ,MACN,0OACAF,CACZ,EACA,CACMC,EAAsB,eAAiB,GACvC,OAAO,eAAeF,EAAO,MAAO,CAClC,IAAKE,EACL,aAAc,EACtB,CAAO,CACP,CACI,SAASE,GAAyC,CAChD,IAAIC,EAAgBnC,EAAyB,KAAK,IAAI,EACtD,OAAAoC,GAAuBD,CAAa,IAChCC,GAAuBD,CAAa,EAAI,GAC1C,QAAQ,MACN,6IACV,GACMA,EAAgB,KAAK,MAAM,IACTA,IAAX,OAA2BA,EAAgB,IACxD,CACI,SAASE,EAAa3C,EAAMG,EAAKiC,EAAOQ,GAAOC,GAAYC,GAAW,CACpE,IAAIC,GAAUX,EAAM,IACpB,OAAApC,EAAO,CACL,SAAUH,EACV,KAAMG,EACN,IAAKG,EACL,MAAOiC,EACP,OAAQQ,KAEWG,KAAX,OAAqBA,GAAU,QAAzC,KACI,OAAO,eAAe/C,EAAM,MAAO,CACjC,WAAY,GACZ,IAAKwC,EACN,EACD,OAAO,eAAexC,EAAM,MAAO,CAAE,WAAY,GAAI,MAAO,KAAM,EACtEA,EAAK,OAAS,CAAA,EACd,OAAO,eAAeA,EAAK,OAAQ,YAAa,CAC9C,aAAc,GACd,WAAY,GACZ,SAAU,GACV,MAAO,CACf,CAAO,EACD,OAAO,eAAeA,EAAM,aAAc,CACxC,aAAc,GACd,WAAY,GACZ,SAAU,GACV,MAAO,IACf,CAAO,EACD,OAAO,eAAeA,EAAM,cAAe,CACzC,aAAc,GACd,WAAY,GACZ,SAAU,GACV,MAAO6C,EACf,CAAO,EACD,OAAO,eAAe7C,EAAM,aAAc,CACxC,aAAc,GACd,WAAY,GACZ,SAAU,GACV,MAAO8C,EACf,CAAO,EACD,OAAO,SAAW,OAAO,OAAO9C,EAAK,KAAK,EAAG,OAAO,OAAOA,CAAI,GACxDA,CACb,CACI,SAASgD,EACPhD,EACAC,EACAC,EACA+C,GACAJ,GACAC,GACA,CACA,IAAII,GAAWjD,EAAO,SACtB,GAAeiD,KAAX,OACF,GAAID,GACF,GAAIE,EAAYD,EAAQ,EAAG,CACzB,IACED,GAAmB,EACnBA,GAAmBC,GAAS,OAC5BD,KAEAG,EAAkBF,GAASD,EAAgB,CAAC,EAC9C,OAAO,QAAU,OAAO,OAAOC,EAAQ,CACnD,MACY,QAAQ,MACN,6JAEDE,EAAkBF,EAAQ,EACjC,GAAIjB,EAAe,KAAKhC,EAAQ,KAAK,EAAG,CACtCiD,GAAW5C,EAAyBN,CAAI,EACxC,IAAIqD,GAAO,OAAO,KAAKpD,CAAM,EAAE,OAAO,SAAU,EAAG,CACjD,OAAiB,IAAV,KACjB,CAAS,EACDgD,GACE,EAAII,GAAK,OACL,kBAAoBA,GAAK,KAAK,SAAS,EAAI,SAC3C,iBACNC,GAAsBJ,GAAWD,EAAgB,IAC7CI,GACA,EAAIA,GAAK,OAAS,IAAMA,GAAK,KAAK,SAAS,EAAI,SAAW,KAC5D,QAAQ,MACN;AAAA;AAAA;AAAA;AAAA;AAAA,mCACAJ,GACAC,GACAG,GACAH,IAEDI,GAAsBJ,GAAWD,EAAgB,EAAI,GAChE,CAMM,GALAC,GAAW,KACAhD,IAAX,SACGoB,EAAuBpB,CAAQ,EAAIgD,GAAW,GAAKhD,GACtD8B,EAAY/B,CAAM,IACfqB,EAAuBrB,EAAO,GAAG,EAAIiD,GAAW,GAAKjD,EAAO,KAC3D,QAASA,EAAQ,CACnBC,EAAW,CAAA,EACX,QAASE,MAAYH,EACTG,KAAV,QAAuBF,EAASE,EAAQ,EAAIH,EAAOG,EAAQ,EACrE,MAAaF,EAAWD,EAClB,OAAAiD,IACEf,EACEjC,EACe,OAAOF,GAAtB,WACIA,EAAK,aAAeA,EAAK,MAAQ,UACjCA,GAED2C,EACL3C,EACAkD,GACAhD,EACA0B,EAAQ,EACRiB,GACAC,GAER,CACI,SAASM,EAAkBG,EAAM,CAC/BC,EAAeD,CAAI,EACfA,EAAK,SAAWA,EAAK,OAAO,UAAY,GAC3B,OAAOA,GAApB,UACSA,IAAT,MACAA,EAAK,WAAapC,IACDoC,EAAK,SAAS,SAA9B,YACGC,EAAeD,EAAK,SAAS,KAAK,GAClCA,EAAK,SAAS,MAAM,SACnBA,EAAK,SAAS,MAAM,OAAO,UAAY,GACxCA,EAAK,SAAWA,EAAK,OAAO,UAAY,GACtD,CACI,SAASC,EAAeC,EAAQ,CAC9B,OACe,OAAOA,GAApB,UACSA,IAAT,MACAA,EAAO,WAAa5D,CAE5B,CACI,IAAI6D,EAAQC,EACV9D,EAAqB,OAAO,IAAI,4BAA4B,EAC5DgB,EAAoB,OAAO,IAAI,cAAc,EAC7Cf,EAAsB,OAAO,IAAI,gBAAgB,EACjDW,EAAyB,OAAO,IAAI,mBAAmB,EACvDD,EAAsB,OAAO,IAAI,gBAAgB,EACjDO,EAAsB,OAAO,IAAI,gBAAgB,EACjDD,EAAqB,OAAO,IAAI,eAAe,EAC/CE,EAAyB,OAAO,IAAI,mBAAmB,EACvDN,EAAsB,OAAO,IAAI,gBAAgB,EACjDC,EAA2B,OAAO,IAAI,qBAAqB,EAC3DO,EAAkB,OAAO,IAAI,YAAY,EACzCC,EAAkB,OAAO,IAAI,YAAY,EACzCP,EAAsB,OAAO,IAAI,gBAAgB,EACjDL,EAAyB,OAAO,IAAI,wBAAwB,EAC5DuB,EACE4B,EAAM,gEACRzB,EAAiB,OAAO,UAAU,eAClCkB,EAAc,MAAM,QACpBS,EAAa,QAAQ,WACjB,QAAQ,WACR,UAAY,CACV,OAAO,IACnB,EACIF,EAAQ,CACN,yBAA0B,SAAUG,EAAmB,CACrD,OAAOA,EAAiB,CAChC,GAEI,IAAItB,EACAG,GAAyB,CAAA,EACzBoB,GAAyBJ,EAAM,yBAAyB,KAC1DA,EACA3B,CACN,EAAK,EACGgC,EAAwBH,EAAWlC,EAAYK,CAAY,CAAC,EAC5DuB,GAAwB,CAAA,EAC5BU,GAAA,SAAmBlE,EACnBkE,GAAA,IAAc,SAAUhE,EAAMC,EAAQC,EAAU,CAC9C,IAAI+D,GACF,IAAMnC,EAAqB,6BAC7B,OAAOkB,EACLhD,EACAC,EACAC,EACA,GACA+D,GACI,MAAM,uBAAuB,EAC7BH,GACJG,GAAmBL,EAAWlC,EAAY1B,CAAI,CAAC,EAAI+D,EAE3D,EACIC,GAAA,KAAe,SAAUhE,EAAMC,EAAQC,EAAU,CAC/C,IAAI+D,GACF,IAAMnC,EAAqB,6BAC7B,OAAOkB,EACLhD,EACAC,EACAC,EACA,GACA+D,GACI,MAAM,uBAAuB,EAC7BH,GACJG,GAAmBL,EAAWlC,EAAY1B,CAAI,CAAC,EAAI+D,EAE3D,CACA,GAAG,4CC7VC,QAAQ,IAAI,WAAa,aAC3BG,GAAA,QAAiBP,GAAA,EAEjBO,GAAA,QAAiBC,GAAA,yBCDZ,MAAMC,GAAgC,CAAC,CAC5C,SAAAC,EACA,QAAAC,EAAU,QACV,KAAAC,EAAO,KACP,OAAAC,EAAS,KACT,SAAAtB,EACA,UAAAuB,EAAY,GACZ,QAAAC,EACA,GAAGtC,CACL,IAAM,CAQJ,MAAMuC,EAAaN,IAAa,QANTA,GACjBA,IAAa,EAAU,kBACvBA,IAAa,IAAY,kBACtB,qBAGiDA,CAAQ,EAAI,kBAEhEO,EAAgB,CACpB,SACA,WAAWL,CAAI,GACf,WAAWD,CAAO,GAClB,kBAAkBE,CAAM,GACxBG,EACAD,GAAW,kBACXD,CAAA,EACA,OAAO,OAAO,EAAE,KAAK,GAAG,EAE1B,OACEI,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,UAAWD,EACX,gBAAeP,EACf,SAAUK,GAAWtC,EAAM,SAC1B,GAAGA,EAEH,WAAU,SAAWc,CAAA,CAAA,CAG5B,ECMa4B,GAAkCT,GACzCA,IAAa,EAAU,OACvBA,IAAa,IAAY,KACtB,OAIIU,GAAsDC,GAA4C,CAC7G,GAAIA,EAAe,SAAW,EAAG,MAAO,GACxC,MAAMC,EAAgBD,EAAe,OAAO,CAACE,EAAKC,IAASD,EAAMC,EAAK,SAAU,CAAC,EACjF,OAAO,KAAK,MAAMF,EAAgBD,EAAe,MAAM,CACzD,ECpDMI,GAA8C,CAAC,CAAE,cAAAC,EAAe,cAAAC,KAAoB,CACxF,MAAMC,EAAmB,IAAM,CAC7BD,EAAcD,CAAa,CAC7B,EAGA,eAAQ,IAAI,wBAAyB,CACnC,SAAUA,EAAc,SACxB,KAAMP,GAAcO,EAAc,QAAQ,CAAA,CAC3C,EAGCG,EAAAA,KAACC,GAAAA,KAAA,CAAK,UAAU,oCACd,SAAA,CAAAD,OAACE,GAAAA,SAAA,CACC,SAAA,CAAAb,EAAAA,IAAC,KAAA,CAAG,UAAU,qCAAsC,SAAAQ,EAAc,MAAM,EACxER,EAAAA,IAAC,IAAA,CAAE,UAAU,2CAA4C,WAAc,WAAA,CAAY,CAAA,EACrF,EACAW,EAAAA,KAACG,GAAAA,WAAA,CAAW,UAAU,uCACpB,SAAA,CAAAH,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAX,EAAAA,IAACe,GAAAA,SAAA,CACC,MAAOP,EAAc,SACrB,KAAK,KACL,MAAM,UACN,aAAY,GAAGA,EAAc,KAAK,MAClC,UAAU,iCAAA,CAAA,EAEZG,EAAAA,KAAC,OAAA,CAAK,UAAU,mCAAoC,SAAA,CAAAH,EAAc,SAAS,GAAA,CAAA,CAAC,CAAA,EAC9E,EACAR,EAAAA,IAACT,GAAA,CACC,KAAK,KACL,OAAO,KACP,QAASmB,EACT,SAAUF,EAAc,SACxB,QAASA,EAAc,WAAa,IAAM,QAAUA,EAAc,WAAa,EAAI,QAAU,WAC7F,UAAU,kCAET,SAAAP,GAAcO,EAAc,QAAQ,CAAA,CAAA,CACvC,CAAA,CACF,CAAA,EACF,CAEJ,EAEMQ,GAAwC,CAAC,CAAE,OAAAC,EAAQ,WAAAC,EAAY,SAAAC,EAAU,cAAAV,KAAoB,CACjG,MAAMW,EAAe,IAAM,CACzBD,EAASF,EAAO,EAAE,CACpB,EAEMI,EAAiBnB,GAAwBe,EAAO,cAAc,EAEpE,cACG,MAAA,CAAI,UAAW,kCAAkCC,EAAa,2CAA6C,EAAE,GAC5G,SAAA,CAAAP,EAAAA,KAAC,MAAA,CACC,UAAU,mCACV,QAASS,EACT,KAAK,SACL,SAAU,EACV,gBAAeF,EACf,aAAY,GAAGD,EAAO,KAAK,MAAMC,EAAa,KAAO,IAAI,GAEzD,SAAA,CAAAP,EAAAA,KAAC,MAAA,CAAI,UAAU,2CACb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,kCAAmC,SAAAiB,EAAO,MAAM,EAC9DN,EAAAA,KAAC,OAAA,CAAK,UAAU,qCAAqC,SAAA,CAAA,KAAGM,EAAO,SAAS,KAAA,CAAA,CAAG,CAAA,EAC7E,EACAN,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAA,EAAAA,KAAC,OAAA,CAAK,UAAU,qCAAsC,SAAA,CAAAU,EAAe,GAAA,EAAC,EACrEH,QACEI,eAAA,CAAY,UAAU,iCAAiC,EAExDtB,MAACuB,GAAAA,aAAA,CAAa,UAAU,gCAAA,CAAiC,CAAA,CAAA,CAE7D,CAAA,CAAA,CAAA,EAGDL,SACE,MAAA,CAAI,UAAU,oCACZ,SAAAD,EAAO,eAAe,IAAKX,GAC1BN,EAAAA,IAACO,GAAA,CAEC,cAAeD,EACf,cAAAG,CAAA,EAFKH,EAAK,EAAA,CAIb,CAAA,CACH,CAAA,EAEJ,CAEJ,EAEakB,GAAoD,CAAC,CAChE,KAAAC,EACA,gBAAAC,EACA,eAAAC,EACA,cAAAlB,EACA,QAAAZ,EAAU,GACV,UAAAD,EAAY,GACZ,WAAAgC,CACF,IACM/B,EAEAG,EAAAA,IAAC,OAAI,UAAU,+CACb,eAAC,MAAA,CAAI,UAAU,6BAA6B,SAAA,QAAA,CAAM,CAAA,CACpD,EAICyB,EASHd,EAAAA,KAAC,MAAA,CAAI,UAAW,qBAAqBf,CAAS,GAE5C,SAAA,CAAAe,EAAAA,KAAC,SAAA,CAAO,UAAU,4BAChB,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,gCAAiC,SAAAyB,EAAK,MAAM,EAC1DzB,EAAAA,IAAC,IAAA,CAAE,UAAU,sCAAuC,WAAK,YAAY,EACrEW,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACb,SAAA,CAAAA,OAAC,OAAA,CAAK,SAAA,CAAA,MAAIc,EAAK,aAAa,KAAA,EAAG,EAC/BzB,EAAAA,IAAC,QAAK,SAAA,GAAA,CAAC,SACN,OAAA,CAAK,SAAA,CAAA,QAAMyB,EAAK,iBAAA,CAAA,CAAkB,CAAA,CAAA,CACrC,CAAA,EACF,EAGAzB,EAAAA,IAAC,OAAI,UAAU,6BACZ,WAAK,QAAQ,IAAKiB,GACjBjB,EAAAA,IAACgB,GAAA,CAEC,OAAAC,EACA,WAAYS,EAAgB,SAAST,EAAO,EAAE,EAC9C,SAAUU,EACV,cAAAlB,CAAA,EAJKQ,EAAO,EAAA,CAMf,CAAA,CACH,CAAA,EACF,EA/BEjB,EAAAA,IAAC,MAAA,CAAI,UAAU,6CACZ,SAAA4B,SAAe,MAAA,CAAI,UAAU,2BAA2B,SAAA,QAAA,CAAM,EACjE,EC/DOC,GAAoBC,GAA0E,CACzG,OAAQA,EAAA,CACN,IAAK,YACH,MAAO,UACT,IAAK,cACH,MAAO,UAET,QACE,MAAO,SAAA,CAEb,EC5DaC,GAAkC,CAAC,CAC9C,KAAAC,EACA,QAAAnC,EAAU,GACV,MAAAoC,EAAQ,KACR,UAAAC,EAAY,GACZ,iBAAAC,EACA,aAAAC,EAAe,KACf,aAAAC,EACA,eAAAC,EACA,UAAA1C,EAAY,GACZ,kBAAA2C,EAAoB,GACpB,MAAAC,EAAQ,CAAA,EACR,cAAAC,EAAgB,CAAA,CAClB,IAAM,CACJ,MAAMC,EAAmB,CAACC,EAAgBC,IAA4B,CACpEA,EAAM,eAAA,EACNP,IAAeM,CAAM,CACvB,EAEME,EAAuB,IAAM,CACjCV,IAAA,CACF,EAGMW,EAAyBrB,GAC7Bd,EAAAA,KAAC,MAAA,CAEC,UAAW,sBAAsB4B,CAAiB,IAChDH,IAAiBX,EAAK,OAAS,6BAA+B,EAChE,IAAIA,EAAK,OAAS,uBAAuBA,EAAK,MAAM,GAAK,EAAE,GAC3D,MAAOgB,EACP,QAAUM,GAAML,EAAiBjB,EAAK,OAAQsB,CAAC,EAC/C,KAAK,SACL,SAAU,EACV,aAAY,GAAGtB,EAAK,KAAK,OAAOA,EAAK,kBAAkB,IAEvD,SAAA,CAAAd,EAAAA,KAAC,MAAA,CAAI,UAAU,8BACZ,SAAA,CAAAc,EAAK,MACJzB,EAAAA,IAAC,OAAA,CAAK,UAAU,2BAA4B,WAAK,KAAK,EAEvD,CAACkC,GACAlC,EAAAA,IAAC,QAAK,UAAU,4BAA6B,WAAK,KAAA,CAAM,CAAA,EAE5D,EAEC,CAACkC,GAAaT,EAAK,qBAAuB,QACzCd,OAAC,MAAA,CAAI,UAAU,+BACb,SAAA,CAAAX,EAAAA,IAACe,GAAAA,SAAA,CACC,MAAOU,EAAK,mBACZ,KAAK,KACL,MAAOI,GAAiBJ,EAAK,MAAM,EACnC,aAAY,GAAGA,EAAK,KAAK,KAAA,CAAA,EAE3Bd,EAAAA,KAAC,OAAA,CAAK,UAAU,sBACb,SAAA,CAAAc,EAAK,mBAAmB,GAAA,CAAA,CAC3B,CAAA,CAAA,CACF,CAAA,CAAA,EA9BGA,EAAK,MAAA,EAoCRuB,EAAgB,IAChBnD,EAEAG,EAAAA,IAAC,MAAA,CAAI,UAAU,mBAAmB,SAAA,SAElC,EAIAiC,EAEAtB,EAAAA,KAAC,MAAA,CAAI,UAAU,iBAAiB,SAAA,CAAA,SACvBsB,EAAM,OAAA,EACf,EAICD,EASHrB,EAAAA,KAAAsC,WAAA,CACE,SAAA,CAAAtC,EAAAA,KAAC,MAAA,CAAI,UAAU,kBACb,SAAA,CAAAX,EAAAA,IAAC,SAAA,CACC,UAAU,sBACV,QAAS6C,EACT,aAAW,YAEV,WAAY,IAAM,GAAA,CAAA,EAEpB,CAACX,GACAvB,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,wBAAyB,SAAAgC,EAAK,YAAY,EACxDrB,EAAAA,KAAC,OAAA,CAAK,UAAU,wBAAyB,SAAA,CAAAqB,EAAK,YAAY,IAAA,CAAA,CAAE,CAAA,CAAA,CAC9D,CAAA,EAEJ,QAEC,MAAA,CAAI,UAAU,mBACb,SAAAhC,MAAC,MAAG,UAAU,qBACX,SAAAgC,EAAK,OAASA,EAAK,MAAM,OAAS,EACjCA,EAAK,MAAM,IAAKP,GACdzB,EAAAA,IAAC,KAAA,CACE,WACGsC,EAAeb,EAAMA,CAAI,EACzBqB,EAAsBrB,CAAI,GAHvBA,EAAK,MAId,CACD,EAEDzB,MAAC,MAAA,CAAI,UAAU,iBAAiB,SAAA,SAEhC,EAEJ,CAAA,CACF,CAAA,EACF,EAzCEA,EAAAA,IAAC,MAAA,CAAI,UAAU,iBAAiB,SAAA,SAEhC,EA2CN,OACEA,EAAAA,IAAC,QAAA,CACC,UAAW,WAAWJ,CAAS,IAAIsC,EAAY,qBAAuB,EAAE,IACtErC,EAAU,mBAAqB,EACjC,IAAIoC,EAAQ,iBAAmB,EAAE,GACjC,MAAAO,EACA,aAAW,UACX,KAAK,gBAEJ,SAAAQ,EAAA,CAAc,CAAA,CAGrB,EC5GME,GAAkC,CAAC,CACvC,QAAAC,EACA,MAAAC,EACA,SAAAC,EAAW,SACX,UAAAC,EAAY,QACZ,UAAAC,EAAY,IACZ,WAAAC,EAAa,IACb,OAAAC,EACA,QAAAC,EACA,WAAAC,EACA,WAAAC,EAAa,CAAA,EACb,UAAAhE,EACA,cAAAiE,EACA,cAAAC,CAEF,IAAM,CACJ,KAAM,CAACC,EAAQC,CAAS,EAAInF,EAAM,SAAS,EAAK,EAC1CoF,EAAiBpF,EAAM,OAA8B,IAAI,EACzDqF,EAAkBrF,EAAM,OAA8B,IAAI,EAE1DsF,EAAgB,IAAM,CACtBF,EAAe,SACjB,aAAaA,EAAe,OAAO,EAEjCC,EAAgB,SAClB,aAAaA,EAAgB,OAAO,CAExC,EAEME,EAAmB,IAAM,CAC7BD,EAAA,EACAF,EAAe,QAAU,WAAW,IAAM,CACxCD,EAAU,EAAI,EACdP,IAAA,CACF,EAAGF,CAAS,CACd,EAEMc,EAAmB,IAAM,CAC7BF,EAAA,EACAD,EAAgB,QAAU,WAAW,IAAM,CACzCF,EAAU,EAAK,EACfN,IAAA,CACF,EAAGF,CAAU,CACf,EAEMc,EAAmBhE,GAAsB,CACzC,CAACA,EAAK,UAAYA,EAAK,SACzBA,EAAK,QAAQA,CAAI,CAErB,EAEAzB,EAAM,UAAU,IACP,IAAMsF,EAAA,EACZ,CAAA,CAAE,EAEL,MAAMI,EAAqBjE,GACzBK,EAAAA,KAAC,MAAA,CAEC,UAAW,gBAAgBL,EAAK,SAAW,cAAgB,EAAE,IAAIwD,GAAiB,EAAE,GACpF,QAAS,IAAMQ,EAAgBhE,CAAI,EAElC,SAAA,CAAAA,EAAK,MAAQN,EAAAA,IAAC,OAAA,CAAK,UAAU,oBAAqB,WAAK,KAAK,EAC7DA,EAAAA,IAAC,OAAA,CAAM,SAAAM,EAAK,KAAA,CAAM,CAAA,CAAA,EALbA,EAAK,EAAA,EASRkE,EAAkB,IAAM,CAC5B,MAAMC,EAAU,CAAC,eAAe,EAEhC,OAAIZ,GACFY,EAAQ,KAAKZ,CAAa,EAI5BY,EAAQ,KAAK,YAAYpB,CAAQ,EAAE,EAG/BC,IAAc,SAChBmB,EAAQ,KAAK,aAAanB,CAAS,EAAE,EAInCS,GACFU,EAAQ,KAAK,SAAS,EAGjBA,EAAQ,KAAK,GAAG,CACzB,EAEA,OACE9D,EAAAA,KAAC,MAAA,CACC,UAAW,qBAAqBf,GAAa,EAAE,GAC/C,aAAcwE,EACd,aAAcC,EAEd,SAAA,CAAArE,EAAAA,IAAC,MAAA,CAAI,UAAU,kBACZ,SAAAmD,EACH,EAEAnD,EAAAA,IAAC,MAAA,CAAI,UAAWwE,EAAA,EACb,SAAApB,EAAM,OACLO,EACIA,EAAWrD,EAAMsD,CAAU,EAC3BW,EAAkBjE,CAAI,CAAA,CAC5B,CACF,CAAA,CAAA,CAAA,CAGN,ECvIe,SAASoE,GAAKC,EAAIC,EAAS,CACxC,OAAO,UAAgB,CACrB,OAAOD,EAAG,MAAMC,EAAS,SAAS,CACpC,CACF,CCPA,KAAM,CAAE,SAAAC,EAAQ,EAAK,OAAO,UACtB,CAAE,eAAAC,EAAc,EAAK,OACrB,CAAE,SAAAC,GAAU,YAAAC,EAAW,EAAK,OAE5BC,IAAWC,GAAWC,GAAU,CACpC,MAAMC,EAAMP,GAAS,KAAKM,CAAK,EAC/B,OAAOD,EAAME,CAAG,IAAMF,EAAME,CAAG,EAAIA,EAAI,MAAM,EAAG,EAAE,EAAE,YAAW,EACjE,GAAG,OAAO,OAAO,IAAI,CAAC,EAEhBC,GAAclK,IAClBA,EAAOA,EAAK,YAAW,EACfgK,GAAUF,GAAOE,CAAK,IAAMhK,GAGhCmK,GAAcnK,GAAUgK,GAAU,OAAOA,IAAUhK,EASnD,CAAE,QAAAoK,EAAO,EAAK,MASdC,GAAcF,GAAW,WAAW,EAS1C,SAASG,GAASC,EAAK,CACrB,OACEA,IAAQ,MACR,CAACF,GAAYE,CAAG,GAChBA,EAAI,cAAgB,MACpB,CAACF,GAAYE,EAAI,WAAW,GAC5BC,GAAWD,EAAI,YAAY,QAAQ,GACnCA,EAAI,YAAY,SAASA,CAAG,CAEhC,CASA,MAAME,GAAgBP,GAAW,aAAa,EAS9C,SAASQ,GAAkBH,EAAK,CAC9B,IAAII,EACJ,OAAI,OAAO,YAAgB,KAAe,YAAY,OACpDA,EAAS,YAAY,OAAOJ,CAAG,EAE/BI,EAASJ,GAAOA,EAAI,QAAUE,GAAcF,EAAI,MAAM,EAEjDI,CACT,CASA,MAAMC,GAAWT,GAAW,QAAQ,EAQ9BK,GAAaL,GAAW,UAAU,EASlCU,GAAWV,GAAW,QAAQ,EAS9BW,GAAYd,GAAUA,IAAU,MAAQ,OAAOA,GAAU,SAQzDe,GAAaf,GAAUA,IAAU,IAAQA,IAAU,GASnDgB,GAAiBT,GAAQ,CAC7B,GAAIT,GAAOS,CAAG,IAAM,SAClB,MAAO,GAGT,MAAMU,EAAYtB,GAAeY,CAAG,EACpC,OACGU,IAAc,MACbA,IAAc,OAAO,WACrB,OAAO,eAAeA,CAAS,IAAM,OACvC,EAAEpB,MAAeU,IACjB,EAAEX,MAAYW,EAElB,EASMW,GAAiBX,GAAQ,CAE7B,GAAI,CAACO,GAASP,CAAG,GAAKD,GAASC,CAAG,EAChC,MAAO,GAGT,GAAI,CACF,OACE,OAAO,KAAKA,CAAG,EAAE,SAAW,GAC5B,OAAO,eAAeA,CAAG,IAAM,OAAO,SAE1C,MAAY,CAEV,MAAO,EACT,CACF,EASMY,GAASjB,GAAW,MAAM,EAS1BkB,GAASlB,GAAW,MAAM,EAS1BmB,GAASnB,GAAW,MAAM,EAS1BoB,GAAapB,GAAW,UAAU,EASlCqB,GAAYhB,GAAQO,GAASP,CAAG,GAAKC,GAAWD,EAAI,IAAI,EASxDiB,GAAcxB,GAAU,CAC5B,IAAIyB,EACJ,OACEzB,IACE,OAAO,UAAa,YAAcA,aAAiB,UAClDQ,GAAWR,EAAM,MAAM,KACpByB,EAAO3B,GAAOE,CAAK,KAAO,YAEzByB,IAAS,UACRjB,GAAWR,EAAM,QAAQ,GACzBA,EAAM,SAAQ,IAAO,qBAEjC,EASM0B,GAAoBxB,GAAW,iBAAiB,EAEhD,CAACyB,GAAkBC,GAAWC,GAAYC,EAAS,EAAI,CAC3D,iBACA,UACA,WACA,SACF,EAAE,IAAI5B,EAAU,EASV6B,GAAQ9B,GACZA,EAAI,KAAOA,EAAI,KAAI,EAAKA,EAAI,QAAQ,qCAAsC,EAAE,EAkB9E,SAAS+B,GAAQC,EAAKzC,EAAI,CAAE,WAAA0C,EAAa,EAAK,EAAK,GAAI,CAErD,GAAID,IAAQ,MAAQ,OAAOA,EAAQ,IACjC,OAGF,IAAIE,EACAC,EAQJ,GALI,OAAOH,GAAQ,WAEjBA,EAAM,CAACA,CAAG,GAGR7B,GAAQ6B,CAAG,EAEb,IAAKE,EAAI,EAAGC,EAAIH,EAAI,OAAQE,EAAIC,EAAGD,IACjC3C,EAAG,KAAK,KAAMyC,EAAIE,CAAC,EAAGA,EAAGF,CAAG,MAEzB,CAEL,GAAI3B,GAAS2B,CAAG,EACd,OAIF,MAAM5I,EAAO6I,EACT,OAAO,oBAAoBD,CAAG,EAC9B,OAAO,KAAKA,CAAG,EACbI,EAAMhJ,EAAK,OACjB,IAAIlD,EAEJ,IAAKgM,EAAI,EAAGA,EAAIE,EAAKF,IACnBhM,EAAMkD,EAAK8I,CAAC,EACZ3C,EAAG,KAAK,KAAMyC,EAAI9L,CAAG,EAAGA,EAAK8L,CAAG,CAEpC,CACF,CAEA,SAASK,GAAQL,EAAK9L,EAAK,CACzB,GAAImK,GAAS2B,CAAG,EACd,OAAO,KAGT9L,EAAMA,EAAI,YAAW,EACrB,MAAMkD,EAAO,OAAO,KAAK4I,CAAG,EAC5B,IAAIE,EAAI9I,EAAK,OACTkJ,EACJ,KAAOJ,KAAM,GAEX,GADAI,EAAOlJ,EAAK8I,CAAC,EACThM,IAAQoM,EAAK,cACf,OAAOA,EAGX,OAAO,IACT,CAEA,MAAMC,GAEA,OAAO,WAAe,IAAoB,WACvC,OAAO,KAAS,IACnB,KACA,OAAO,OAAW,IAChB,OACA,OAGFC,GAAoBC,GACxB,CAACrC,GAAYqC,CAAO,GAAKA,IAAYF,GAoBvC,SAASG,IAAmC,CAC1C,KAAM,CAAE,SAAAC,EAAU,cAAAC,CAAa,EAAMJ,GAAiB,IAAI,GAAK,MAAS,CAAA,EAClE9B,EAAS,CAAA,EACTmC,EAAc,CAACvC,EAAKpK,IAAQ,CAEhC,GAAIA,IAAQ,aAAeA,IAAQ,eAAiBA,IAAQ,YAC1D,OAGF,MAAM4M,EAAaH,GAAYN,GAAQ3B,EAAQxK,CAAG,GAAMA,EACpD6K,GAAcL,EAAOoC,CAAS,CAAC,GAAK/B,GAAcT,CAAG,EACvDI,EAAOoC,CAAS,EAAIJ,GAAMhC,EAAOoC,CAAS,EAAGxC,CAAG,EACvCS,GAAcT,CAAG,EAC1BI,EAAOoC,CAAS,EAAIJ,GAAM,CAAA,EAAIpC,CAAG,EACxBH,GAAQG,CAAG,EACpBI,EAAOoC,CAAS,EAAIxC,EAAI,MAAK,GACpB,CAACsC,GAAiB,CAACxC,GAAYE,CAAG,KAC3CI,EAAOoC,CAAS,EAAIxC,EAExB,EAEA,QAAS4B,EAAI,EAAGC,EAAI,UAAU,OAAQD,EAAIC,EAAGD,IAC3C,UAAUA,CAAC,GAAKH,GAAQ,UAAUG,CAAC,EAAGW,CAAW,EAEnD,OAAOnC,CACT,CAaA,MAAMqC,GAAS,CAACC,EAAGC,EAAGzD,EAAS,CAAE,WAAAyC,CAAU,EAAK,MAC9CF,GACEkB,EACA,CAAC3C,EAAKpK,IAAQ,CACRsJ,GAAWe,GAAWD,CAAG,EAC3B,OAAO,eAAe0C,EAAG9M,EAAK,CAC5B,MAAOoJ,GAAKgB,EAAKd,CAAO,EACxB,SAAU,GACV,WAAY,GACZ,aAAc,EACxB,CAAS,EAED,OAAO,eAAewD,EAAG9M,EAAK,CAC5B,MAAOoK,EACP,SAAU,GACV,WAAY,GACZ,aAAc,EACxB,CAAS,CAEL,EACA,CAAE,WAAA2B,CAAU,CAChB,EACSe,GAUHE,GAAYC,IACZA,EAAQ,WAAW,CAAC,IAAM,QAC5BA,EAAUA,EAAQ,MAAM,CAAC,GAEpBA,GAYHC,GAAW,CAACC,EAAaC,EAAkBnL,EAAOoL,IAAgB,CACtEF,EAAY,UAAY,OAAO,OAC7BC,EAAiB,UACjBC,CACJ,EACE,OAAO,eAAeF,EAAY,UAAW,cAAe,CAC1D,MAAOA,EACP,SAAU,GACV,WAAY,GACZ,aAAc,EAClB,CAAG,EACD,OAAO,eAAeA,EAAa,QAAS,CAC1C,MAAOC,EAAiB,SAC5B,CAAG,EACDnL,GAAS,OAAO,OAAOkL,EAAY,UAAWlL,CAAK,CACrD,EAWMqL,GAAe,CAACC,EAAWC,EAASC,EAAQC,IAAe,CAC/D,IAAIzL,EACA+J,EACA2B,EACJ,MAAMC,EAAS,CAAA,EAIf,GAFAJ,EAAUA,GAAW,CAAA,EAEjBD,GAAa,KAAM,OAAOC,EAE9B,EAAG,CAGD,IAFAvL,EAAQ,OAAO,oBAAoBsL,CAAS,EAC5CvB,EAAI/J,EAAM,OACH+J,KAAM,GACX2B,EAAO1L,EAAM+J,CAAC,GAEX,CAAC0B,GAAcA,EAAWC,EAAMJ,EAAWC,CAAO,IACnD,CAACI,EAAOD,CAAI,IAEZH,EAAQG,CAAI,EAAIJ,EAAUI,CAAI,EAC9BC,EAAOD,CAAI,EAAI,IAGnBJ,EAAYE,IAAW,IAASjE,GAAe+D,CAAS,CAC1D,OACEA,IACC,CAACE,GAAUA,EAAOF,EAAWC,CAAO,IACrCD,IAAc,OAAO,WAGvB,OAAOC,CACT,EAWMK,GAAW,CAAC/D,EAAKgE,EAAc/F,IAAa,CAChD+B,EAAM,OAAOA,CAAG,GACZ/B,IAAa,QAAaA,EAAW+B,EAAI,UAC3C/B,EAAW+B,EAAI,QAEjB/B,GAAY+F,EAAa,OACzB,MAAMC,EAAYjE,EAAI,QAAQgE,EAAc/F,CAAQ,EACpD,OAAOgG,IAAc,IAAMA,IAAchG,CAC3C,EASMiG,GAAWnE,GAAU,CACzB,GAAI,CAACA,EAAO,OAAO,KACnB,GAAII,GAAQJ,CAAK,EAAG,OAAOA,EAC3B,IAAImC,EAAInC,EAAM,OACd,GAAI,CAACa,GAASsB,CAAC,EAAG,OAAO,KACzB,MAAMiC,EAAM,IAAI,MAAMjC,CAAC,EACvB,KAAOA,KAAM,GACXiC,EAAIjC,CAAC,EAAInC,EAAMmC,CAAC,EAElB,OAAOiC,CACT,EAWMC,IAAiBC,GAEbtE,GACCsE,GAActE,aAAiBsE,GAEvC,OAAO,WAAe,KAAe3E,GAAe,UAAU,CAAC,EAU5D4E,GAAe,CAACtC,EAAKzC,IAAO,CAGhC,MAAMgF,GAFYvC,GAAOA,EAAIrC,EAAQ,GAET,KAAKqC,CAAG,EAEpC,IAAItB,EAEJ,MAAQA,EAAS6D,EAAU,KAAI,IAAO,CAAC7D,EAAO,MAAM,CAClD,MAAM8D,EAAO9D,EAAO,MACpBnB,EAAG,KAAKyC,EAAKwC,EAAK,CAAC,EAAGA,EAAK,CAAC,CAAC,CAC/B,CACF,EAUMC,GAAW,CAACC,EAAQ1E,IAAQ,CAChC,IAAI2E,EACJ,MAAMR,EAAM,CAAA,EAEZ,MAAQQ,EAAUD,EAAO,KAAK1E,CAAG,KAAO,MACtCmE,EAAI,KAAKQ,CAAO,EAGlB,OAAOR,CACT,EAGMS,GAAa3E,GAAW,iBAAiB,EAEzC4E,GAAe7E,GACZA,EACJ,YAAW,EACX,QAAQ,wBAAyB,SAAkB8E,EAAGC,EAAIC,EAAI,CAC7D,OAAOD,EAAG,YAAW,EAAKC,CAC5B,CAAC,EAIChN,IACJ,CAAC,CAAE,eAAAA,CAAc,IACjB,CAACgK,EAAK6B,IACJ7L,EAAe,KAAKgK,EAAK6B,CAAI,GAC/B,OAAO,SAAS,EASZoB,GAAWhF,GAAW,QAAQ,EAE9BiF,GAAoB,CAAClD,EAAKmD,IAAY,CAC1C,MAAM5B,EAAc,OAAO,0BAA0BvB,CAAG,EAClDoD,EAAqB,CAAA,EAE3BrD,GAAQwB,EAAa,CAAC8B,EAAY3N,IAAS,CACzC,IAAI4N,GACCA,EAAMH,EAAQE,EAAY3N,EAAMsK,CAAG,KAAO,KAC7CoD,EAAmB1N,CAAI,EAAI4N,GAAOD,EAEtC,CAAC,EAED,OAAO,iBAAiBrD,EAAKoD,CAAkB,CACjD,EAOMG,GAAiBvD,GAAQ,CAC7BkD,GAAkBlD,EAAK,CAACqD,EAAY3N,IAAS,CAE3C,GACE6I,GAAWyB,CAAG,GACd,CAAC,YAAa,SAAU,QAAQ,EAAE,QAAQtK,CAAI,IAAM,GAEpD,MAAO,GAGT,MAAMN,EAAQ4K,EAAItK,CAAI,EAEtB,GAAK6I,GAAWnJ,CAAK,EAIrB,IAFAiO,EAAW,WAAa,GAEpB,aAAcA,EAAY,CAC5BA,EAAW,SAAW,GACtB,MACF,CAEKA,EAAW,MACdA,EAAW,IAAM,IAAM,CACrB,MAAM,MAAM,qCAAuC3N,EAAO,GAAG,CAC/D,GAEJ,CAAC,CACH,EAEM8N,GAAc,CAACC,EAAeC,IAAc,CAChD,MAAM1D,EAAM,CAAA,EAEN2D,EAAUxB,GAAQ,CACtBA,EAAI,QAAS/M,GAAU,CACrB4K,EAAI5K,CAAK,EAAI,EACf,CAAC,CACH,EAEA,OAAA+I,GAAQsF,CAAa,EACjBE,EAAOF,CAAa,EACpBE,EAAO,OAAOF,CAAa,EAAE,MAAMC,CAAS,CAAC,EAE1C1D,CACT,EAEM4D,GAAO,IAAM,CAAC,EAEdC,GAAiB,CAACzO,EAAO0O,IACtB1O,GAAS,MAAQ,OAAO,SAAUA,EAAQ,CAACA,CAAK,EACnDA,EACA0O,EAUN,SAASC,GAAoBhG,EAAO,CAClC,MAAO,CAAC,EACNA,GACAQ,GAAWR,EAAM,MAAM,GACvBA,EAAMH,EAAW,IAAM,YACvBG,EAAMJ,EAAQ,EAElB,CAEA,MAAMqG,GAAgBhE,GAAQ,CAC5B,MAAMiE,EAAQ,IAAI,MAAM,EAAE,EAEpBC,EAAQ,CAACC,EAAQjE,IAAM,CAC3B,GAAIrB,GAASsF,CAAM,EAAG,CACpB,GAAIF,EAAM,QAAQE,CAAM,GAAK,EAC3B,OAIF,GAAI9F,GAAS8F,CAAM,EACjB,OAAOA,EAGT,GAAI,EAAE,WAAYA,GAAS,CACzBF,EAAM/D,CAAC,EAAIiE,EACX,MAAMC,EAASjG,GAAQgG,CAAM,EAAI,CAAA,EAAK,CAAA,EAEtC,OAAApE,GAAQoE,EAAQ,CAAC/O,EAAOlB,IAAQ,CAC9B,MAAMmQ,EAAeH,EAAM9O,EAAO8K,EAAI,CAAC,EACvC,CAAC9B,GAAYiG,CAAY,IAAMD,EAAOlQ,CAAG,EAAImQ,EAC/C,CAAC,EAEDJ,EAAM/D,CAAC,EAAI,OAEJkE,CACT,CACF,CAEA,OAAOD,CACT,EAEA,OAAOD,EAAMlE,EAAK,CAAC,CACrB,EAEMsE,GAAYrG,GAAW,eAAe,EAEtCsG,GAAcxG,GAClBA,IACCc,GAASd,CAAK,GAAKQ,GAAWR,CAAK,IACpCQ,GAAWR,EAAM,IAAI,GACrBQ,GAAWR,EAAM,KAAK,EAKlByG,IAAiB,CAACC,EAAuBC,IACzCD,EACK,aAGFC,GACF,CAACC,EAAOC,KACPrE,GAAQ,iBACN,UACA,CAAC,CAAE,OAAA4D,EAAQ,KAAAvJ,KAAW,CAChBuJ,IAAW5D,IAAW3F,IAAS+J,GACjCC,EAAU,QAAUA,EAAU,QAAO,CAEzC,EACA,EACV,EAEgBC,GAAO,CACbD,EAAU,KAAKC,CAAE,EACjBtE,GAAQ,YAAYoE,EAAO,GAAG,CAChC,IACC,SAAS,KAAK,OAAM,CAAE,GAAI,CAAA,CAAE,EAC9BE,GAAO,WAAWA,CAAE,GACxB,OAAO,cAAiB,WAAYtG,GAAWgC,GAAQ,WAAW,CAAC,EAEhEuE,GACJ,OAAO,eAAmB,IACtB,eAAe,KAAKvE,EAAO,EAC1B,OAAO,QAAY,KAAe,QAAQ,UAAaiE,GAIxDO,GAAchH,GAAUA,GAAS,MAAQQ,GAAWR,EAAMJ,EAAQ,CAAC,EAEzEqH,EAAe,CACb,QAAA7G,GACA,cAAAK,GACA,SAAAH,GACA,WAAAkB,GACA,kBAAAd,GACA,SAAAE,GACA,SAAAC,GACA,UAAAE,GACA,SAAAD,GACA,cAAAE,GACA,cAAAE,GACA,iBAAAS,GACA,UAAAC,GACA,WAAAC,GACA,UAAAC,GACA,YAAAzB,GACA,OAAAc,GACA,OAAAC,GACA,OAAAC,GACA,SAAA6D,GACF,WAAE1E,GACA,SAAAe,GACA,kBAAAG,GACA,aAAA2C,GACA,WAAA/C,GACA,QAAAU,GACA,MAAAW,GACA,OAAAK,GACF,KAAEjB,GACA,SAAAoB,GACA,SAAAE,GACA,aAAAI,GACA,OAAA3D,GACA,WAAAI,GACA,SAAA8D,GACA,QAAAG,GACA,aAAAI,GACA,SAAAG,GACA,WAAAG,GACA,eAAA5M,GACA,WAAYA,GACZ,kBAAAkN,GACA,cAAAK,GACA,YAAAC,GACA,YAAAX,GACA,KAAAe,GACA,eAAAC,GACA,QAAAxD,GACA,OAAQE,GACR,iBAAAC,GACA,oBAAAuD,GACA,aAAAC,GACA,UAAAM,GACA,WAAAC,GACA,aAAcC,GACd,KAAAM,GACA,WAAAC,EACF,QC11BA,MAAME,WAAmB,KAAM,CAC3B,OAAO,KAAKpK,EAAOqK,EAAMlR,EAAQmR,EAASC,EAAUC,EAAa,CAC7D,MAAMC,EAAa,IAAIL,GAAWpK,EAAM,QAASqK,GAAQrK,EAAM,KAAM7G,EAAQmR,EAASC,CAAQ,EAC9F,OAAAE,EAAW,MAAQzK,EACnByK,EAAW,KAAOzK,EAAM,KACxBwK,GAAe,OAAO,OAAOC,EAAYD,CAAW,EAC7CC,CACX,CAaA,YAAYC,EAASL,EAAMlR,EAAQmR,EAASC,EAAU,CAClD,MAAMG,CAAO,EACb,KAAK,KAAO,aACZ,KAAK,aAAe,GACpBL,IAAS,KAAK,KAAOA,GACrBlR,IAAW,KAAK,OAASA,GACzBmR,IAAY,KAAK,QAAUA,GACvBC,IACA,KAAK,SAAWA,EAChB,KAAK,OAASA,EAAS,OAE/B,CAEA,QAAS,CACL,MAAO,CAEH,QAAS,KAAK,QACd,KAAM,KAAK,KAEX,YAAa,KAAK,YAClB,OAAQ,KAAK,OAEb,SAAU,KAAK,SACf,WAAY,KAAK,WACjB,aAAc,KAAK,aACnB,MAAO,KAAK,MAEZ,OAAQI,EAAM,aAAa,KAAK,MAAM,EACtC,KAAM,KAAK,KACX,OAAQ,KAAK,MACzB,CACI,CACJ,EAGAP,EAAW,qBAAuB,uBAClCA,EAAW,eAAiB,iBAC5BA,EAAW,aAAe,eAC1BA,EAAW,UAAY,YACvBA,EAAW,YAAc,cACzBA,EAAW,0BAA4B,4BACvCA,EAAW,eAAiB,iBAC5BA,EAAW,iBAAmB,mBAC9BA,EAAW,gBAAkB,kBAC7BA,EAAW,aAAe,eAC1BA,EAAW,gBAAkB,kBAC7BA,EAAW,gBAAkB,kBCrE7B,MAAAQ,GAAe,KCaf,SAASC,GAAY3H,EAAO,CAC1B,OAAOyH,EAAM,cAAczH,CAAK,GAAKyH,EAAM,QAAQzH,CAAK,CAC1D,CASA,SAAS4H,GAAezR,EAAK,CAC3B,OAAOsR,EAAM,SAAStR,EAAK,IAAI,EAAIA,EAAI,MAAM,EAAG,EAAE,EAAIA,CACxD,CAWA,SAAS0R,GAAUC,EAAM3R,EAAK4R,EAAM,CAClC,OAAKD,EACEA,EAAK,OAAO3R,CAAG,EAAE,IAAI,SAAcyQ,EAAOzE,EAAG,CAElD,OAAAyE,EAAQgB,GAAehB,CAAK,EACrB,CAACmB,GAAQ5F,EAAI,IAAMyE,EAAQ,IAAMA,CAC1C,CAAC,EAAE,KAAKmB,EAAO,IAAM,EAAE,EALL5R,CAMpB,CASA,SAAS6R,GAAY5D,EAAK,CACxB,OAAOqD,EAAM,QAAQrD,CAAG,GAAK,CAACA,EAAI,KAAKuD,EAAW,CACpD,CAEA,MAAMM,GAAaR,EAAM,aAAaA,EAAO,CAAA,EAAI,KAAM,SAAgB3D,EAAM,CAC3E,MAAO,WAAW,KAAKA,CAAI,CAC7B,CAAC,EAyBD,SAASoE,GAAWjG,EAAKkG,EAAUC,EAAS,CAC1C,GAAI,CAACX,EAAM,SAASxF,CAAG,EACrB,MAAM,IAAI,UAAU,0BAA0B,EAIhDkG,EAAWA,GAAY,IAAyB,SAGhDC,EAAUX,EAAM,aAAaW,EAAS,CACpC,WAAY,GACZ,KAAM,GACN,QAAS,EACb,EAAK,GAAO,SAAiBC,EAAQjC,EAAQ,CAEzC,MAAO,CAACqB,EAAM,YAAYrB,EAAOiC,CAAM,CAAC,CAC1C,CAAC,EAED,MAAMC,EAAaF,EAAQ,WAErBG,EAAUH,EAAQ,SAAWI,EAC7BT,EAAOK,EAAQ,KACfK,EAAUL,EAAQ,QAElBM,GADQN,EAAQ,MAAQ,OAAO,KAAS,KAAe,OACpCX,EAAM,oBAAoBU,CAAQ,EAE3D,GAAI,CAACV,EAAM,WAAWc,CAAO,EAC3B,MAAM,IAAI,UAAU,4BAA4B,EAGlD,SAASI,EAAatR,EAAO,CAC3B,GAAIA,IAAU,KAAM,MAAO,GAE3B,GAAIoQ,EAAM,OAAOpQ,CAAK,EACpB,OAAOA,EAAM,YAAW,EAG1B,GAAIoQ,EAAM,UAAUpQ,CAAK,EACvB,OAAOA,EAAM,SAAQ,EAGvB,GAAI,CAACqR,GAAWjB,EAAM,OAAOpQ,CAAK,EAChC,MAAM,IAAI6P,EAAW,8CAA8C,EAGrE,OAAIO,EAAM,cAAcpQ,CAAK,GAAKoQ,EAAM,aAAapQ,CAAK,EACjDqR,GAAW,OAAO,MAAS,WAAa,IAAI,KAAK,CAACrR,CAAK,CAAC,EAAI,OAAO,KAAKA,CAAK,EAG/EA,CACT,CAYA,SAASmR,EAAenR,EAAOlB,EAAK2R,EAAM,CACxC,IAAI1D,EAAM/M,EAEV,GAAIA,GAAS,CAACyQ,GAAQ,OAAOzQ,GAAU,UACrC,GAAIoQ,EAAM,SAAStR,EAAK,IAAI,EAE1BA,EAAMmS,EAAanS,EAAMA,EAAI,MAAM,EAAG,EAAE,EAExCkB,EAAQ,KAAK,UAAUA,CAAK,UAE3BoQ,EAAM,QAAQpQ,CAAK,GAAK2Q,GAAY3Q,CAAK,IACxCoQ,EAAM,WAAWpQ,CAAK,GAAKoQ,EAAM,SAAStR,EAAK,IAAI,KAAOiO,EAAMqD,EAAM,QAAQpQ,CAAK,GAGrF,OAAAlB,EAAMyR,GAAezR,CAAG,EAExBiO,EAAI,QAAQ,SAAcwE,EAAIC,EAAO,CACnC,EAAEpB,EAAM,YAAYmB,CAAE,GAAKA,IAAO,OAAST,EAAS,OAElDM,IAAY,GAAOZ,GAAU,CAAC1R,CAAG,EAAG0S,EAAOd,CAAI,EAAKU,IAAY,KAAOtS,EAAMA,EAAM,KACnFwS,EAAaC,CAAE,CAC3B,CACQ,CAAC,EACM,GAIX,OAAIjB,GAAYtQ,CAAK,EACZ,IAGT8Q,EAAS,OAAON,GAAUC,EAAM3R,EAAK4R,CAAI,EAAGY,EAAatR,CAAK,CAAC,EAExD,GACT,CAEA,MAAM6O,EAAQ,CAAA,EAER4C,EAAiB,OAAO,OAAOb,GAAY,CAC/C,eAAAO,EACA,aAAAG,EACA,YAAAhB,EACJ,CAAG,EAED,SAASoB,EAAM1R,EAAOyQ,EAAM,CAC1B,GAAIL,CAAAA,EAAM,YAAYpQ,CAAK,EAE3B,IAAI6O,EAAM,QAAQ7O,CAAK,IAAM,GAC3B,MAAM,MAAM,kCAAoCyQ,EAAK,KAAK,GAAG,CAAC,EAGhE5B,EAAM,KAAK7O,CAAK,EAEhBoQ,EAAM,QAAQpQ,EAAO,SAAcuR,EAAIzS,EAAK,EAC3B,EAAEsR,EAAM,YAAYmB,CAAE,GAAKA,IAAO,OAASL,EAAQ,KAChEJ,EAAUS,EAAInB,EAAM,SAAStR,CAAG,EAAIA,EAAI,KAAI,EAAKA,EAAK2R,EAAMgB,CACpE,KAEqB,IACbC,EAAMH,EAAId,EAAOA,EAAK,OAAO3R,CAAG,EAAI,CAACA,CAAG,CAAC,CAE7C,CAAC,EAED+P,EAAM,IAAG,EACX,CAEA,GAAI,CAACuB,EAAM,SAASxF,CAAG,EACrB,MAAM,IAAI,UAAU,wBAAwB,EAG9C,OAAA8G,EAAM9G,CAAG,EAEFkG,CACT,CChNA,SAASa,GAAO/I,EAAK,CACnB,MAAMgJ,EAAU,CACd,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,MAAO,IACP,MAAO,IACX,EACE,OAAO,mBAAmBhJ,CAAG,EAAE,QAAQ,mBAAoB,SAAkBiJ,EAAO,CAClF,OAAOD,EAAQC,CAAK,CACtB,CAAC,CACH,CAUA,SAASC,GAAqBC,EAAQhB,EAAS,CAC7C,KAAK,OAAS,CAAA,EAEdgB,GAAUlB,GAAWkB,EAAQ,KAAMhB,CAAO,CAC5C,CAEA,MAAMnH,GAAYkI,GAAqB,UAEvClI,GAAU,OAAS,SAAgBtJ,EAAMN,EAAO,CAC9C,KAAK,OAAO,KAAK,CAACM,EAAMN,CAAK,CAAC,CAChC,EAEA4J,GAAU,SAAW,SAAkBoI,EAAS,CAC9C,MAAMC,EAAUD,EAAU,SAAShS,EAAO,CACxC,OAAOgS,EAAQ,KAAK,KAAMhS,EAAO2R,EAAM,CACzC,EAAIA,GAEJ,OAAO,KAAK,OAAO,IAAI,SAAcvE,EAAM,CACzC,OAAO6E,EAAQ7E,EAAK,CAAC,CAAC,EAAI,IAAM6E,EAAQ7E,EAAK,CAAC,CAAC,CACjD,EAAG,EAAE,EAAE,KAAK,GAAG,CACjB,EC1CA,SAASuE,GAAOzI,EAAK,CACnB,OAAO,mBAAmBA,CAAG,EAC3B,QAAQ,QAAS,GAAG,EACpB,QAAQ,OAAQ,GAAG,EACnB,QAAQ,QAAS,GAAG,EACpB,QAAQ,OAAQ,GAAG,CACvB,CAWe,SAASgJ,GAASC,EAAKJ,EAAQhB,EAAS,CACrD,GAAI,CAACgB,EACH,OAAOI,EAGT,MAAMF,EAAUlB,GAAWA,EAAQ,QAAUY,GAEvCS,EAAWhC,EAAM,WAAWW,CAAO,EAAI,CAC3C,UAAWA,CACf,EAAMA,EAEEsB,EAAcD,GAAYA,EAAS,UAEzC,IAAIE,EAUJ,GARID,EACFC,EAAmBD,EAAYN,EAAQK,CAAQ,EAE/CE,EAAmBlC,EAAM,kBAAkB2B,CAAM,EAC/CA,EAAO,SAAQ,EACf,IAAID,GAAqBC,EAAQK,CAAQ,EAAE,SAASH,CAAO,EAG3DK,EAAkB,CACpB,MAAMC,EAAgBJ,EAAI,QAAQ,GAAG,EAEjCI,IAAkB,KACpBJ,EAAMA,EAAI,MAAM,EAAGI,CAAa,GAElCJ,IAAQA,EAAI,QAAQ,GAAG,IAAM,GAAK,IAAM,KAAOG,CACjD,CAEA,OAAOH,CACT,CC3DA,MAAMK,EAAmB,CACvB,aAAc,CACZ,KAAK,SAAW,CAAA,CAClB,CAWA,IAAIC,EAAWC,EAAU3B,EAAS,CAChC,YAAK,SAAS,KAAK,CACjB,UAAA0B,EACA,SAAAC,EACA,YAAa3B,EAAUA,EAAQ,YAAc,GAC7C,QAASA,EAAUA,EAAQ,QAAU,IAC3C,CAAK,EACM,KAAK,SAAS,OAAS,CAChC,CASA,MAAM4B,EAAI,CACJ,KAAK,SAASA,CAAE,IAClB,KAAK,SAASA,CAAE,EAAI,KAExB,CAOA,OAAQ,CACF,KAAK,WACP,KAAK,SAAW,CAAA,EAEpB,CAYA,QAAQxK,EAAI,CACViI,EAAM,QAAQ,KAAK,SAAU,SAAwBwC,EAAG,CAClDA,IAAM,MACRzK,EAAGyK,CAAC,CAER,CAAC,CACH,CACF,CCnEA,MAAAC,GAAe,CACb,kBAAmB,GACnB,kBAAmB,GACnB,oBAAqB,GACrB,gCAAiC,EACnC,ECJAC,GAAe,OAAO,gBAAoB,IAAc,gBAAkBhB,GCD1EiB,GAAe,OAAO,SAAa,IAAc,SAAW,KCA5DC,GAAe,OAAO,KAAS,IAAc,KAAO,KCEpDC,GAAe,CACb,UAAW,GACX,QAAS,CACX,gBAAIC,GACJ,SAAIC,GACJ,KAAIC,EACJ,EACE,UAAW,CAAC,OAAQ,QAAS,OAAQ,OAAQ,MAAO,MAAM,CAC5D,ECZMC,GAAgB,OAAO,OAAW,KAAe,OAAO,SAAa,IAErEC,GAAa,OAAO,WAAc,UAAY,WAAa,OAmB3DC,GAAwBF,KAC3B,CAACC,IAAc,CAAC,cAAe,eAAgB,IAAI,EAAE,QAAQA,GAAW,OAAO,EAAI,GAWhFE,GAEF,OAAO,kBAAsB,KAE7B,gBAAgB,mBAChB,OAAO,KAAK,eAAkB,WAI5BC,GAASJ,IAAiB,OAAO,SAAS,MAAQ,oNCvCxDK,GAAe,CACb,GAAGtD,GACH,GAAGsD,EACL,ECAe,SAASC,GAAiBnO,EAAMuL,EAAS,CACtD,OAAOF,GAAWrL,EAAM,IAAIkO,GAAS,QAAQ,gBAAmB,CAC9D,QAAS,SAAS1T,EAAOlB,EAAK2R,EAAMmD,EAAS,CAC3C,OAAIF,GAAS,QAAUtD,EAAM,SAASpQ,CAAK,GACzC,KAAK,OAAOlB,EAAKkB,EAAM,SAAS,QAAQ,CAAC,EAClC,IAGF4T,EAAQ,eAAe,MAAM,KAAM,SAAS,CACrD,EACA,GAAG7C,CACP,CAAG,CACH,CCPA,SAAS8C,GAAcvT,EAAM,CAK3B,OAAO8P,EAAM,SAAS,gBAAiB9P,CAAI,EAAE,IAAIuR,GACxCA,EAAM,CAAC,IAAM,KAAO,GAAKA,EAAM,CAAC,GAAKA,EAAM,CAAC,CACpD,CACH,CASA,SAASiC,GAAc/G,EAAK,CAC1B,MAAMnC,EAAM,CAAA,EACN5I,EAAO,OAAO,KAAK+K,CAAG,EAC5B,IAAIjC,EACJ,MAAME,EAAMhJ,EAAK,OACjB,IAAIlD,EACJ,IAAKgM,EAAI,EAAGA,EAAIE,EAAKF,IACnBhM,EAAMkD,EAAK8I,CAAC,EACZF,EAAI9L,CAAG,EAAIiO,EAAIjO,CAAG,EAEpB,OAAO8L,CACT,CASA,SAASmJ,GAAejD,EAAU,CAChC,SAASkD,EAAUvD,EAAMzQ,EAAOgP,EAAQwC,EAAO,CAC7C,IAAIlR,EAAOmQ,EAAKe,GAAO,EAEvB,GAAIlR,IAAS,YAAa,MAAO,GAEjC,MAAM2T,EAAe,OAAO,SAAS,CAAC3T,CAAI,EACpC4T,EAAS1C,GAASf,EAAK,OAG7B,OAFAnQ,EAAO,CAACA,GAAQ8P,EAAM,QAAQpB,CAAM,EAAIA,EAAO,OAAS1O,EAEpD4T,GACE9D,EAAM,WAAWpB,EAAQ1O,CAAI,EAC/B0O,EAAO1O,CAAI,EAAI,CAAC0O,EAAO1O,CAAI,EAAGN,CAAK,EAEnCgP,EAAO1O,CAAI,EAAIN,EAGV,CAACiU,KAGN,CAACjF,EAAO1O,CAAI,GAAK,CAAC8P,EAAM,SAASpB,EAAO1O,CAAI,CAAC,KAC/C0O,EAAO1O,CAAI,EAAI,CAAA,GAGF0T,EAAUvD,EAAMzQ,EAAOgP,EAAO1O,CAAI,EAAGkR,CAAK,GAE3CpB,EAAM,QAAQpB,EAAO1O,CAAI,CAAC,IACtC0O,EAAO1O,CAAI,EAAIwT,GAAc9E,EAAO1O,CAAI,CAAC,GAGpC,CAAC2T,EACV,CAEA,GAAI7D,EAAM,WAAWU,CAAQ,GAAKV,EAAM,WAAWU,EAAS,OAAO,EAAG,CACpE,MAAMlG,EAAM,CAAA,EAEZwF,OAAAA,EAAM,aAAaU,EAAU,CAACxQ,EAAMN,IAAU,CAC5CgU,EAAUH,GAAcvT,CAAI,EAAGN,EAAO4K,EAAK,CAAC,CAC9C,CAAC,EAEMA,CACT,CAEA,OAAO,IACT,CCxEA,SAASuJ,GAAgBC,EAAUC,EAAQrC,EAAS,CAClD,GAAI5B,EAAM,SAASgE,CAAQ,EACzB,GAAI,CACF,OAACC,GAAU,KAAK,OAAOD,CAAQ,EACxBhE,EAAM,KAAKgE,CAAQ,CAC5B,OAAS7N,EAAG,CACV,GAAIA,EAAE,OAAS,cACb,MAAMA,CAEV,CAGF,OAAQyL,GAAW,KAAK,WAAWoC,CAAQ,CAC7C,CAEA,MAAME,GAAW,CAEf,aAAczB,GAEd,QAAS,CAAC,MAAO,OAAQ,OAAO,EAEhC,iBAAkB,CAAC,SAA0BrN,EAAM+O,EAAS,CAC1D,MAAMC,EAAcD,EAAQ,eAAc,GAAM,GAC1CE,EAAqBD,EAAY,QAAQ,kBAAkB,EAAI,GAC/DE,EAAkBtE,EAAM,SAAS5K,CAAI,EAQ3C,GANIkP,GAAmBtE,EAAM,WAAW5K,CAAI,IAC1CA,EAAO,IAAI,SAASA,CAAI,GAGP4K,EAAM,WAAW5K,CAAI,EAGtC,OAAOiP,EAAqB,KAAK,UAAUV,GAAevO,CAAI,CAAC,EAAIA,EAGrE,GAAI4K,EAAM,cAAc5K,CAAI,GAC1B4K,EAAM,SAAS5K,CAAI,GACnB4K,EAAM,SAAS5K,CAAI,GACnB4K,EAAM,OAAO5K,CAAI,GACjB4K,EAAM,OAAO5K,CAAI,GACjB4K,EAAM,iBAAiB5K,CAAI,EAE3B,OAAOA,EAET,GAAI4K,EAAM,kBAAkB5K,CAAI,EAC9B,OAAOA,EAAK,OAEd,GAAI4K,EAAM,kBAAkB5K,CAAI,EAC9B,OAAA+O,EAAQ,eAAe,kDAAmD,EAAK,EACxE/O,EAAK,SAAQ,EAGtB,IAAIyE,EAEJ,GAAIyK,EAAiB,CACnB,GAAIF,EAAY,QAAQ,mCAAmC,EAAI,GAC7D,OAAOb,GAAiBnO,EAAM,KAAK,cAAc,EAAE,SAAQ,EAG7D,IAAKyE,EAAamG,EAAM,WAAW5K,CAAI,IAAMgP,EAAY,QAAQ,qBAAqB,EAAI,GAAI,CAC5F,MAAMG,EAAY,KAAK,KAAO,KAAK,IAAI,SAEvC,OAAO9D,GACL5G,EAAa,CAAC,UAAWzE,CAAI,EAAIA,EACjCmP,GAAa,IAAIA,EACjB,KAAK,cACf,CACM,CACF,CAEA,OAAID,GAAmBD,GACrBF,EAAQ,eAAe,mBAAoB,EAAK,EACzCJ,GAAgB3O,CAAI,GAGtBA,CACT,CAAC,EAED,kBAAmB,CAAC,SAA2BA,EAAM,CACnD,MAAMoP,EAAe,KAAK,cAAgBN,GAAS,aAC7CO,EAAoBD,GAAgBA,EAAa,kBACjDE,EAAgB,KAAK,eAAiB,OAE5C,GAAI1E,EAAM,WAAW5K,CAAI,GAAK4K,EAAM,iBAAiB5K,CAAI,EACvD,OAAOA,EAGT,GAAIA,GAAQ4K,EAAM,SAAS5K,CAAI,IAAOqP,GAAqB,CAAC,KAAK,cAAiBC,GAAgB,CAEhG,MAAMC,EAAoB,EADAH,GAAgBA,EAAa,oBACPE,EAEhD,GAAI,CACF,OAAO,KAAK,MAAMtP,EAAM,KAAK,YAAY,CAC3C,OAASe,EAAG,CACV,GAAIwO,EACF,MAAIxO,EAAE,OAAS,cACPsJ,EAAW,KAAKtJ,EAAGsJ,EAAW,iBAAkB,KAAM,KAAM,KAAK,QAAQ,EAE3EtJ,CAEV,CACF,CAEA,OAAOf,CACT,CAAC,EAMD,QAAS,EAET,eAAgB,aAChB,eAAgB,eAEhB,iBAAkB,GAClB,cAAe,GAEf,IAAK,CACH,SAAUkO,GAAS,QAAQ,SAC3B,KAAMA,GAAS,QAAQ,IAC3B,EAEE,eAAgB,SAAwBpO,EAAQ,CAC9C,OAAOA,GAAU,KAAOA,EAAS,GACnC,EAEA,QAAS,CACP,OAAQ,CACN,OAAU,oCACV,eAAgB,MACtB,CACA,CACA,EAEA8K,EAAM,QAAQ,CAAC,SAAU,MAAO,OAAQ,OAAQ,MAAO,OAAO,EAAI4E,GAAW,CAC3EV,GAAS,QAAQU,CAAM,EAAI,CAAA,CAC7B,CAAC,ECxJD,MAAMC,GAAoB7E,EAAM,YAAY,CAC1C,MAAO,gBAAiB,iBAAkB,eAAgB,OAC1D,UAAW,OAAQ,OAAQ,oBAAqB,sBAChD,gBAAiB,WAAY,eAAgB,sBAC7C,UAAW,cAAe,YAC5B,CAAC,EAgBD8E,GAAeC,GAAc,CAC3B,MAAMC,EAAS,CAAA,EACf,IAAItW,EACAoK,EACA4B,EAEJ,OAAAqK,GAAcA,EAAW,MAAM;AAAA,CAAI,EAAE,QAAQ,SAAgBE,EAAM,CACjEvK,EAAIuK,EAAK,QAAQ,GAAG,EACpBvW,EAAMuW,EAAK,UAAU,EAAGvK,CAAC,EAAE,KAAI,EAAG,YAAW,EAC7C5B,EAAMmM,EAAK,UAAUvK,EAAI,CAAC,EAAE,KAAI,EAE5B,GAAChM,GAAQsW,EAAOtW,CAAG,GAAKmW,GAAkBnW,CAAG,KAI7CA,IAAQ,aACNsW,EAAOtW,CAAG,EACZsW,EAAOtW,CAAG,EAAE,KAAKoK,CAAG,EAEpBkM,EAAOtW,CAAG,EAAI,CAACoK,CAAG,EAGpBkM,EAAOtW,CAAG,EAAIsW,EAAOtW,CAAG,EAAIsW,EAAOtW,CAAG,EAAI,KAAOoK,EAAMA,EAE3D,CAAC,EAEMkM,CACT,ECjDME,GAAa,OAAO,WAAW,EAErC,SAASC,GAAgBC,EAAQ,CAC/B,OAAOA,GAAU,OAAOA,CAAM,EAAE,KAAI,EAAG,YAAW,CACpD,CAEA,SAASC,GAAezV,EAAO,CAC7B,OAAIA,IAAU,IAASA,GAAS,KACvBA,EAGFoQ,EAAM,QAAQpQ,CAAK,EAAIA,EAAM,IAAIyV,EAAc,EAAI,OAAOzV,CAAK,CACxE,CAEA,SAAS0V,GAAY9M,EAAK,CACxB,MAAM+M,EAAS,OAAO,OAAO,IAAI,EAC3BC,EAAW,mCACjB,IAAI/D,EAEJ,KAAQA,EAAQ+D,EAAS,KAAKhN,CAAG,GAC/B+M,EAAO9D,EAAM,CAAC,CAAC,EAAIA,EAAM,CAAC,EAG5B,OAAO8D,CACT,CAEA,MAAME,GAAqBjN,GAAQ,iCAAiC,KAAKA,EAAI,MAAM,EAEnF,SAASkN,GAAiBzK,EAASrL,EAAOwV,EAAQjJ,EAAQwJ,EAAoB,CAC5E,GAAI3F,EAAM,WAAW7D,CAAM,EACzB,OAAOA,EAAO,KAAK,KAAMvM,EAAOwV,CAAM,EAOxC,GAJIO,IACF/V,EAAQwV,GAGN,EAACpF,EAAM,SAASpQ,CAAK,EAEzB,IAAIoQ,EAAM,SAAS7D,CAAM,EACvB,OAAOvM,EAAM,QAAQuM,CAAM,IAAM,GAGnC,GAAI6D,EAAM,SAAS7D,CAAM,EACvB,OAAOA,EAAO,KAAKvM,CAAK,EAE5B,CAEA,SAASgW,GAAaR,EAAQ,CAC5B,OAAOA,EAAO,KAAI,EACf,YAAW,EAAG,QAAQ,kBAAmB,CAACS,EAAGC,EAAMtN,IAC3CsN,EAAK,YAAW,EAAKtN,CAC7B,CACL,CAEA,SAASuN,GAAevL,EAAK4K,EAAQ,CACnC,MAAMY,EAAehG,EAAM,YAAY,IAAMoF,CAAM,EAEnD,CAAC,MAAO,MAAO,KAAK,EAAE,QAAQa,GAAc,CAC1C,OAAO,eAAezL,EAAKyL,EAAaD,EAAc,CACpD,MAAO,SAASE,EAAMC,EAAMC,EAAM,CAChC,OAAO,KAAKH,CAAU,EAAE,KAAK,KAAMb,EAAQc,EAAMC,EAAMC,CAAI,CAC7D,EACA,aAAc,EACpB,CAAK,CACH,CAAC,CACH,CAEA,IAAAC,GAAA,KAAmB,CACjB,YAAYlC,EAAS,CACnBA,GAAW,KAAK,IAAIA,CAAO,CAC7B,CAEA,IAAIiB,EAAQkB,EAAgBC,EAAS,CACnC,MAAMC,EAAO,KAEb,SAASC,EAAUC,EAAQC,EAASC,EAAU,CAC5C,MAAMC,EAAU1B,GAAgBwB,CAAO,EAEvC,GAAI,CAACE,EACH,MAAM,IAAI,MAAM,wCAAwC,EAG1D,MAAMnY,EAAMsR,EAAM,QAAQwG,EAAMK,CAAO,GAEpC,CAACnY,GAAO8X,EAAK9X,CAAG,IAAM,QAAakY,IAAa,IAASA,IAAa,QAAaJ,EAAK9X,CAAG,IAAM,MAClG8X,EAAK9X,GAAOiY,CAAO,EAAItB,GAAeqB,CAAM,EAEhD,CAEA,MAAMI,EAAa,CAAC3C,EAASyC,IAC3B5G,EAAM,QAAQmE,EAAS,CAACuC,EAAQC,IAAYF,EAAUC,EAAQC,EAASC,CAAQ,CAAC,EAElF,GAAI5G,EAAM,cAAcoF,CAAM,GAAKA,aAAkB,KAAK,YACxD0B,EAAW1B,EAAQkB,CAAc,UACzBtG,EAAM,SAASoF,CAAM,IAAMA,EAASA,EAAO,KAAI,IAAO,CAACK,GAAkBL,CAAM,EACvF0B,EAAWhC,GAAaM,CAAM,EAAGkB,CAAc,UACtCtG,EAAM,SAASoF,CAAM,GAAKpF,EAAM,WAAWoF,CAAM,EAAG,CAC7D,IAAI5K,EAAM,GAAIuM,EAAMrY,EACpB,UAAWsY,KAAS5B,EAAQ,CAC1B,GAAI,CAACpF,EAAM,QAAQgH,CAAK,EACtB,MAAM,UAAU,8CAA8C,EAGhExM,EAAI9L,EAAMsY,EAAM,CAAC,CAAC,GAAKD,EAAOvM,EAAI9L,CAAG,GAClCsR,EAAM,QAAQ+G,CAAI,EAAI,CAAC,GAAGA,EAAMC,EAAM,CAAC,CAAC,EAAI,CAACD,EAAMC,EAAM,CAAC,CAAC,EAAKA,EAAM,CAAC,CAC5E,CAEAF,EAAWtM,EAAK8L,CAAc,CAChC,MACElB,GAAU,MAAQqB,EAAUH,EAAgBlB,EAAQmB,CAAO,EAG7D,OAAO,IACT,CAEA,IAAInB,EAAQnB,EAAQ,CAGlB,GAFAmB,EAASD,GAAgBC,CAAM,EAE3BA,EAAQ,CACV,MAAM1W,EAAMsR,EAAM,QAAQ,KAAMoF,CAAM,EAEtC,GAAI1W,EAAK,CACP,MAAMkB,EAAQ,KAAKlB,CAAG,EAEtB,GAAI,CAACuV,EACH,OAAOrU,EAGT,GAAIqU,IAAW,GACb,OAAOqB,GAAY1V,CAAK,EAG1B,GAAIoQ,EAAM,WAAWiE,CAAM,EACzB,OAAOA,EAAO,KAAK,KAAMrU,EAAOlB,CAAG,EAGrC,GAAIsR,EAAM,SAASiE,CAAM,EACvB,OAAOA,EAAO,KAAKrU,CAAK,EAG1B,MAAM,IAAI,UAAU,wCAAwC,CAC9D,CACF,CACF,CAEA,IAAIwV,EAAQ6B,EAAS,CAGnB,GAFA7B,EAASD,GAAgBC,CAAM,EAE3BA,EAAQ,CACV,MAAM1W,EAAMsR,EAAM,QAAQ,KAAMoF,CAAM,EAEtC,MAAO,CAAC,EAAE1W,GAAO,KAAKA,CAAG,IAAM,SAAc,CAACuY,GAAWvB,GAAiB,KAAM,KAAKhX,CAAG,EAAGA,EAAKuY,CAAO,GACzG,CAEA,MAAO,EACT,CAEA,OAAO7B,EAAQ6B,EAAS,CACtB,MAAMT,EAAO,KACb,IAAIU,EAAU,GAEd,SAASC,EAAaR,EAAS,CAG7B,GAFAA,EAAUxB,GAAgBwB,CAAO,EAE7BA,EAAS,CACX,MAAMjY,EAAMsR,EAAM,QAAQwG,EAAMG,CAAO,EAEnCjY,IAAQ,CAACuY,GAAWvB,GAAiBc,EAAMA,EAAK9X,CAAG,EAAGA,EAAKuY,CAAO,KACpE,OAAOT,EAAK9X,CAAG,EAEfwY,EAAU,GAEd,CACF,CAEA,OAAIlH,EAAM,QAAQoF,CAAM,EACtBA,EAAO,QAAQ+B,CAAY,EAE3BA,EAAa/B,CAAM,EAGd8B,CACT,CAEA,MAAMD,EAAS,CACb,MAAMrV,EAAO,OAAO,KAAK,IAAI,EAC7B,IAAI8I,EAAI9I,EAAK,OACTsV,EAAU,GAEd,KAAOxM,KAAK,CACV,MAAMhM,EAAMkD,EAAK8I,CAAC,GACf,CAACuM,GAAWvB,GAAiB,KAAM,KAAKhX,CAAG,EAAGA,EAAKuY,EAAS,EAAI,KACjE,OAAO,KAAKvY,CAAG,EACfwY,EAAU,GAEd,CAEA,OAAOA,CACT,CAEA,UAAUE,EAAQ,CAChB,MAAMZ,EAAO,KACPrC,EAAU,CAAA,EAEhBnE,OAAAA,EAAM,QAAQ,KAAM,CAACpQ,EAAOwV,IAAW,CACrC,MAAM1W,EAAMsR,EAAM,QAAQmE,EAASiB,CAAM,EAEzC,GAAI1W,EAAK,CACP8X,EAAK9X,CAAG,EAAI2W,GAAezV,CAAK,EAChC,OAAO4W,EAAKpB,CAAM,EAClB,MACF,CAEA,MAAMiC,EAAaD,EAASxB,GAAaR,CAAM,EAAI,OAAOA,CAAM,EAAE,KAAI,EAElEiC,IAAejC,GACjB,OAAOoB,EAAKpB,CAAM,EAGpBoB,EAAKa,CAAU,EAAIhC,GAAezV,CAAK,EAEvCuU,EAAQkD,CAAU,EAAI,EACxB,CAAC,EAEM,IACT,CAEA,UAAUC,EAAS,CACjB,OAAO,KAAK,YAAY,OAAO,KAAM,GAAGA,CAAO,CACjD,CAEA,OAAOC,EAAW,CAChB,MAAM/M,EAAM,OAAO,OAAO,IAAI,EAE9BwF,OAAAA,EAAM,QAAQ,KAAM,CAACpQ,EAAOwV,IAAW,CACrCxV,GAAS,MAAQA,IAAU,KAAU4K,EAAI4K,CAAM,EAAImC,GAAavH,EAAM,QAAQpQ,CAAK,EAAIA,EAAM,KAAK,IAAI,EAAIA,EAC5G,CAAC,EAEM4K,CACT,CAEA,CAAC,OAAO,QAAQ,GAAI,CAClB,OAAO,OAAO,QAAQ,KAAK,OAAM,CAAE,EAAE,OAAO,QAAQ,EAAC,CACvD,CAEA,UAAW,CACT,OAAO,OAAO,QAAQ,KAAK,OAAM,CAAE,EAAE,IAAI,CAAC,CAAC4K,EAAQxV,CAAK,IAAMwV,EAAS,KAAOxV,CAAK,EAAE,KAAK;AAAA,CAAI,CAChG,CAEA,cAAe,CACb,OAAO,KAAK,IAAI,YAAY,GAAK,CAAA,CACnC,CAEA,IAAK,OAAO,WAAW,GAAI,CACzB,MAAO,cACT,CAEA,OAAO,KAAK2I,EAAO,CACjB,OAAOA,aAAiB,KAAOA,EAAQ,IAAI,KAAKA,CAAK,CACvD,CAEA,OAAO,OAAOiP,KAAUF,EAAS,CAC/B,MAAMG,EAAW,IAAI,KAAKD,CAAK,EAE/B,OAAAF,EAAQ,QAAS1I,GAAW6I,EAAS,IAAI7I,CAAM,CAAC,EAEzC6I,CACT,CAEA,OAAO,SAASrC,EAAQ,CAKtB,MAAMsC,GAJY,KAAKxC,EAAU,EAAK,KAAKA,EAAU,EAAI,CACvD,UAAW,CAAA,CACjB,GAEgC,UACtB1L,EAAY,KAAK,UAEvB,SAASmO,EAAehB,EAAS,CAC/B,MAAME,EAAU1B,GAAgBwB,CAAO,EAElCe,EAAUb,CAAO,IACpBd,GAAevM,EAAWmN,CAAO,EACjCe,EAAUb,CAAO,EAAI,GAEzB,CAEA7G,OAAAA,EAAM,QAAQoF,CAAM,EAAIA,EAAO,QAAQuC,CAAc,EAAIA,EAAevC,CAAM,EAEvE,IACT,CACF,EAEAwC,GAAa,SAAS,CAAC,eAAgB,iBAAkB,SAAU,kBAAmB,aAAc,eAAe,CAAC,EAGpH5H,EAAM,kBAAkB4H,GAAa,UAAW,CAAC,CAAC,MAAAhY,CAAK,EAAGlB,IAAQ,CAChE,IAAImZ,EAASnZ,EAAI,CAAC,EAAE,YAAW,EAAKA,EAAI,MAAM,CAAC,EAC/C,MAAO,CACL,IAAK,IAAMkB,EACX,IAAIkY,EAAa,CACf,KAAKD,CAAM,EAAIC,CACjB,CACJ,CACA,CAAC,EAED9H,EAAM,cAAc4H,EAAY,ECzSjB,SAASG,GAAcC,EAAKpI,EAAU,CACnD,MAAMpR,EAAS,MAAQ0V,GACjBjJ,EAAU2E,GAAYpR,EACtB2V,EAAUyD,GAAa,KAAK3M,EAAQ,OAAO,EACjD,IAAI7F,EAAO6F,EAAQ,KAEnB+E,OAAAA,EAAM,QAAQgI,EAAK,SAAmBjQ,EAAI,CACxC3C,EAAO2C,EAAG,KAAKvJ,EAAQ4G,EAAM+O,EAAQ,UAAS,EAAIvE,EAAWA,EAAS,OAAS,MAAS,CAC1F,CAAC,EAEDuE,EAAQ,UAAS,EAEV/O,CACT,CCzBe,SAAS6S,GAASrY,EAAO,CACtC,MAAO,CAAC,EAAEA,GAASA,EAAM,WAC3B,QCAA,cAA4B6P,CAAW,CAUrC,YAAYM,EAASvR,EAAQmR,EAAS,CACpC,MAAMI,GAAkB,WAAsBN,EAAW,aAAcjR,EAAQmR,CAAO,EACtF,KAAK,KAAO,gBACZ,KAAK,WAAa,EACpB,CACF,ECNe,SAASuI,GAAOC,EAASC,EAAQxI,EAAU,CACxD,MAAMyI,EAAiBzI,EAAS,OAAO,eACnC,CAACA,EAAS,QAAU,CAACyI,GAAkBA,EAAezI,EAAS,MAAM,EACvEuI,EAAQvI,CAAQ,EAEhBwI,EAAO,IAAI3I,EACT,mCAAqCG,EAAS,OAC9C,CAACH,EAAW,gBAAiBA,EAAW,gBAAgB,EAAE,KAAK,MAAMG,EAAS,OAAS,GAAG,EAAI,CAAC,EAC/FA,EAAS,OACTA,EAAS,QACTA,CACN,CAAK,CAEL,CCxBe,SAAS0I,GAAcvG,EAAK,CACzC,MAAMN,EAAQ,4BAA4B,KAAKM,CAAG,EAClD,OAAON,GAASA,EAAM,CAAC,GAAK,EAC9B,CCGA,SAAS8G,GAAYC,EAAcC,EAAK,CACtCD,EAAeA,GAAgB,GAC/B,MAAME,EAAQ,IAAI,MAAMF,CAAY,EAC9BG,EAAa,IAAI,MAAMH,CAAY,EACzC,IAAII,EAAO,EACPC,EAAO,EACPC,EAEJ,OAAAL,EAAMA,IAAQ,OAAYA,EAAM,IAEzB,SAAcM,EAAa,CAChC,MAAMC,EAAM,KAAK,IAAG,EAEdC,EAAYN,EAAWE,CAAI,EAE5BC,IACHA,EAAgBE,GAGlBN,EAAME,CAAI,EAAIG,EACdJ,EAAWC,CAAI,EAAII,EAEnB,IAAItO,EAAImO,EACJK,EAAa,EAEjB,KAAOxO,IAAMkO,GACXM,GAAcR,EAAMhO,GAAG,EACvBA,EAAIA,EAAI8N,EASV,GANAI,GAAQA,EAAO,GAAKJ,EAEhBI,IAASC,IACXA,GAAQA,EAAO,GAAKL,GAGlBQ,EAAMF,EAAgBL,EACxB,OAGF,MAAMU,EAASF,GAAaD,EAAMC,EAElC,OAAOE,EAAS,KAAK,MAAMD,EAAa,IAAOC,CAAM,EAAI,MAC3D,CACF,CC9CA,SAASC,GAASrR,EAAIsR,EAAM,CAC1B,IAAIC,EAAY,EACZC,EAAY,IAAOF,EACnBG,EACAC,EAEJ,MAAMC,EAAS,CAACC,EAAMX,EAAM,KAAK,IAAG,IAAO,CACzCM,EAAYN,EACZQ,EAAW,KACPC,IACF,aAAaA,CAAK,EAClBA,EAAQ,MAEV1R,EAAG,GAAG4R,CAAI,CACZ,EAoBA,MAAO,CAlBW,IAAIA,IAAS,CAC7B,MAAMX,EAAM,KAAK,IAAG,EACdG,EAASH,EAAMM,EAChBH,GAAUI,EACbG,EAAOC,EAAMX,CAAG,GAEhBQ,EAAWG,EACNF,IACHA,EAAQ,WAAW,IAAM,CACvBA,EAAQ,KACRC,EAAOF,CAAQ,CACjB,EAAGD,EAAYJ,CAAM,GAG3B,EAEc,IAAMK,GAAYE,EAAOF,CAAQ,CAEvB,CAC1B,CCrCO,MAAMI,GAAuB,CAACC,EAAUC,EAAkBT,EAAO,IAAM,CAC5E,IAAIU,EAAgB,EACpB,MAAMC,EAAezB,GAAY,GAAI,GAAG,EAExC,OAAOa,GAASjT,GAAK,CACnB,MAAM8T,EAAS9T,EAAE,OACX+T,EAAQ/T,EAAE,iBAAmBA,EAAE,MAAQ,OACvCgU,EAAgBF,EAASF,EACzBK,EAAOJ,EAAaG,CAAa,EACjCE,EAAUJ,GAAUC,EAE1BH,EAAgBE,EAEhB,MAAM7U,EAAO,CACX,OAAA6U,EACA,MAAAC,EACA,SAAUA,EAASD,EAASC,EAAS,OACrC,MAAOC,EACP,KAAMC,GAAc,OACpB,UAAWA,GAAQF,GAASG,GAAWH,EAAQD,GAAUG,EAAO,OAChE,MAAOjU,EACP,iBAAkB+T,GAAS,KAC3B,CAACJ,EAAmB,WAAa,QAAQ,EAAG,EAClD,EAEID,EAASzU,CAAI,CACf,EAAGiU,CAAI,CACT,EAEaiB,GAAyB,CAACJ,EAAOK,IAAc,CAC1D,MAAMC,EAAmBN,GAAS,KAElC,MAAO,CAAED,GAAWM,EAAU,CAAC,EAAE,CAC/B,iBAAAC,EACA,MAAAN,EACA,OAAAD,CACJ,CAAG,EAAGM,EAAU,CAAC,CAAC,CAClB,EAEaE,GAAkB1S,GAAO,IAAI4R,IAAS3J,EAAM,KAAK,IAAMjI,EAAG,GAAG4R,CAAI,CAAC,ECzC/Ee,GAAepH,GAAS,uBAAyB,CAACD,EAAQsH,IAAY5I,IACpEA,EAAM,IAAI,IAAIA,EAAKuB,GAAS,MAAM,EAGhCD,EAAO,WAAatB,EAAI,UACxBsB,EAAO,OAAStB,EAAI,OACnB4I,GAAUtH,EAAO,OAAStB,EAAI,QAGjC,IAAI,IAAIuB,GAAS,MAAM,EACvBA,GAAS,WAAa,kBAAkB,KAAKA,GAAS,UAAU,SAAS,CAC3E,EAAI,IAAM,GCVVsH,GAAetH,GAAS,sBAGtB,CACE,MAAMpT,EAAMN,EAAOib,EAASxK,EAAMyK,EAAQC,EAAQC,EAAU,CAC1D,GAAI,OAAO,SAAa,IAAa,OAErC,MAAMC,EAAS,CAAC,GAAG/a,CAAI,IAAI,mBAAmBN,CAAK,CAAC,EAAE,EAElDoQ,EAAM,SAAS6K,CAAO,GACxBI,EAAO,KAAK,WAAW,IAAI,KAAKJ,CAAO,EAAE,YAAW,CAAE,EAAE,EAEtD7K,EAAM,SAASK,CAAI,GACrB4K,EAAO,KAAK,QAAQ5K,CAAI,EAAE,EAExBL,EAAM,SAAS8K,CAAM,GACvBG,EAAO,KAAK,UAAUH,CAAM,EAAE,EAE5BC,IAAW,IACbE,EAAO,KAAK,QAAQ,EAElBjL,EAAM,SAASgL,CAAQ,GACzBC,EAAO,KAAK,YAAYD,CAAQ,EAAE,EAGpC,SAAS,OAASC,EAAO,KAAK,IAAI,CACpC,EAEA,KAAK/a,EAAM,CACT,GAAI,OAAO,SAAa,IAAa,OAAO,KAC5C,MAAMuR,EAAQ,SAAS,OAAO,MAAM,IAAI,OAAO,WAAavR,EAAO,UAAU,CAAC,EAC9E,OAAOuR,EAAQ,mBAAmBA,EAAM,CAAC,CAAC,EAAI,IAChD,EAEA,OAAOvR,EAAM,CACX,KAAK,MAAMA,EAAM,GAAI,KAAK,IAAG,EAAK,MAAU,GAAG,CACjD,CACJ,EAKE,CACE,OAAQ,CAAC,EACT,MAAO,CACL,OAAO,IACT,EACA,QAAS,CAAC,CACd,EC1Ce,SAASgb,GAAcnJ,EAAK,CAIzC,OAAI,OAAOA,GAAQ,SACV,GAGF,8BAA8B,KAAKA,CAAG,CAC/C,CCRe,SAASoJ,GAAYC,EAASC,EAAa,CACxD,OAAOA,EACHD,EAAQ,QAAQ,SAAU,EAAE,EAAI,IAAMC,EAAY,QAAQ,OAAQ,EAAE,EACpED,CACN,CCCe,SAASE,GAAcF,EAASG,EAAcC,EAAmB,CAC9E,IAAIC,EAAgB,CAACP,GAAcK,CAAY,EAC/C,OAAIH,IAAYK,GAAiBD,GAAqB,IAC7CL,GAAYC,EAASG,CAAY,EAEnCA,CACT,CChBA,MAAMG,GAAmBnT,GACvBA,aAAiBqP,GAAe,CAAE,GAAGrP,CAAK,EAAKA,EAWlC,SAASoT,GAAYC,EAASC,EAAS,CAEpDA,EAAUA,GAAW,CAAA,EACrB,MAAMrd,EAAS,CAAA,EAEf,SAASsd,EAAelN,EAAQD,EAAQtC,EAAMlB,EAAU,CACtD,OAAI6E,EAAM,cAAcpB,CAAM,GAAKoB,EAAM,cAAcrB,CAAM,EACpDqB,EAAM,MAAM,KAAK,CAAE,SAAA7E,CAAQ,EAAIyD,EAAQD,CAAM,EAC3CqB,EAAM,cAAcrB,CAAM,EAC5BqB,EAAM,MAAM,CAAA,EAAIrB,CAAM,EACpBqB,EAAM,QAAQrB,CAAM,EACtBA,EAAO,MAAK,EAEdA,CACT,CAEA,SAASoN,EAAoBvQ,EAAGC,EAAGY,EAAMlB,EAAU,CACjD,GAAK6E,EAAM,YAAYvE,CAAC,GAEjB,GAAI,CAACuE,EAAM,YAAYxE,CAAC,EAC7B,OAAOsQ,EAAe,OAAWtQ,EAAGa,EAAMlB,CAAQ,MAFlD,QAAO2Q,EAAetQ,EAAGC,EAAGY,EAAMlB,CAAQ,CAI9C,CAGA,SAAS6Q,EAAiBxQ,EAAGC,EAAG,CAC9B,GAAI,CAACuE,EAAM,YAAYvE,CAAC,EACtB,OAAOqQ,EAAe,OAAWrQ,CAAC,CAEtC,CAGA,SAASwQ,EAAiBzQ,EAAGC,EAAG,CAC9B,GAAKuE,EAAM,YAAYvE,CAAC,GAEjB,GAAI,CAACuE,EAAM,YAAYxE,CAAC,EAC7B,OAAOsQ,EAAe,OAAWtQ,CAAC,MAFlC,QAAOsQ,EAAe,OAAWrQ,CAAC,CAItC,CAGA,SAASyQ,EAAgB1Q,EAAGC,EAAGY,EAAM,CACnC,GAAIA,KAAQwP,EACV,OAAOC,EAAetQ,EAAGC,CAAC,EACrB,GAAIY,KAAQuP,EACjB,OAAOE,EAAe,OAAWtQ,CAAC,CAEtC,CAEA,MAAM2Q,EAAW,CACf,IAAKH,EACL,OAAQA,EACR,KAAMA,EACN,QAASC,EACT,iBAAkBA,EAClB,kBAAmBA,EACnB,iBAAkBA,EAClB,QAASA,EACT,eAAgBA,EAChB,gBAAiBA,EACjB,cAAeA,EACf,QAASA,EACT,aAAcA,EACd,eAAgBA,EAChB,eAAgBA,EAChB,iBAAkBA,EAClB,mBAAoBA,EACpB,WAAYA,EACZ,iBAAkBA,EAClB,cAAeA,EACf,eAAgBA,EAChB,UAAWA,EACX,UAAWA,EACX,WAAYA,EACZ,YAAaA,EACb,WAAYA,EACZ,iBAAkBA,EAClB,eAAgBC,EAChB,QAAS,CAAC1Q,EAAGC,EAAGY,IACd0P,EAAoBL,GAAgBlQ,CAAC,EAAGkQ,GAAgBjQ,CAAC,EAAGY,EAAM,EAAI,CAC5E,EAEE2D,OAAAA,EAAM,QACJ,OAAO,KAAK,CAAE,GAAG4L,EAAS,GAAGC,CAAO,CAAE,EACtC,SAA4BxP,EAAM,CAChC,GACEA,IAAS,aACTA,IAAS,eACTA,IAAS,YAET,OACF,MAAMnB,EAAQ8E,EAAM,WAAWmM,EAAU9P,CAAI,EACzC8P,EAAS9P,CAAI,EACb0P,EACEK,EAAclR,EAAM0Q,EAAQvP,CAAI,EAAGwP,EAAQxP,CAAI,EAAGA,CAAI,EAC3D2D,EAAM,YAAYoM,CAAW,GAAKlR,IAAUgR,IAC1C1d,EAAO6N,CAAI,EAAI+P,EACpB,CACJ,EAES5d,CACT,CC7GA,MAAA6d,GAAgB7d,GAAW,CACzB,MAAM8d,EAAYX,GAAY,CAAA,EAAInd,CAAM,EAExC,GAAI,CAAE,KAAA4G,EAAM,cAAAmX,EAAe,eAAAC,EAAgB,eAAAC,EAAgB,QAAAtI,EAAS,KAAAuI,CAAI,EAAKJ,EAa7E,GAXAA,EAAU,QAAUnI,EAAUyD,GAAa,KAAKzD,CAAO,EAEvDmI,EAAU,IAAMxK,GAASwJ,GAAcgB,EAAU,QAASA,EAAU,IAAKA,EAAU,iBAAiB,EAAG9d,EAAO,OAAQA,EAAO,gBAAgB,EAGzIke,GACFvI,EAAQ,IAAI,gBAAiB,SAC3B,MAAMuI,EAAK,UAAY,IAAM,KAAOA,EAAK,SAAW,SAAS,mBAAmBA,EAAK,QAAQ,CAAC,EAAI,GAAG,CAC3G,EAGM1M,EAAM,WAAW5K,CAAI,GACvB,GAAIkO,GAAS,uBAAyBA,GAAS,+BAC7Ca,EAAQ,eAAe,MAAS,UACvBnE,EAAM,WAAW5K,EAAK,UAAU,EAAG,CAE5C,MAAMuX,EAAcvX,EAAK,WAAU,EAE7BwX,EAAiB,CAAC,eAAgB,gBAAgB,EACxD,OAAO,QAAQD,CAAW,EAAE,QAAQ,CAAC,CAACje,EAAKoK,CAAG,IAAM,CAC9C8T,EAAe,SAASle,EAAI,YAAW,CAAE,GAC3CyV,EAAQ,IAAIzV,EAAKoK,CAAG,CAExB,CAAC,CACH,EAOF,GAAIwK,GAAS,wBACXiJ,GAAiBvM,EAAM,WAAWuM,CAAa,IAAMA,EAAgBA,EAAcD,CAAS,GAExFC,GAAkBA,IAAkB,IAAS7B,GAAgB4B,EAAU,GAAG,GAAI,CAEhF,MAAMO,EAAYL,GAAkBC,GAAkB7B,GAAQ,KAAK6B,CAAc,EAE7EI,GACF1I,EAAQ,IAAIqI,EAAgBK,CAAS,CAEzC,CAGF,OAAOP,CACT,EChDMQ,GAAwB,OAAO,eAAmB,IAExDC,GAAeD,IAAyB,SAAUte,EAAQ,CACxD,OAAO,IAAI,QAAQ,SAA4B2Z,EAASC,EAAQ,CAC9D,MAAM4E,EAAUX,GAAc7d,CAAM,EACpC,IAAIye,EAAcD,EAAQ,KAC1B,MAAME,EAAiBtF,GAAa,KAAKoF,EAAQ,OAAO,EAAE,UAAS,EACnE,GAAI,CAAC,aAAAG,EAAc,iBAAAC,EAAkB,mBAAAC,CAAkB,EAAIL,EACvDM,EACAC,EAAiBC,EACjBC,EAAaC,EAEjB,SAASC,GAAO,CACdF,GAAeA,EAAW,EAC1BC,GAAiBA,EAAa,EAE9BV,EAAQ,aAAeA,EAAQ,YAAY,YAAYM,CAAU,EAEjEN,EAAQ,QAAUA,EAAQ,OAAO,oBAAoB,QAASM,CAAU,CAC1E,CAEA,IAAI3N,EAAU,IAAI,eAElBA,EAAQ,KAAKqN,EAAQ,OAAO,YAAW,EAAIA,EAAQ,IAAK,EAAI,EAG5DrN,EAAQ,QAAUqN,EAAQ,QAE1B,SAASY,GAAY,CACnB,GAAI,CAACjO,EACH,OAGF,MAAMkO,EAAkBjG,GAAa,KACnC,0BAA2BjI,GAAWA,EAAQ,sBAAqB,CAC3E,EAGYC,EAAW,CACf,KAHmB,CAACuN,GAAgBA,IAAiB,QAAUA,IAAiB,OAChFxN,EAAQ,aAAeA,EAAQ,SAG/B,OAAQA,EAAQ,OAChB,WAAYA,EAAQ,WACpB,QAASkO,EACT,OAAArf,EACA,QAAAmR,CACR,EAEMuI,GAAO,SAAkBtY,EAAO,CAC9BuY,EAAQvY,CAAK,EACb+d,EAAI,CACN,EAAG,SAAiBG,EAAK,CACvB1F,EAAO0F,CAAG,EACVH,EAAI,CACN,EAAG/N,CAAQ,EAGXD,EAAU,IACZ,CAEI,cAAeA,EAEjBA,EAAQ,UAAYiO,EAGpBjO,EAAQ,mBAAqB,UAAsB,CAC7C,CAACA,GAAWA,EAAQ,aAAe,GAQnCA,EAAQ,SAAW,GAAK,EAAEA,EAAQ,aAAeA,EAAQ,YAAY,QAAQ,OAAO,IAAM,IAK9F,WAAWiO,CAAS,CACtB,EAIFjO,EAAQ,QAAU,UAAuB,CAClCA,IAILyI,EAAO,IAAI3I,EAAW,kBAAmBA,EAAW,aAAcjR,EAAQmR,CAAO,CAAC,EAGlFA,EAAU,KACZ,EAGFA,EAAQ,QAAU,SAAqB3J,EAAO,CAIzC,MAAM+X,EAAM/X,GAASA,EAAM,QAAUA,EAAM,QAAU,gBAC/C8X,EAAM,IAAIrO,EAAWsO,EAAKtO,EAAW,YAAajR,EAAQmR,CAAO,EAEvEmO,EAAI,MAAQ9X,GAAS,KACrBoS,EAAO0F,CAAG,EACVnO,EAAU,IACb,EAGAA,EAAQ,UAAY,UAAyB,CAC3C,IAAIqO,EAAsBhB,EAAQ,QAAU,cAAgBA,EAAQ,QAAU,cAAgB,mBAC9F,MAAMxI,EAAewI,EAAQ,cAAgBvK,GACzCuK,EAAQ,sBACVgB,EAAsBhB,EAAQ,qBAEhC5E,EAAO,IAAI3I,EACTuO,EACAxJ,EAAa,oBAAsB/E,EAAW,UAAYA,EAAW,aACrEjR,EACAmR,CAAO,CAAC,EAGVA,EAAU,IACZ,EAGAsN,IAAgB,QAAaC,EAAe,eAAe,IAAI,EAG3D,qBAAsBvN,GACxBK,EAAM,QAAQkN,EAAe,OAAM,EAAI,SAA0BpU,EAAKpK,EAAK,CACzEiR,EAAQ,iBAAiBjR,EAAKoK,CAAG,CACnC,CAAC,EAIEkH,EAAM,YAAYgN,EAAQ,eAAe,IAC5CrN,EAAQ,gBAAkB,CAAC,CAACqN,EAAQ,iBAIlCG,GAAgBA,IAAiB,SACnCxN,EAAQ,aAAeqN,EAAQ,cAI7BK,IACD,CAACG,EAAmBE,CAAa,EAAI9D,GAAqByD,EAAoB,EAAI,EACnF1N,EAAQ,iBAAiB,WAAY6N,CAAiB,GAIpDJ,GAAoBzN,EAAQ,SAC7B,CAAC4N,EAAiBE,CAAW,EAAI7D,GAAqBwD,CAAgB,EAEvEzN,EAAQ,OAAO,iBAAiB,WAAY4N,CAAe,EAE3D5N,EAAQ,OAAO,iBAAiB,UAAW8N,CAAW,IAGpDT,EAAQ,aAAeA,EAAQ,UAGjCM,EAAaW,GAAU,CAChBtO,IAGLyI,EAAO,CAAC6F,GAAUA,EAAO,KAAO,IAAIC,GAAc,KAAM1f,EAAQmR,CAAO,EAAIsO,CAAM,EACjFtO,EAAQ,MAAK,EACbA,EAAU,KACZ,EAEAqN,EAAQ,aAAeA,EAAQ,YAAY,UAAUM,CAAU,EAC3DN,EAAQ,SACVA,EAAQ,OAAO,QAAUM,EAAU,EAAKN,EAAQ,OAAO,iBAAiB,QAASM,CAAU,IAI/F,MAAMa,EAAW7F,GAAc0E,EAAQ,GAAG,EAE1C,GAAImB,GAAY7K,GAAS,UAAU,QAAQ6K,CAAQ,IAAM,GAAI,CAC3D/F,EAAO,IAAI3I,EAAW,wBAA0B0O,EAAW,IAAK1O,EAAW,gBAAiBjR,CAAM,CAAC,EACnG,MACF,CAIAmR,EAAQ,KAAKsN,GAAe,IAAI,CAClC,CAAC,CACH,ECnMMmB,GAAiB,CAACC,EAASC,IAAY,CAC3C,KAAM,CAAC,OAAAC,CAAM,EAAKF,EAAUA,EAAUA,EAAQ,OAAO,OAAO,EAAI,GAEhE,GAAIC,GAAWC,EAAQ,CACrB,IAAIC,EAAa,IAAI,gBAEjBC,EAEJ,MAAMC,EAAU,SAAUC,EAAQ,CAChC,GAAI,CAACF,EAAS,CACZA,EAAU,GACVG,EAAW,EACX,MAAMd,EAAMa,aAAkB,MAAQA,EAAS,KAAK,OACpDH,EAAW,MAAMV,aAAerO,EAAaqO,EAAM,IAAII,GAAcJ,aAAe,MAAQA,EAAI,QAAUA,CAAG,CAAC,CAChH,CACF,EAEA,IAAIrE,EAAQ6E,GAAW,WAAW,IAAM,CACtC7E,EAAQ,KACRiF,EAAQ,IAAIjP,EAAW,cAAc6O,CAAO,cAAe7O,EAAW,SAAS,CAAC,CAClF,EAAG6O,CAAO,EAEV,MAAMM,EAAc,IAAM,CACpBP,IACF5E,GAAS,aAAaA,CAAK,EAC3BA,EAAQ,KACR4E,EAAQ,QAAQQ,GAAU,CACxBA,EAAO,YAAcA,EAAO,YAAYH,CAAO,EAAIG,EAAO,oBAAoB,QAASH,CAAO,CAChG,CAAC,EACDL,EAAU,KAEd,EAEAA,EAAQ,QAASQ,GAAWA,EAAO,iBAAiB,QAASH,CAAO,CAAC,EAErE,KAAM,CAAC,OAAAG,CAAM,EAAIL,EAEjB,OAAAK,EAAO,YAAc,IAAM7O,EAAM,KAAK4O,CAAW,EAE1CC,CACT,CACF,EC5CaC,GAAc,UAAWC,EAAOC,EAAW,CACtD,IAAIpU,EAAMmU,EAAM,WAEhB,GAAkBnU,EAAMoU,EAAW,CACjC,MAAMD,EACN,MACF,CAEA,IAAIE,EAAM,EACNC,EAEJ,KAAOD,EAAMrU,GACXsU,EAAMD,EAAMD,EACZ,MAAMD,EAAM,MAAME,EAAKC,CAAG,EAC1BD,EAAMC,CAEV,EAEaC,GAAY,gBAAiBC,EAAUJ,EAAW,CAC7D,gBAAiBD,KAASM,GAAWD,CAAQ,EAC3C,MAAON,GAAYC,EAAOC,CAAS,CAEvC,EAEMK,GAAa,gBAAiBC,EAAQ,CAC1C,GAAIA,EAAO,OAAO,aAAa,EAAG,CAChC,MAAOA,EACP,MACF,CAEA,MAAMC,EAASD,EAAO,UAAS,EAC/B,GAAI,CACF,OAAS,CACP,KAAM,CAAC,KAAA3B,EAAM,MAAA/d,CAAK,EAAI,MAAM2f,EAAO,KAAI,EACvC,GAAI5B,EACF,MAEF,MAAM/d,CACR,CACF,QAAC,CACC,MAAM2f,EAAO,OAAM,CACrB,CACF,EAEaC,GAAc,CAACF,EAAQN,EAAWS,EAAYC,IAAa,CACtE,MAAMvX,EAAWgX,GAAUG,EAAQN,CAAS,EAE5C,IAAItG,EAAQ,EACRiF,EACAgC,EAAaxZ,GAAM,CAChBwX,IACHA,EAAO,GACP+B,GAAYA,EAASvZ,CAAC,EAE1B,EAEA,OAAO,IAAI,eAAe,CACxB,MAAM,KAAKqY,EAAY,CACrB,GAAI,CACF,KAAM,CAAC,KAAAb,EAAM,MAAA/d,CAAK,EAAI,MAAMuI,EAAS,KAAI,EAEzC,GAAIwV,EAAM,CACTgC,EAAS,EACRnB,EAAW,MAAK,EAChB,MACF,CAEA,IAAI5T,EAAMhL,EAAM,WAChB,GAAI6f,EAAY,CACd,IAAIG,EAAclH,GAAS9N,EAC3B6U,EAAWG,CAAW,CACxB,CACApB,EAAW,QAAQ,IAAI,WAAW5e,CAAK,CAAC,CAC1C,OAASke,EAAK,CACZ,MAAA6B,EAAU7B,CAAG,EACPA,CACR,CACF,EACA,OAAOa,EAAQ,CACb,OAAAgB,EAAUhB,CAAM,EACTxW,EAAS,OAAM,CACxB,CACJ,EAAK,CACD,cAAe,CACnB,CAAG,CACH,EC5EM0X,GAAqB,GAAK,KAE1B,CAAC,WAAA9W,EAAU,EAAIiH,EAEf8P,IAAkB,CAAC,CAAC,QAAAC,EAAS,SAAAC,CAAQ,KAAO,CAChD,QAAAD,EAAS,SAAAC,CACX,IAAIhQ,EAAM,MAAM,EAEV,CACN,eAAEiQ,GAAgB,YAAAC,EAClB,EAAIlQ,EAAM,OAGJmQ,GAAO,CAACpY,KAAO4R,IAAS,CAC5B,GAAI,CACF,MAAO,CAAC,CAAC5R,EAAG,GAAG4R,CAAI,CACrB,MAAY,CACV,MAAO,EACT,CACF,EAEMyG,GAAWC,GAAQ,CACvBA,EAAMrQ,EAAM,MAAM,KAAK,CACrB,cAAe,EACnB,EAAK8P,GAAgBO,CAAG,EAEtB,KAAM,CAAC,MAAOC,EAAU,QAAAP,EAAS,SAAAC,CAAQ,EAAIK,EACvCE,EAAmBD,EAAWvX,GAAWuX,CAAQ,EAAI,OAAO,OAAU,WACtEE,EAAqBzX,GAAWgX,CAAO,EACvCU,EAAsB1X,GAAWiX,CAAQ,EAE/C,GAAI,CAACO,EACH,MAAO,GAGT,MAAMG,EAA4BH,GAAoBxX,GAAWkX,EAAc,EAEzEU,EAAaJ,IAAqB,OAAOL,IAAgB,YACzDtO,GAAapJ,GAAQoJ,EAAQ,OAAOpJ,CAAG,GAAG,IAAI0X,EAAa,EAC7D,MAAO1X,GAAQ,IAAI,WAAW,MAAM,IAAIuX,EAAQvX,CAAG,EAAE,YAAW,CAAE,GAGhEoY,EAAwBJ,GAAsBE,GAA6BP,GAAK,IAAM,CAC1F,IAAIU,EAAiB,GAErB,MAAMC,EAAiB,IAAIf,EAAQzM,GAAS,OAAQ,CAClD,KAAM,IAAI2M,GACV,OAAQ,OACR,IAAI,QAAS,CACX,OAAAY,EAAiB,GACV,MACT,CACN,CAAK,EAAE,QAAQ,IAAI,cAAc,EAE7B,OAAOA,GAAkB,CAACC,CAC5B,CAAC,EAEKC,EAAyBN,GAAuBC,GACpDP,GAAK,IAAMnQ,EAAM,iBAAiB,IAAIgQ,EAAS,EAAE,EAAE,IAAI,CAAC,EAEpDgB,EAAY,CAChB,OAAQD,IAA4BE,GAAQA,EAAI,KACpD,EAEEV,GACE,CAAC,OAAQ,cAAe,OAAQ,WAAY,QAAQ,EAAE,QAAQhiB,GAAQ,CACpE,CAACyiB,EAAUziB,CAAI,IAAMyiB,EAAUziB,CAAI,EAAI,CAAC0iB,EAAKziB,IAAW,CACtD,IAAIoW,EAASqM,GAAOA,EAAI1iB,CAAI,EAE5B,GAAIqW,EACF,OAAOA,EAAO,KAAKqM,CAAG,EAGxB,MAAM,IAAIxR,EAAW,kBAAkBlR,CAAI,qBAAsBkR,EAAW,gBAAiBjR,CAAM,CACrG,EACF,CAAC,EAGH,MAAM0iB,EAAgB,MAAOC,GAAS,CACpC,GAAIA,GAAQ,KACV,MAAO,GAGT,GAAInR,EAAM,OAAOmR,CAAI,EACnB,OAAOA,EAAK,KAGd,GAAInR,EAAM,oBAAoBmR,CAAI,EAKhC,OAAQ,MAJS,IAAIpB,EAAQzM,GAAS,OAAQ,CAC5C,OAAQ,OACR,KAAA6N,CACR,CAAO,EACsB,YAAW,GAAI,WAGxC,GAAInR,EAAM,kBAAkBmR,CAAI,GAAKnR,EAAM,cAAcmR,CAAI,EAC3D,OAAOA,EAAK,WAOd,GAJInR,EAAM,kBAAkBmR,CAAI,IAC9BA,EAAOA,EAAO,IAGZnR,EAAM,SAASmR,CAAI,EACrB,OAAQ,MAAMR,EAAWQ,CAAI,GAAG,UAEpC,EAEMC,EAAoB,MAAOjN,EAASgN,IAAS,CACjD,MAAM5C,EAASvO,EAAM,eAAemE,EAAQ,iBAAgB,CAAE,EAE9D,OAAOoK,GAAiB2C,EAAcC,CAAI,CAC5C,EAEA,MAAO,OAAO3iB,GAAW,CACvB,GAAI,CACF,IAAAuT,EACA,OAAA6C,EACA,KAAAxP,EACA,OAAAyZ,EACA,YAAAwC,EACA,QAAA/C,EACA,mBAAAjB,EACA,iBAAAD,EACA,aAAAD,EACA,QAAAhJ,EACA,gBAAAmN,EAAkB,cAClB,aAAAC,CACN,EAAQlF,GAAc7d,CAAM,EAEpBgjB,EAASlB,GAAY,MAEzBnD,EAAeA,GAAgBA,EAAe,IAAI,YAAW,EAAK,OAElE,IAAIsE,EAAiBrD,GAAe,CAACS,EAAQwC,GAAeA,EAAY,eAAe,EAAG/C,CAAO,EAE7F3O,EAAU,KAEd,MAAMiP,EAAc6C,GAAkBA,EAAe,cAAgB,IAAM,CACzEA,EAAe,YAAW,CAC5B,GAEA,IAAIC,EAEJ,GAAI,CACF,GACEtE,GAAoBwD,GAAyBhM,IAAW,OAASA,IAAW,SAC3E8M,EAAuB,MAAMN,EAAkBjN,EAAS/O,CAAI,KAAO,EACpE,CACA,IAAIuc,EAAW,IAAI5B,EAAQhO,EAAK,CAC9B,OAAQ,OACR,KAAM3M,EACN,OAAQ,MAClB,CAAS,EAEGwc,EAMJ,GAJI5R,EAAM,WAAW5K,CAAI,IAAMwc,EAAoBD,EAAS,QAAQ,IAAI,cAAc,IACpFxN,EAAQ,eAAeyN,CAAiB,EAGtCD,EAAS,KAAM,CACjB,KAAM,CAAClC,EAAYoC,EAAK,EAAIvH,GAC1BoH,EACA9H,GAAqBa,GAAe2C,CAAgB,CAAC,CACjE,EAEUhY,EAAOoa,GAAYmC,EAAS,KAAM9B,GAAoBJ,EAAYoC,EAAK,CACzE,CACF,CAEK7R,EAAM,SAASsR,CAAe,IACjCA,EAAkBA,EAAkB,UAAY,QAKlD,MAAMQ,EAAyBtB,GAAsB,gBAAiBT,EAAQ,UAExEgC,GAAkB,CACtB,GAAGR,EACH,OAAQE,EACR,OAAQ7M,EAAO,YAAW,EAC1B,QAAST,EAAQ,UAAS,EAAG,OAAM,EACnC,KAAM/O,EACN,OAAQ,OACR,YAAa0c,EAAyBR,EAAkB,MAChE,EAEM3R,EAAU6Q,GAAsB,IAAIT,EAAQhO,EAAKgQ,EAAe,EAEhE,IAAInS,GAAW,MAAO4Q,EAAqBgB,EAAO7R,EAAS4R,CAAY,EAAIC,EAAOzP,EAAKgQ,EAAe,GAEtG,MAAMC,EAAmBjB,IAA2B5D,IAAiB,UAAYA,IAAiB,YAElG,GAAI4D,IAA2B1D,GAAuB2E,GAAoBpD,GAAe,CACvF,MAAMjO,EAAU,CAAA,EAEhB,CAAC,SAAU,aAAc,SAAS,EAAE,QAAQtE,IAAQ,CAClDsE,EAAQtE,EAAI,EAAIuD,GAASvD,EAAI,CAC/B,CAAC,EAED,MAAM4V,EAAwBjS,EAAM,eAAeJ,GAAS,QAAQ,IAAI,gBAAgB,CAAC,EAEnF,CAAC6P,EAAYoC,EAAK,EAAIxE,GAAsB/C,GAChD2H,EACArI,GAAqBa,GAAe4C,CAAkB,EAAG,EAAI,CACvE,GAAa,CAAA,EAELzN,GAAW,IAAIoQ,EACbR,GAAY5P,GAAS,KAAMiQ,GAAoBJ,EAAY,IAAM,CAC/DoC,IAASA,GAAK,EACdjD,GAAeA,EAAW,CAC5B,CAAC,EACDjO,CACV,CACM,CAEAwM,EAAeA,GAAgB,OAE/B,IAAI+E,GAAe,MAAMlB,EAAUhR,EAAM,QAAQgR,EAAW7D,CAAY,GAAK,MAAM,EAAEvN,GAAUpR,CAAM,EAErG,OAACwjB,GAAoBpD,GAAeA,EAAW,EAExC,MAAM,IAAI,QAAQ,CAACzG,EAASC,IAAW,CAC5CF,GAAOC,EAASC,EAAQ,CACtB,KAAM8J,GACN,QAAStK,GAAa,KAAKhI,GAAS,OAAO,EAC3C,OAAQA,GAAS,OACjB,WAAYA,GAAS,WACrB,OAAApR,EACA,QAAAmR,CACV,CAAS,CACH,CAAC,CACH,OAASmO,EAAK,CAGZ,MAFAc,GAAeA,EAAW,EAEtBd,GAAOA,EAAI,OAAS,aAAe,qBAAqB,KAAKA,EAAI,OAAO,EACpE,OAAO,OACX,IAAIrO,EAAW,gBAAiBA,EAAW,YAAajR,EAAQmR,EAASmO,GAAOA,EAAI,QAAQ,EAC5F,CACE,MAAOA,EAAI,OAASA,CAChC,CACA,EAGYrO,EAAW,KAAKqO,EAAKA,GAAOA,EAAI,KAAMtf,EAAQmR,EAASmO,GAAOA,EAAI,QAAQ,CAClF,CACF,CACF,EAEMqE,GAAY,IAAI,IAETC,GAAY5jB,GAAW,CAClC,IAAI6hB,EAAO7hB,GAAUA,EAAO,KAAQ,CAAA,EACpC,KAAM,CAAC,MAAA6jB,EAAO,QAAAtC,EAAS,SAAAC,CAAQ,EAAIK,EAC7BiC,EAAQ,CACZvC,EAASC,EAAUqC,CACvB,EAEE,IAAIzX,EAAM0X,EAAM,OAAQ5X,EAAIE,EAC1B2X,EAAM3T,EAAQ4T,EAAML,GAEtB,KAAOzX,KACL6X,EAAOD,EAAM5X,CAAC,EACdkE,EAAS4T,EAAI,IAAID,CAAI,EAErB3T,IAAW,QAAa4T,EAAI,IAAID,EAAM3T,EAAUlE,EAAI,IAAI,IAAQ0V,GAAQC,CAAG,CAAE,EAE7EmC,EAAM5T,EAGR,OAAOA,CACT,EAEgBwT,GAAQ,EC9QxB,MAAMK,GAAgB,CACpB,KAAMxS,GACN,IAAK8M,GACL,MAAO,CACL,IAAK2F,EACT,CACA,EAGA1S,EAAM,QAAQyS,GAAe,CAAC1a,EAAInI,IAAU,CAC1C,GAAImI,EAAI,CACN,GAAI,CACF,OAAO,eAAeA,EAAI,OAAQ,CAAE,MAAAnI,CAAK,CAAE,CAC7C,MAAY,CAEZ,CACA,OAAO,eAAemI,EAAI,cAAe,CAAE,MAAAnI,CAAK,CAAE,CACpD,CACF,CAAC,EAQD,MAAM+iB,GAAgBhE,GAAW,KAAKA,CAAM,GAQtCiE,GAAoBC,GAAY7S,EAAM,WAAW6S,CAAO,GAAKA,IAAY,MAAQA,IAAY,GAYnG,SAASC,GAAWC,EAAUvkB,EAAQ,CACpCukB,EAAW/S,EAAM,QAAQ+S,CAAQ,EAAIA,EAAW,CAACA,CAAQ,EAEzD,KAAM,CAAE,OAAAxE,CAAM,EAAKwE,EACnB,IAAIC,EACAH,EAEJ,MAAMI,EAAkB,CAAA,EAExB,QAAS,EAAI,EAAG,EAAI1E,EAAQ,IAAK,CAC/ByE,EAAgBD,EAAS,CAAC,EAC1B,IAAIxQ,EAIJ,GAFAsQ,EAAUG,EAEN,CAACJ,GAAiBI,CAAa,IACjCH,EAAUJ,IAAelQ,EAAK,OAAOyQ,CAAa,GAAG,aAAa,EAE9DH,IAAY,QACd,MAAM,IAAIpT,EAAW,oBAAoB8C,CAAE,GAAG,EAIlD,GAAIsQ,IAAY7S,EAAM,WAAW6S,CAAO,IAAMA,EAAUA,EAAQ,IAAIrkB,CAAM,IACxE,MAGFykB,EAAgB1Q,GAAM,IAAM,CAAC,EAAIsQ,CACnC,CAEA,GAAI,CAACA,EAAS,CACZ,MAAMK,EAAU,OAAO,QAAQD,CAAe,EAC3C,IAAI,CAAC,CAAC1Q,EAAI4Q,CAAK,IAAM,WAAW5Q,CAAE,KAChC4Q,IAAU,GAAQ,sCAAwC,gCACnE,EAEI,IAAIC,EAAI7E,EACL2E,EAAQ,OAAS,EAAI;AAAA,EAAcA,EAAQ,IAAIP,EAAY,EAAE,KAAK;AAAA,CAAI,EAAI,IAAMA,GAAaO,EAAQ,CAAC,CAAC,EACxG,0BAEF,MAAM,IAAIzT,EACR,wDAA0D2T,EAC1D,iBACN,CACE,CAEA,OAAOP,CACT,CAKA,MAAAE,GAAe,CAKf,WAAED,GAMA,SAAUL,EACZ,EC7GA,SAASY,GAA6B7kB,EAAQ,CAK5C,GAJIA,EAAO,aACTA,EAAO,YAAY,iBAAgB,EAGjCA,EAAO,QAAUA,EAAO,OAAO,QACjC,MAAM,IAAI0f,GAAc,KAAM1f,CAAM,CAExC,CASe,SAAS8kB,GAAgB9kB,EAAQ,CAC9C,OAAA6kB,GAA6B7kB,CAAM,EAEnCA,EAAO,QAAUoZ,GAAa,KAAKpZ,EAAO,OAAO,EAGjDA,EAAO,KAAOuZ,GAAc,KAC1BvZ,EACAA,EAAO,gBACX,EAEM,CAAC,OAAQ,MAAO,OAAO,EAAE,QAAQA,EAAO,MAAM,IAAM,IACtDA,EAAO,QAAQ,eAAe,oCAAqC,EAAK,EAG1DukB,GAAS,WAAWvkB,EAAO,SAAW0V,GAAS,QAAS1V,CAAM,EAE/DA,CAAM,EAAE,KAAK,SAA6BoR,EAAU,CACjE,OAAAyT,GAA6B7kB,CAAM,EAGnCoR,EAAS,KAAOmI,GAAc,KAC5BvZ,EACAA,EAAO,kBACPoR,CACN,EAEIA,EAAS,QAAUgI,GAAa,KAAKhI,EAAS,OAAO,EAE9CA,CACT,EAAG,SAA4B+O,EAAQ,CACrC,OAAK1G,GAAS0G,CAAM,IAClB0E,GAA6B7kB,CAAM,EAG/BmgB,GAAUA,EAAO,WACnBA,EAAO,SAAS,KAAO5G,GAAc,KACnCvZ,EACAA,EAAO,kBACPmgB,EAAO,QACjB,EACQA,EAAO,SAAS,QAAU/G,GAAa,KAAK+G,EAAO,SAAS,OAAO,IAIhE,QAAQ,OAAOA,CAAM,CAC9B,CAAC,CACH,CChFO,MAAM4E,GAAU,SCKjBC,GAAa,CAAA,EAGnB,CAAC,SAAU,UAAW,SAAU,WAAY,SAAU,QAAQ,EAAE,QAAQ,CAACjlB,EAAMmM,IAAM,CACnF8Y,GAAWjlB,CAAI,EAAI,SAAmBgK,EAAO,CAC3C,OAAO,OAAOA,IAAUhK,GAAQ,KAAOmM,EAAI,EAAI,KAAO,KAAOnM,CAC/D,CACF,CAAC,EAED,MAAMklB,GAAqB,CAAA,EAW3BD,GAAW,aAAe,SAAsBE,EAAWC,EAAS5T,EAAS,CAC3E,SAAS6T,EAAcC,EAAKC,EAAM,CAChC,MAAO,WAAaP,GAAU,0BAA6BM,EAAM,IAAOC,GAAQ/T,EAAU,KAAOA,EAAU,GAC7G,CAGA,MAAO,CAACnQ,EAAOikB,EAAKE,IAAS,CAC3B,GAAIL,IAAc,GAChB,MAAM,IAAIjU,EACRmU,EAAcC,EAAK,qBAAuBF,EAAU,OAASA,EAAU,GAAG,EAC1ElU,EAAW,cACnB,EAGI,OAAIkU,GAAW,CAACF,GAAmBI,CAAG,IACpCJ,GAAmBI,CAAG,EAAI,GAE1B,QAAQ,KACND,EACEC,EACA,+BAAiCF,EAAU,yCACrD,CACA,GAGWD,EAAYA,EAAU9jB,EAAOikB,EAAKE,CAAI,EAAI,EACnD,CACF,EAEAP,GAAW,SAAW,SAAkBQ,EAAiB,CACvD,MAAO,CAACpkB,EAAOikB,KAEb,QAAQ,KAAK,GAAGA,CAAG,+BAA+BG,CAAe,EAAE,EAC5D,GAEX,EAYA,SAASC,GAActT,EAASuT,EAAQC,EAAc,CACpD,GAAI,OAAOxT,GAAY,SACrB,MAAM,IAAIlB,EAAW,4BAA6BA,EAAW,oBAAoB,EAEnF,MAAM7N,EAAO,OAAO,KAAK+O,CAAO,EAChC,IAAIjG,EAAI9I,EAAK,OACb,KAAO8I,KAAM,GAAG,CACd,MAAMmZ,EAAMjiB,EAAK8I,CAAC,EACZgZ,EAAYQ,EAAOL,CAAG,EAC5B,GAAIH,EAAW,CACb,MAAM9jB,EAAQ+Q,EAAQkT,CAAG,EACnB3a,EAAStJ,IAAU,QAAa8jB,EAAU9jB,EAAOikB,EAAKlT,CAAO,EACnE,GAAIzH,IAAW,GACb,MAAM,IAAIuG,EAAW,UAAYoU,EAAM,YAAc3a,EAAQuG,EAAW,oBAAoB,EAE9F,QACF,CACA,GAAI0U,IAAiB,GACnB,MAAM,IAAI1U,EAAW,kBAAoBoU,EAAKpU,EAAW,cAAc,CAE3E,CACF,CAEA,MAAAiU,GAAe,CACb,cAAAO,GACF,WAAET,EACF,ECtFMA,GAAaE,GAAU,WAS7B,IAAAU,GAAA,KAAY,CACV,YAAYC,EAAgB,CAC1B,KAAK,SAAWA,GAAkB,CAAA,EAClC,KAAK,aAAe,CAClB,QAAS,IAAIjS,GACb,SAAU,IAAIA,EACpB,CACE,CAUA,MAAM,QAAQkS,EAAa9lB,EAAQ,CACjC,GAAI,CACF,OAAO,MAAM,KAAK,SAAS8lB,EAAa9lB,CAAM,CAChD,OAASsf,EAAK,CACZ,GAAIA,aAAe,MAAO,CACxB,IAAIyG,EAAQ,CAAA,EAEZ,MAAM,kBAAoB,MAAM,kBAAkBA,CAAK,EAAKA,EAAQ,IAAI,MAGxE,MAAM9V,EAAQ8V,EAAM,MAAQA,EAAM,MAAM,QAAQ,QAAS,EAAE,EAAI,GAC/D,GAAI,CACGzG,EAAI,MAGErP,GAAS,CAAC,OAAOqP,EAAI,KAAK,EAAE,SAASrP,EAAM,QAAQ,YAAa,EAAE,CAAC,IAC5EqP,EAAI,OAAS;AAAA,EAAOrP,GAHpBqP,EAAI,MAAQrP,CAKhB,MAAY,CAEZ,CACF,CAEA,MAAMqP,CACR,CACF,CAEA,SAASwG,EAAa9lB,EAAQ,CAGxB,OAAO8lB,GAAgB,UACzB9lB,EAASA,GAAU,CAAA,EACnBA,EAAO,IAAM8lB,GAEb9lB,EAAS8lB,GAAe,CAAA,EAG1B9lB,EAASmd,GAAY,KAAK,SAAUnd,CAAM,EAE1C,KAAM,CAAC,aAAAgW,EAAc,iBAAAgQ,EAAkB,QAAArQ,CAAO,EAAI3V,EAE9CgW,IAAiB,QACnBkP,GAAU,cAAclP,EAAc,CACpC,kBAAmBgP,GAAW,aAAaA,GAAW,OAAO,EAC7D,kBAAmBA,GAAW,aAAaA,GAAW,OAAO,EAC7D,oBAAqBA,GAAW,aAAaA,GAAW,OAAO,EAC/D,gCAAiCA,GAAW,aAAaA,GAAW,OAAO,CACnF,EAAS,EAAK,EAGNgB,GAAoB,OAClBxU,EAAM,WAAWwU,CAAgB,EACnChmB,EAAO,iBAAmB,CACxB,UAAWgmB,CACrB,EAEQd,GAAU,cAAcc,EAAkB,CACxC,OAAQhB,GAAW,SACnB,UAAWA,GAAW,QAChC,EAAW,EAAI,GAKPhlB,EAAO,oBAAsB,SAEtB,KAAK,SAAS,oBAAsB,OAC7CA,EAAO,kBAAoB,KAAK,SAAS,kBAEzCA,EAAO,kBAAoB,IAG7BklB,GAAU,cAAcllB,EAAQ,CAC9B,QAASglB,GAAW,SAAS,SAAS,EACtC,cAAeA,GAAW,SAAS,eAAe,CACxD,EAAO,EAAI,EAGPhlB,EAAO,QAAUA,EAAO,QAAU,KAAK,SAAS,QAAU,OAAO,YAAW,EAG5E,IAAIimB,EAAiBtQ,GAAWnE,EAAM,MACpCmE,EAAQ,OACRA,EAAQ3V,EAAO,MAAM,CAC3B,EAEI2V,GAAWnE,EAAM,QACf,CAAC,SAAU,MAAO,OAAQ,OAAQ,MAAO,QAAS,QAAQ,EACzD4E,GAAW,CACV,OAAOT,EAAQS,CAAM,CACvB,CACN,EAEIpW,EAAO,QAAUoZ,GAAa,OAAO6M,EAAgBtQ,CAAO,EAG5D,MAAMuQ,EAA0B,CAAA,EAChC,IAAIC,EAAiC,GACrC,KAAK,aAAa,QAAQ,QAAQ,SAAoCC,EAAa,CACjF,GAAI,OAAOA,EAAY,SAAY,YAAcA,EAAY,QAAQpmB,CAAM,IAAM,GAC/E,OAGFmmB,EAAiCA,GAAkCC,EAAY,YAE/E,MAAMpQ,EAAehW,EAAO,cAAgBiU,GACJ+B,GAAgBA,EAAa,gCAGnEkQ,EAAwB,QAAQE,EAAY,UAAWA,EAAY,QAAQ,EAE3EF,EAAwB,KAAKE,EAAY,UAAWA,EAAY,QAAQ,CAE5E,CAAC,EAED,MAAMC,EAA2B,CAAA,EACjC,KAAK,aAAa,SAAS,QAAQ,SAAkCD,EAAa,CAChFC,EAAyB,KAAKD,EAAY,UAAWA,EAAY,QAAQ,CAC3E,CAAC,EAED,IAAIE,EACApa,EAAI,EACJE,EAEJ,GAAI,CAAC+Z,EAAgC,CACnC,MAAMI,EAAQ,CAACzB,GAAgB,KAAK,IAAI,EAAG,MAAS,EAOpD,IANAyB,EAAM,QAAQ,GAAGL,CAAuB,EACxCK,EAAM,KAAK,GAAGF,CAAwB,EACtCja,EAAMma,EAAM,OAEZD,EAAU,QAAQ,QAAQtmB,CAAM,EAEzBkM,EAAIE,GACTka,EAAUA,EAAQ,KAAKC,EAAMra,GAAG,EAAGqa,EAAMra,GAAG,CAAC,EAG/C,OAAOoa,CACT,CAEAla,EAAM8Z,EAAwB,OAE9B,IAAIpI,EAAY9d,EAEhB,KAAOkM,EAAIE,GAAK,CACd,MAAMoa,EAAcN,EAAwBha,GAAG,EACzCua,EAAaP,EAAwBha,GAAG,EAC9C,GAAI,CACF4R,EAAY0I,EAAY1I,CAAS,CACnC,OAASjX,EAAO,CACd4f,EAAW,KAAK,KAAM5f,CAAK,EAC3B,KACF,CACF,CAEA,GAAI,CACFyf,EAAUxB,GAAgB,KAAK,KAAMhH,CAAS,CAChD,OAASjX,EAAO,CACd,OAAO,QAAQ,OAAOA,CAAK,CAC7B,CAKA,IAHAqF,EAAI,EACJE,EAAMia,EAAyB,OAExBna,EAAIE,GACTka,EAAUA,EAAQ,KAAKD,EAAyBna,GAAG,EAAGma,EAAyBna,GAAG,CAAC,EAGrF,OAAOoa,CACT,CAEA,OAAOtmB,EAAQ,CACbA,EAASmd,GAAY,KAAK,SAAUnd,CAAM,EAC1C,MAAM0mB,EAAW5J,GAAc9c,EAAO,QAASA,EAAO,IAAKA,EAAO,iBAAiB,EACnF,OAAOsT,GAASoT,EAAU1mB,EAAO,OAAQA,EAAO,gBAAgB,CAClE,CACF,EAGAwR,EAAM,QAAQ,CAAC,SAAU,MAAO,OAAQ,SAAS,EAAG,SAA6B4E,EAAQ,CAEvFuQ,GAAM,UAAUvQ,CAAM,EAAI,SAAS7C,EAAKvT,EAAQ,CAC9C,OAAO,KAAK,QAAQmd,GAAYnd,GAAU,CAAA,EAAI,CAC5C,OAAAoW,EACA,IAAA7C,EACA,MAAOvT,GAAU,IAAI,IAC3B,CAAK,CAAC,CACJ,CACF,CAAC,EAEDwR,EAAM,QAAQ,CAAC,OAAQ,MAAO,OAAO,EAAG,SAA+B4E,EAAQ,CAG7E,SAASwQ,EAAmBC,EAAQ,CAClC,OAAO,SAAoBtT,EAAK3M,EAAM5G,EAAQ,CAC5C,OAAO,KAAK,QAAQmd,GAAYnd,GAAU,CAAA,EAAI,CAC5C,OAAAoW,EACA,QAASyQ,EAAS,CAChB,eAAgB,qBAC1B,EAAY,CAAA,EACJ,IAAAtT,EACA,KAAA3M,CACR,CAAO,CAAC,CACJ,CACF,CAEA+f,GAAM,UAAUvQ,CAAM,EAAIwQ,EAAkB,EAE5CD,GAAM,UAAUvQ,EAAS,MAAM,EAAIwQ,EAAmB,EAAI,CAC5D,CAAC,EC3OD,IAAAE,GAAA,MAAMC,EAAY,CAChB,YAAYC,EAAU,CACpB,GAAI,OAAOA,GAAa,WACtB,MAAM,IAAI,UAAU,8BAA8B,EAGpD,IAAIC,EAEJ,KAAK,QAAU,IAAI,QAAQ,SAAyBtN,EAAS,CAC3DsN,EAAiBtN,CACnB,CAAC,EAED,MAAMhJ,EAAQ,KAGd,KAAK,QAAQ,KAAK8O,GAAU,CAC1B,GAAI,CAAC9O,EAAM,WAAY,OAEvB,IAAIzE,EAAIyE,EAAM,WAAW,OAEzB,KAAOzE,KAAM,GACXyE,EAAM,WAAWzE,CAAC,EAAEuT,CAAM,EAE5B9O,EAAM,WAAa,IACrB,CAAC,EAGD,KAAK,QAAQ,KAAOuW,GAAe,CACjC,IAAIC,EAEJ,MAAMb,EAAU,IAAI,QAAQ3M,GAAW,CACrChJ,EAAM,UAAUgJ,CAAO,EACvBwN,EAAWxN,CACb,CAAC,EAAE,KAAKuN,CAAW,EAEnB,OAAAZ,EAAQ,OAAS,UAAkB,CACjC3V,EAAM,YAAYwW,CAAQ,CAC5B,EAEOb,CACT,EAEAU,EAAS,SAAgBzV,EAASvR,EAAQmR,EAAS,CAC7CR,EAAM,SAKVA,EAAM,OAAS,IAAI+O,GAAcnO,EAASvR,EAAQmR,CAAO,EACzD8V,EAAetW,EAAM,MAAM,EAC7B,CAAC,CACH,CAKA,kBAAmB,CACjB,GAAI,KAAK,OACP,MAAM,KAAK,MAEf,CAMA,UAAU0K,EAAU,CAClB,GAAI,KAAK,OAAQ,CACfA,EAAS,KAAK,MAAM,EACpB,MACF,CAEI,KAAK,WACP,KAAK,WAAW,KAAKA,CAAQ,EAE7B,KAAK,WAAa,CAACA,CAAQ,CAE/B,CAMA,YAAYA,EAAU,CACpB,GAAI,CAAC,KAAK,WACR,OAEF,MAAMzI,EAAQ,KAAK,WAAW,QAAQyI,CAAQ,EAC1CzI,IAAU,IACZ,KAAK,WAAW,OAAOA,EAAO,CAAC,CAEnC,CAEA,eAAgB,CACd,MAAMoN,EAAa,IAAI,gBAEjBoH,EAAS9H,GAAQ,CACrBU,EAAW,MAAMV,CAAG,CACtB,EAEA,YAAK,UAAU8H,CAAK,EAEpBpH,EAAW,OAAO,YAAc,IAAM,KAAK,YAAYoH,CAAK,EAErDpH,EAAW,MACpB,CAMA,OAAO,QAAS,CACd,IAAIP,EAIJ,MAAO,CACL,MAJY,IAAIsH,GAAY,SAAkBM,EAAG,CACjD5H,EAAS4H,CACX,CAAC,EAGC,OAAA5H,CACN,CACE,CACF,EC7Ge,SAAS6H,GAAOC,EAAU,CACvC,OAAO,SAAcpZ,EAAK,CACxB,OAAOoZ,EAAS,MAAM,KAAMpZ,CAAG,CACjC,CACF,CChBe,SAASqZ,GAAaC,EAAS,CAC5C,OAAOjW,EAAM,SAASiW,CAAO,GAAMA,EAAQ,eAAiB,EAC9D,CCbA,MAAMC,GAAiB,CACrB,SAAU,IACV,mBAAoB,IACpB,WAAY,IACZ,WAAY,IACZ,GAAI,IACJ,QAAS,IACT,SAAU,IACV,4BAA6B,IAC7B,UAAW,IACX,aAAc,IACd,eAAgB,IAChB,YAAa,IACb,gBAAiB,IACjB,OAAQ,IACR,gBAAiB,IACjB,iBAAkB,IAClB,MAAO,IACP,SAAU,IACV,YAAa,IACb,SAAU,IACV,OAAQ,IACR,kBAAmB,IACnB,kBAAmB,IACnB,WAAY,IACZ,aAAc,IACd,gBAAiB,IACjB,UAAW,IACX,SAAU,IACV,iBAAkB,IAClB,cAAe,IACf,4BAA6B,IAC7B,eAAgB,IAChB,SAAU,IACV,KAAM,IACN,eAAgB,IAChB,mBAAoB,IACpB,gBAAiB,IACjB,WAAY,IACZ,qBAAsB,IACtB,oBAAqB,IACrB,kBAAmB,IACnB,UAAW,IACX,mBAAoB,IACpB,oBAAqB,IACrB,OAAQ,IACR,iBAAkB,IAClB,SAAU,IACV,gBAAiB,IACjB,qBAAsB,IACtB,gBAAiB,IACjB,4BAA6B,IAC7B,2BAA4B,IAC5B,oBAAqB,IACrB,eAAgB,IAChB,WAAY,IACZ,mBAAoB,IACpB,eAAgB,IAChB,wBAAyB,IACzB,sBAAuB,IACvB,oBAAqB,IACrB,aAAc,IACd,YAAa,IACb,8BAA+B,IAC/B,gBAAiB,IACjB,mBAAoB,IACpB,oBAAqB,IACrB,gBAAiB,IACjB,mBAAoB,IACpB,sBAAuB,GACzB,EAEA,OAAO,QAAQA,EAAc,EAAE,QAAQ,CAAC,CAACxnB,EAAKkB,CAAK,IAAM,CACvDsmB,GAAetmB,CAAK,EAAIlB,CAC1B,CAAC,EC/CD,SAASynB,GAAeC,EAAe,CACrC,MAAMnb,EAAU,IAAIka,GAAMiB,CAAa,EACjCC,EAAWve,GAAKqd,GAAM,UAAU,QAASla,CAAO,EAGtD+E,OAAAA,EAAM,OAAOqW,EAAUlB,GAAM,UAAWla,EAAS,CAAC,WAAY,EAAI,CAAC,EAGnE+E,EAAM,OAAOqW,EAAUpb,EAAS,KAAM,CAAC,WAAY,EAAI,CAAC,EAGxDob,EAAS,OAAS,SAAgBhC,EAAgB,CAChD,OAAO8B,GAAexK,GAAYyK,EAAe/B,CAAc,CAAC,CAClE,EAEOgC,CACT,CAGA,MAAMC,GAAQH,GAAejS,EAAQ,EAGrCoS,GAAM,MAAQnB,GAGdmB,GAAM,cAAgBpI,GACtBoI,GAAM,YAAcf,GACpBe,GAAM,SAAWrO,GACjBqO,GAAM,QAAU/C,GAChB+C,GAAM,WAAa7V,GAGnB6V,GAAM,WAAa7W,EAGnB6W,GAAM,OAASA,GAAM,cAGrBA,GAAM,IAAM,SAAaC,EAAU,CACjC,OAAO,QAAQ,IAAIA,CAAQ,CAC7B,EAEAD,GAAM,OAASR,GAGfQ,GAAM,aAAeN,GAGrBM,GAAM,YAAc3K,GAEpB2K,GAAM,aAAe1O,GAErB0O,GAAM,WAAa/d,GAASoL,GAAe3D,EAAM,WAAWzH,CAAK,EAAI,IAAI,SAASA,CAAK,EAAIA,CAAK,EAEhG+d,GAAM,WAAavD,GAAS,WAE5BuD,GAAM,eAAiBJ,GAEvBI,GAAM,QAAUA,GChFhB,KAAM,CACJ,MAAAnB,GACA,WAAA1V,GACA,cAAAyO,GACA,SAAAjG,GACA,YAAAsN,GACF,QAAEhC,GACA,IAAAiD,GACA,OAAAC,GACA,aAAAT,GACA,OAAAF,GACA,WAAArV,GACA,aAAAmH,GACA,eAAAsO,GACA,WAAAQ,GACA,WAAA5D,GACA,YAAAnH,EACF,EAAI2K,GCbEK,GAAW,IAAMvjB,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,YAAa,EAAG,SAAU,OAAA,EAAW,SAAA,IAAA,CAAE,EACvEwjB,GAAe,IAAMxjB,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,YAAa,EAAG,SAAU,OAAA,EAAW,SAAA,IAAA,CAAE,EAC3EyjB,GAAW,IAAMzjB,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,YAAa,EAAG,SAAU,OAAA,EAAW,SAAA,GAAA,CAAC,EACtE0jB,GAAa,IAAM1jB,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,YAAa,EAAG,SAAU,OAAA,EAAW,SAAA,IAAA,CAAE,EAazE2jB,GAAoC,CACxC,CAAE,GAAI,UAAW,MAAO,OAAQ,KAAM3jB,EAAAA,IAACujB,KAAS,CAAA,EAChD,CAAE,GAAI,WAAY,MAAO,KAAM,KAAMvjB,EAAAA,IAACwjB,KAAa,CAAA,EACnD,CAAE,GAAI,OAAQ,MAAO,KAAM,KAAMxjB,EAAAA,IAACyjB,KAAS,CAAA,EAC3C,CAAE,GAAI,SAAU,MAAO,KAAM,KAAMzjB,EAAAA,IAAC0jB,KAAW,CAAA,CACjD,EAmCME,GAA0C,CAAC,CAC/C,OAAAC,EACA,SAAUC,EACV,WAAYC,EACZ,UAAAC,EACA,UAAAC,EAAYN,GACZ,WAAAO,EAAa,KACb,UAAAC,EAAY,GACZ,MAAAliB,EAAQ,KACR,gBAAAmiB,EACA,kBAAAC,EACA,mBAAAC,EACA,WAAAC,EACA,YAAAC,EACA,gBAAAC,EACA,SAAAC,EACA,eAAAC,EACA,eAAAC,CACF,IAAM,CACJ,KAAM,CAACC,EAAUC,CAAW,EAAIjmB,EAAM,SAAmB,CACvD,GAAIglB,GAAU,GACd,KAAMC,GAAmB,GACzB,OAAQC,GAAqB,GAC7B,MAAO,EACP,OAAQ,CAAA,CAAC,CACV,EAEK,CAAClkB,EAASklB,CAAU,EAAIlmB,EAAM,SAASslB,CAAS,EAChD,CAACa,EAAYC,CAAa,EAAIpmB,EAAM,SAAuBoD,CAAK,EAGtEpD,EAAM,UAAU,IAAM,CAChBglB,GAAUG,GAAa,CAACF,GAAmB,CAACC,GAC9CmB,EAAA,CAEJ,EAAG,CAACrB,EAAQG,EAAWF,EAAiBC,CAAiB,CAAC,EAE1D,MAAMmB,EAAgB,SAAY,CAChCH,EAAW,EAAI,EACfE,EAAc,IAAI,EAElB,GAAI,CACF,MAAME,EAAWnB,EAAW,UAAU,YAAY,QAAQ,UAAWH,CAAO,EACtErX,EAAW,MAAM0W,GAAM,IAAI,GAAGc,EAAW,OAAO,GAAGmB,CAAQ,GAAI,CACnE,QAASnB,EAAW,OAAA,CACrB,EAEDc,EAAYtY,EAAS,IAAI,CAC3B,OAASkO,EAAK,CACZuK,EAAcvK,CAAY,CAC5B,QAAA,CACEqK,EAAW,EAAK,CAClB,CACF,EAGMK,EAAuB9kB,GAAsB,CACjDmkB,IAAkBnkB,EAAK,EAAY,EAE/BA,EAAK,KAAO,UACdokB,IAAA,CAEJ,EAGMW,EAAiB,IAAM,CAC3Bd,IAAA,CACF,EAGMe,EAAkB,IAAM,CAC5Bd,IAAA,CACF,EAGMe,EAAwB,IAC5B5kB,OAAC,MAAA,CAAI,UAAU,uBACb,SAAA,CAAAX,EAAAA,IAACwlB,GAAAA,OAAA,CACC,IAAKX,EAAS,OACd,KAAMX,EACN,UAAWE,EACX,IAAI,MAAA,CAAA,EAENpkB,EAAAA,IAAC,QAAK,UAAW,aAAaqkB,GAAqB,EAAE,GAClD,WAAS,IAAA,CACZ,CAAA,EACF,EAIIoB,EAA0BnlB,GAC9BK,EAAAA,KAAC,MAAA,CAEC,UAAU,eACV,QAAS,IAAMykB,EAAoB9kB,CAAI,EAEtC,SAAA,CAAAA,EAAK,MAAQN,EAAAA,IAAC,OAAA,CAAK,UAAU,oBAAqB,WAAK,KAAK,EAC7DA,EAAAA,IAAC,OAAA,CAAM,SAAAM,EAAK,KAAA,CAAM,CAAA,CAAA,EALbA,EAAK,EAAA,EASd,OAAIT,EAEAG,EAAAA,IAAC,MAAA,CAAI,UAAW,0BAA0BskB,GAAsB,EAAE,cAChE,SAAAtkB,EAAAA,IAAC,MAAA,CAAI,UAAU,uBAAuB,SAAA,QAAA,CAAM,EAC9C,EAIAglB,EAEAhlB,EAAAA,IAAC,MAAA,CAAI,UAAW,0BAA0BskB,GAAsB,EAAE,aAChE,SAAA3jB,EAAAA,KAAC,MAAA,CAAI,UAAU,qBAAqB,SAAA,CAAA,OAC7BqkB,EAAW,OAAA,CAAA,CAClB,CAAA,CACF,EAICH,EAAS,WASX,MAAA,CAAI,UAAW,0BAA0BP,GAAsB,EAAE,GAChE,SAAAtkB,EAAAA,IAACkD,GAAA,CACC,QAAS0hB,EAAiBA,EAAeC,CAAQ,EAAIU,EAAA,EACrD,MAAOtB,EAAU,IAAI3jB,IAAS,CAC5B,GAAGA,EACH,QAAS,IAAM8kB,EAAoB9kB,CAAI,CAAA,EACvC,EACF,SAAS,SACT,UAAU,MACV,OAAQ+kB,EACR,QAASC,EACT,WAAYX,EAAkBrkB,GAASqkB,EAAerkB,EAAMukB,CAAQ,EAAIY,CAAA,CAAA,EAE5E,EApBEzlB,EAAAA,IAAC,MAAA,CAAI,UAAW,0BAA0BskB,GAAsB,EAAE,GAChE,SAAAtkB,EAAAA,IAAC,MAAA,CAAI,UAAU,uBAAuB,SAAA,KAAA,CAAG,EAC3C,CAoBN,ECxMM0lB,GAA4BplB,GAChCK,EAAAA,KAAC,MAAA,CAEC,UAAU,oBACV,QAAS,IAAML,EAAK,UAAUA,CAAI,EAElC,SAAA,CAAAN,EAAAA,IAAC,OAAA,CAAK,UAAU,qBAAsB,SAAAM,EAAK,MAAM,EAChDA,EAAK,QACJN,EAAAA,IAAC,OAAA,CAAK,UAAW,8BAA8BM,EAAK,OAAO,YAAA,EAAc,QAAQ,IAAK,EAAE,EAAE,QAAQ,IAAK,GAAG,CAAC,GACxG,WAAK,MAAA,CACR,CAAA,CAAA,EARGA,EAAK,EAUZ,EAIIqlB,GAAkB,CAAC,CAAE,UAAA/lB,CAAA,IACzBe,EAAAA,KAAC,SAAA,CAAO,UAAAf,EAAsB,aAAW,SACvC,SAAA,CAAAI,EAAAA,IAAC,OAAA,CAAK,UAAU,eAAe,SAAA,KAAE,EACjCA,EAAAA,IAAC,OAAA,CAAK,UAAU,eAAe,SAAA,IAAA,CAAE,CAAA,EACnC,EAGI4lB,GAA8C,CAAC,CAEnD,UAAAhmB,EAAY,GACZ,MAAA4C,EACA,SAAAqjB,EAAW,IACX,SAAAC,EAAW,UACX,YAAAC,EAGA,aAAAC,EAAe,CAAA,EACf,gBAAAC,EAAkB,GAClB,oBAAAC,EACA,mBAAAC,EACA,kBAAAC,EAAoBV,GAGpB,SAAAb,EACA,cAAAwB,EACA,oBAAAC,EACA,SAAA5B,EAGA,UAAAP,EAAY,GACZ,MAAAliB,EAAQ,KAGR,gBAAAskB,EAAkB,GAClB,cAAAC,EAAgB,GAChB,iBAAAC,EAAmB,GACnB,qBAAAC,EAAuB,GAGvB,QAAAjnB,EAAU,WACV,MAAAknB,EACA,WAAAC,EACA,OAAAC,EACA,aAAAC,EACA,WAAAC,EACA,YAAAC,EACA,UAAAC,EACA,SAAAC,EAAW,KACX,qBAAAC,EAAuB,OACvB,mBAAAC,EAAqB,UAGrB,aAAcC,EACd,kBAAmBC,EAEnB,GAAGC,EACL,IAAM,CAEJ,MAAMC,GAAsCxB,EAAa,IAAI1lB,IAAS,CACpE,GAAIA,EAAK,GACT,MAAO8lB,EAAkB9lB,CAAI,EAC7B,QAAS,IAAM6lB,IAAqB7lB,CAAI,CAAA,EACxC,EAGImnB,EAAmB,CACvB,iBACA,mBAAmBhoB,CAAO,GAC1BknB,GAAS,yBAAyBA,CAAK,GACvCJ,EACA3mB,CAAA,EACA,OAAO,OAAO,EAAE,KAAK,GAAG,EAEpB8nB,GAAiB,CACrB,OACA,SAASR,CAAQ,GACjBV,CAAA,EACA,OAAO,OAAO,EAAE,KAAK,GAAG,EAEpBmB,EAA0B,CAC9B,iBACA,mBAAmBR,CAAoB,GACvC,yBAAyBC,CAAkB,GAC3CX,CAAA,EACA,OAAO,OAAO,EAAE,KAAK,GAAG,EAGpBmB,EAAoC,CACxC,GAAGplB,EACH,GAAIqkB,GAAU,CAAE,OAAQ,OAAOA,GAAW,SAAW,GAAGA,CAAM,KAAOA,CAAA,EACrE,GAAID,GAAc,CAAE,cAAeA,CAAA,EACnC,GAAIK,GAAa,CAAE,eAAgBA,CAAA,EACnC,GAAIH,GAAgBC,GAAc,CAChC,cAAeC,EACX,6BAA6BF,CAAY,KAAKE,CAAW,KAAKD,CAAU,IACxE,6BAA6BD,CAAY,KAAKC,CAAU,GAAA,CAC9D,EAGF,OACE/mB,EAAAA,IAAC,SAAA,CACC,UAAWynB,EACX,MAAOG,EACP,aAAYP,EACZ,kBAAiBC,EACjB,KAAK,SACJ,GAAGC,GAEJ,SAAA5mB,EAAAA,KAAC,MAAA,CAAI,UAAU,iBAEb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,sBACb,SAAAA,EAAAA,IAACkD,GAAA,CACC,QAASlD,EAAAA,IAAC2lB,GAAA,CAAgB,UAAWgC,CAAA,CAAyB,EAC9D,MAAOH,GACP,SAAS,SACT,UAAU,QACV,UAAW,IACX,WAAY,IACZ,OAAQ,IAAMtB,IAAsB,EAAI,EACxC,QAAS,IAAMA,IAAsB,EAAK,EAC1C,UAAU,kBACV,cAAc,eAAA,CAAA,EAElB,EAGAlmB,EAAAA,IAAC,MAAA,CAAI,UAAU,wBACb,SAAAA,EAAAA,IAAC,IAAA,CACC,KAAM6lB,EACN,UAAW6B,GACX,QAAS3B,EACT,aAAW,aAEV,SAAAD,CAAA,CAAA,EAEL,EAGA9lB,EAAAA,IAAC,MAAA,CAAI,UAAU,uBACb,SAAAA,EAAAA,IAAC4jB,GAAA,CACC,SAAUiB,GAAU,KACpB,WAAYA,GAAU,OACtB,UAAWwB,EACX,gBAAiBC,EACjB,SAAA5B,EACA,mBAAoBgC,EACpB,UAAAvC,EACA,MAAAliB,CAAA,CAAA,CACF,CACF,CAAA,CAAA,CACF,CAAA,CAAA,CAGN,EAGA2jB,GAAe/mB,EAAM,KAAK+mB,GAAe,CAACiC,EAAWC,IAGjDD,EAAU,WAAaC,EAAU,UACjCD,EAAU,WAAaC,EAAU,UACjCD,EAAU,YAAcC,EAAU,WAClCD,EAAU,kBAAoBC,EAAU,iBACxCD,EAAU,gBAAkBC,EAAU,eACtCD,EAAU,mBAAqBC,EAAU,kBACzCD,EAAU,uBAAyBC,EAAU,sBAC7CD,EAAU,YAAY,IAAMC,EAAU,YAAY,GAClDD,EAAU,iBAAiB,IAAMC,EAAU,iBAAiB,GAC5DD,EAAU,YAAcC,EAAU,WAClCD,EAAU,QAAUC,EAAU,OAE9BD,EAAU,UAAYC,EAAU,SAChCD,EAAU,QAAUC,EAAU,OAC9BD,EAAU,aAAeC,EAAU,YACnCD,EAAU,SAAWC,EAAU,QAC/BD,EAAU,eAAiBC,EAAU,cACrCD,EAAU,aAAeC,EAAU,YACnCD,EAAU,cAAgBC,EAAU,aACpCD,EAAU,YAAcC,EAAU,WAClCD,EAAU,WAAaC,EAAU,UACjCD,EAAU,uBAAyBC,EAAU,sBAC7CD,EAAU,qBAAuBC,EAAU,oBAE3C,KAAK,UAAUD,EAAU,YAAY,IAAM,KAAK,UAAUC,EAAU,YAAY,GAEhF,KAAK,UAAUD,EAAU,QAAQ,IAAM,KAAK,UAAUC,EAAU,QAAQ,GACxE,KAAK,UAAUD,EAAU,aAAa,IAAM,KAAK,UAAUC,EAAU,aAAa,CAErF,EC9MKC,GAAgDlpB,EAAM,KAC1D,CAAC,CACC,MAAAmpB,EAAQ,CAAA,EACR,SAAA3pB,EAAW,KACX,SAAA4pB,EAAW,OACX,MAAAtB,EAAQ,UACR,YAAAuB,EAAc,GACd,UAAAtoB,EAAY,EAAA,IACR,CAEJuoB,EAAAA,UAAU,IAAM,CACV,QAAQ,IAAI,WAAa,eAAiB,OAAO,OAAW,MAE1C,MAAM,KAAK,SAAS,WAAW,EAAE,KAAKC,GAAS,CACjE,GAAI,CACF,OAAOA,EAAM,MAAQA,EAAM,KAAK,SAAS,OAAO,CAClD,MAAQ,CAEN,MAAO,EACT,CACF,CAAC,GAGC,QAAQ,KACN;AAAA;AAAA,cAAA,EAMR,EAAG,CAAA,CAAE,EAGL,MAAMC,EAAgBC,EAAAA,QAAQ,IAExBN,EAAM,SAAW,EACZ,CAAA,EAIFA,EAAM,IAAI,CAACO,EAAMva,IAAU,CAChC,GAAI,CACF,OAAOwa,GAAAA,eAAeD,EAAM,CAC1B,YAAAL,EACA,aAAc,GACd,WAAY,SAAA,CACb,CACH,OAASjmB,EAAO,CACd,eAAQ,MAAM,iCAAiC+L,CAAK,IAAK/L,CAAK,EACvD,8CACT,CACF,CAAC,EACA,CAAC+lB,EAAOE,CAAW,CAAC,EAGvB,GAAIF,EAAM,SAAW,EACnB,OAAO,KAIT,MAAMS,EAAcP,EAAc,MAAQ,OAGpCQ,EAAgB7pB,EAAM,SAAS,QAAQR,CAAQ,EAG/C2E,EAAmC,CAAA,EACzC,OAAAqlB,EAAc,QAAQ,CAACM,EAAc3a,IAAU,CAC7ChL,EAAc,KACZhD,EAAAA,IAAC,OAAA,CAEC,wBAAyB,CAAE,OAAQ2oB,CAAA,EACnC,MAAO,CAAE,QAAS,cAAA,CAAe,EAF5B,QAAQ3a,CAAK,EAAA,CAGpB,EAIEA,EAAQ0a,EAAc,QAAU1a,EAAQga,EAAM,OAAS,GACzDhlB,EAAc,KACZhD,EAAAA,IAAC,OAAA,CAA2B,MAAO,CAAE,QAAS,cAAA,EAC3C,SAAA0oB,EAAc1a,CAAK,CAAA,EADX,QAAQA,CAAK,EAExB,CAAA,CAGN,CAAC,EAGChO,EAAAA,IAACyoB,EAAA,CACC,UAAW,mBAAmB7oB,CAAS,GAAG,KAAA,EAC1C,MAAO,CACL,SAAAqoB,EACA,MAAAtB,EACA,QAAS,OACT,WAAY,SACZ,IAAK,QACL,GAAIuB,EAAc,CAAE,eAAgB,SAAU,OAAQ,OAAA,EAAY,CAAA,CAAC,EAGpE,SAAAllB,CAAA,CAAA,CAGP,CACF,ECjGO,SAAS4lB,GAAkBxtB,EAAoD,CACpF,OAAOA,EAAO,OAAS,WACzB,CAEO,SAASytB,GAAqBztB,EAA6D,CAChG,OAAOA,EAAO,OAAS,WACzB,CAuDO,SAAS0tB,IAA0C,CAExD,MAAO,CACL,KAAM,cACN,OAAQ,CACN,UAAW,aACX,SAAU,CAAA,CACZ,CAEJ,CAGO,SAASC,GAA6BC,EAAoC,CAE/E,GAAI,CAACA,EACH,OAAOF,GAAA,EAIT,GAAIE,EAAa,OAAS,aAAe,MAAM,QAAQA,EAAa,UAAU,EAO5E,MAAO,CACL,KAAM,YACN,WAPoCA,EAAa,WAAW,IAAKC,GAE1DF,GAA6BE,CAAS,CAC9C,EAKC,cAAeD,EAAa,eAAiB,YAAA,EAIjD,GAAIA,EAAa,MAAQA,EAAa,OACpC,OAAOA,EAIT,MAAME,EAAYF,EASlB,GAAIE,EAAU,OAAS,aAAe,MAAM,QAAQA,EAAU,SAAS,EAQrE,MAAO,CACL,KAAM,YACN,WARoCA,EAAU,UAAU,IAAI,CAAC5oB,EAAM6oB,IAEjDJ,GAA6BzoB,CAAI,CAEpD,EAKC,cAAe,YAAA,EAKnB,IAAIlF,EACAD,EAA6C,cAEjD,OAAI+tB,EAAU,UACZ/tB,EAAO,WACPC,EAAS8tB,EAAU,UACVA,EAAU,aACnB/tB,EAAO,cACPC,EAAS8tB,EAAU,aACVA,EAAU,OACnB/tB,EAAO,QACPC,EAAS8tB,EAAU,QAGnB/tB,EAAO,cACPC,EAAS,CAAE,UAAW,aAAc,SAAU,CAAA,GAGzC,CACL,KAAAD,EACA,OAAAC,EACA,YAAa8tB,EAAU,WAAA,CAE3B,CCvJO,MAAME,GAAqBC,GAAwD,CACxF,GAAIA,EAAS,SAAW,EAAG,MAAO,CAAC,EAAG,CAAC,EAEvC,IAAIC,EAAO,EACPC,EAAO,EAEX,SAAW,CAACC,EAAGC,CAAC,IAAKJ,EACnBC,GAAQE,EACRD,GAAQE,EAGV,MAAO,CAACH,EAAOD,EAAS,OAAQE,EAAOF,EAAS,MAAM,CACxD,EAgCaK,GAAiCtuB,GAA2C,CAEvF,GAAIwtB,GAAkBxtB,CAAM,EAAG,CAC7B,MAAM6tB,EAAY7tB,EAClB,GAAI,CAAC6tB,EAAU,OACb,MAAO,GAAGA,EAAU,IAAI,SAG1B,OAAQA,EAAU,KAAA,CAChB,IAAK,cACH,GAAKA,EAAU,OAAe,UAAY,EAAG,MAAO,YACpD,MACF,IAAK,WACH,GAAKA,EAAU,OAAe,aAAgBA,EAAU,OAAe,SACrE,MAAO,kBAET,MACF,IAAK,QACH,MAAMU,EAAcV,EAAU,OAC9B,GAAIU,EAAY,YAAc,GAAKA,EAAY,UAAY,EACzD,MAAO,YAET,KAAA,CAEJ,OAAO,IACT,CAGA,GAAId,GAAqBztB,CAAM,EAAG,CAChC,MAAMwuB,EAAkBxuB,EACxB,GAAI,CAACwuB,EAAgB,WACnB,MAAO,qBAKT,UAAWC,KAAaD,EAAgB,WAAY,CAClD,MAAM3nB,EAAQynB,GAA8BG,CAAS,EACrD,GAAI5nB,EAAO,MAAO,cAAcA,CAAK,EACvC,CACA,OAAO,IACT,CAGA,MAAO,WACT,EAKa6nB,GAAyB,CACpCC,EACAlD,EACAmD,EACAf,IACkB,CAElB,GAAIc,GAAQ,EAAG,MAAO,YACtB,GAAIlD,GAAU,EAAG,MAAO,UAIxB,GAAImD,EAAO,SAAS,SAAW,EAC7B,MAAO,aAIT,MAAMC,EAAuBP,GAA8BT,CAAS,EACpE,GAAIgB,EACF,MAAO,aAAaA,CAAoB,GAI1C,UAAWC,KAASF,EAAO,SACzB,GAAIE,EAAM,UAAW,CAEnB,MAAMC,EAAoBpB,GAA6BmB,EAAM,SAAS,EAChEE,EAAsBV,GAA8BS,CAAiB,EAC3E,GAAIC,EACF,MAAO,MAAMF,EAAM,UAAU,IAAM,IAAI,cAAcE,CAAmB,EAE5E,CAIF,UAAWF,IAAS,CAAC,GAAGF,EAAO,OAAQ,GAAGA,EAAO,QAAQ,EAAG,CAC1D,GAAI,CAACE,EAAM,UAAYA,EAAM,SAAS,OAAS,EAC7C,MAAO,MAAMA,EAAM,UAAU,IAAM,IAAI,aAEzC,UAAWG,KAAUH,EAAM,SAAU,CACnC,GAAI,CAAC,MAAM,QAAQG,CAAM,GAAKA,EAAO,SAAW,EAC9C,MAAO,MAAMH,EAAM,UAAU,IAAM,IAAI,UAEzC,KAAM,CAACV,EAAGC,CAAC,EAAIY,EACf,GAAI,OAAOb,GAAM,UAAY,OAAOC,GAAM,UAAY,CAAC,SAASD,CAAC,GAAK,CAAC,SAASC,CAAC,EAC/E,MAAO,MAAMS,EAAM,UAAU,IAAM,IAAI,SAE3C,CACF,CAEA,OAAO,IACT,ECjJaJ,GACXvsB,GACkC,CAClC,KAAM,CAAE,KAAAwsB,EAAM,OAAAlD,EAAQ,OAAAmD,EAAQ,UAAAf,GAAc1rB,EAGtC+sB,EAAevB,GAA6BE,CAAS,EAErDsB,EAAeC,GAAiBT,EAAMlD,EAAQmD,EAAQM,CAAY,EAExE,OAAIC,EACK,CACL,KAAM,iBACN,QAASA,EACT,UAAW,IAAI,KAAA,EAAO,YAAA,CAAY,EAI/B,IACT,EAMaE,GACXC,GACkB,CAElB,GAAIA,EAAU,OAAQ,CACpB,KAAM,CAAE,OAAAC,GAAWD,EAEnB,GAAIC,EAAO,QAAU,EACnB,MAAO,YAGT,GAAIA,EAAO,MAAQ,QAAaA,EAAO,MAAQ,QAAaA,EAAO,KAAOA,EAAO,IAC/E,MAAO,eAGT,GAAIA,EAAO,OAAS,QAAaA,EAAO,MAAQ,EAC9C,MAAO,WAEX,CAEA,OAAO,IACT,EAKaC,GACXC,GACkB,CAClB,GAAI,CAACA,EAAa,OAAO,KAEzB,GAAIA,EAAY,YAAa,CAC3B,KAAM,CAACC,EAAMC,EAAKC,EAAOC,CAAM,EAAIJ,EAAY,YAC/C,GAAIC,GAAQE,GAASD,GAAOE,EAC1B,MAAO,uCAEX,CAEA,OAAIJ,EAAY,WAAa,QAAaA,EAAY,UAAY,EACzD,YAGF,IACT,EAKaK,GACX3tB,GACkC,CAElC,MAAM4tB,EAAgBrB,GAAuB,CAC3C,KAAMvsB,EAAM,KACZ,OAAQA,EAAM,OACd,OAAQA,EAAM,OACd,UAAWA,EAAM,SAAA,CAClB,EAED,GAAI4tB,EAAe,OAAOA,EAG1B,MAAMC,EAAiBX,GAAwBltB,EAAM,SAAS,EAC9D,GAAI6tB,EACF,MAAO,CACL,KAAM,iBACN,QAASA,EACT,UAAW,IAAI,KAAA,EAAO,YAAA,CAAY,EAKtC,MAAMC,EAAaT,GAAoBrtB,EAAM,WAAW,EACxD,OAAI8tB,EACK,CACL,KAAM,iBACN,QAASA,EACT,UAAW,IAAI,KAAA,EAAO,YAAA,CAAY,EAKlC9tB,EAAM,wBAA0B,SAC9BA,EAAM,sBAAwB,GAAKA,EAAM,sBAAwB,GAC5D,CACL,KAAM,iBACN,QAAS,iBACT,UAAW,IAAI,KAAA,EAAO,YAAA,CAAY,EAKjC,IACT,ECpEO,MAAe+tB,EACmB,CAe7B,eAAe9uB,EAAe+uB,EAAmBlW,EAAcmW,EAAkC,CACzG,GAAI,OAAOhvB,GAAU,UAAY,MAAMA,CAAK,EAC1C,MAAO,GAAG+uB,CAAS,WAGrB,GAAIlW,IAAQ,QAAa7Y,EAAQ6Y,EAC/B,MAAO,GAAGkW,CAAS,OAAOlW,CAAG,GAG/B,GAAImW,IAAQ,QAAahvB,EAAQgvB,EAC/B,MAAO,GAAGD,CAAS,OAAOC,CAAG,EAIjC,CAEU,cAAchvB,EAAc+uB,EAAmBpQ,EAAqC,CAC5F,GAAI,CAAC,MAAM,QAAQ3e,CAAK,EACtB,MAAO,GAAG+uB,CAAS,QAGrB,GAAIpQ,IAAW,QAAa3e,EAAM,SAAW2e,EAC3C,MAAO,GAAGoQ,CAAS,SAASpQ,CAAM,KAItC,CAEU,eAAe3e,EAAe+uB,EAAmBhe,EAAwC,CACjG,GAAI,OAAO/Q,GAAU,SACnB,MAAO,GAAG+uB,CAAS,SAGrB,GAAIhe,IAAY,QAAa,CAACA,EAAQ,SAAS/Q,CAAK,EAClD,MAAO,GAAG+uB,CAAS,aAAahe,EAAQ,KAAK,IAAI,CAAC,EAItD,CAGU,uBACRke,EACAC,EACAC,EACkB,CAClB,MAAO,CACL,QAAAF,EACA,OAAQC,GAAQ,OAAO,OAAO,EAC9B,SAAUC,GAAU,OAAO,OAAO,CAAA,CAEtC,CAGU,iBAAiBtC,EAAwC,CACjE,GAAI,CAAC,MAAM,QAAQA,CAAQ,GAAKA,EAAS,SAAW,EAClD,MAAO,WAGT,QAAS/hB,EAAI,EAAGA,EAAI+hB,EAAS,OAAQ/hB,IAAK,CACxC,MAAM+iB,EAAShB,EAAS/hB,CAAC,EACnBrF,EAAQ,KAAK,cAAcooB,EAAQ,MAAM/iB,CAAC,IAAK,CAAC,EACtD,GAAIrF,EAAO,OAAOA,EAElB,KAAM,CAACunB,EAAGC,CAAC,EAAIY,EACTuB,EAAS,KAAK,eAAepC,EAAG,MAAMliB,CAAC,KAAK,EAC5CukB,EAAS,KAAK,eAAepC,EAAG,MAAMniB,CAAC,KAAK,EAElD,GAAIskB,GAAUC,EACZ,MAAO,GAAGD,GAAUC,CAAM,QAAQvkB,CAAC,IAEvC,CAGF,CACF,CC9IO,MAAMwkB,GAAuB,CAClCzC,EACA7pB,EACApE,IACuB,CAEnB,QAAQ,IAAI,WAAa,eAC3B,QAAQ,IAAI,kCAAmC,CAC7C,SAAAiuB,EACA,SAAA7pB,EACA,OAAApE,EACA,SAAUA,EAAO,SACjB,aAAc,OAAOA,EAAO,SAC5B,UAAWA,EAAO,UAClB,cAAe,OAAOA,EAAO,UAC7B,WAAY,OAAOA,EACnB,WAAY,OAAO,KAAKA,CAAM,CAAA,CAC/B,EAGH,IAAI2wB,EAEA3wB,EAAO,YAAc,aACvB2wB,EAAkB,CAAC3wB,EAAO,SAAU,CAAC,EAC5BA,EAAO,YAAc,WAC9B2wB,EAAkB,CAAC,EAAG3wB,EAAO,QAAQ,EAGrC2wB,EAAkB,CAChB3wB,EAAO,UAAU,CAAC,EAAIA,EAAO,SAC7BA,EAAO,UAAU,CAAC,EAAIA,EAAO,QAAA,EAIjC,MAAM4wB,EAAUD,EAAgB,CAAC,EAAIvsB,EAC/BysB,EAAUF,EAAgB,CAAC,EAAIvsB,EAGrC,OAAI,QAAQ,IAAI,WAAa,eAC3B,QAAQ,IAAI,kCAAmC,CAC7C,gBAAAusB,EACA,QAAAC,EACA,QAAAC,EACA,oBAAqB5C,EAAS,CAAC,EAC/B,uBAAwB,CAACA,EAAS,CAAC,EAAE,CAAC,EAAI2C,EAAS3C,EAAS,CAAC,EAAE,CAAC,EAAI4C,CAAO,CAAA,CAC5E,EAGI5C,EAAS,IAAI,CAAC,CAACG,EAAGC,CAAC,IAAM,CAACD,EAAIwC,EAASvC,EAAIwC,CAAO,CAAC,CAC5D,EAKaC,GAAoB,CAC/B7C,EACA7pB,EACApE,IACuB,CAEvB,MAAM+wB,EAAS/wB,EAAO,SAAW,OAC7BguB,GAAkBC,CAAQ,EAC1BjuB,EAAO,OAEL,CAACgxB,EAAIC,CAAE,EAAIF,EACXG,EAAalxB,EAAO,SAAWA,EAAO,WACtCmxB,EAAYnxB,EAAO,YAAc,YAAc,GAAK,EACpDoxB,EAAepxB,EAAO,WAAckxB,EAAa9sB,EAAW+sB,EAElE,OAAOlD,EAAS,IAAI,CAAC,CAACG,EAAGC,CAAC,IAAM,CAC9B,MAAMgD,EAAKjD,EAAI4C,EACTM,EAAKjD,EAAI4C,EACTM,EAAM,KAAK,IAAIH,CAAY,EAC3BI,EAAM,KAAK,IAAIJ,CAAY,EAEjC,MAAO,CACLJ,EAAKK,EAAKE,EAAMD,EAAKE,EACrBP,EAAKI,EAAKG,EAAMF,EAAKC,CAAA,CAEzB,CAAC,CACH,EAKaE,GAAiB,CAC5BxD,EACA7pB,EACApE,IACuB,CAEvB,MAAM+wB,EAAS/wB,EAAO,SAAW,WAC7BguB,GAAkBC,CAAQ,EAC1BjuB,EAAO,OAEL,CAACgxB,EAAIC,CAAE,EAAIF,EACXW,EAAa1xB,EAAO,SAAWA,EAAO,WACtC2xB,EAAe3xB,EAAO,WAAc0xB,EAAattB,EAEvD,OAAO6pB,EAAS,IAAI,CAAC,CAACG,EAAGC,CAAC,IAAM,CAC9B,MAAMgD,EAAKjD,EAAI4C,EACTM,EAAKjD,EAAI4C,EACf,MAAO,CACLD,EAAKK,EAAKM,EACVV,EAAKK,EAAKK,CAAA,CAEd,CAAC,CACH,EAwIaC,GAAqB,CAChCC,EACA9W,EAAoB,MAEb8W,GAAmB9W,ECpPrB,MAAM+W,WAA4B5B,EAAyC,CACvE,KAAO,cAEhB,gBAAyB,CACvB,MAAO,MACT,CAEA,gBAAyB,CACvB,MAAO,iBACT,CAEA,kBAAsC,CACpC,MAAO,CACL,UAAW,aACX,SAAU,EACV,YAAa,CAAA,CAEjB,CAEA,QAAQjC,EAAoB7pB,EAAkBpE,EAAqC,CAEjF,OAAO0wB,GAAqBzC,EAAU7pB,EAAUpE,CAAM,CACxD,CAEA,SAASA,EAA6C,CACpD,MAAMswB,EAAmB,CAAA,EACnBC,EAAqB,CAAA,EAG3B,GAAI,OAAOvwB,EAAO,WAAc,SAAU,CAExC,MAAM+xB,EAAiB,KAAK,eAC1B/xB,EAAO,UACP,YACA,CAAC,aAAc,UAAU,CAAA,EAEvB+xB,GAAgBzB,EAAO,KAAKyB,CAAc,CAChD,SAAW,MAAM,QAAQ/xB,EAAO,SAAS,EAAG,CAE1C,MAAM+xB,EAAiB,KAAK,cAAc/xB,EAAO,UAAW,YAAa,CAAC,EAC1E,GAAI+xB,EACFzB,EAAO,KAAKyB,CAAc,MACrB,CAEL,KAAM,CAAC3D,EAAGC,CAAC,EAAIruB,EAAO,UAChBwwB,EAAS,KAAK,eAAepC,EAAG,cAAc,EAC9CqC,EAAS,KAAK,eAAepC,EAAG,cAAc,EAChDmC,GAAQF,EAAO,KAAKE,CAAM,EAC1BC,GAAQH,EAAO,KAAKG,CAAM,CAChC,CACF,MACEH,EAAO,KAAK,oBAAoB,EAIlC,MAAM0B,EAAgB,KAAK,eAAehyB,EAAO,SAAU,WAAY,CAAC,EAIxE,GAHIgyB,GAAe1B,EAAO,KAAK0B,CAAa,EAGxChyB,EAAO,cAAgB,OAAW,CACpC,MAAMiyB,EAAc,KAAK,eAAejyB,EAAO,YAAa,cAAe,EAAG,CAAC,EAC3EiyB,GAAa1B,EAAS,KAAK0B,CAAW,CAC5C,CAGA,GAAI,MAAM,QAAQjyB,EAAO,SAAS,EAAG,CACnC,KAAM,CAACouB,EAAGC,CAAC,EAAIruB,EAAO,UACP,KAAK,KAAKouB,EAAIA,EAAIC,EAAIA,CAAC,EACzB,MACXkC,EAAS,KAAK,sBAAsB,CAExC,CAEA,OAAO,KAAK,uBAAuBD,EAAO,SAAW,EAAGA,EAAQC,CAAQ,CAC1E,CAGQ,mBAAmBvwB,EAA6C,CACtE,OAAIA,EAAO,YAAc,aAChB,CAAC,EAAG,CAAC,EACHA,EAAO,YAAc,WACvB,CAAC,EAAG,CAAC,EAELA,EAAO,SAElB,CAGA,wBAAwBA,EAA2BoE,EAAoC,CACrF,MAAMusB,EAAkB,KAAK,mBAAmB3wB,CAAM,EAChDkyB,EAAclyB,EAAO,aAAe,EACpCmyB,EAAoB,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG/tB,EAAW8tB,CAAW,CAAC,GAAK,EAAIA,GAElF,MAAO,CACLvB,EAAgB,CAAC,EAAI3wB,EAAO,SAAWmyB,EACvCxB,EAAgB,CAAC,EAAI3wB,EAAO,SAAWmyB,CAAA,CAE3C,CACF,CCjGO,MAAMC,WAAyBlC,EAAsC,CACjE,KAAO,WAEhB,gBAAyB,CACvB,MAAO,MACT,CAEA,gBAAyB,CACvB,MAAO,iBACT,CAEA,kBAAmC,CACjC,MAAO,CACL,OAAQ,OACR,WAAY,EACZ,SAAU,KAAK,GACf,UAAW,WAAA,CAEf,CAEA,QAAQjC,EAAoB7pB,EAAkBpE,EAAkC,CAE9E,OAAO8wB,GAAkB7C,EAAU7pB,EAAUpE,CAAM,CACrD,CAEA,SAASA,EAA0C,CACjD,MAAMswB,EAAmB,CAAA,EACnBC,EAAqB,CAAA,EAG3B,GAAIvwB,EAAO,SAAW,OAEtB,GAAW,MAAM,QAAQA,EAAO,MAAM,EAAG,CACvC,MAAMqyB,EAAc,KAAK,cAAcryB,EAAO,OAAQ,SAAU,CAAC,EACjE,GAAIqyB,EACF/B,EAAO,KAAK+B,CAAW,MAClB,CACL,KAAM,CAACjE,EAAGC,CAAC,EAAIruB,EAAO,OAChBwwB,EAAS,KAAK,eAAepC,EAAG,WAAW,EAC3CqC,EAAS,KAAK,eAAepC,EAAG,WAAW,EAC7CmC,GAAQF,EAAO,KAAKE,CAAM,EAC1BC,GAAQH,EAAO,KAAKG,CAAM,CAChC,CACF,MACEH,EAAO,KAAK,0BAA0B,EAIxC,MAAMgC,EAAkB,KAAK,eAAetyB,EAAO,WAAY,YAAY,EACvEsyB,GAAiBhC,EAAO,KAAKgC,CAAe,EAGhD,MAAMC,EAAgB,KAAK,eAAevyB,EAAO,SAAU,UAAU,EAIrE,GAHIuyB,GAAejC,EAAO,KAAKiC,CAAa,EAGxC,CAACD,GAAmB,CAACC,EAAe,CACtC,MAAMrB,EAAa,KAAK,IAAIlxB,EAAO,SAAWA,EAAO,UAAU,EAC3DkxB,EAAa,MACfX,EAAS,KAAK,oBAAoB,EAEhCW,EAAa,EAAI,KAAK,IACxBX,EAAS,KAAK,eAAe,CAEjC,CAGA,MAAMwB,EAAiB,KAAK,eAC1B/xB,EAAO,UACP,YACA,CAAC,YAAa,mBAAoB,aAAc,UAAU,CAAA,EAE5D,OAAI+xB,GAAgBzB,EAAO,KAAKyB,CAAc,EAavC,KAAK,uBAAuBzB,EAAO,SAAW,EAAGA,EAAQC,CAAQ,CAC1E,CAIQ,iBAAiBtC,EAAgF,CACvG,GAAIA,EAAS,SAAW,EACtB,MAAO,CAAE,KAAM,EAAG,KAAM,EAAG,KAAM,EAAG,KAAM,CAAA,EAG5C,IAAIuE,EAAOvE,EAAS,CAAC,EAAE,CAAC,EACpBwE,EAAOxE,EAAS,CAAC,EAAE,CAAC,EACpByE,EAAOzE,EAAS,CAAC,EAAE,CAAC,EACpB0E,EAAO1E,EAAS,CAAC,EAAE,CAAC,EAExB,QAAS,EAAI,EAAG,EAAIA,EAAS,OAAQ,IAAK,CACxC,KAAM,CAACG,EAAGC,CAAC,EAAIJ,EAAS,CAAC,EACzBuE,EAAO,KAAK,IAAIA,EAAMpE,CAAC,EACvBqE,EAAO,KAAK,IAAIA,EAAMrE,CAAC,EACvBsE,EAAO,KAAK,IAAIA,EAAMrE,CAAC,EACvBsE,EAAO,KAAK,IAAIA,EAAMtE,CAAC,CACzB,CAEA,MAAO,CAAE,KAAAmE,EAAM,KAAAC,EAAM,KAAAC,EAAM,KAAAC,CAAA,CAC7B,CAGA,gBAAgB1E,EAAoBjuB,EAA0C,CAC5E,OAAIA,EAAO,SAAW,OACbguB,GAAkBC,CAAQ,EAE5BjuB,EAAO,MAChB,CAGA,sBAAsBA,EAAwBoE,EAA0B,CACtE,MAAM8sB,EAAalxB,EAAO,SAAWA,EAAO,WACtCmxB,EAAYnxB,EAAO,YAAc,YAAc,GAAK,EAC1D,OAAOA,EAAO,WAAckxB,EAAa9sB,EAAW+sB,CACtD,CACF,CC7HO,MAAMyB,WAAsB1C,EAAmC,CAC3D,KAAO,QAEhB,gBAAyB,CACvB,MAAO,MACT,CAEA,gBAAyB,CACvB,MAAO,cACT,CAEA,kBAAgC,CAC9B,MAAO,CACL,OAAQ,WACR,WAAY,EACZ,SAAU,EACV,QAAS,EAAA,CAEb,CAEA,QAAQjC,EAAoB7pB,EAAkBpE,EAA+B,CAE3E,OAAOyxB,GAAexD,EAAU7pB,EAAUpE,CAAM,CAClD,CAEA,SAASA,EAAuC,CAC9C,MAAMswB,EAAmB,CAAA,EACnBC,EAAqB,CAAA,EAG3B,GAAIvwB,EAAO,SAAW,WAEtB,GAAW,MAAM,QAAQA,EAAO,MAAM,EAAG,CACvC,MAAMqyB,EAAc,KAAK,cAAcryB,EAAO,OAAQ,SAAU,CAAC,EACjE,GAAIqyB,EACF/B,EAAO,KAAK+B,CAAW,MAClB,CACL,KAAM,CAACjE,EAAGC,CAAC,EAAIruB,EAAO,OAChBwwB,EAAS,KAAK,eAAepC,EAAG,WAAW,EAC3CqC,EAAS,KAAK,eAAepC,EAAG,WAAW,EAC7CmC,GAAQF,EAAO,KAAKE,CAAM,EAC1BC,GAAQH,EAAO,KAAKG,CAAM,CAChC,CACF,MACEH,EAAO,KAAK,8BAA8B,EAI5C,MAAMuC,EAAkB,KAAK,eAAe7yB,EAAO,WAAY,aAAc,GAAI,EAC7E6yB,GAAiBvC,EAAO,KAAKuC,CAAe,EAGhD,MAAMC,EAAgB,KAAK,eAAe9yB,EAAO,SAAU,WAAY,GAAI,EAI3E,GAHI8yB,GAAexC,EAAO,KAAKwC,CAAa,EAGxC,CAACD,GAAmB,CAACC,EAAe,CACtC,MAAMC,EAAa/yB,EAAO,SAAWA,EAAO,WAExC,KAAK,IAAIA,EAAO,SAAWA,EAAO,UAAU,EAAI,KAClDuwB,EAAS,KAAK,sBAAsB,EAGlCwC,EAAa,IACfxC,EAAS,KAAK,mBAAmB,EAG/BwC,EAAa,IACfxC,EAAS,KAAK,oBAAoB,CAEtC,CAGA,OAAI,OAAOvwB,EAAO,SAAY,UAC5BswB,EAAO,KAAK,eAAe,EACjBtwB,EAAO,SACjBuwB,EAAS,KAAK,eAAe,EAUxB,KAAK,uBAAuBD,EAAO,SAAW,EAAGA,EAAQC,CAAQ,CAC1E,CAGA,gBAAgBtC,EAAoBjuB,EAAuC,CACzE,OAAIA,EAAO,SAAW,WACbguB,GAAkBC,CAAQ,EAE5BjuB,EAAO,MAChB,CAGA,sBAAsBA,EAAqBoE,EAA0B,CACnE,MAAMstB,EAAa1xB,EAAO,SAAWA,EAAO,WAC5C,OAAOA,EAAO,WAAc0xB,EAAattB,CAC3C,CAGA,oBAAoB6pB,EAAoBjuB,EAAqBoE,EAI3D,CACA,GAAI6pB,EAAS,OAAS,EACpB,MAAO,CAAE,YAAa,EAAG,aAAc,EAAG,WAAY,CAAA,EAGxD,MAAM+E,EAAS,KAAK,gBAAgB/E,CAAQ,EACtCgF,EAAgBD,EAAO,KAAOA,EAAO,KACrCE,EAAiBF,EAAO,KAAOA,EAAO,KACtCG,EAAeF,EAAgBC,EAE/BvB,EAAe,KAAK,sBAAsB3xB,EAAQoE,CAAQ,EAC1DgvB,GAAcpzB,EAAO,QAAU2xB,GAE/B0B,EAAWJ,EAAgBG,EAC3BE,EAAYJ,EAAiBE,EAC7BG,EAAUF,EAAWC,EAE3B,MAAO,CACL,aAAcD,EAAWJ,GAAiBA,EAC1C,cAAeK,EAAYJ,GAAkBA,EAC7C,YAAaK,EAAUJ,GAAgBA,CAAA,CAE3C,CAGQ,gBAAgBlF,EAAgF,CACtG,GAAIA,EAAS,SAAW,EACtB,MAAO,CAAE,KAAM,EAAG,KAAM,EAAG,KAAM,EAAG,KAAM,CAAA,EAG5C,IAAIuE,EAAOvE,EAAS,CAAC,EAAE,CAAC,EACpBwE,EAAOxE,EAAS,CAAC,EAAE,CAAC,EACpByE,EAAOzE,EAAS,CAAC,EAAE,CAAC,EACpB0E,EAAO1E,EAAS,CAAC,EAAE,CAAC,EAExB,QAAS,EAAI,EAAG,EAAIA,EAAS,OAAQ,IAAK,CACxC,KAAM,CAACG,EAAGC,CAAC,EAAIJ,EAAS,CAAC,EACzBuE,EAAO,KAAK,IAAIA,EAAMpE,CAAC,EACvBqE,EAAO,KAAK,IAAIA,EAAMrE,CAAC,EACvBsE,EAAO,KAAK,IAAIA,EAAMrE,CAAC,EACvBsE,EAAO,KAAK,IAAIA,EAAMtE,CAAC,CACzB,CAEA,MAAO,CAAE,KAAAmE,EAAM,KAAAC,EAAM,KAAAC,EAAM,KAAAC,CAAA,CAC7B,CACF,CC1JO,SAASa,GAASC,EAAuC,CAE9D,IAAIC,EAAWD,EAAI,KAAA,EAAO,QAAQ,KAAM,EAAE,EAO1C,IAJIC,EAAS,SAAW,GAAKA,EAAS,SAAW,KAC/CA,EAAWA,EAAS,MAAM,EAAE,EAAE,OAAUC,EAAKA,CAAE,EAAE,KAAK,EAAE,GAGtDD,EAAS,SAAW,GAAKA,EAAS,SAAW,EAC/C,MAAM,IAAI,MAAM,gBAAgBD,CAAG,EAAE,EAIvC,MAAMG,EAAI,SAASF,EAAS,UAAU,EAAG,CAAC,EAAG,EAAE,EACzCG,EAAI,SAASH,EAAS,UAAU,EAAG,CAAC,EAAG,EAAE,EACzCzmB,EAAI,SAASymB,EAAS,UAAU,EAAG,CAAC,EAAG,EAAE,EAE/C,GAAI,MAAME,CAAC,GAAK,MAAMC,CAAC,GAAK,MAAM5mB,CAAC,EACjC,MAAM,IAAI,MAAM,eAAewmB,CAAG,EAAE,EAGtC,MAAO,CAACG,EAAGC,EAAG5mB,CAAC,CACjB,CASO,SAAS6mB,GAAS,EAAWD,EAAW5mB,EAAmB,CAEhE,MAAM8mB,EAAS3yB,GAAkB,KAAK,IAAI,EAAG,KAAK,IAAI,IAAK,KAAK,MAAMA,CAAK,CAAC,CAAC,EAEvE4yB,EAAOD,EAAM,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,EAC5CE,EAAOF,EAAMF,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,EAC5CK,EAAOH,EAAM9mB,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,EAElD,MAAO,IAAI+mB,CAAI,GAAGC,CAAI,GAAGC,CAAI,GAAG,YAAA,CAClC,CAQO,SAASC,GAAW5I,EAAyC,CAClE,MAAM6I,EAAU7I,EAAM,KAAA,EAGtB,GAAI6I,EAAQ,WAAW,GAAG,EACxB,OAAOZ,GAASY,CAAO,EAIzB,MAAMC,EAAWD,EAAQ,MAAM,mEAAmE,EAClG,GAAIC,EAAU,CACZ,MAAMT,EAAI,SAASS,EAAS,CAAC,EAAG,EAAE,EAC5BR,EAAI,SAASQ,EAAS,CAAC,EAAG,EAAE,EAC5BpnB,EAAI,SAASonB,EAAS,CAAC,EAAG,EAAE,EAElC,GAAIT,GAAK,GAAKA,GAAK,KAAOC,GAAK,GAAKA,GAAK,KAAO5mB,GAAK,GAAKA,GAAK,IAC7D,MAAO,CAAC2mB,EAAGC,EAAG5mB,CAAC,CAEnB,CAGA,MAAMqnB,EAAmC,CACvC,IAAK,UACL,MAAO,UACP,KAAM,UACN,OAAQ,UACR,KAAM,UACN,QAAS,UACT,MAAO,UACP,MAAO,UACP,KAAM,UACN,KAAM,UACN,YAAa,aAAA,EAGTC,EAAaH,EAAQ,YAAA,EAC3B,GAAIE,EAASC,CAAU,EACrB,OAAIA,IAAe,cACV,CAAC,EAAG,EAAG,CAAC,EAEVf,GAASc,EAASC,CAAU,CAAC,EAGtC,MAAM,IAAI,MAAM,cAAchJ,CAAK,EAAE,CACvC,CAOO,SAASiJ,GAAajJ,EAAwB,CACnD,GAAI,CACF,OAAA4I,GAAW5I,CAAK,EACT,EACT,MAAQ,CACN,MAAO,EACT,CACF,CASO,SAASkJ,GAAiBC,EAAcC,EAAYvwB,EAA0B,CAEnF,GAAIA,GAAY,EAAG,OAAOswB,EAC1B,GAAItwB,GAAY,EAAG,OAAOuwB,EAE1B,GAAI,CACF,MAAMC,EAAUT,GAAWO,CAAI,EACzBG,EAAQV,GAAWQ,CAAE,EAGrBf,EAAIgB,EAAQ,CAAC,GAAKC,EAAM,CAAC,EAAID,EAAQ,CAAC,GAAKxwB,EAC3CyvB,EAAIe,EAAQ,CAAC,GAAKC,EAAM,CAAC,EAAID,EAAQ,CAAC,GAAKxwB,EAC3C6I,EAAI2nB,EAAQ,CAAC,GAAKC,EAAM,CAAC,EAAID,EAAQ,CAAC,GAAKxwB,EAEjD,OAAO0vB,GAASF,EAAGC,EAAG5mB,CAAC,CACzB,OAASpG,EAAO,CACd,eAAQ,KAAK,iBAAkBA,CAAK,EAC7B6tB,CACT,CACF,CAsBO,SAASI,GACdJ,EACAC,EACAvwB,EACA2wB,EAAqE,SAC7D,CAER,IAAIC,EAAgB5wB,EAEpB,OAAQ2wB,EAAA,CACN,IAAK,UACHC,EAAgB5wB,EAAWA,EAC3B,MACF,IAAK,WACH4wB,EAAgB,GAAK,EAAI5wB,IAAa,EAAIA,GAC1C,MACF,IAAK,cACH4wB,EAAgB5wB,EAAW,GACvB,EAAIA,EAAWA,EACf,EAAI,KAAK,IAAI,GAAKA,EAAW,EAAG,CAAC,EAAI,EACzC,MACF,IAAK,OACH4wB,EAAgB5wB,GAAY,EAAI,EAAI,EACpC,KAIA,CAGJ,OAAOqwB,GAAiBC,EAAMC,EAAIK,CAAa,CACjD,CC5LO,MAAMC,WAA6B/E,EAA0C,CACzE,KAAO,gBAEhB,gBAAyB,CACvB,MAAO,MACT,CAEA,gBAAyB,CACvB,MAAO,sBACT,CAEA,kBAAuC,CACrC,MAAO,CACL,YAAa,UACb,QAAS,EACT,MAAO,EACP,OAAQ,SACR,UAAW,MAAA,CAEf,CAEA,QAAQjC,EAAoBiH,EAAmB1W,EAAuC,CAGpF,OAAOyP,CACT,CAEA,SAASjuB,EAA8C,CACrD,MAAMswB,EAAmB,CAAA,EACnBC,EAAqB,CAAA,EAmB3B,GAhBI,CAACvwB,EAAO,aAAe,OAAOA,EAAO,aAAgB,SACvDswB,EAAO,KAAK,yBAAyB,EAC3BkE,GAAax0B,EAAO,WAAW,GACzCswB,EAAO,KAAK,qBAAqBtwB,EAAO,WAAW,EAAE,EAInDA,EAAO,YAAc,SACnB,OAAOA,EAAO,WAAc,SAC9BswB,EAAO,KAAK,kBAAkB,EACpBkE,GAAax0B,EAAO,SAAS,GACvCswB,EAAO,KAAK,mBAAmBtwB,EAAO,SAAS,EAAE,GAKjDA,EAAO,UAAY,OAAW,CAChC,MAAMm1B,EAAe,KAAK,eAAen1B,EAAO,QAAS,UAAW,EAAG,CAAC,EACpEm1B,GAAc7E,EAAO,KAAK6E,CAAY,CAC5C,CAGA,GAAIn1B,EAAO,QAAU,OAAW,CAC9B,MAAMo1B,EAAa,KAAK,eAAep1B,EAAO,MAAO,QAAS,EAAG,CAAC,EAC9Do1B,GAAY9E,EAAO,KAAK8E,CAAU,CACxC,CAUA,GAPIp1B,EAAO,UAAY,QAAaA,EAAO,QAAU,QAC/CA,EAAO,SAAWA,EAAO,OAC3BswB,EAAO,KAAK,oBAAoB,EAKhCtwB,EAAO,SAAW,OAAW,CAC/B,MAAMq1B,EAAc,KAAK,eACvBr1B,EAAO,OACP,SACA,CAAC,SAAU,UAAW,WAAY,cAAe,MAAM,CAAA,EAErDq1B,GAAa/E,EAAO,KAAK+E,CAAW,CAC1C,CAGA,OAAIr1B,EAAO,aAAeA,EAAO,UAS1B,KAAK,uBAAuBswB,EAAO,SAAW,EAAGA,EAAQC,CAAQ,CAC1E,CASA,sBACEnsB,EACApE,EACAs1B,EACQ,CAER,MAAMC,EAAYv1B,EAAO,WAAas1B,EAChCE,EAAcx1B,EAAO,YAGrBmyB,EAAoB,KAAK,2BAA2B/tB,EAAUpE,CAAM,EAG1E,OAAO80B,GACLS,EACAC,EACArD,EACAnyB,EAAO,MAAA,CAEX,CAQQ,2BACNoE,EACApE,EACQ,CACR,MAAMy1B,EAAUz1B,EAAO,SAAW,EAC5B01B,EAAQ11B,EAAO,OAAS,EAE9B,OAAIoE,GAAYqxB,EAAgB,EAC5BrxB,GAAYsxB,EAAc,GAGtBtxB,EAAWqxB,IAAYC,EAAQD,EACzC,CAQA,SAASrxB,EAAkBpE,EAAqC,CAC9D,MAAMy1B,EAAUz1B,EAAO,SAAW,EAC5B01B,EAAQ11B,EAAO,OAAS,EAE9B,OAAOoE,GAAYqxB,GAAWrxB,GAAYsxB,CAC5C,CACF,CCnJO,MAAMC,EAA0B,CAC7B,cAAsE,IAM9E,SAA6C3O,EAAuC,CAC9E,KAAK,UAAU,IAAIA,EAAS,IAA8B,GAC5D,QAAQ,KAAK,UAAUA,EAAS,IAAI,YAAY,EAGlD,KAAK,UAAU,IAAIA,EAAS,KAAgCA,CAAQ,CACtE,CAOA,IAAwCjnB,EAAiE,CACvG,OAAO,KAAK,UAAU,IAAIA,CAAI,CAChC,CAOA,IAAIA,EAAuC,CACzC,OAAO,KAAK,UAAU,IAAIA,CAAI,CAChC,CAMA,mBAA8C,CAC5C,OAAO,MAAM,KAAK,KAAK,UAAU,MAAM,CACzC,CAMA,yBAAkE,CAChE,MAAM2K,EAAiC,CAAA,EAEvC,SAAW,CAAC3K,EAAMinB,CAAQ,IAAK,KAAK,UAClCtc,EAAO3K,CAAI,EAAIinB,EAAS,eAAA,EAG1B,OAAOtc,CACT,CAQA,eACE3K,EACAC,EACkB,CAClB,MAAMgnB,EAAW,KAAK,IAAOjnB,CAAI,EACjC,OAAKinB,EAOEA,EAAS,SAAShnB,CAAM,EANtB,CACL,QAAS,GACT,OAAQ,CAAC,YAAYD,CAAI,EAAE,CAAA,CAKjC,CAUA,iBACEA,EACAkuB,EACA7pB,EACApE,EACoB,CACpB,MAAMgnB,EAAW,KAAK,IAAOjnB,CAAI,EACjC,GAAI,CAACinB,EACH,eAAQ,MAAM,YAAYjnB,CAAI,EAAE,EACzBkuB,EAIT,MAAM2H,EAAmB5O,EAAS,SAAShnB,CAAM,EACjD,OAAK41B,EAAiB,QAKf5O,EAAS,QAAQiH,EAAU7pB,EAAUpE,CAAM,GAJhD,QAAQ,MAAM,UAAW41B,EAAiB,MAAM,EACzC3H,EAIX,CASA,kBACE4H,EACA5H,EACA7pB,EACoB,CACpB,IAAIsG,EAASujB,EAEb,UAAWJ,KAAagI,EAAY,CAClC,MAAM7O,EAAW,KAAK,IAAI6G,EAAU,IAAI,EACxC,GAAI,CAAC7G,EAAU,CACb,QAAQ,KAAK,eAAe6G,EAAU,IAAI,EAAE,EAC5C,QACF,CAEAnjB,EAASsc,EAAS,QAAQtc,EAAQtG,EAAUypB,EAAU,MAAM,CAC9D,CAEA,OAAOnjB,CACT,CAOA,iBAAqD3K,EAA6C,CAEhG,OADiB,KAAK,IAAOA,CAAI,GAChB,iBAAA,CACnB,CAKA,OAAc,CACZ,KAAK,UAAU,MAAA,CACjB,CAMA,MAAe,CACb,OAAO,KAAK,UAAU,IACxB,CACF,CAGA,IAAI+1B,GAAoD,KAMjD,SAASC,IAAgD,CAC9D,OAAKD,KACHA,GAAkB,IAAIH,GAEtBG,GAAgB,SAAS,IAAIhE,EAAqB,EAClDgE,GAAgB,SAAS,IAAI1D,EAAkB,EAC/C0D,GAAgB,SAAS,IAAIlD,EAAe,EAC5CkD,GAAgB,SAAS,IAAIb,EAAsB,GAE9Ca,EACT,CCtLO,MAAME,EAAa,CAIxB,OAAO,aACLC,EACAC,EACAC,EACS,CACT,GAAI,CAACD,EAEH,MAAO,CAACC,GAAiB,KAAK,eAAeF,CAAa,IAAME,EAIlE,GAAI,gBAAiBD,GAAcA,EAAW,YAC5C,OAAO,KAAK,mBAAmBD,EAAeC,EAAW,YAAaA,EAAW,aAAa,EAIhG,GAAI,YAAaA,EAAY,CAE3B,GAAIA,EAAW,WAAa,MAC1B,OAAO,KAAK,kBAAkBD,EAAeC,CAAU,EAGzD,GAAIA,EAAW,QACb,OAAO,KAAK,kBAAkBD,EAAeC,CAAU,CAE3D,CAEA,MAAO,EACT,CAKA,OAAe,mBACbE,EACAC,EACAC,EACS,CACT,MAAMC,EAAU,KAAK,eAAeH,EAAUE,CAAa,EAC3D,GAAI,CAACC,EAAS,MAAO,GAGrB,GAAIF,EAAY,SAAS,GAAG,EAAG,CAC7B,MAAMG,EAAUH,EAAY,QAAQ,MAAO,IAAI,EAC/C,OAAO,IAAI,OAAO,IAAIG,CAAO,GAAG,EAAE,KAAKD,CAAO,CAChD,CAEA,OAAOA,IAAYF,CACrB,CAKA,OAAe,kBACbD,EACAp2B,EACS,CACT,MAAMu2B,EAAU,KAAK,eAAeH,EAAUp2B,EAAO,aAAa,EAClE,GAAI,CAACu2B,EAAS,MAAO,GAErB,MAAMC,EAAUx2B,EAAO,QACjBy2B,EAAWz2B,EAAO,UAAY,QAC9B02B,EAAgB12B,EAAO,eAAiB,GAE9C,OAAQy2B,EAAA,CACN,IAAK,QACH,OAAOC,EACHH,IAAYC,EACZD,EAAQ,YAAA,IAAmBC,EAAmB,YAAA,EAEpD,IAAK,WACH,MAAMG,EAAmBH,EAAmB,QAAQ,MAAO,IAAI,EAC/D,OAAO,IAAI,OAAO,IAAIG,CAAe,IAAKD,EAAgB,GAAK,GAAG,EAAE,KAAKH,CAAO,EAElF,IAAK,QAIH,OAHcC,aAAmB,OAC7BA,EACA,IAAI,OAAOA,EAAmBE,EAAgB,GAAK,GAAG,GAC7C,KAAKH,CAAO,EAE3B,IAAK,WAEH,OADiB,MAAM,QAAQC,CAAO,EAAIA,EAAWA,EAAmB,MAAM,GAAG,GACjE,KAAKI,GAAK,KAAK,mBAAmBR,EAAUQ,EAAG52B,EAAO,aAAa,CAAC,EAEtF,IAAK,MACH,MAAO,GAET,QACE,MAAO,EAAA,CAEb,CAKA,OAAO,eACLo2B,EACAjG,EAAoB,gBACA,CACpB,GAAI,CAACiG,EAAU,OAGf,MAAMS,EAAS1G,EAAU,MAAM,GAAG,EAClC,IAAI/uB,EAAag1B,EAEjB,UAAWU,KAASD,EAAQ,CAC1B,GAAIz1B,GAAS,KAAM,OACnBA,EAAQA,EAAM01B,CAAK,CACrB,CAEA,OAAO,OAAO11B,GAAU,SAAWA,EAAQ,MAC7C,CAKA,OAAO,eAAepB,EAIpB,CACA,MAAMswB,EAAmB,CAAA,EACnBC,EAAqB,CAAA,EAG3B,GAAI,CAACvwB,GAAU,OAAOA,GAAW,SAC/B,OAAAswB,EAAO,KAAK,SAAS,EACd,CAAE,QAAS,GAAO,OAAAA,EAAQ,SAAAC,CAAA,EASnC,OALKvwB,EAAO,SACVswB,EAAO,KAAK,aAAa,EAInBtwB,EAAO,SAAA,CACb,IAAK,QACL,IAAK,WACC,OAAOA,EAAO,SAAY,UAC5BswB,EAAO,KAAK,GAAGtwB,EAAO,QAAQ,kBAAkB,EAElD,MAEF,IAAK,QACC,EAAEA,EAAO,mBAAmB,SAAW,OAAOA,EAAO,SAAY,UACnEswB,EAAO,KAAK,gCAAgC,EAE9C,MAEF,IAAK,WACC,CAAC,MAAM,QAAQtwB,EAAO,OAAO,GAAK,OAAOA,EAAO,SAAY,UAC9DswB,EAAO,KAAK,kCAAkC,EAEhD,MAEF,IAAK,MAEH,MAEF,QACEA,EAAO,KAAK,YAAYtwB,EAAO,QAAQ,EAAE,CAAA,CAI7C,OAAIA,EAAO,gBAAkB,QAAa,OAAOA,EAAO,eAAkB,UACxEswB,EAAO,KAAK,qBAAqB,EAI/BtwB,EAAO,gBAAkB,QAAa,OAAOA,EAAO,eAAkB,WACxEswB,EAAO,KAAK,qBAAqB,EAI/BtwB,EAAO,WAAa,SACtBuwB,EAAS,KAAK,yBAAyB,EAGlC,CACL,QAASD,EAAO,SAAW,EAC3B,OAAAA,EACA,SAAAC,CAAA,CAEJ,CAKA,OAAO,0BACL8F,EACAC,EAC8B,CAC9B,GAAI,CAACD,EACH,OAIF,MAAMI,EAAiCJ,EAAY,SAAS,GAAG,EAAI,WAAa,QAEhF,MAAO,CACL,QAASA,EACT,SAAAI,EACA,cAAAH,CAAA,CAEJ,CACF,CCxIO,SAASS,GACdlB,EACAQ,EACAJ,EACmB,CACnB,MAAI,CAACI,GAAe,CAACJ,EAEZJ,EAAW,OAAOmB,GAAK,CAACA,EAAE,aAAe,CAACA,EAAE,UAAU,EAGxDnB,EAAW,OAAOhI,GAAa,CAEpC,GAAIA,EAAU,YAAcoI,EAC1B,OAAOD,GAAa,aAAaC,EAAepI,EAAU,UAAU,EAItE,GAAIA,EAAU,YAAa,CACzB,GAAI,CAACwI,EAAa,MAAO,GAGzB,GAAIxI,EAAU,YAAY,SAAS,GAAG,EAAG,CACvC,MAAM2I,EAAU3I,EAAU,YAAY,QAAQ,MAAO,IAAI,EACzD,OAAO,IAAI,OAAO,IAAI2I,CAAO,GAAG,EAAE,KAAKH,CAAW,CACpD,CAEA,OAAOxI,EAAU,cAAgBwI,CACnC,CAIA,MAAO,CAACA,CACV,CAAC,CACH,CChGO,MAAMY,EAAoB,CACvB,SAMR,YAAYC,EAAsC,CAChD,KAAK,SAAWA,GAAY,KAAK,mBAAA,CACnC,CAWA,QACEjJ,EACA7pB,EACApE,EACAq2B,EACAJ,EACU,CAEV,MAAML,EAAmB,KAAK,SAAS51B,CAAM,EAC7C,GAAI,CAAC41B,EAAiB,QACpB,eAAQ,MAAM,cAAeA,EAAiB,MAAM,EAC7C3H,EAIT,MAAMkJ,EAAqB,KAAK,wBAAwBn3B,EAAO,WAAYq2B,EAAaJ,CAAa,EAErG,GAAIkB,EAAmB,SAAW,EAChC,OAAOlJ,EAIT,OAAQjuB,EAAO,cAAA,CACb,IAAK,aACH,OAAO,KAAK,oBAAoBiuB,EAAU7pB,EAAU+yB,CAAkB,EACxE,IAAK,WACH,OAAO,KAAK,kBAAkBlJ,EAAU7pB,EAAU+yB,CAAkB,EACtE,QACE,eAAQ,KAAK,YAAYn3B,EAAO,aAAa,SAAS,EAC/C,KAAK,oBAAoBiuB,EAAU7pB,EAAU+yB,CAAkB,CAAA,CAE5E,CAOA,SAASn3B,EAAoD,CAC3D,MAAMswB,EAAmB,CAAA,EACnBC,EAAqB,CAAA,EAG3B,GAAI,CAACvwB,GAAUA,EAAO,OAAS,YAC7B,OAAAswB,EAAO,KAAK,aAAa,EAClB,KAAK,uBAAuB,GAAOA,EAAQC,CAAQ,EAG5D,GAAI,CAAC,MAAM,QAAQvwB,EAAO,UAAU,EAClC,OAAAswB,EAAO,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,GAAOA,EAAQC,CAAQ,EAGxDvwB,EAAO,WAAW,SAAW,GAC/BuwB,EAAS,KAAK,qBAAqB,EAGjCvwB,EAAO,gBAAkB,cAAgBA,EAAO,gBAAkB,YACpEswB,EAAO,KAAK,yCAAyC,EAIvD,QAAS,EAAI,EAAG,EAAItwB,EAAO,WAAW,OAAQ,IAAK,CACjD,MAAM6tB,EAAY7tB,EAAO,WAAW,CAAC,EAC/Bo3B,EAAiB,KAAK,wBAAwBvJ,EAAW,CAAC,EAC5DuJ,GACF9G,EAAO,KAAK8G,CAAc,CAE9B,CAGA,MAAMC,EAAMr3B,EAAO,WAAW,OAASg3B,EAAE,EAAE,EAAE,OAAO,OAAO,EACrDM,EAAY,IAAI,IAAID,CAAG,EAC7B,OAAIA,EAAI,SAAWC,EAAU,MAC3B/G,EAAS,KAAK,uBAAuB,EAGhC,KAAK,uBAAuBD,EAAO,SAAW,EAAGA,EAAQC,CAAQ,CAC1E,CAOA,iBAAiBvwB,EAAiD,CAChE,MAAMu3B,EAAQv3B,EAAO,WAAW,IAAIg3B,GAAKA,EAAE,IAAI,EACzCQ,EAAS,MAAM,KACnB,IAAI,IACFx3B,EAAO,WACJ,IAAIg3B,GAAKA,EAAE,WAAW,EACtB,OAAQS,GAA2BA,IAAU,MAAS,CAAA,CAC3D,EAGF,MAAO,CACL,MAAOz3B,EAAO,WAAW,OACzB,MAAAu3B,EACA,OAAAC,EACA,cAAex3B,EAAO,aAAA,CAE1B,CASA,wBACE61B,EACAQ,EACAJ,EACmB,CACnB,OAAOyB,GAA0B7B,EAAYQ,EAAaJ,CAAa,CACzE,CASA,sBACEj2B,EACAq2B,EACAJ,EACmB,CACnB,OAAO,KAAK,wBAAwBj2B,EAAO,WAAYq2B,EAAaJ,CAAa,CACnF,CAOA,QAAQj2B,EAA2C,CACjD,OAAOA,EAAO,WAAW,SAAW,CACtC,CAGQ,oBACNiuB,EACA7pB,EACAyxB,EACU,CACV,IAAInrB,EAASujB,EAEb,UAAWJ,KAAagI,EAAY,CAClC,MAAM7O,EAAW,KAAK,SAAS,IAAI6G,EAAU,IAAI,EACjD,GAAI,CAAC7G,EAAU,CACb,QAAQ,KAAK,eAAe6G,EAAU,IAAI,EAAE,EAC5C,QACF,CAGA,MAAM+H,EAAmB5O,EAAS,SAAS6G,EAAU,MAAM,EAC3D,GAAI,CAAC+H,EAAiB,QAAS,CAC7B,QAAQ,KAAK,cAAc/H,EAAU,IAAI,GAAI+H,EAAiB,MAAM,EACpE,QACF,CAEAlrB,EAASsc,EAAS,QAAQtc,EAAQtG,EAAUypB,EAAU,MAAM,CAC9D,CAEA,OAAOnjB,CACT,CAGQ,kBACNujB,EACA7pB,EACAyxB,EACU,CACV,GAAIA,EAAW,SAAW,EACxB,OAAO5H,EAGT,GAAI4H,EAAW,SAAW,EAExB,OAAO,KAAK,oBAAoB5H,EAAU7pB,EAAUyxB,CAAU,EAKhE,MAAM8B,EAAiC,CAAA,EAEvC,UAAW9J,KAAagI,EAAY,CAClC,MAAM7O,EAAW,KAAK,SAAS,IAAI6G,EAAU,IAAI,EACjD,GAAI,CAAC7G,EAAU,CACb,QAAQ,KAAK,eAAe6G,EAAU,IAAI,EAAE,EAC5C,QACF,CAGA,MAAM+H,EAAmB5O,EAAS,SAAS6G,EAAU,MAAM,EAC3D,GAAI,CAAC+H,EAAiB,QAAS,CAC7B,QAAQ,KAAK,cAAc/H,EAAU,IAAI,GAAI+H,EAAiB,MAAM,EACpE,QACF,CAEA,MAAMgC,EAAc5Q,EAAS,QAAQiH,EAAU7pB,EAAUypB,EAAU,MAAM,EACzE8J,EAAmB,KAAKC,CAAW,CACrC,CAEA,OAAID,EAAmB,SAAW,EACzB1J,EAIF,KAAK,yBAAyB0J,CAAkB,CACzD,CAGQ,yBAAyBE,EAAoC,CACnE,GAAIA,EAAa,SAAW,EAC1B,MAAO,CAAA,EAIT,MAAM9X,EAAS8X,EAAa,CAAC,EAAE,OAC/B,UAAWC,KAASD,EAClB,GAAIC,EAAM,SAAW/X,EACnB,eAAQ,MAAM,mBAAmB,EAC1B8X,EAAa,CAAC,EAKzB,MAAMntB,EAAmB,CAAA,EAEzB,QAASwB,EAAI,EAAGA,EAAI6T,EAAQ7T,IAAK,CAC/B,IAAIgiB,EAAO,EACPC,EAAO,EAEX,UAAW2J,KAASD,EAClB3J,GAAQ4J,EAAM5rB,CAAC,EAAE,CAAC,EAClBiiB,GAAQ2J,EAAM5rB,CAAC,EAAE,CAAC,EAGpBxB,EAAO,KAAK,CAACwjB,EAAO2J,EAAa,OAAQ1J,EAAO0J,EAAa,MAAM,CAAC,CACtE,CAEA,OAAOntB,CACT,CAGQ,wBAAwBmjB,EAA4Bjb,EAAmC,CAC7F,GAAI,CAACib,GAAa,OAAOA,GAAc,SACrC,MAAO,MAAMjb,CAAK,SAGpB,GAAI,CAACib,EAAU,KACb,MAAO,MAAMjb,CAAK,YAGpB,GAAI,CAACib,EAAU,OACb,MAAO,MAAMjb,CAAK,cAIpB,MAAMoU,EAAW,KAAK,SAAS,IAAI6G,EAAU,IAAI,EACjD,GAAI,CAAC7G,EACH,MAAO,MAAMpU,CAAK,cAAcib,EAAU,IAAI,GAIhD,MAAM+H,EAAmB5O,EAAS,SAAS6G,EAAU,MAAM,EAC3D,GAAI,CAAC+H,EAAiB,QACpB,MAAO,MAAMhjB,CAAK,YAAYgjB,EAAiB,QAAQ,KAAK,IAAI,CAAC,EAIrE,CAGQ,uBACNvF,EACAC,EACAC,EACkB,CAClB,MAAO,CACL,QAAAF,EACA,OAAQC,GAAQ,OAAO,OAAO,EAC9B,SAAUC,GAAU,OAAO,OAAO,CAAA,CAEtC,CAGQ,oBAAgD,CACtD,OAAOwF,GAAA,CACT,CACF,CC5TO,MAAMgC,EAAkB,CACrB,SACA,WAMR,YAAYb,EAAsC,CAChD,KAAK,SAAWA,GAAY,KAAK,mBAAA,EACjC,KAAK,WAAa,IAAID,GAAoB,KAAK,QAAQ,CACzD,CASA,sBACEnI,EACA1qB,EACA4zB,EACU,CAEV,MAAMC,EAAqB,KAAK,sBAAsBnJ,EAAOkJ,CAAe,EAG5E,OAAKC,EAKE,KAAK,iBAAiBnJ,EAAM,SAAU1qB,EAAU6zB,EAAoBnJ,EAAM,QAAQ,EAJhFA,EAAM,QAKjB,CAUA,iBACEb,EACA7pB,EACAypB,EACAuI,EACU,CACV,GAAI,CAACvI,EACH,OAAOI,EAIT,MAAMiK,EAAalC,GAAa,eAAeI,EAAU,eAAe,EAExE,OAAI5I,GAAkBK,CAAS,EAEtB,KAAK,uBAAuBI,EAAU7pB,EAAUypB,EAAWuI,EAAU8B,CAAU,EAC7EzK,GAAqBI,CAAS,EAEhC,KAAK,WAAW,QAAQI,EAAU7pB,EAAUypB,EAAWqK,EAAY9B,CAAQ,GAIpF,QAAQ,MAAM,WAAYvI,CAAS,EAC5BI,EACT,CAQA,sBACEa,EACAkJ,EAC6B,CAE7B,OAAIlJ,EAAM,UACDA,EAAM,UAIRkJ,CACT,CAOA,iBAAiBnK,EAA6B,CAC5C,OAAKA,EASDL,GAAkBK,CAAS,EACtB,CACL,MAAO,EACP,MAAO,CAACA,EAAU,IAAI,EACtB,OAAQA,EAAU,YAAc,CAACA,EAAU,WAAW,EAAI,CAAA,EAC1D,aAAc,EAAA,EAEPJ,GAAqBI,CAAS,EAEhC,CACL,GAFW,KAAK,WAAW,iBAAiBA,CAAS,EAGrD,aAAc,EAAA,EAIX,CACL,MAAO,EACP,MAAO,CAAA,EACP,OAAQ,CAAA,EACR,aAAc,EAAA,EA3BP,CACL,MAAO,EACP,MAAO,CAAA,EACP,OAAQ,CAAA,EACR,aAAc,EAAA,CAyBpB,CAOA,kBAAkBA,EAA4B,CAC5C,OAAKA,EAQDL,GAAkBK,CAAS,EACtB,KAAK,wBAAwBA,CAAS,EACpCJ,GAAqBI,CAAS,EAChC,KAAK,WAAW,SAASA,CAAS,EAGpC,CACL,QAAS,GACT,OAAQ,CAAC,SAAS,EAClB,SAAU,CAAA,CAAC,EAhBJ,CACL,QAAS,GACT,OAAQ,CAAA,EACR,SAAU,CAAC,QAAQ,CAAA,CAezB,CAOA,iBAAiBA,EAAsC,CACrD,OAAKA,EAIDL,GAAkBK,CAAS,EACtB,GACEJ,GAAqBI,CAAS,EAChC,KAAK,WAAW,QAAQA,CAAS,EAGnC,GATE,EAUX,CASA,sBACEe,EACAxqB,EACA4zB,EACiB,CACjB,OAAOpJ,EAAO,IAAIE,IAAU,CAC1B,GAAGA,EACH,SAAU,KAAK,sBAAsBA,EAAO1qB,EAAU4zB,CAAe,CAAA,EACrE,CACJ,CAGQ,uBACN/J,EACA7pB,EACAypB,EACAuI,EACA8B,EACU,CAQV,GAAI,CANYlC,GAAa,aAC3BI,EACAvI,EAAU,aAAeA,EAAU,YAAc,CAAE,YAAaA,EAAU,aAAgB,QAC1FqK,CAAA,EAIA,OAAOjK,EAIT,MAAMjH,EAAW,KAAK,SAAS,IAAI6G,EAAU,IAAI,EACjD,GAAI,CAAC7G,EACH,eAAQ,MAAM,YAAY6G,EAAU,IAAI,EAAE,EACnCI,EAIT,MAAM2H,EAAmB5O,EAAS,SAAS6G,EAAU,MAAM,EAC3D,OAAK+H,EAAiB,QAMf5O,EAAS,QAAQiH,EAAU7pB,EAAUypB,EAAU,MAAM,GAL1D,QAAQ,MAAM,YAAa+H,EAAiB,MAAM,EAC3C3H,EAKX,CAGQ,wBAAwBJ,EAA4B,CAC1D,MAAM7G,EAAW,KAAK,SAAS,IAAI6G,EAAU,IAAI,EACjD,OAAK7G,EAQEA,EAAS,SAAS6G,EAAU,MAAM,EAPhC,CACL,QAAS,GACT,OAAQ,CAAC,YAAYA,EAAU,IAAI,EAAE,EACrC,SAAU,CAAA,CAAC,CAKjB,CAGQ,oBAAgD,CACtD,OAAOkI,GAAA,CACT,CACF,CC/PO,MAAMoC,GAAuB,IAAM,CACxC,MAAMC,EAAmBC,EAAAA,OAA8B,IAAI,EAKrDC,EAAuBC,EAAAA,YAAY,CACvCC,EACAjR,EACAkR,EAAqB,KAClB,CAECL,EAAiB,SACnB,aAAaA,EAAiB,OAAO,EAIvCA,EAAiB,QAAU,WAAW,IAAM,CACtC7Q,GACFA,EAASiR,CAAW,CAExB,EAAGC,CAAU,CACf,EAAG,CAAA,CAAE,EAKCC,EAAmBH,EAAAA,YAAY,CAACn0B,EAAkBu0B,IAA4B,CAClF,MAAMC,EAAa,KAAK,MAAMx0B,EAAW,GAAG,EAE5C,OAAIu0B,GAAUA,EAAS,EAId,MADOv0B,GAAY,EAAIu0B,EAAS,KAAK,IAAI,KAAK,MAAMv0B,EAAWu0B,CAAM,EAAI,EAAGA,CAAM,CACvE,IAAIA,CAAM,KAAKC,CAAU,KAGtC,GAAGA,CAAU,GACtB,EAAG,CAAA,CAAE,EAKCC,EAAgBN,EAAAA,YAAY,KAC5BH,EAAiB,UACnB,aAAaA,EAAiB,OAAO,EACrCA,EAAiB,QAAU,MAEtB,GACN,CAAA,CAAE,EAEL,MAAO,CACL,qBAAAE,EACA,mBAAA1G,GACA,iBAAA8G,EACA,cAAAG,CAAA,CAEJ,EC1DaC,GAAwB,IAAM,CAIzC,MAAMC,EAAgBR,EAAAA,YAAY,CAChC/wB,EACAqqB,EACAmH,EAAe,MACG,CAClB,IAAIR,EAAc3G,EAElB,OAAQrqB,EAAM,IAAA,CACZ,IAAK,aACL,IAAK,UACHgxB,EAAc,KAAK,IAAI3G,EAAkBmH,EAAM,CAAC,EAChD,MAEF,IAAK,YACL,IAAK,YACHR,EAAc,KAAK,IAAI3G,EAAkBmH,EAAM,CAAC,EAChD,MAEF,IAAK,OACHR,EAAc,EACd,MAEF,IAAK,MACHA,EAAc,EACd,MAEF,IAAK,SACHA,EAAc,KAAK,IAAI3G,EAAkBmH,EAAO,EAAG,CAAC,EACpD,MAEF,IAAK,WACHR,EAAc,KAAK,IAAI3G,EAAkBmH,EAAO,EAAG,CAAC,EACpD,MAEF,IAAK,IACL,IAAK,QAEHR,EAAc3G,GAAmB,IAAO,EAAI,EAC5C,MAEF,IAAK,SACH2G,EAAc,EACd,MAEF,QACE,OAAO,IAAA,CAIX,OAAAhxB,EAAM,eAAA,EAECgxB,CACT,EAAG,CAAA,CAAE,EAKCS,EAA4BV,EAAAA,YAAY,IACrC,CACL,UACA,wBACA,qBACA,4BACA,gBACA,WAAA,EACA,KAAK;AAAA,CAAI,EACV,CAAA,CAAE,EAEL,MAAO,CACL,cAAAQ,EACA,0BAAAE,CAAA,CAEJ,EChEMC,GAAMC,GAAS,SAEfC,GAAuDj3B,GAAU,CACrE,KAAM,CACJ,KAAAwsB,EACA,OAAAlD,EACA,KAAAplB,EACA,cAAAgzB,EAAgB,UAChB,YAAAC,EACA,OAAA1K,EACA,UAAAf,EACA,UAAAyB,EACA,YAAAG,EAAc,CAAA,EACd,MAAA8J,EAAQ,QACR,UAAA/0B,EAAY,GAEZ,2BAAAg1B,EAA6B,GAC7B,yBAAAC,EAA2B,GAC3B,sBAAAC,EAAwB,IACxB,WAAAC,EACA,iBAAAC,EACA,kBAAAC,EACA,oBAAAC,EACA,QAAAC,CAAA,EACE53B,EAGE,CAACiC,EAAU41B,CAAW,EAAIC,EAAAA,SAAS,CAAC,EACpC,CAACpzB,EAAOqzB,CAAQ,EAAID,EAAAA,SAAwC,IAAI,EAEhE,CAACE,EAAeC,CAAe,EAAIH,EAAAA,SAAS,CAAC,EAC7C,CAACI,EAAOC,CAAQ,EAAIL,EAAAA,SAAc,IAAI,EAGtC,CAACM,EAAeC,CAAgB,EAAIP,WAAS,CACjD,MAAO,IACP,OAAQ,GAAA,CACT,EAEKQ,EAAoBvN,EAAAA,QAAQ,IAAM,IAAI6K,GAAqB,CAAA,CAAE,EAG7D2C,EAAqBxN,EAAAA,QAAQ,IACjCS,GAA6BE,CAAS,EACpC,CAACA,CAAS,CAAA,EAGR8M,EAAoBtC,EAAAA,OAAuB,IAAI,EAC/CuC,GAAmBvC,EAAAA,OAA4B,EAAE,EAEjDwC,GAAoBxC,EAAAA,OAAuB,IAAI,EAC/C,CACJ,qBAAsByC,EACtB,mBAAAlJ,GACA,cAAAiH,CAAA,EACEV,GAAA,EAEE,CACJ,cAAAY,EACA,0BAAAE,CAAA,EACEH,GAAA,EAQJ/L,EAAAA,UAAU,IAAM,CACd,MAAMgO,EAAa,IAAM,CACvB,GAAIF,GAAkB,QAAS,CAC7B,KAAM,CAAE,YAAAG,GAAgBH,GAAkB,QAE1C,GAAIG,EAAc,EAAG,CAEnB,MAAMC,EAAOxL,EAAY,aAAe,CAAC,EAAG,EAAG,GAAI,CAAC,EAC9CyL,GAAYD,EAAK,CAAC,EAAIA,EAAK,CAAC,EAC5BE,EAAaF,EAAK,CAAC,EAAIA,EAAK,CAAC,EAGnC,IAAIG,EAEA9B,EACF8B,EAAmB9B,EAGnB8B,EAAmB,KAAK,MAAMJ,GAAeG,EAAaD,GAAU,EAGtE,QAAQ,IAAI,+BAAgC,CAC1C,YAAaD,EACb,MAAO,GAAGE,CAAU,IAAID,EAAS,GACjC,eAAgBF,EAChB,iBAAAI,EACA,eAAgB,CAAC,CAAC9B,CAAA,CACnB,EAEDkB,EAAiB,CACf,MAAOQ,EACP,OAAQI,CAAA,CACT,CACH,CACF,CACF,EAGAL,EAAA,EAGA,OAAO,iBAAiB,SAAUA,CAAU,EAG5C,MAAMM,EAAiB,IAAI,eAAeN,CAAU,EACpD,OAAIF,GAAkB,SACpBQ,EAAe,QAAQR,GAAkB,OAAO,EAG3C,IAAM,CACX,OAAO,oBAAoB,SAAUE,CAAU,EAC/CM,EAAe,WAAA,CACjB,CACF,EAAG,CAAC5L,EAAY,YAAa6J,CAAW,CAAC,EAGzC,MAAMgC,GAAiB,CACrB,MAAO3B,GAAc,GAAGY,EAAc,KAAK,KAC3C,OAAQ,GAAGA,EAAc,MAAM,IAAA,EAK3BgB,GAA2BhD,EAAAA,YAAY,CAC3CzJ,EACA1qB,IACG,CACH,QAAQ,IAAI,sCAAuC,CACjD,QAAS0qB,EAAM,UAAU,GACzB,UAAWA,EAAM,KACjB,SAAA1qB,EACA,YAAa,CAAC,CAAC0qB,EAAM,SACrB,qBAAsB,CAAC,CAACA,EAAM,UAAU,kBACxC,kBAAmBA,EAAM,UAAU,iBAAA,CACpC,EAED,MAAM0M,EAAoB1M,EAAM,UAAU,kBACpC2M,EAAY3M,EAAM,OAAS,CAAA,EAGjC,IAAI4M,GACJ,GAAI5M,EAAM,WAAW,OAAS,iBAAmBA,EAAM,UAAU,aAAc,CAC7E,MAAM6M,GAAc7M,EAAM,UAAU,aAC9B,CAAE,YAAA0G,GAAa,QAAAC,GAAU,EAAG,MAAAC,GAAQ,EAAG,OAAAX,GAAS,SAAU,UAAAQ,EAAA,EAAcoG,GAG9E,GAAInH,GAAagB,EAAW,IAAM,CAACD,IAAaf,GAAae,EAAS,GAAI,CAExE,IAAIpD,GAAoB/tB,EACpBA,EAAWqxB,GACbtD,GAAoB,EACX/tB,EAAWsxB,GACpBvD,GAAoB,EAEpBA,IAAqB/tB,EAAWqxB,KAAYC,GAAQD,IAItD,MAAMmG,GAAarG,IAAakG,EAAU,WAAa,UACvDC,GAAiB5G,GAA2B8G,GAAYpG,GAAarD,GAAmB4C,EAAM,EAE9F,QAAQ,IAAI,4BAA6B,CACvC,QAASjG,EAAM,UAAU,GACzB,SAAA1qB,EACA,kBAAA+tB,GACA,WAAAyJ,GACA,YAAApG,GACA,YAAakG,EAAA,CACd,CACH,MACE,QAAQ,KAAK,2BAA4B,CAAE,YAAAlG,GAAa,UAAAD,GAAW,CAEvE,CAGA,GAAI,CAACiG,EAEH,OADA,QAAQ,IAAI,+CAA+C,EACvDE,GACK,CAAE,GAAGD,EAAW,UAAWC,EAAA,EAE7BD,EAIT,MAAMI,EAA0B77B,IAAwB,CACtD,GAAI,CAACA,GAAQ,MAAO,GAEpB,MAAM+a,GAAY/a,GAAO,WAAa,GAChC87B,GAAa97B,GAAO,YAAc,EAClC+7B,GAAW/7B,GAAO,UAAY,EAC9BD,GAAOC,GAAO,MAAQ,OAE5B,GAAID,KAAS,OAEX,OAAOqE,GAAY2W,GAAYghB,GAAWD,GAC5C,GAAW/7B,KAAS,OAAQ,CAE1B,GAAIqE,EAAW2W,GACb,OAAO+gB,GACF,CAEL,MAAME,GAAe,KAAK,KAAK53B,EAAW2W,KAAc,EAAIA,IAAY,CAAC,EACzE,OAAO+gB,IAAcC,GAAWD,IAAcE,EAChD,CACF,CAEA,MAAO,EACT,EAEMC,EAAc,CAAE,GAAGR,CAAA,EACzB,IAAIS,GAAU,GAGd,MAAMC,GAAkBN,EAAuBL,EAAkB,UAAU,EACrEY,GAAuBP,EAAuBL,EAAkB,eAAe,EAoCrF,GAlCA,QAAQ,IAAI,wBAAyB,CACnC,QAAS1M,EAAM,UAAU,GACzB,SAAA1qB,EACA,gBAAA+3B,GACA,qBAAAC,GACA,cAAe,CAAC,CAACZ,EAAkB,WACnC,mBAAoB,CAAC,CAACA,EAAkB,eAAA,CACzC,EAGGA,EAAkB,aAEhBS,EAAY,cAAgB,SAC9BA,EAAY,YAAc,GAE5BA,EAAY,aAAeE,GAGvBA,KAAoB,IACtBF,EAAY,YAAc,EAC1B,QAAQ,IAAI,wCAAwC,GAGlDA,EAAY,YAMhBC,GAAUC,GAAkB,EAC5B,QAAQ,IAAI,wBAAyB,CAAE,QAASrN,EAAM,UAAU,GAAI,QAAAoN,GAAS,gBAAAC,GAAiB,GAI5FX,EAAkB,gBAAiB,CACrC,MAAMa,GAAeD,GAAuB,EAC5CH,EAAY,aAAeI,GAC3B,QAAQ,IAAI,wBAAyB,CACnC,QAASvN,EAAM,UAAU,GACzB,aAAAuN,GACA,qBAAAD,GACA,SAAU,CAAC,CAACtN,EAAM,UAAU,KAAA,CAC7B,CACH,CAGA,GAAI0M,EAAkB,QAAS,CAC7B,MAAMc,GAAUd,EAAkB,QAC5B/F,GAAU6G,GAAQ,SAAW,EAC7B5G,GAAQ4G,GAAQ,OAAS,EACzB5H,GAAO4H,GAAQ,MAAQ,EACvB3H,GAAK2H,GAAQ,IAAM,EACnBv8B,GAAOu8B,GAAQ,MAAQ,SAE7B,IAAIC,GAAe7H,GAEnB,GAAItwB,EAAWqxB,GACb8G,GAAe7H,WACNtwB,EAAWsxB,GACpB6G,GAAe5H,OACV,CAEL,MAAM6H,IAAiBp4B,EAAWqxB,KAAYC,GAAQD,IAGpD8G,GAAe7H,IAAQC,GAAKD,IAAQ8H,EAKxC,CAEAP,EAAY,YAAcM,EAC5B,CAGA,GAAIb,GACFO,EAAY,UAAYP,GACxB,QAAQ,IAAI,+DAAgE,CAC1E,QAAS5M,EAAM,UAAU,GACzB,eAAA4M,EAAA,CACD,UACQF,EAAkB,MAAO,CAClC,MAAMjQ,GAAQiQ,EAAkB,MAC1B/F,GAAUlK,GAAM,SAAW,EAC3BmK,GAAQnK,GAAM,OAAS,EACvBmJ,GAAOnJ,GAAM,MAAQ0Q,EAAY,UACjCtH,GAAKpJ,GAAM,IAAM0Q,EAAY,UAC7Bl8B,GAAOwrB,GAAM,MAAQ,WAE3B,GAAImJ,IAAQC,GACV,GAAIvwB,EAAWqxB,GACbwG,EAAY,UAAYvH,WACftwB,EAAWsxB,GACpBuG,EAAY,UAAYtH,OACnB,CAEL,MAAM6H,IAAiBp4B,EAAWqxB,KAAYC,GAAQD,IAElD11B,KAAS,WAEXk8B,EAAY,UAAYtH,GAExBsH,EAAY,UAAYO,IAAiB,GAAM7H,GAAKD,EAExD,CAEJ,CAGA,OAAAuH,EAAY,QAAUC,GAGlBD,EAAY,eAAiB,SAC/BA,EAAY,aAAe,IAG7B,QAAQ,IAAI,2BAA4B,CACtC,QAASnN,EAAM,UAAU,GACzB,QAASmN,EAAY,QACrB,aAAcA,EAAY,aAC1B,YAAaA,EAAY,YACzB,YAAaA,EAAY,WAAA,CAC1B,EAEMA,CACT,EAAG,CAAA,CAAE,EAGCQ,GAAclE,EAAAA,YAAY,CAC9B8B,EACAvL,EACA4N,EAAoB,GACpBt4B,EAAmB,IAChB,CACH,QAAQ,IAAI,yBAA0B,CACpC,QAAS0qB,EAAM,UAAU,GACzB,UAAWA,EAAM,KACjB,SAAA4N,EACA,SAAAt4B,EACA,eAAgB0qB,EAAM,UAAU,OAChC,YAAa,CAAC,CAACA,EAAM,SACrB,qBAAsB,CAAC,CAACA,EAAM,UAAU,iBAAA,CACzC,EAGD,MAAM6N,GAAc7N,EAAM,OAAS,QAAU,EAAI,EACjD,GAAI,CAACuL,GAAS,CAACvL,EAAM,UAAYA,EAAM,SAAS,OAAS6N,GACvD,eAAQ,KAAK,iDAAiD7N,EAAM,IAAI,GAAI,CAC1E,QAASA,EAAM,UAAU,GACzB,UAAWA,EAAM,KACjB,eAAgBA,EAAM,UAAU,OAChC,YAAA6N,EAAA,CACD,EACM,KAIT,MAAMC,EAAgBrB,GAAyBzM,EAAO1qB,CAAQ,EAC9D,IAAIy4B,EAEJ,OAAQ/N,EAAM,KAAA,CACZ,IAAK,WACL,IAAK,YACL,IAAK,gBACL,IAAK,YACL,IAAK,UAEH,MAAMgO,GAAkBF,EAAc,eAAiB,OACnDA,EAAc,aACb9N,EAAM,OAAO,eAAiB,OAAYA,EAAM,MAAM,aAAe,GAGpEiO,GAAYjO,EAAM,UAAU,OAASA,EAAM,UAAU,IAAM,GAEjE+N,EAAUxC,EAAM,OAAO,UAAWvL,EAAM,SAAU,CAChD,KAAMiO,GACN,UAAWH,EAAc,YAAc,OAAYA,EAAc,UAAaF,EAAW,UAAY,UACrG,YAAaE,EAAc,cAAgB,OAAYA,EAAc,YAAeF,EAAW,GAAM,GACrG,YAAaE,EAAc,cAAgB,OAAYA,EAAc,YAAeF,EAAW,UAAY,UAC3G,YAAaE,EAAc,cAAgB,OAAYA,EAAc,YAAeF,EAAW,EAAI,EACnG,KAAME,EAAc,YAAc,OAAYA,EAAc,UAAY,EACxE,MAAOF,EACP,UAAW,CAACA,EACZ,UAAWI,GACX,QAASF,EAAc,UAAY,OAAYA,EAAc,QAAU,EAAA,CACxE,EACD,MAEF,IAAK,SACH,GAAI9N,EAAM,SAAS,QAAU,EAAG,CAC9B,KAAM,CAACiC,GAAQiM,EAAW,EAAIlO,EAAM,SAE9BgO,GAAkBF,EAAc,eAAiB,OACnDA,EAAc,aACb9N,EAAM,OAAO,eAAiB,OAAYA,EAAM,MAAM,aAAe,GAGpEiO,GAAYjO,EAAM,UAAU,OAASA,EAAM,UAAU,IAAM,GAEjE+N,EAAUxC,EAAM,OAAO,SAAU,CAACtJ,GAAQiM,EAAW,EAAG,CACtD,KAAMD,GACN,UAAWH,EAAc,YAAc,OAAYA,EAAc,UAAaF,EAAW,UAAY,UACrG,YAAaE,EAAc,cAAgB,OAAYA,EAAc,YAAeF,EAAW,GAAM,GACrG,YAAaE,EAAc,cAAgB,OAAYA,EAAc,YAAeF,EAAW,UAAY,UAC3G,YAAaE,EAAc,cAAgB,OAAYA,EAAc,YAAeF,EAAW,EAAI,EACnG,KAAME,EAAc,YAAc,OAAYA,EAAc,UAAY,EACxE,MAAOF,EACP,UAAW,CAACA,EACZ,UAAWI,EAAA,CACZ,CACH,CACA,MAEF,IAAK,QACH,GAAIhO,EAAM,SAAS,QAAU,EAAG,CAC9B,KAAM,CAACV,GAAGC,EAAC,EAAIS,EAAM,SAAS,CAAC,EAEzBgO,GAAkBF,EAAc,eAAiB,OACnDA,EAAc,aACb9N,EAAM,OAAO,eAAiB,OAAYA,EAAM,MAAM,aAAe,GAGpEiO,GAAYjO,EAAM,UAAU,OAASA,EAAM,UAAU,IAAM,GAGjE+N,EAAUxC,EAAM,OAAO,QAAS,CAACjM,GAAGC,EAAC,EAAG,CACtC,KAAM0O,GACN,UAAWD,GACX,MAAOJ,EACP,KAAM,EACN,YAAaE,EAAc,cAAgB,OAAYA,EAAc,YAAeF,EAAW,UAAY,UAC3G,UAAWE,EAAc,YAAc,OAAYA,EAAc,UAAaF,EAAW,UAAY,UACrG,QAASE,EAAc,UAAY,OAAYA,EAAc,QAAU,GACvE,UAAW,CAACF,CAAA,CACb,CACH,CACA,MAEF,QACE,eAAQ,KAAK,2BAA2B5N,EAAM,IAAI,EAAE,EAC7C,IAAA,CAGX,eAAQ,IAAI,0BAA2B,CACrC,QAASA,EAAM,UAAU,GACzB,YAAa+N,GAAS,KACtB,YAAaA,GAAS,KACtB,YAAaA,GAAS,eAAe,aAAa,EAClD,YAAaA,GAAS,eAAe,aAAa,EAClD,aAAcD,EAAc,aAC5B,SAAU,CAAC,CAAC9N,EAAM,UAAU,MAC5B,UAAW,CAAC,CAACA,EAAM,UAAU,OAAS8N,EAAc,YAAA,CACrD,EAEMC,CACT,EAAG,CAACtB,EAAwB,CAAC,EAG7BxO,EAAAA,UAAU,IAAM,CAGd,GAAI,EADgB4B,EAAO,GAAKlD,EAAS,GAAKmD,GAAQ,UAAU,OAAS,GACvD,CAChB,QAAQ,IAAI,mCAAoC,CAC9C,KAAAD,EACA,OAAAlD,EACA,qBAAsBmD,GAAQ,UAAU,OACxC,YAAaD,EAAO,EACpB,cAAelD,EAAS,EACxB,kBAAmBmD,GAAQ,UAAU,OAAS,CAAA,CAC/C,EACD,MACF,CAEA,QAAQ,IAAI,qCAAsC,CAChD,KAAMzsB,EAAM,KACZ,OAAQA,EAAM,OACd,KAAMA,EAAM,KACZ,OAAQA,EAAM,OACd,qBAAsBA,EAAM,QAAQ,UAAU,OAC9C,mBAAoBA,EAAM,QAAQ,QAAQ,OAC1C,UAAWA,EAAM,UACjB,UAAWA,EAAM,UACjB,YAAaA,EAAM,WAAA,CACpB,EACD,MAAM86B,EAAkBnN,GAAmB3tB,CAAK,EAChD,QAAQ,IAAI,+BAAgC86B,CAAe,EAC3D/C,EAAS+C,CAAe,EAEpBA,GAAmBlD,GACrBA,EAAQkD,CAAe,CAE3B,EAAG,CAACtO,EAAMlD,EAAQmD,EAAQf,EAAWyB,EAAWG,EAAasK,EAAS53B,CAAK,CAAC,EAG5E4qB,EAAAA,UAAU,IAAM,CACd,GAAK4N,EAAkB,QAEvB,IAAI,CACF,MAAMuC,EAAqBzN,EAAY,aAAe,CAAC,EAAG,EAAG,GAAI,CAAC,EAC5D0N,EAAS5D,IAAU,OACzB,QAAQ,KAAK,mCAAmC,EAChD,QAAQ,KAAK,4BAA6B9J,EAAY,WAAW,EACjE,QAAQ,KAAK,4BAA6B8K,EAAc,MAAO,IAAKA,EAAc,MAAM,EACxF,QAAQ,KAAK,mCAAoCI,EAAkB,QAAQ,YAAa,IAAKA,EAAkB,QAAQ,YAAY,EACnI,MAAMyC,EAAWlE,GAAI,UAAUyB,EAAkB,QAAS,CACxD,YAAauC,EACb,gBAAiBzN,EAAY,iBAAmB,GAChD,cAAe,GACf,eAAgB,GAChB,KAAMA,EAAY,UAAY,GAC9B,KAAMA,EAAY,UAAY,GAC9B,IAAK,CAAE,QAAS,EAAA,EAChB,KAAM,CAAE,QAAS,EAAA,CAAM,CACjB,EAGF4N,EAAY5N,EAAY,YAAc0N,EAAS,UAAY,WAC3DG,GAAY7N,EAAY,YAAc0N,EAAS,UAAY,WAE5DC,EAAiB,aAAa,GAChCA,EAAiB,YAAY,EAAE,aAAa,CAAE,YAAaC,EAAW,EAEpED,EAAiB,aAAa,GAChCA,EAAiB,YAAY,EAAE,aAAa,CAAE,YAAaC,EAAW,EAEpED,EAAiB,aACnBA,EAAiB,YAAY,aAAa,CAAE,YAAaE,GAAW,EAGvEhD,EAAS8C,CAAQ,CACnB,OAASv2B,EAAO,CACd,MAAM02B,EAAwC,CAC5C,KAAM,iBACN,QAAS,mBACT,QAAS12B,EACT,UAAW,IAAI,KAAA,EAAO,YAAA,CAAY,EAEpCqzB,EAASqD,CAAa,EACtBxD,IAAUwD,CAAa,CACzB,CAEA,MAAO,IAAM,CACX,GAAIlD,EACF,GAAI,CACFnB,GAAI,UAAUmB,CAAK,CACrB,OAAS1yB,EAAG,CAENA,aAAa,OAASA,EAAE,OAAS,cACnC,QAAQ,KAAK,yBAA0BA,CAAC,CAE5C,CAEJ,EACF,EAAG,CAAC4yB,CAAa,CAAC,EAGlBxN,EAAAA,UAAU,IAAM,CACd,GAAKsN,EAEL,GAAI,CACFA,EAAM,cAAA,EAGN,OAAO,OAAOO,GAAiB,OAAO,EAAE,QAASiC,GAAiB,CAChE,GAAIA,GAAWxC,EAAM,aACnB,GAAI,CACFA,EAAM,aAAawC,CAAO,CAC5B,MAAY,CAEZ,CAEJ,CAAC,EACDjC,GAAiB,QAAU,CAAA,EAG3BhM,EAAO,OAAO,QAAQ,CAACE,EAAOlc,IAAU,CACtC,MAAMmB,EAAK+a,EAAM,UAAU,IAAM,UAAUlc,CAAK,GAC1CiqB,EAAUJ,GAAYpC,EAAOvL,EAAO,GAAM,CAAC,EAC7C+N,IACFjC,GAAiB,QAAQ7mB,CAAE,EAAI8oB,EAEnC,CAAC,EAGDjO,EAAO,SAAS,QAAQ,CAACE,EAAOlc,IAAU,CACxC,MAAMmB,EAAK+a,EAAM,UAAU,IAAM,YAAYlc,CAAK,GAC5CiqB,EAAUJ,GAAYpC,EAAOvL,EAAO,GAAO,CAAC,EAC9C+N,IACFjC,GAAiB,QAAQ7mB,CAAE,EAAI8oB,EAEnC,CAAC,EAEDxC,EAAM,gBAAA,EAGFT,GACFA,EAAA,CAEJ,OAAS/yB,EAAO,CACd,MAAM22B,EAAsC,CAC1C,KAAM,eACN,QAAS,SACT,QAAS32B,EACT,UAAW,IAAI,KAAA,EAAO,YAAA,CAAY,EAEpCqzB,EAASsD,CAAW,EACpBzD,IAAUyD,CAAW,CACvB,CACF,EAAG,CAACnD,EAAOzL,EAAQD,EAAMlD,CAAM,CAAC,EAGhCsB,EAAAA,UAAU,IAAM,CACd,GAAKsN,EAEL,CAAAA,EAAM,cAAA,EAEN,GAAI,CAEFzL,EAAO,SAAS,QAAQ,CAACE,EAAOlc,IAAU,CACxC,MAAMmB,GAAK+a,EAAM,UAAU,IAAM,YAAYlc,CAAK,GAC5CiqB,EAAUjC,GAAiB,QAAQ7mB,EAAE,EAC3C,GAAI8oB,EAAS,CACX,GAAI,CACFxC,EAAM,aAAawC,CAAO,CAC5B,MAAY,CAEZ,CACA,OAAOjC,GAAiB,QAAQ7mB,EAAE,CACpC,CACF,CAAC,EAGD6a,EAAO,SAAS,QAAQ,CAACE,EAAOlc,IAAU,CACxC,MAAMmB,GAAK+a,EAAM,UAAU,IAAM,YAAYlc,CAAK,GAG5C6qB,EAAiB3O,EAAM,UAAY,CACvC,GAAGA,EACH,UAAWnB,GAA6BmB,EAAM,SAAS,CAAA,EACrDA,EAGE4O,EAAsBjD,EAAkB,sBAC5CgD,EACAr5B,EACAs2B,CAAA,EAIIiD,GAAmB,CACvB,GAAG7O,EACH,SAAU4O,EACV,SAAU,CACR,GAAG5O,EAAM,SACT,GAAA/a,GACA,gBAAkB+a,EAAM,UAAY,QAAU,QAAA,CAChD,EAII+N,GAAUJ,GAAYpC,EAAOsD,GAAkB,GAAOv5B,CAAQ,EAChEy4B,KACFjC,GAAiB,QAAQ7mB,EAAE,EAAI8oB,GAEnC,CAAC,EAGD,MAAMe,EAAiBtO,EAAU,mBAAmB,QAAU,EACxDuO,EAAW,KAAK,IAAI,KAAK,MAAMz5B,EAAWw5B,CAAc,EAAGA,EAAiB,CAAC,EACnFxD,EAAgByD,CAAQ,CAE1B,OAASh3B,EAAO,CAEd,GAAIA,aAAiB,OAASA,EAAM,OAAS,aAC3C,OAEF,QAAQ,KAAK,2BAA4BA,CAAK,CAChD,QAAA,CACE,GAAI,CACFwzB,EAAM,gBAAA,CACR,MAAY,CAEZ,CACF,EACF,EAAG,CAACA,EAAOj2B,EAAUwqB,EAAQf,EAAWyB,EAAWmN,GAAa/B,EAAoBD,CAAiB,CAAC,EAGtG,MAAMqD,GAAqBvF,cAAan3B,GAA6B,CACnE,MAAM28B,EAAgB,MAAM,QAAQ38B,CAAK,EAAIA,EAAM,CAAC,EAAIA,EACxD44B,EAAY+D,CAAa,EAGzBjD,EAA8BiD,EAAgBC,GAAmB,CAC/DnE,IAAoBmE,CAAc,CACpC,CAAC,EAGGpM,GAAmBmM,EAAerE,CAAqB,IACzDM,EAAY,CAAC,EACbF,IAAA,EAEJ,EAAG,CAACD,EAAmBC,EAAqBJ,EAAuBoB,EAA+BlJ,EAAkB,CAAC,EAGrH7E,EAAAA,UAAU,IAAM,CACd,GAAI,CAAC0M,EAA0B,OAE/B,MAAMwE,EAAuBt2B,GAAqB,CAChD,MAAM6wB,EAAcO,EAAcpxB,EAAGvD,CAAQ,EACzCo0B,IAAgB,MAAQA,IAAgBp0B,GAC1C05B,GAAmBtF,CAAW,CAElC,EAEA,cAAO,iBAAiB,UAAWyF,CAAmB,EAC/C,IAAM,CACX,OAAO,oBAAoB,UAAWA,CAAmB,CAC3D,CACF,EAAG,CAACxE,EAA0Br1B,EAAU05B,GAAoB/E,CAAa,CAAC,EAI7CR,EAAAA,YAAY,IAAM,CAC7CyB,EAAY,CAAC,EACbI,EAAgB,CAAC,EACjBvB,EAAA,CACF,EAAG,CAACA,CAAa,CAAC,EAGlB,MAAMqF,GAAc3F,EAAAA,YAAY,IAAM,CACpC2B,EAAS,IAAI,EACbF,EAAY,CAAC,EACbI,EAAgB,CAAC,EACjBvB,EAAA,CAEF,EAAG,CAACA,CAAa,CAAC,EAMlB,OAHoBlK,EAAO,GAAKlD,EAAS,GAAKmD,GAAQ,UAAU,OAAS,EAyBrE/nB,EAEAjC,EAAAA,IAACY,GAAAA,KAAA,CACC,cAAY,OACZ,UAAW,gDAAgDhB,CAAS,GAEpE,SAAAI,EAAAA,IAACa,GAAAA,SAAA,CAAS,cAAY,YACpB,SAAAF,EAAAA,KAAC,MAAA,CACC,UAAU,oCACV,KAAK,QACL,YAAU,YACV,cAAY,OAGZ,SAAA,CAAAX,EAAAA,IAAC,OAAI,UAAU,iCAAiC,cAAY,OAC1D,SAAAW,EAAAA,KAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,OAAO,eAAe,YAAY,IAC5F,SAAA,CAAAX,MAAC,UAAO,GAAG,KAAK,GAAG,KAAK,EAAE,KAAK,EAC/BA,EAAAA,IAAC,QAAK,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,IAAA,CAAK,EACrCA,EAAAA,IAAC,QAAK,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,IAAA,CAAK,CAAA,CAAA,CAC3C,CAAA,CACF,EAEAA,EAAAA,IAAC,MAAG,SAAA,YAAA,CAAU,EACdA,EAAAA,IAAC,IAAA,CAAG,SAAAiC,EAAM,OAAA,CAAQ,EAEjBA,EAAM,SACLtB,OAAC,UAAA,CAAQ,UAAU,4CACjB,SAAA,CAAAX,EAAAA,IAAC,WAAQ,SAAA,QAAA,CAAM,EACfA,EAAAA,IAAC,MAAA,CAAI,UAAU,oCACZ,SAAA,KAAK,UAAUiC,EAAM,QAAS,KAAM,CAAC,CAAA,CACxC,CAAA,EACF,EAIFjC,EAAAA,IAAC,MAAA,CAAI,UAAU,oCACb,SAAAA,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,UAAU,mCACV,QAASs5B,GACT,aAAW,aACZ,SAAA,MAAA,CAAA,CAED,CACF,CAAA,CAAA,CAAA,CACF,CACF,CAAA,CAAA,EAMJt5B,EAAAA,IAACY,GAAAA,KAAA,CACC,cAAY,OACZ,UAAW,sBAAsB6zB,IAAkB,UAAY,8BAAgC,EAAE,IAAIE,IAAU,OAAS,2BAA6B,EAAE,IAAI/0B,CAAS,GAEpK,SAAAe,EAAAA,KAACE,GAAAA,SAAA,CAAS,cAAY,YAEpB,SAAA,CAAAF,EAAAA,KAAC,MAAA,CAAI,IAAKs1B,GAAmB,UAAU,sCACrC,SAAA,CAAAj2B,EAAAA,IAAC,MAAA,CACC,IAAK+1B,EACL,GAAG,iBACH,UAAU,4BACV,MAAOW,GACP,cAAY,iBACZ,KAAK,cACL,aAAW,WACX,mBAAiB,4BAAA,CAAA,QAElB,MAAA,CAAI,GAAG,6BAA6B,UAAU,UAAU,SAAA,4CAAA,CAGzD,CAAA,EACF,EAGA/1B,EAAAA,KAAC,MAAA,CAAI,UAAU,+BAEb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,mCACb,SAAAA,EAAAA,IAACu5B,GAAAA,OAAA,CACC,GAAG,mBAEH,cAAY,SACZ,MAAO/5B,EACP,SAAU05B,GACV,SAAU,EACV,SAAU,EACV,KAAM,IACN,KAAK,KACL,MAAM,UACN,UAAU,6BAEV,MAAM,OACN,YAAa,GACb,cAAe,CAAE,MAAO,SAAA,EACxB,aAAW,UAAA,CAAA,EAEf,EAWCrE,GACC70B,EAAAA,IAAC,MAAA,CAAI,UAAU,oCAAoC,KAAK,OAAO,aAAW,SACxE,SAAAW,EAAAA,KAAC,UAAA,CACC,SAAA,CAAAX,EAAAA,IAAC,WAAQ,SAAA,QAAA,CAAM,EACfA,EAAAA,IAAC,MAAA,CAAI,UAAU,4CACZ,YAA0B,CAC7B,CAAA,CAAA,CACF,CAAA,CACF,CAAA,CAAA,CAEJ,CAAA,CAAA,CACF,CAAA,CAAA,GA5IF,QAAQ,IAAI,qCAAsC,CAChD,KAAA+pB,EACA,OAAAlD,EACA,qBAAsBmD,GAAQ,UAAU,OACxC,MAAA/nB,CAAA,CACD,EAECjC,EAAAA,IAACY,GAAAA,KAAA,CACC,cAAY,OACZ,UAAW,kDAAkDhB,CAAS,GAEtE,SAAAI,EAAAA,IAACa,GAAAA,UAAS,cAAY,YACpB,eAAC,MAAA,CAAI,UAAU,sCAAsC,SAAA,eAAA,CAErD,CAAA,CACF,CAAA,CAAA,EAgIR,EAGM24B,GAA4B36B,EAAM,KAAK21B,GAAmB,CAAC3M,EAAWC,IAAc,CAkBxF,GAdED,EAAU,OAASC,EAAU,MAC7BD,EAAU,SAAWC,EAAU,QAC/BD,EAAU,OAASC,EAAU,MAC7BD,EAAU,QAAUC,EAAU,OAC9BD,EAAU,YAAcC,EAAU,WAClCD,EAAU,6BAA+BC,EAAU,4BACnDD,EAAU,2BAA6BC,EAAU,0BACjDD,EAAU,wBAA0BC,EAAU,uBAQ9CD,EAAU,mBAAqBC,EAAU,kBACzCD,EAAU,oBAAsBC,EAAU,mBAC1CD,EAAU,sBAAwBC,EAAU,qBAC5CD,EAAU,UAAYC,EAAU,QAEhC,MAAO,GAKT,MAAM2R,EAAa,KAAK,UAAU,CAChC,OAAQ5R,EAAU,OAClB,UAAWA,EAAU,UACrB,UAAWA,EAAU,UACrB,YAAaA,EAAU,WAAA,CACxB,EAEK6R,EAAa,KAAK,UAAU,CAChC,OAAQ5R,EAAU,OAClB,UAAWA,EAAU,UACrB,UAAWA,EAAU,UACrB,YAAaA,EAAU,WAAA,CACxB,EAED,OAAO2R,IAAeC,CACxB,CAAC,ECt7BYC,GAAuBC,GAAAA,OAA0B,CAACC,EAAKC,KAAS,CAE3E,cAAe,EACf,WAAY,GACZ,UAAW,CACT,WAAY,GACZ,WAAY,GACZ,aAAc,GACd,UAAW,IAAA,EAIb,iBAAmBt9B,GAAkB,CACnCq9B,EAAI,CAAE,cAAe,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGr9B,CAAK,CAAC,CAAA,CAAG,CACxD,EAEA,UAAYu9B,GAAuB,CACjCF,EAAI,CACF,WAAY,GACZ,UAAW,CACT,WAAY,GACZ,WAAAE,EACA,aAAcA,EACd,UAAW,IAAA,CACb,CACD,CACH,EAEA,WAAaC,GAAyB,CACpC,KAAM,CAAE,UAAAC,CAAA,EAAcH,EAAA,EAGtB,IAAIvN,EAAoC,KACxC,GAAI0N,EAAU,aAAe,IAAMD,IAAiB,GAAI,CACtD,MAAME,EAAW,KAAK,MAAMD,EAAU,WAAa,EAAE,EAC/CE,EAAWF,EAAU,WAAa,GAClCG,EAAa,KAAK,MAAMJ,EAAe,EAAE,EACzCK,EAAaL,EAAe,GAE9BI,IAAeF,EACjB3N,EAAY8N,EAAaF,EAAW,MAAQ,MACnCE,IAAeF,IACxB5N,EAAY6N,EAAaF,EAAW,MAAQ,MAEhD,CAEAL,EAAI,CACF,UAAW,CACT,GAAGI,EACH,aAAAD,EACA,UAAAzN,CAAA,CACF,CACD,CACH,EAEA,QAAS,IAAM,CACbsN,EAAI,CACF,WAAY,GACZ,UAAW,CACT,WAAY,GACZ,WAAY,GACZ,aAAc,GACd,UAAW,IAAA,CACb,CACD,CACH,EAEA,UAAW,IAAM,CACfA,EAAI,CACF,WAAY,GACZ,UAAW,CACT,WAAY,GACZ,WAAY,GACZ,aAAc,GACd,UAAW,IAAA,CACb,CACD,CACH,CACF,EAAE,EAKWS,GAAuB,IAClCX,GACEY,GAAAA,WAAYxa,IAAW,CACrB,cAAeA,EAAM,cACrB,iBAAkBA,EAAM,gBAAA,EACxB,CACJ,EAKWya,GAAsB,IACjCb,GACEY,GAAAA,WAAYxa,IAAW,CACrB,WAAYA,EAAM,WAClB,UAAWA,EAAM,UACjB,UAAWA,EAAM,UACjB,WAAYA,EAAM,WAClB,QAASA,EAAM,QACf,UAAWA,EAAM,SAAA,EACjB,CACJ,ECrHW0a,GACXr/B,GACwB,CACxB,KAAM,CAAE,WAAAs/B,EAAY,UAAAC,EAAW,UAAApO,EAAW,KAAAqO,EAAM,KAAAC,GAASz/B,EAGnD0/B,EAAc,KAAK,MAAMJ,EAAaC,CAAS,EAC/CI,EAAwB,CAAA,EAE9B,GAAIxO,IAAc,MAEhB,QAASjlB,EAAI,EAAGA,EAAIwzB,EAAaxzB,IAC/ByzB,EAAY,KAAKzzB,CAAC,MAIpB,SAAS0zB,EAAM,EAAGA,EAAMJ,EAAMI,IAC5B,QAASC,EAAM,EAAGA,EAAMJ,EAAMI,IAAO,CACnC,MAAMjtB,EAAQgtB,EAAMH,EAAOI,EACvBF,EAAY,OAASD,GACvBC,EAAY,KAAK/sB,CAAK,CAE1B,CAIJ,MAAO,CACL,YAAA+sB,EACA,YAAAD,EACA,YAAaA,EAAcJ,CAAA,CAE/B,EAUaQ,GAAmB,CAC9BN,EACAC,EACAM,EACAJ,IACe,CACf,MAAMK,EAAoB,CAAA,EAE1B,QAASJ,EAAM,EAAGA,EAAMJ,EAAMI,IAC5B,QAASC,EAAM,EAAGA,EAAMJ,EAAMI,IAAO,CACnC,MAAMjtB,EAAQgtB,EAAMH,EAAOI,EAC3BG,EAAM,KAAK,CACT,MAAAptB,EACA,IAAAgtB,EACA,IAAAC,EACA,OAAQF,EAAY,SAAS/sB,CAAK,EAClC,EAAGitB,EAAME,EACT,EAAGH,EAAMG,CAAA,CACV,CACH,CAGF,OAAOC,CACT,EAWaC,GAAqB,CAChCtB,EACAC,EACAzN,EACA+O,EACAT,IACa,CACb,GAAId,IAAe,IAAMC,IAAiB,IAAM,CAACzN,EAC/C,MAAO,CAAA,EAGT,MAAM2N,EAAW,KAAK,MAAMH,EAAac,CAAI,EACvCV,EAAWJ,EAAac,EACxBT,EAAa,KAAK,MAAMJ,EAAea,CAAI,EAC3CR,EAAaL,EAAea,EAE5BU,EAAkB,CAAA,EAExB,OAAQhP,EAAA,CACN,IAAK,MAEH,QAAS0O,EAAMd,EAAUc,GAAOZ,EAAYY,IAC1CM,EAAM,KAAKrB,EAAWW,EAAOI,CAAG,EAElC,MAEF,IAAK,MAEH,QAASA,EAAMd,EAAUc,GAAOZ,EAAYY,IAC1CM,EAAM,KAAKrB,EAAWW,EAAOI,CAAG,EAElC,MAEF,IAAK,MAEH,QAASD,EAAMd,EAAUc,GAAOZ,EAAYY,IAC1CO,EAAM,KAAKP,EAAMH,EAAOV,CAAQ,EAElC,MAEF,IAAK,MAEH,QAASa,EAAMd,EAAUc,GAAOZ,EAAYY,IAC1CO,EAAM,KAAKP,EAAMH,EAAOV,CAAQ,EAElC,KAAA,CAGJ,OAAOoB,CACT,EAQaC,GAAyB,CACpCC,EACAf,IAEO,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGe,EAAU,OAASf,CAAU,CAAC,EAQlDgB,GAAiBl/B,GACrB,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGA,CAAK,CAAC,EAQ1Bm/B,GAAoBn/B,GACxB,GAAG,KAAK,MAAMA,EAAQ,GAAG,CAAC,ICrJ7Bo/B,GAA4C,CAAC,CACjD,MAAAp/B,EACA,aAAA0O,EAAe,EACf,KAAA2wB,EAAO,WACP,SAAAC,EACA,KAAAlB,EAAO,GACP,KAAAC,EAAO,GACP,SAAAM,EAAW,GACX,UAAAY,EAAY,UACZ,UAAAC,EAAY,UACZ,YAAAC,EAAc,UACd,iBAAAC,EAAmB,MACnB,UAAAC,EAAY,GACZ,UAAAv8B,EAAY,EACd,IAAM,CAEJ,KAAM,CAAE,cAAAw8B,EAAe,iBAAAC,CAAA,EAAqB/B,GAAA,EACtC,CAAE,WAAAgC,EAAY,UAAArC,EAAW,UAAAsC,EAAW,WAAAC,EAAY,QAAAC,CAAA,EAAYjC,GAAA,EAG5DkC,EAAelgC,IAAU,OACzBmgC,EAAeD,EAAehB,GAAcl/B,CAAK,EAAI4/B,EAGrD,CAACQ,EAAaC,CAAc,EAAIxH,EAAAA,SAAS,EAAK,EAChD,CAACuH,GAAe,CAACF,IACnBL,EAAiBX,GAAcxwB,CAAY,CAAC,EAC5C2xB,EAAe,EAAI,GAIrB,MAAM9B,EAAczS,EAAAA,QAAQ,IAAM,CAEhC,MAAMltB,GAAS,CACb,WAFiBw/B,EAAOC,EAGxB,UAAW8B,EACX,UAAWT,EACX,KAAAtB,EACA,KAAAC,CAAA,EAEF,OAAOJ,GAAqBr/B,EAAM,EAAE,WACtC,EAAG,CAACuhC,EAAc/B,EAAMC,EAAMqB,CAAgB,CAAC,EAGzCY,EAAWxU,EAAAA,QAAQ,IAChB4S,GAAiBN,EAAMC,EAAMM,EAAUJ,CAAW,EACxD,CAACH,EAAMC,EAAMM,EAAUJ,CAAW,CAAC,EAGhCU,EAAYnT,EAAAA,QAAQ,IACpB,CAACgU,GAAcrC,EAAU,aAAe,IAAMA,EAAU,eAAiB,GACpE,CAAA,EAEFoB,GACLpB,EAAU,WACVA,EAAU,aACVA,EAAU,UACVW,EACAC,CAAA,EAED,CAACyB,EAAYrC,EAAWW,EAAMC,CAAI,CAAC,EAGhCkC,EAAkBpJ,cAAaqJ,GAAsB,CACzD,GAAInB,IAAS,OAAQ,OAErB,MAAMoB,GAAWvB,IAAesB,EAAY,IAAMpC,EAAOC,EAAK,EAE1D6B,GAGFL,EAAiBY,EAAQ,EACzBnB,IAAWmB,EAAQ,CAEvB,EAAG,CAACpB,EAAMjB,EAAMC,EAAM6B,EAAcZ,EAAUO,CAAgB,CAAC,EAGzDa,EAAkBvJ,cAAaqJ,GAAsB,CACrDnB,IAAS,QACbU,EAAUS,CAAS,CACrB,EAAG,CAACnB,EAAMU,CAAS,CAAC,EAEdn4B,EAAmBuvB,cAAaqJ,GAAsB,CACtDnB,IAAS,QAAU,CAACS,GACxBE,EAAWQ,CAAS,CACtB,EAAG,CAACnB,EAAMS,EAAYE,CAAU,CAAC,EAE3BW,EAAgBxJ,EAAAA,YAAY,IAAM,CACtC,GAAI,EAAAkI,IAAS,QAAU,CAACS,GAExB,IAAIb,EAAU,OAAS,EAAG,CACxB,MAAMwB,EAAWzB,GAAuBC,EAAWb,EAAOC,CAAI,EAE1D6B,GAGFL,EAAiBY,CAAQ,EACzBnB,IAAWmB,CAAQ,CAEvB,CAEAR,EAAA,EACF,EAAG,CAACZ,EAAMS,EAAYb,EAAWb,EAAMC,EAAM6B,EAAcZ,EAAUO,EAAkBI,CAAO,CAAC,EAGzFW,EAAWvC,EAAOM,EAClBkC,EAAYzC,EAAOO,EAGnBmC,GAAmB,CACvB,0BACA,kBAAkBzB,CAAI,GACtBM,GAAa,4BACbv8B,CAAA,EACA,OAAO,OAAO,EAAE,KAAK,GAAG,EAGpB29B,GAAiB,KAAK,MAAMZ,EAAe,GAAG,EAEpD,OACE38B,EAAAA,IAAC,MAAA,CACC,UAAWs9B,GACX,cAAY,0BAEZ,SAAAt9B,EAAAA,IAAC,MAAA,CACC,MAAOo9B,EACP,OAAQC,EACR,UAAU,oBACV,cAAY,oBACZ,KAAK,MACL,aAAY,SAASE,EAAc,QAElC,SAAAT,EAAS,IAAKU,GAAmB,CAChC,MAAMC,GAAW1C,EAAY,SAASyC,EAAK,KAAK,EAC1CE,EAAgBjC,EAAU,SAAS+B,EAAK,KAAK,EAC7CG,EAAWF,IAAYC,EAE7B,OACE19B,EAAAA,IAAC,OAAA,CAEC,EAAGw9B,EAAK,EACR,EAAGA,EAAK,EACR,MAAOrC,EACP,OAAQA,EACR,KAAMwC,EAAW5B,EAAYC,EAC7B,OAAQC,EACR,YAAa,EACb,UAAU,qBACV,cAAY,qBACZ,cAAawB,GACb,YAAWC,EACX,aAAY,IAAIF,EAAK,IAAM,CAAC,KAAKA,EAAK,IAAM,CAAC,KAAKG,EAAW,MAAQ,KAAK,GAC1E,SAAU9B,IAAS,OAAS,EAAI,GAChC,QAAS,IAAMkB,EAAgBS,EAAK,KAAK,EACzC,YAAa,IAAMN,EAAgBM,EAAK,KAAK,EAC7C,aAAc,IAAMp5B,EAAiBo5B,EAAK,KAAK,EAC/C,UAAWL,EACX,UAAYp6B,GAAM,CACZ84B,IAAS,QAAU94B,EAAE,MAAQ,SAC/Bg6B,EAAgBS,EAAK,KAAK,CAE9B,CAAA,EAtBKA,EAAK,KAAA,CAyBhB,CAAC,CAAA,CAAA,CACH,CAAA,CAGN,ECpLaI,GAAoB/+B,EAAM,cAAiD,MAAS,ECGpFg/B,GAAiB,CAC5B77B,EACA87B,IAEOxV,EAAAA,QAAQ,IAAM,CACnB,MAAMyV,EAAY/7B,EAAK,SAAS87B,CAAK,EAErC,MAAO,CACL,GAAG97B,EACH,QAAS+7B,GAAW,SAAW/7B,EAAK,QACpC,OAAQ+7B,GAAW,QAAU/7B,EAAK,OAClC,SAAU+7B,GAAW,UAAY/7B,EAAK,QAAA,CAE1C,EAAG,CAACA,EAAM87B,CAAK,CAAC,EChBLE,GAAwC,CAAC,CACpD,SAAA3/B,EACA,QAAA4/B,EACA,OAAAC,EAAS,GACT,OAAAC,EAAS,GACT,MAAAxJ,EAAQ,QACR,UAAA/0B,EAAY,EACd,IAAM,CACJ,MAAMw+B,EAAazJ,IAAU,OAAS,aAAe,GAC/C0J,EAAcH,EAAS,cAAgB,GACvCI,EAAcH,EAAS,cAAgB,GAGvC37B,EAAQy7B,EAAU,CAAE,oBAAqBA,GAAmC,OAElF,OACEj+B,EAAAA,IAAC,MAAA,CACC,UAAW,oBAAoBo+B,CAAU,IAAIC,CAAW,IAAIC,CAAW,IAAI1+B,CAAS,GACpF,MAAA4C,EACA,cAAY,wBAEX,SAAAnE,CAAA,CAAA,CAGP,ECxBakgC,GAAwC,CAAC,CACpD,SAAAlgC,EACA,QAAAmgC,EACA,IAAAC,EACA,WAAAC,EAAa,GACb,UAAA9+B,EAAY,EACd,IAAM,CAEJ,MAAM4C,EAAQ,CACZ,iBAAkBg8B,EAClB,aAAcC,CAAA,EAGVE,EAAkBD,EAAa,8BAAgC,GAErE,OACE1+B,EAAAA,IAAC,MAAA,CACC,MAAAwC,EACA,UAAW,oBAAoBm8B,CAAe,IAAI/+B,CAAS,GAC3D,cAAY,cAEX,SAAAvB,CAAA,CAAA,CAGP,ECxBaugC,GAAwC,CAAC,CACpD,SAAAvgC,EACA,UAAAkuB,EAAY,WACZ,IAAAkS,EACA,KAAAI,EAAO,GACP,UAAAj/B,EAAY,EACd,IAAM,CAEJ,MAAM4C,EAAQ,CACZ,aAAci8B,EACd,mBAAoBlS,IAAc,aAAe,MAAQ,SACzD,cAAesS,EAAO,OAAS,QAAA,EAG3BC,EAAiBvS,IAAc,aAAe,aAAe,GAC7DwS,EAAYF,EAAO,OAAS,GAElC,OACE7+B,EAAAA,IAAC,MAAA,CACC,MAAAwC,EACA,UAAW,oBAAoBs8B,CAAc,IAAIC,CAAS,IAAIn/B,CAAS,GACvE,cAAY,cAEX,SAAAvB,CAAA,CAAA,CAGP,EC3Ba2gC,GAA0C,CAAC,CACtD,QAAAz2B,EACA,MAAA/F,EAAQ,CAAA,EACR,cAAAy8B,EACA,UAAAr/B,EAAY,EACd,IAEII,EAAAA,IAAC,MAAA,CACC,UAAW,oBAAoBJ,CAAS,GACxC,MAAA4C,EACA,QAAS,IAAMy8B,IAAgB,CAAE,KAAM,QAAS,QAAA12B,EAAS,EACzD,cAAY,eAEX,SAAAA,CAAA,CAAA,ECZM22B,GAAgD,CAAC,CAC5D,MAAAlX,EACA,SAAA3pB,EACA,YAAA6pB,EAAc,GACd,MAAA1lB,EAAQ,CAAA,EACR,UAAA5C,EAAY,EACd,IAEII,MAAC,OAAI,UAAW,uBAAuBJ,CAAS,GAAI,MAAA4C,EAAc,cAAY,kBAC5E,SAAAxC,EAAAA,IAAC+nB,GAAA,CACC,MAAAC,EACA,SAAA3pB,EACA,YAAA6pB,CAAA,CAAA,EAEJ,ECNG,MAAMiX,WAA+BtgC,EAAM,SAGhD,CACA,MAAqC,CAAE,SAAU,GAAO,MAAO,IAAA,EAE/D,OAAO,yBAAyBoD,EAA2C,CACzE,MAAO,CAAE,SAAU,GAAM,MAAAA,CAAA,CAC3B,CAEA,kBAAkBA,EAAcm9B,EAAuB,CACrD,QAAQ,MAAM,mBAAoBn9B,EAAOm9B,EAAK,cAAc,CAC9D,CAEA,QAAS,CACP,OAAI,KAAK,MAAM,SAEXz+B,EAAAA,KAAC,MAAA,CAAI,UAAU,iDACb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,yBAAyB,SAAA,WAAQ,QAC9C,IAAA,CAAE,UAAU,eAAgB,SAAA,KAAK,MAAM,OAAO,QAAQ,EACvDA,EAAAA,IAAC,SAAA,CACC,UAAU,qDACV,QAAS,IAAM,KAAK,SAAS,CAAE,SAAU,GAAO,EACjD,SAAA,IAAA,CAAA,CAED,EACF,EAIG,KAAK,MAAM,QACpB,CACF,CCbO,SAASq/B,GAAoBC,EAA6C,CAC/E,GAAI,OAAOA,GAAU,SACnB,MAAM,IAAI,MAAM,6CAA6C,OAAOA,CAAK,EAAE,EAG7E,MAAMC,EAAWD,EAAM,KAAA,EAGjBE,EAAaD,EAAS,MAAM,sGAAsG,EAExI,GAAIC,EAAY,CACd,MAAMC,GAAcD,EAAW,CAAC,GAAKA,EAAW,CAAC,GAAK,IAAI,KAAA,EAE1D,GAAI,CAACC,EACH,MAAM,IAAI,MAAM,oDAAoDF,CAAQ,GAAG,EAGjF,GAAI,CAEF,OAAOG,GAAuBD,CAAU,CAC1C,OAASx9B,EAAO,CACd,MAAM,IAAI,MAAM,mCAAmCs9B,CAAQ,MAAMt9B,CAAK,EAAE,CAC1E,CACF,CAEA,MAAM,IAAI,MAAM,oCAAoCs9B,CAAQ,4DAA4D,CAC1H,CAMA,SAASG,GAAuBD,EAAkD,CAChF,MAAME,EAAOF,EAAW,KAAA,EAGxB,GAAIE,IAAS,sBAAwBA,IAAS,mBAC5C,OAAQngC,GAAqBA,EAAW,KAAK,GAI/C,GAAImgC,IAAS,0BAA4BA,IAAS,qBAChD,OAAQngC,GAAqBA,EAAW,KAAK,GAAK,EAIpD,MAAMogC,EAAgB,8BAChBC,EAAcF,EAAK,MAAMC,CAAa,EAC5C,GAAIC,EAAa,CACf,MAAMC,EAAa,WAAWD,EAAY,CAAC,CAAC,EAC5C,OAAQrgC,GAAqBA,EAAWsgC,CAC1C,CAGA,MAAMC,EAAsB,8CACtBC,EAAoBL,EAAK,MAAMI,CAAmB,EACxD,GAAIC,EAAmB,CACrB,MAAMF,EAAa,WAAWE,EAAkB,CAAC,CAAC,EAClD,OAAQxgC,GAAqBA,EAAW,KAAK,GAAKsgC,CACpD,CAGA,GAAIH,EAAK,SAAS,UAAU,GAAKA,EAAK,SAAS,UAAU,EACvD,OAAQngC,GAAqB,KAAK,IAAIA,EAAW,KAAK,EAAE,EAI1D,GAAImgC,EAAK,SAAS,UAAU,GAAKA,EAAK,SAAS,UAAU,EACvD,OAAQngC,GAAqB,KAAK,IAAIA,EAAW,KAAK,EAAE,EAI1D,MAAMygC,EAAkB,cAClBC,EAAgBP,EAAK,MAAMM,CAAe,EAChD,GAAIC,EAAe,CACjB,MAAM1jC,EAAQ,WAAW0jC,EAAc,CAAC,CAAC,EACzC,MAAO,IAAM1jC,CACf,CAGA,OAAImjC,IAAS,WACHngC,GAAqBA,EAI3BmgC,EAAK,SAAS,eAAe,GAC/B,QAAQ,KAAK,sCAAsCA,CAAI,8CAA8C,EAC7FngC,GAAqBA,EAAW,KAAK,KAI/C,QAAQ,KAAK,oCAAoCmgC,CAAI,6BAA6B,EAC1EngC,GAAqB,CAC3B,IAAI2gC,EAAWR,EAAK,QAAQ,gBAAiBngC,EAAS,UAAU,EAChE,OAAA2gC,EAAWA,EAAS,QAAQ,YAAa,KAAK,GAAG,UAAU,EAC3DA,EAAWA,EAAS,QAAQ,WAAY,KAAK,EAAE,UAAU,EAElDC,GAAmBD,CAAQ,CACpC,EACF,CASA,SAASC,GAAmBT,EAAsB,CAEhD,MAAMU,EAAYV,EAAK,QAAQ,MAAO,EAAE,EAGxC,SAASW,EAASX,EAAsB,CAEtC,KAAOA,EAAK,SAAS,GAAG,GAAG,CAEzB,MAAMtxB,EAAQsxB,EAAK,MAAM,cAAc,EACvC,GAAI,CAACtxB,EAAO,MAEZ,MAAMkyB,EAAaD,EAASjyB,EAAM,CAAC,CAAC,EACpCsxB,EAAOA,EAAK,QAAQtxB,EAAM,CAAC,EAAGkyB,EAAW,UAAU,CACrD,CAGA,MAAMC,EAAUb,EAAK,MAAM,kCAAkC,EAC7D,GAAIa,EAAS,CACX,MAAM1V,EAAO,WAAW0V,EAAQ,CAAC,CAAC,EAC5BC,EAAKD,EAAQ,CAAC,EACdxV,EAAQ,WAAWwV,EAAQ,CAAC,CAAC,EAC7B16B,EAAS26B,IAAO,IAAM3V,EAAOE,EAAQF,EAAOE,EAClD2U,OAAAA,EAAOA,EAAK,QAAQa,EAAQ,CAAC,EAAG16B,EAAO,UAAU,EAC1Cw6B,EAASX,CAAI,CACtB,CAGA,MAAMe,EAAUf,EAAK,MAAM,mCAAmC,EAC9D,GAAIe,EAAS,CACX,MAAM5V,EAAO,WAAW4V,EAAQ,CAAC,CAAC,EAC5BD,EAAKC,EAAQ,CAAC,EACd1V,EAAQ,WAAW0V,EAAQ,CAAC,CAAC,EAC7B56B,EAAS26B,IAAO,IAAM3V,EAAOE,EAAQF,EAAOE,EAClD2U,OAAAA,EAAOA,EAAK,QAAQe,EAAQ,CAAC,EAAG56B,EAAO,UAAU,EAC1Cw6B,EAASX,CAAI,CACtB,CAGA,MAAMnjC,EAAQ,WAAWmjC,CAAI,EAC7B,GAAI,MAAMnjC,CAAK,EACb,MAAM,IAAI,MAAM,uBAAuBmjC,CAAI,EAAE,EAE/C,OAAOnjC,CACT,CAEA,OAAO8jC,EAASD,CAAS,CAC3B,CAKO,SAASM,GAAiBnkC,EAAqB,CACpD,OAAO,OAAOA,GAAU,WAChBA,EAAM,SAAS,IAAI,GAAKA,EAAM,SAAS,UAAU,EAC3D,CAUO,SAASokC,GAAeC,EAAmBrhC,EAAmB,EAAW,CAC9E,OAAI,OAAOqhC,GAAU,WACZA,EAAMrhC,CAAQ,EAEhBqhC,CACT,CAUO,SAASC,GACd1lC,EACAoE,EACAuhC,EACO,CACP,OAAQ3lC,EAAO,OAAO,KAAA,CACpB,IAAK,YAAa,CAChB,MAAMmT,EAASnT,EAAO,OAGhB4lC,EAAU,OAAOzyB,EAAO,GAAM,YAAcwyB,EAC9C,UAAW,CACT,MAAM9T,EAAkB8T,EAAQ,MAAA,EAChC,OAAQxyB,EAAO,EAAe0e,CAAe,CAC/C,EACA2T,GAAeryB,EAAO,EAAG/O,CAAQ,EAE/ByhC,EAAU,OAAO1yB,EAAO,GAAM,YAAcwyB,EAC9C,UAAW,CACT,MAAM9T,EAAkB8T,EAAQ,MAAA,EAChC,OAAQxyB,EAAO,EAAe0e,CAAe,CAC/C,EACA2T,GAAeryB,EAAO,EAAG/O,CAAQ,EAErC,MAAO,CAACwhC,EAAQC,CAAM,CACxB,CAEA,IAAK,SAAU,CACb,MAAM1yB,EAASnT,EAAO,OAChB+wB,EAAS5d,EAAO,QAAU,CAAC,EAAG,CAAC,EAGrC,OAAI,OAAOA,EAAO,OAAU,YAAcwyB,EACjC,CACL,UAAW,CACT,MAAM9T,EAAkB8T,EAAQ,MAAA,EAChC,OAAQxyB,EAAO,MAAmB0e,CAAe,CACnD,EACAd,EAAO,CAAC,EACRA,EAAO,CAAC,CAAA,EAML,CADOyU,GAAeryB,EAAO,MAAO/O,CAAQ,EACpC2sB,EAAO,CAAC,EAAGA,EAAO,CAAC,CAAC,CACrC,CAEA,IAAK,QAAS,CACZ,MAAM5d,EAASnT,EAAO,OAGhB8lC,EAAe,OAAO3yB,EAAO,QAAW,YAAcwyB,EACxD,UAAW,CACT,MAAM9T,EAAkB8T,EAAQ,MAAA,EAChC,OAAQxyB,EAAO,OAAoB0e,CAAe,CACpD,EACA2T,GAAeryB,EAAO,OAAQ/O,CAAQ,EAEpC2hC,EAAe,OAAO5yB,EAAO,QAAW,YAAcwyB,EACxD,UAAW,CACT,MAAM9T,EAAkB8T,EAAQ,MAAA,EAChC,OAAQxyB,EAAO,OAAoB0e,CAAe,CACpD,EACA2T,GAAeryB,EAAO,OAAQ/O,CAAQ,EAE1C,MAAO,CAAC0hC,EAAaC,CAAW,CAClC,CAEA,IAAK,UAAW,CACd,MAAM5yB,EAASnT,EAAO,OAItB,GAAImT,EAAO,KAET,MAAO,CAACA,EAAO,IAAI,EAIrB,GAAIA,EAAO,QAAUA,EAAO,OAC1B,MAAO,CAACA,EAAO,OAAQA,EAAO,MAAM,EAItC,GAAIA,EAAO,IAAMA,EAAO,GACtB,MAAO,CAACA,EAAO,GAAIA,EAAO,EAAE,EAG9B,MAAM,IAAI,MACR;AAAA;AAAA;AAAA;AAAA,YAIa,KAAK,UAAUA,CAAM,CAAC,EAAA,CAEvC,CAEA,IAAK,QAAS,CACZ,MAAMA,EAASnT,EAAO,OAChBgmC,EAASR,GAAeryB,EAAO,OAAQ/O,CAAQ,EAC/C6hC,EAAST,GAAeryB,EAAO,OAAQ/O,CAAQ,EACrD,MAAO,CAAC4hC,EAAQC,CAAM,CACxB,CAEA,IAAK,UAAW,CACd,MAAM9yB,EAASnT,EAAO,OACtB,MAAO,CACLwlC,GAAeryB,EAAO,EAAG/O,CAAQ,EAAGohC,GAAeryB,EAAO,EAAG/O,CAAQ,EAAGohC,GAAeryB,EAAO,EAAG/O,CAAQ,EACzGohC,GAAeryB,EAAO,EAAG/O,CAAQ,EAAGohC,GAAeryB,EAAO,EAAG/O,CAAQ,EAAGohC,GAAeryB,EAAO,EAAG/O,CAAQ,EACzGohC,GAAeryB,EAAO,EAAG/O,CAAQ,EAAGohC,GAAeryB,EAAO,EAAG/O,CAAQ,EAAGohC,GAAeryB,EAAO,EAAG/O,CAAQ,CAAA,CAE7G,CAEA,IAAK,SAAU,CACb,MAAM+O,EAASnT,EAAO,OAEtB,GAAI,CAAC,MAAM,QAAQmT,EAAO,MAAM,GAAKA,EAAO,OAAO,SAAW,GAC1D,CAACA,EAAO,OAAO,SAAa,MAAM,QAAQysB,CAAG,GAAKA,EAAI,SAAW,CAAC,EACpE,MAAM,IAAI,MAAM,8CAA8C,EAEhE,MAAO,CAACzsB,EAAO,MAAM,CACvB,CAEA,QACE,MAAM,IAAI,MAAM,+BAAgCnT,EAAO,OAAe,IAAI,EAAE,CAAA,CAElF,CASO,SAASkmC,GAAqBC,EAA4D,CAC/F,MAAMC,EAAuC,CAAA,EAE7C,cAAO,QAAQD,CAAS,EAAE,QAAQ,CAAC,CAACjmC,EAAKkB,CAAK,IAAM,CAElD,GAAI,OAAOA,GAAU,UAAYmkC,GAAiBnkC,CAAK,EACrD,GAAI,CACFglC,EAASlmC,CAAG,EAAI+jC,GAAoB7iC,CAAK,CAC3C,OAASyF,EAAO,CACd,QAAQ,KAAK,uCAAuC3G,CAAG,KAAKkB,CAAK,GAAIyF,CAAK,EAE1Eu/B,EAASlmC,CAAG,EAAI,IAAM,CACxB,MAGAkmC,EAASlmC,CAAG,EAAIkB,CAEpB,CAAC,EAEMglC,CACT,CA4CO,SAAS/W,GAAwBrvB,EAAoD,CAC1F,GAAI,CAACA,GAAU,OAAOA,GAAW,SAC/B,MAAO,CAAE,MAAO,GAAO,OAAQ,CAAC,0BAA0B,CAAA,EAG5D,MAAMswB,EAAmB,CAAA,EAGzB,OAAI,CAACtwB,EAAO,IAAM,OAAOA,EAAO,IAAO,UAAYA,EAAO,GAAG,KAAA,IAAW,KACtEswB,EAAO,KAAK,sCAAsC,EAI/C,MAAM,QAAQtwB,EAAO,UAAU,EAGlCA,EAAO,WAAW,QAAQ,CAAC6tB,EAAgBjb,IAAkB,EAEvD,CAACib,EAAU,IAAM,OAAOA,EAAU,IAAO,WAC3CyC,EAAO,KAAK,sBAAsB1d,CAAK,uBAAuB,GAG5D,CAACib,EAAU,MAAQ,OAAOA,EAAU,MAAS,WAC/CyC,EAAO,KAAK,sBAAsB1d,CAAK,yBAAyB,GAG9D,CAACib,EAAU,QAAU,OAAOA,EAAU,QAAW,WACnDyC,EAAO,KAAK,sBAAsB1d,CAAK,yBAAyB,EAG7D,MAAM,QAAQib,EAAU,YAAY,EAE9BA,EAAU,aAAa,SAAW,GAC3CyC,EAAO,KAAK,gCAAgC,EAF5CA,EAAO,KAAK,sBAAsB1d,CAAK,+BAA+B,CAI1E,CAAC,EArBD0d,EAAO,KAAK,qCAAqC,EAwB5C,CACL,MAAOA,EAAO,SAAW,EACzB,OAAQA,EAAO,OAAS,EAAIA,EAAS,MAAA,CAEzC,CC/bA,MAAM4I,GAAMC,GAAS,SAORkN,GAAiDlkC,GAAU,CACtE,QAAQ,KAAK,2BAA4B,CACvC,aAAc,CAAC,CAACA,EAAM,UACtB,YAAaA,EAAM,WAAW,GAC9B,WAAY,CAAC,CAACA,EAAM,WAAW,QAC/B,cAAeA,EAAM,WAAW,QAChC,kBAAmBA,EAAM,iBAAA,CAC1B,EAED,MAAMmkC,EAAejO,EAAAA,OAAuB,IAAI,EAC1C,CAACgC,EAAOC,CAAQ,EAAIL,EAAAA,SAAgC,IAAI,EACxD,EAAGsM,CAAgB,EAAItM,EAAAA,SAA8B,EAAE,EACvD,CAACuM,EAAaC,CAAc,EAAIxM,EAAAA,SAAS,EAAK,EAC9CyM,EAAgBrO,EAAAA,OAA4B,EAAE,EAC9CuC,EAAmBvC,EAAAA,OAA4B,EAAE,EACjDsO,EAAatO,EAAAA,OAAY,IAAI,EAC7BuO,EAAqBvO,EAAAA,OAAiC,EAAE,EAGxDwO,EAAoBtO,EAAAA,YAAY,CAACuO,EAAkBC,IAAwB,CAC3E5kC,EAAM,aAKZ,EAAG,CAACA,EAAM,aAAa,CAAC,EAGlB6kC,EAAwBzO,cAAa0O,GAA2B,CAChE9kC,EAAM,mBACRA,EAAM,kBAAkB8kC,EAAU,CAACA,CAAO,EAAI,CAAA,CAAE,CAEpD,EAAG,CAAC9kC,EAAM,iBAAiB,CAAC,EAG5B4qB,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAKuZ,EAAa,QAElB,IAAI,CACF,MAAMY,EAAc/kC,EAAM,aAAe,CAAC,IAAK,GAAI,GAAI,GAAG,EAC1D,QAAQ,KAAK,mCAAmC,EAChD,QAAQ,KAAK,4BAA6B+kC,CAAW,EACrD,QAAQ,KAAK,4BAA6BZ,EAAa,QAAQ,YAAa,IAAKA,EAAa,QAAQ,YAAY,EAElH,MAAMjM,EAAQnB,GAAI,UAAUoN,EAAa,QAAS,CAChD,YAAaY,EACb,KAAM/kC,EAAM,UAAY,GACxB,KAAMA,EAAM,UAAY,GACxB,eAAgB,GAChB,IAAK,CAAE,QAASA,EAAM,OAAS,MAAA,EAC/B,gBAAiB,GACjB,cAAe,EAAA,CAChB,EAGD,QAAQ,KAAK,gCAAiCk4B,EAAM,eAAA,CAAgB,EAMpE,WAAW,IAAM,CACf,QAAQ,KAAK,aAAa,EAC1B,QAAQ,KAAK,eAAgB6M,CAAW,EACxC,QAAQ,KAAK,eAAgB7M,EAAM,eAAA,CAAgB,EACnD,QAAQ,KAAK,gBAAiB,CAC5B,KAAMA,EAAM,eAAA,EAAiB,CAAC,EAC9B,IAAKA,EAAM,eAAA,EAAiB,CAAC,EAC7B,MAAOA,EAAM,eAAA,EAAiB,CAAC,EAC/B,OAAQA,EAAM,eAAA,EAAiB,CAAC,CAAA,CACjC,CACH,EAAG,GAAG,EAENC,EAASD,CAAK,CAChB,OAASxzB,EAAO,CACd,QAAQ,MAAM,kCAAmCA,CAAK,CACxD,CAEA,MAAO,IAAM,CACPwzB,GACFnB,GAAI,UAAUmB,CAAK,CAEvB,EACF,EAAG,CAAA,CAAE,EAGLtN,EAAAA,UAAU,IAAM,CAWd,GAVA,QAAQ,KAAK,kCAAmC,CAC9C,SAAU,CAAC,CAACsN,EACZ,aAAc,CAAC,CAACl4B,EAAM,UACtB,WAAY,CAAC,CAACA,EAAM,WAAW,QAC/B,YAAaA,EAAM,WAAW,GAC9B,YAAaA,EAAM,WAAW,SAAS,KACvC,gBAAkBA,EAAM,WAAW,SAAiB,SACpD,aAAcA,EAAM,WAAW,SAAS,KAAA,CACzC,EAEG,CAACk4B,GAAS,CAACl4B,EAAM,WAAW,QAAS,CAGvC,GAFA,QAAQ,KAAK,qCAAuC,CAAC,CAACk4B,EAAQ,aAAe,CAAC,CAACl4B,EAAM,WAAW,OAAO,EAEnGwkC,EAAW,QAAS,CACtB,GAAI,CACEA,EAAW,QAAQ,QACrBA,EAAW,QAAQ,OAAA,CAEvB,OAAS9/B,EAAO,CACd,QAAQ,KAAK,4BAA6BA,CAAK,CACjD,CACA8/B,EAAW,QAAU,IACvB,CACA,MACF,CAEA,MAAMQ,EAAgBhlC,EAAM,UAAU,QACtC,QAAQ,KAAK,gCAAiC,CAC5C,KAAMglC,EAAc,KACpB,OAAQA,EACR,SAAWA,EAAsB,SACjC,MAAOA,EAAc,KAAA,CACtB,EAED,GAAI,CACF,GAAIA,EAAc,OAAS,SAAU,CAEnC,MAAMC,EAAOD,EAAc,SAAS,CAAC,GAAKA,EAAc,QAAU,GAClE,QAAQ,KAAK,iCAAkC,CAC7C,WAAYA,EAAc,SAC1B,SAAU,CAACC,EAAMD,EAAc,SAAS,CAAC,CAAC,EAC1C,OAAQ,CAACA,EAAc,MAAM,CAAC,EAAGA,EAAc,SAAW,EAAGA,EAAc,MAAM,CAAC,CAAC,EACnF,MAAOA,EAAc,MACrB,UAAWA,EAAc,WAAa,GAAA,CACvC,EAED,MAAM5X,EAAS8K,EAAM,OAAO,SAAU,CACpC8M,EAAc,SACd,CAACC,EAAMD,EAAc,SAAS,CAAC,CAAC,EAChC,CAACA,EAAc,MAAM,CAAC,EAAGA,EAAc,SAAW,EAAGA,EAAc,MAAM,CAAC,CAAC,CAAA,EAC1E,CACD,KAAMA,EAAc,OAAS,UAC7B,UAAWA,EAAc,WAAa,IACtC,UAAWA,EAAc,YAAc,OAAYA,EAAc,UAAY,GAC7E,QAAS,GACT,YAAa,UACb,UAAW,UACX,mBAAoB,SAAA,CACrB,EAEDR,EAAW,QAAUpX,EACrB,QAAQ,KAAK,oBAAqB,CAChC,GAAIA,EAAO,GACX,KAAMA,EAAO,KACb,aAAcA,EAAO,MAAA,EACrB,WAAY4X,EAAc,SAC1B,SAAU,CAACC,EAAMD,EAAc,SAAS,CAAC,CAAC,EAC1C,YAAa9M,EAAM,eAAA,EACnB,QAAS9K,EAAO,OAAA,CACjB,EAGD,MAAM8X,EAAahN,EAAM,YAAY,IAAKruB,IAAc,CACtD,GAAIA,EAAI,GACR,KAAMA,EAAI,OACV,KAAMA,EAAI,KACV,QAASA,EAAI,SAAS,OAAA,EACtB,EACIs7B,EAAeD,EAAW,KAAMr7B,GAAaA,EAAI,KAAOujB,EAAO,EAAE,EAKvE,GAJA,QAAQ,KAAK,kCAAmC,CAAC,CAAC+X,EAAcA,CAAY,EAC5E,QAAQ,KAAK,8BAA+BD,EAAW,MAAM,EAGzDllC,EAAM,kBAAmB,CAC3B,IAAIolC,EAAa,GACjBhY,EAAO,GAAG,OAAQ,IAAM,CACtB,GAAIgY,EAAY,OAChBA,EAAa,GAGb,MAAMC,GADQjY,EAAO,MAAA,EACY4X,EAAc,MAAM,CAAC,IAAMA,EAAc,MAAM,CAAC,EAAIA,EAAc,MAAM,CAAC,GAC1GhlC,EAAM,oBAAoBqlC,CAAe,EAEzCD,EAAa,EACf,CAAC,CACH,CACF,SAAWJ,EAAc,OAAS,SAAU,CAE1C,MAAM1wB,EAAO4jB,EAAM,OAAO8M,EAAc,KAAM,EAAI,EAClD,GAAI1wB,EAAM,CACR,MAAMgxB,EAASpN,EAAM,OAAO,SAAU,CACpC8M,EAAc,SAAW,EAAG,EAAG1wB,CAAA,EAC9B,CACD,KAAM0wB,EAAc,OAAS,UAC7B,UAAWA,EAAc,WAAa,GAAA,CACvC,EAQD,GANAR,EAAW,QAAUc,EACrB,QAAQ,KAAK,oBAAqB,CAChC,GAAKA,EAAe,GACpB,KAAOA,EAAe,IAAA,CACvB,EAEGtlC,EAAM,kBAAmB,CAC3B,IAAIolC,EAAa,GAChBE,EAAe,GAAG,OAAQ,IAAM,CAC/B,GAAIF,EAAY,OAChBA,EAAa,GAEb,MAAMnmC,EAASqmC,EAAe,MAAA,EAC9BtlC,EAAM,oBAAoBf,CAAK,EAE/BmmC,EAAa,EACf,CAAC,CACH,CACF,MACE,QAAQ,KAAK,wCAAwCJ,EAAc,IAAI,EAAE,CAE7E,CACF,OAAStgC,EAAO,CACd,QAAQ,MAAM,sCAAuCA,CAAK,CAC5D,CAGA,MAAO,IAAM,CACX,GAAI8/B,EAAW,QAAS,CACtB,GAAI,CACFA,EAAW,QAAQ,OAAA,CACrB,OAAS9/B,EAAO,CACd,QAAQ,KAAK,uCAAwCA,CAAK,CAC5D,CACA8/B,EAAW,QAAU,IACvB,CACF,CACF,EAAG,CAACtM,EAAOl4B,EAAM,WAAW,OAAO,CAAC,EAGpC4qB,EAAAA,UAAU,IAAM,CACd,GAAI,CAACsN,GAAS,CAACl4B,EAAM,UAAW,CAE1B,OAAO,KAAKukC,EAAc,OAAO,EAAE,OAAS,IAC9CA,EAAc,QAAU,CAAA,GAE1B,MACF,CAEA,GAAI,CACF,QAAQ,KAAK,yBAA0B,CACrC,YAAavkC,EAAM,UAAU,GAC7B,eAAgBA,EAAM,UAAU,WAAW,MAAA,CAC5C,EAGD,OAAO,OAAOukC,EAAc,OAAO,EAAE,QAAS7Y,GAAmB,CAC/D,GAAI,CACEA,GAAaA,EAAU,QACzBA,EAAU,OAAA,CAEd,OAAShnB,EAAO,CACd,QAAQ,KAAK,8BAA+BA,CAAK,CACnD,CACF,CAAC,EACD6/B,EAAc,QAAU,CAAA,EAGxB,MAAMgB,EAAqC,CAAA,EACrCtjC,EAAWjC,EAAM,mBAAqB,EAE5CA,EAAM,UAAU,WAAW,QAASnC,GAA+B,CACjE,GAAI,CAEF,IAAImT,EACA0a,EACJ,MAAM8Z,EAAc3nC,EAAO,aAAe,GAE1C,GAAI2mC,EAAW,SAAWgB,EAAa,CAErCx0B,EAASuyB,GAAkB1lC,EAAQoE,EAAUuiC,EAAW,OAAO,EAE/D,QAAQ,KAAK,yBAAyB3mC,EAAO,EAAE,0BAA2B,CACxE,KAAMA,EAAO,KACb,YAAamT,EAAO,IAAIyjB,GAAK,OAAOA,CAAC,EACrC,aAAc52B,EAAO,aACrB,aAAc2mC,EAAW,QAAQ,MAAA,CAAM,CACxC,EAGD9Y,EAAYwM,EAAM,OAAO,YAAalnB,EAAQ,CAC5C,KAAMnT,EAAO,KACb,GAAI,aAAaA,EAAO,EAAE,EAAA,CAC3B,EAGD,MAAM4nC,EAAgB,IAAM,CAC1B,GAAI,CAACjB,EAAW,QAAS,OAGzBtM,EAAM,OAAA,EAEN,MAAMwN,EAAelB,EAAW,QAAQ,MAAA,EAIxC,GAHA,QAAQ,KAAK,8BAA8B3mC,EAAO,EAAE,gCAAgC6nC,CAAY,GAAG,EAG/F1lC,EAAM,kBAAmB,CAE3B,MAAMg+B,EAAQh+B,EAAM,WAAW,SAAS,OAAS,CAAC,EAAG,CAAC,EAChDiC,GAAYyjC,EAAe1H,EAAM,CAAC,IAAMA,EAAM,CAAC,EAAIA,EAAM,CAAC,GAChEh+B,EAAM,kBAAkBiC,CAAQ,CAClC,CACF,EAGAuiC,EAAW,QAAQ,GAAG,OAAQiB,CAAa,EAG3ChB,EAAmB,QAAQ5mC,EAAO,EAAE,EAAI4nC,EAExC,QAAQ,KAAK,6CAA6C5nC,EAAO,EAAE,qBAAqB,CAC1F,MAEEmT,EAASuyB,GAAkB1lC,EAAQoE,CAAQ,EAC3C,QAAQ,KAAK,yBAAyBpE,EAAO,EAAE,mBAAmBoE,CAAQ,KAAM,CAC9E,KAAMpE,EAAO,KACb,OAAAmT,EACA,aAAcnT,EAAO,YAAA,CACtB,EAGD6tB,EAAYwM,EAAM,OAAO,YAAalnB,EAAQ,CAC5C,KAAMnT,EAAO,KACb,GAAI,aAAaA,EAAO,EAAE,EAAA,CAC3B,EAGH0nC,EAAc1nC,EAAO,EAAE,EAAI6tB,EAC3B,QAAQ,KAAK,gBAAgB7tB,EAAO,EAAE,YAAa,CACjD,KAAMA,EAAO,KACb,YAAamT,EAAO,IAAIyjB,GAAK,OAAOA,CAAC,EACrC,iBAAkB,OAAO,KAAK/I,CAAS,EAAE,OAAOia,GAAK,OAAOja,EAAUia,CAAC,GAAM,UAAU,CAAA,CACxF,CACH,OAASjhC,EAAO,CACd,QAAQ,MAAM,8BAA8B7G,EAAO,EAAE,IAAK6G,CAAK,CACjE,CACF,CAAC,EAED6/B,EAAc,QAAUgB,CAE1B,OAAS7gC,EAAO,CACd,QAAQ,MAAM,0BAA2BA,CAAK,CAChD,CACF,EAAG,CAACwzB,EAAOl4B,EAAM,SAAS,CAAC,EAG3B4qB,EAAAA,UAAU,IAAM,CACd,GAAI,CAACyZ,GAAe,CAACnM,GAAS,CAACl4B,EAAM,UAAW,CAC9C,QAAQ,KAAK,4CAA4CqkC,CAAW,WAAW,CAAC,CAACnM,CAAK,eAAe,CAAC,CAACl4B,EAAM,SAAS,EAAE,EACxH,MACF,CAMA,GAJA,QAAQ,KAAK,8CAA8C,EAC3D,QAAQ,KAAK,wBAAwB,OAAO,KAAKy4B,EAAiB,OAAO,EAAE,MAAM,EAAE,EACnF,QAAQ,KAAK,4BAA4B,OAAO,KAAK8L,EAAc,OAAO,EAAE,MAAM,EAAE,EAEhF,OAAO,KAAK9L,EAAiB,OAAO,EAAE,SAAW,EAAG,CACtD,QAAQ,KAAK,mDAAmD,EAChE,MACF,CAEA,GAAI,OAAO,KAAK8L,EAAc,OAAO,EAAE,SAAW,EAAG,CACnD,QAAQ,KAAK,6CAA6C,EAC1D,MACF,CAEA,OAAO,QAAQA,EAAc,OAAO,EAAE,QAAQ,CAAC,CAACqB,EAAala,CAAS,IAAM,CAC1E,MAAM7tB,EAASmC,EAAM,WAAW,WAAW,KAAK60B,GAAKA,EAAE,KAAO+Q,CAAW,EACzE,GAAI,CAAC/nC,EAAQ,OAEb,QAAQ,KAAK,wBAAwB+nC,CAAW,WAAW/nC,EAAO,IAAI,eAAgBA,EAAO,YAAY,EACzG,QAAQ,KAAK,2CAA4C,OAAO,KAAK46B,EAAiB,OAAO,CAAC,EAE9F,MAAMoN,EAAiBhoC,EAAO,aAC3B,IAAIinC,GAAW,CACd,MAAMpK,EAAUjC,EAAiB,QAAQqM,CAAO,EAChD,OAAKpK,EAIH,QAAQ,KAAK,iBAAiBoK,CAAO,IAAKpK,CAAO,GAHjD,QAAQ,KAAK,4CAA4CoK,CAAO,EAAE,EAClE,QAAQ,KAAK,oBAAqB,OAAO,KAAKrM,EAAiB,OAAO,CAAC,GAIlEiC,CACT,CAAC,EACA,OAAO,OAAO,EAIjB,GAFA,QAAQ,KAAK,sCAAuCmL,EAAe,MAAM,EAErEA,EAAe,OAAS,EAC1B,GAAI,CACF,QAAQ,KAAK,mCAAmCD,CAAW,OAAOC,EAAe,MAAM,SAAS,EAChGna,EAAU,OAAOma,CAAc,EAC/B,QAAQ,KAAK,kCAAkCD,CAAW,OAAOC,EAAe,MAAM,SAAS,EAE/F,QAAQ,KAAK,uBAAwBna,CAAS,EAC9C,QAAQ,KAAK,sBAAuBma,EAAe,IAAIr1B,IAAO,CAC5D,GAAIA,EAAG,GACP,KAAMA,EAAG,KACT,KAAMA,EAAG,YAAA,EACT,CAAC,CACL,OAAS9L,EAAO,CACd,QAAQ,MAAM,8BAA8BkhC,CAAW,IAAKlhC,CAAK,EACjE,QAAQ,MAAM,gBAAiBgnB,CAAS,EACxC,QAAQ,MAAM,qBAAsBma,CAAc,CACpD,MAEA,QAAQ,KAAK,6CAA6CD,CAAW,EAAE,CAE3E,CAAC,EAGD1N,EAAM,OAAA,EACN,QAAQ,KAAK,0CAA0C,CACzD,EAAG,CAACmM,EAAanM,EAAOl4B,EAAM,SAAS,CAAC,EAGxC4qB,EAAAA,UAAU,IAAM,CACd,GAAI,CAACsN,GAAS,OAAO,KAAKqM,EAAc,OAAO,EAAE,SAAW,EAAG,OAE/D,MAAMtiC,EAAWjC,EAAM,mBAAqB,EAC5C,QAAQ,KAAK,wCAAwCiC,CAAQ,EAAE,EAE/D,GAAI,CAEF,OAAO,QAAQsiC,EAAc,OAAO,EAAE,QAAQ,CAAC,CAACqB,EAAala,CAAS,IAAM,CAC1E,MAAM7tB,EAASmC,EAAM,WAAW,WAAW,KAAK60B,GAAKA,EAAE,KAAO+Q,CAAW,EACzE,GAAI,CAAC/nC,EAAQ,OAEb,MAAMmT,EAASuyB,GAAkB1lC,EAAQoE,CAAQ,EAIjD,QAAQ,KAAK,qCAAqC2jC,CAAW,gBAAiB50B,CAAM,EAGhF0a,EAAU,QACZ,QAAQ,KAAK,kCAAkC,EAC/CA,EAAU,OAAO1a,CAAM,GACd0a,EAAU,WACnB,QAAQ,KAAK,yDAAyD,EACtEA,EAAU,UAAUwM,EAAOr6B,EAAO,KAAMmT,CAAM,IAE9C,QAAQ,KAAK,+CAA+C,EAC5D,QAAQ,KAAK,uBAAwB,OAAO,KAAK0a,CAAS,EAAE,OAAOia,GAAK,OAAOja,EAAUia,CAAC,GAAM,UAAU,CAAC,EAE/G,CAAC,EAGDzN,EAAM,OAAA,CACR,OAASxzB,EAAO,CACd,QAAQ,MAAM,2BAA4BA,CAAK,CACjD,CACF,EAAG,CAACwzB,EAAOl4B,EAAM,iBAAiB,CAAC,EAGnC4qB,EAAAA,UAAU,IAAM,CACd,GAAKsN,EAEL,GAAI,CAEF,QAAQ,KAAK,sCAAuC,CAClD,YAAal4B,EAAM,OAAO,OAC1B,OAAQA,EAAM,OAAO,IAAI2sB,IAAU,CACjC,GAAIA,EAAM,GACV,KAAMA,EAAM,KACZ,YAAa,aAAcA,EAC3B,cAAgB,aAAcA,GAASA,EAAM,SAAYA,EAAM,SAAS,OAAS,YACjF,YAAa,aAAcA,EAC3B,eAAgB,gBAAiBA,EACjC,YAAa,gBAAiBA,EAAQA,EAAM,YAAc,MAAA,EAC1D,CAAA,CACH,EAGDuL,EAAM,cAAA,EAG8C,CAAC,GAAGA,EAAM,WAAW,EACzD,QAAQruB,GAAO,CAC7BquB,EAAM,aAAaruB,CAAG,CACxB,CAAC,EAGD,MAAMi8B,EAAwC,CAAA,EAC9CrN,EAAiB,QAAU,CAAA,EAG3Bz4B,EAAM,OAAO,QAAQ2sB,GAAS,CAC5B,GAAIA,EAAM,OAAS,QACjB,GAAI,CACF,MAAM+N,EAAUqL,GACd7N,EACAvL,EACA3sB,EAAM,KACN0kC,EACAG,CAAA,EAEEnK,IACFoL,EAAiBnZ,EAAM,EAAE,EAAI+N,EAEjC,OAASh2B,EAAO,CACd,QAAQ,KAAK,gCAAgCioB,EAAM,EAAE,IAAKjoB,CAAK,CACjE,CAEJ,CAAC,EAGD,QAAQ,KAAK,2DAA2D,EACxE,QAAQ,KAAK,gCAAiCwzB,EAAM,YAAY,IAAKruB,IAAc,CACjF,GAAIA,EAAI,GACR,KAAMA,EAAI,KACV,KAAMA,EAAI,YAAA,EACV,CAAC,EAEH7J,EAAM,OAAO,QAAQ2sB,GAAS,CAC5B,GAAIA,EAAM,OAAS,QAAUA,EAAM,OAAS,UAAYA,EAAM,OAAS,UACrE,GAAI,CACF,MAAM+N,EAAUqL,GACd7N,EACAvL,EACA3sB,EAAM,KACN0kC,EACAG,CAAA,EAEEnK,IACFoL,EAAiBnZ,EAAM,EAAE,EAAI+N,EAEjC,OAASh2B,EAAO,CACd,QAAQ,KAAK,0BAA0BioB,EAAM,EAAE,IAAKjoB,CAAK,CAC3D,CAEJ,CAAC,EAGD,QAAQ,KAAK,2CAA2C,EACxD1E,EAAM,OAAO,QAAQ2sB,GAAS,CAC5B,GAAIA,EAAM,OAAS,OACjB,GAAI,CACF,MAAM+N,EAAUqL,GACd7N,EACAvL,EACA3sB,EAAM,KACN0kC,EACAG,CAAA,EAEEnK,IACFoL,EAAiBnZ,EAAM,EAAE,EAAI+N,EAEjC,OAASh2B,EAAO,CACd,QAAQ,KAAK,yBAAyBioB,EAAM,EAAE,IAAKjoB,CAAK,CAC1D,CAEJ,CAAC,EAED0/B,EAAiB0B,CAAgB,EAEjCrN,EAAiB,QAAUqN,EAC3BxB,EAAe,EAAI,EACnB,QAAQ,KAAK,iCAAiC,OAAO,KAAKwB,CAAgB,EAAE,MAAM,iBAAiB,EACnG5N,EAAM,gBAAA,CACR,OAASxzB,EAAO,CACd,QAAQ,MAAM,0BAA2BA,CAAK,CAChD,CACF,EAAG,CAACwzB,EAAOl4B,EAAM,OAAQA,EAAM,KAAM0kC,EAAmBG,CAAqB,CAAC,EAG9Eja,EAAAA,UAAU,IACD,IAAM,CACX,QAAQ,KAAK,yCAAyC,EAGlD4Z,EAAW,SACb,OAAO,QAAQC,EAAmB,OAAO,EAAE,QAAQ,CAAC,CAACmB,EAAa1sB,CAAQ,IAAM,CAC9E,GAAI,CACFsrB,EAAW,QAAQ,IAAI,OAAQtrB,CAAQ,EACvC,QAAQ,KAAK,0CAA0C0sB,CAAW,EAAE,CACtE,OAASlhC,EAAO,CACd,QAAQ,KAAK,sCAAsCkhC,CAAW,IAAKlhC,CAAK,CAC1E,CACF,CAAC,EAEH+/B,EAAmB,QAAU,CAAA,EAG7B,OAAO,OAAOF,EAAc,OAAO,EAAE,QAAS7Y,GAAmB,CAC/D,GAAI,CACEA,GAAaA,EAAU,QACzBA,EAAU,OAAA,CAEd,OAAShnB,EAAO,CACd,QAAQ,KAAK,6CAA8CA,CAAK,CAClE,CACF,CAAC,EACD6/B,EAAc,QAAU,CAAA,EACxB9L,EAAiB,QAAU,CAAA,EAC3B6L,EAAe,EAAK,EAEpB,QAAQ,KAAK,oBAAoB,CACnC,EACC,CAAA,CAAE,EAEE7hC,EAAAA,IAAC,MAAA,CAAI,IAAK0hC,EAAc,UAAU,gBAAgB,CAC3D,EAKA,SAAS4B,GACP7N,EACAvL,EACA2R,EACA0H,EACAC,EACY,CACZ,MAAMC,EAAa5H,IAAS,OAE5B,OAAQ3R,EAAM,KAAA,CACZ,IAAK,QACH,GAAI,CAeF,GAbA,QAAQ,KAAK,qBAAqBA,EAAM,EAAE,IAAK,CAC7C,GAAIA,EAAM,GACV,KAAMA,EAAM,KACZ,SAAUA,EAAM,SAChB,YAAa,aAAcA,EAC3B,aAAc,OAAOA,EAAM,SAC3B,gBAAiB,MAAM,QAAQA,EAAM,QAAQ,EAC7C,UAAWA,EAAM,UAAU,EAC3B,UAAWA,EAAM,UAAU,EAC3B,UAAW,MAAM,QAAQA,EAAM,QAAQ,EAAIA,EAAM,SAAS,CAAC,EAAI,OAC/D,UAAW,MAAM,QAAQA,EAAM,QAAQ,EAAIA,EAAM,SAAS,CAAC,EAAI,MAAA,CAChE,EAEG,CAACA,EAAM,SACT,eAAQ,MAAM,WAAWA,EAAM,EAAE,wBAAwB,EAClD,KAIT,IAAIV,EAAWC,EACf,GAAIS,EAAM,SAAS,IAAM,QAAaA,EAAM,SAAS,IAAM,OACzDV,EAAIU,EAAM,SAAS,EACnBT,EAAIS,EAAM,SAAS,UACV,MAAM,QAAQA,EAAM,QAAQ,GAAKA,EAAM,SAAS,QAAU,EACnEV,EAAIU,EAAM,SAAS,CAAC,EACpBT,EAAIS,EAAM,SAAS,CAAC,MAEpB,gBAAQ,MAAM,WAAWA,EAAM,EAAE,gCAAiCA,EAAM,QAAQ,EACzE,KAGT,MAAMwZ,EAAkCjO,EAAM,OAAO,QAAS,CAACjM,EAAGC,CAAC,EAAG,CACpE,GAAIS,EAAM,GACV,KAAMA,EAAM,MAAQ,GACpB,UAAWA,EAAM,WAAc,CAAC,CAACA,EAAM,KACvC,MAAO,CAACuZ,EACR,KAAMvZ,EAAM,MAAQ,EACpB,YAAaA,EAAM,aAAeA,EAAM,OAAS,QACjD,QAASA,EAAM,SAAW,GAE1B,MAAOA,EAAM,MAAQ,CACnB,OAAQA,EAAM,MAAM,QAAU,CAAC,GAAI,EAAE,EACrC,SAAUA,EAAM,MAAM,UAAY,GAClC,MAAOA,EAAM,MAAM,MACnB,QAASA,EAAM,MAAM,SAAW,SAChC,QAASA,EAAM,MAAM,SAAW,SAChC,SAAUA,EAAM,MAAM,SACtB,SAAUA,EAAM,MAAM,UAAY,MAClC,aAAcA,EAAM,MAAM,cAAgB,GAC1C,SAAUA,EAAM,MAAM,UAAY,GAAA,EAChC,MAAA,CACL,EAGD,eAAQ,KAAK,oBAAqB,CAChC,QAASA,EAAM,GACf,QAAUwZ,EAAc,GACxB,UAAYA,EAAc,KAC1B,cAAe,OAAQA,CAAA,CACxB,EAGGD,IAEFhO,EAAM,GAAG,OAAQ,IAAM,CACrB8N,EAAcrZ,EAAM,GAAI,CAAE,EAAIwZ,EAAc,EAAA,EAAK,EAAIA,EAAc,EAAA,CAAE,CAAG,CAC1E,CAAC,EAGDjO,EAAM,GAAG,OAAQ,IAAM,CACrB+N,EAAkBtZ,EAAM,EAAE,CAC5B,CAAC,GAGIwZ,CACT,OAASzhC,EAAO,CACd,eAAQ,MAAM,0BAA0BioB,EAAM,EAAE,IAAKjoB,CAAK,EACnD,IACT,CAEF,IAAK,OACH,MAAM0hC,EAAaC,GAAgB1Z,EAAM,MAAOuL,CAAK,EAC/CoO,EAAWD,GAAgB1Z,EAAM,IAAKuL,CAAK,EAEjD,GAAIkO,GAAcE,EAChB,GAAI,CACF,MAAMhyB,EAAO4jB,EAAM,OAAO,OAAQ,CAACkO,EAAYE,CAAQ,EAAG,CACxD,YAAa3Z,EAAM,aAAe,EAClC,YAAaA,EAAM,aAAeA,EAAM,OAAS,QACjD,KAAMA,EAAM,MAAQ,EACpB,MAAO,CAACuZ,EACR,QAASvZ,EAAM,SAAW,GAE1B,cAAe,GACf,aAAc,EAAA,CACf,EAGD,OAAIuZ,GACFhO,EAAM,GAAG,OAAQ,IAAM,CACrB+N,EAAkBtZ,EAAM,EAAE,CAC5B,CAAC,EAGIrY,CACT,OAAS5P,EAAO,CACd,eAAQ,MAAM,yBAAyBioB,EAAM,EAAE,IAAKjoB,CAAK,EAClD,IACT,MAEA,QAAQ,KAAK,sBAAsBioB,EAAM,EAAE,+BAAgC,CACzE,WAAY,CAAC,CAACyZ,EACd,SAAU,CAAC,CAACE,EACZ,SAAU3Z,EAAM,MAChB,OAAQA,EAAM,GAAA,CACf,EAEH,MAEF,IAAK,SACH,MAAM4Z,EAAcF,GAAgB1Z,EAAM,OAAQuL,CAAK,EAEvD,GAAIqO,EAAa,CACf,IAAIC,EAEJ,GAAI7Z,EAAM,QAAS,CACjB,MAAM8Z,EAAeJ,GAAgB1Z,EAAM,QAASuL,CAAK,EACrDuO,IACFD,EAAStO,EAAM,OAAO,SAAU,CAACqO,EAAaE,CAAY,EAAG,CAC3D,YAAa9Z,EAAM,aAAe,EAClC,YAAaA,EAAM,aAAeA,EAAM,OAAS,QACjD,UAAWA,EAAM,WAAa,OAC9B,YAAaA,EAAM,aAAe,GAClC,KAAMA,EAAM,MAAQ,EACpB,MAAO,CAACuZ,EACR,QAASvZ,EAAM,SAAW,EAAA,CAC3B,EAEL,MAAWA,EAAM,SAAW,SAC1B6Z,EAAStO,EAAM,OAAO,SAAU,CAACqO,EAAa5Z,EAAM,MAAM,EAAG,CAC3D,YAAaA,EAAM,aAAe,EAClC,YAAaA,EAAM,aAAeA,EAAM,OAAS,QACjD,UAAWA,EAAM,WAAa,OAC9B,YAAaA,EAAM,aAAe,GAClC,KAAMA,EAAM,MAAQ,EACpB,MAAO,CAACuZ,EACR,QAASvZ,EAAM,SAAW,EAAA,CAC3B,GAIH,OAAI6Z,GAAUN,GACZhO,EAAM,GAAG,OAAQ,IAAM,CACrB+N,EAAkBtZ,EAAM,EAAE,CAC5B,CAAC,EAGI6Z,CACT,CACA,MAEF,IAAK,UACH,GAAI,CAeF,GAdA,QAAQ,MAAM,uBAAuB7Z,EAAM,EAAE,IAAK,CAChD,GAAIA,EAAM,GACV,KAAMA,EAAM,KACZ,YAAa,aAAcA,EAC3B,SAAUA,EAAM,SAChB,gBAAiB,MAAM,QAAQA,EAAM,QAAQ,EAC7C,eAAgBA,EAAM,SAAWA,EAAM,SAAS,OAAS,YACzD,UAAW,OAAO,KAAKA,CAAK,EAC5B,YAAa,gBAAiBA,EAAQA,EAAM,YAAc,OAC1D,SAAU,aAAcA,EAAQA,EAAM,SAAW,OACjD,cAAe,KAAK,UAAUA,EAAO,KAAM,CAAC,CAAA,CAC7C,EAGG,CAACA,EAAM,SACT,eAAQ,MAAM,oBAAoBA,EAAM,EAAE,qCAAsC,KAAK,UAAUA,EAAO,KAAM,CAAC,CAAC,EACvG,KAGT,GAAI,CAAC,MAAM,QAAQA,EAAM,QAAQ,EAC/B,eAAQ,MAAM,oBAAoBA,EAAM,EAAE,6BAA8BA,EAAM,QAAQ,EAC/E,KAIT,MAAMb,EAAWa,EAAM,SAAS,IAAI,CAACG,EAAQrc,IAAU,CACrD,MAAMi2B,EAAe/Z,EAAM,eAAiBA,EAAM,eAAelc,CAAK,EAAI,KAC1E,OAAOk2B,GAA0B7Z,EAAQoL,EAAOwO,CAAY,CAC9D,CAAC,EASD,GANA,QAAQ,KAAK,cAAc/Z,EAAM,EAAE,sBAAuBb,CAAQ,EAClE,QAAQ,KAAK,cAAca,EAAM,EAAE,mBAAoBb,EAAS,IAAI8a,IAAM,CACxE,KAAM,OAAOA,EACb,QAAS,MAAM,QAAQA,CAAC,EACxB,MAAOA,CAAA,EACP,CAAC,EACC9a,EAAS,MAAMgB,GAAUA,IAAW,IAAI,EAAG,CAE7C,MAAM+Z,EAAqB,CACzB,YAAala,EAAM,aAAe,EAClC,YAAaA,EAAM,aAAeA,EAAM,OAAS,QACjD,UAAWA,EAAM,WAAa,YAC9B,YAAaA,EAAM,aAAe,GAClC,KAAMA,EAAM,MAAQ,EACpB,MAAO,CAACuZ,EACR,QAASvZ,EAAM,SAAW,EAAA,EAI5B,GAAIA,EAAM,eAAgB,CACxB,QAAQ,KAAK,2DAA2DA,EAAM,EAAE,IAAK,CACnF,eAAgBA,EAAM,eACtB,mBAAoB,OAAO,KAAKA,EAAM,cAAc,EACpD,mBAAoB,OAAOA,EAAM,cAAA,CAClC,EAID,MAAMma,EAA8B,CAAA,EAGhCna,EAAM,eAAe,YAAc,OACrCma,EAAuB,UAAYna,EAAM,eAAe,UAGxDma,EAAuB,UAAY,GAIrC,MAAMC,EAAmB,CAAA,EACzB,IAAIC,EAAiB,GAEjBra,EAAM,eAAe,SACvBoa,EAAY,OAASpa,EAAM,eAAe,OAC1Cqa,EAAiB,IAEfra,EAAM,eAAe,WACvBoa,EAAY,SAAWpa,EAAM,eAAe,SAC5Cqa,EAAiB,IAEfra,EAAM,eAAe,QACvBoa,EAAY,MAAQpa,EAAM,eAAe,MACzCqa,EAAiB,IAEfra,EAAM,eAAe,UACvBoa,EAAY,QAAUpa,EAAM,eAAe,QAC3Cqa,EAAiB,IAEfra,EAAM,eAAe,UACvBoa,EAAY,QAAUpa,EAAM,eAAe,QAC3Cqa,EAAiB,IAGfA,IACFF,EAAuB,MAAQC,GAGjCF,EAAc,SAAWC,EACzB,QAAQ,KAAK,qCAAsCA,CAAsB,CAC3E,MAEED,EAAc,SAAW,CAAE,UAAW,EAAA,EAGxC,QAAQ,KAAK,mCAAoCA,CAAa,EAC9D,MAAMI,EAAU/O,EAAM,OAAO,UAAWpM,EAAU+a,CAAa,EAC/D,eAAQ,KAAK,sBAAuBI,CAAO,EAC3C,QAAQ,KAAK,uBAAwBA,EAAQ,QAAQ,EACrD,QAAQ,KAAK,6BAA8BA,EAAQ,SAAWA,EAAQ,SAAS,IAAKL,GAAWA,EAAE,IAAI,EAAI,aAAa,EACtH,QAAQ,KAAK,8BAA+BK,EAAQ,SAAWA,EAAQ,SAAS,IAAKL,GAAWA,EAAE,SAAWA,EAAE,MAAQ,UAAU,EAAI,aAAa,EAG9IV,GACFhO,EAAM,GAAG,OAAQ,IAAM,CACrB+N,EAAkBtZ,EAAM,EAAE,CAC5B,CAAC,EAGIsa,CACT,MACE,QAAQ,KAAK,yBAAyBta,EAAM,EAAE,8BAA+B,CAC3E,SAAUA,EAAM,SAChB,iBAAkBb,CAAA,CACnB,CAEL,OAASpnB,EAAO,CACd,QAAQ,MAAM,4BAA4BioB,EAAM,EAAE,IAAKjoB,CAAK,CAC9D,CACA,MAEF,IAAK,OACH,GAAI,CACF,eAAQ,KAAK,oBAAoBioB,EAAM,EAAE,IAAK,CAC5C,GAAIA,EAAM,GACV,KAAMA,EAAM,KACZ,YAAa,aAAcA,EAC3B,SAAUA,EAAM,SAChB,UAAWA,EAAM,UAAU,EAC3B,UAAWA,EAAM,UAAU,EAC3B,WAAY,YAAaA,EACzB,QAASA,EAAM,QACf,UAAW,OAAO,KAAKA,CAAK,CAAA,CAC7B,EACYuL,EAAM,OAAO,OAAQ,CAACvL,EAAM,SAAS,EAAGA,EAAM,SAAS,EAAGA,EAAM,OAAO,EAAG,CACrF,MAAOA,EAAM,OAAS,QACtB,SAAUA,EAAM,UAAY,GAC5B,MAAO,GACP,QAASA,EAAM,SAAW,EAAA,CAC3B,CAGH,OAASjoB,EAAO,CACd,QAAQ,MAAM,yBAAyBioB,EAAM,EAAE,IAAKjoB,CAAK,CAC3D,CACA,KAAA,CAGJ,OAAO,IACT,CAMA,SAAS2hC,GAAgBa,EAAUhP,EAAmC,CAEpE,GAAI,MAAM,QAAQgP,CAAG,GAAKA,EAAI,QAAU,EACtC,OAAOA,EAGT,GAAI,OAAOA,GAAQ,UAAYA,IAAQ,KAAM,CAE3C,GAAI,MAAOA,GAAO,MAAOA,EACvB,MAAO,CAACA,EAAI,EAAGA,EAAI,CAAC,EAItB,GAAI,SAAUA,EACZ,GAAI,CAEF,GAAKhP,EAAc,SAAYA,EAAc,QAAQgP,EAAI,IAAI,EAAG,CAC9D,MAAMC,EAAmBjP,EAAc,QAAQgP,EAAI,IAAI,EACvD,GAAIC,EACF,OAAOA,CAEX,CAGA,MAAMA,EAAkBjP,EAAM,YAAY,KAAMruB,GAAaA,EAAI,KAAOq9B,EAAI,IAAI,EAEhF,GAAIC,EACF,eAAQ,KAAK,4BAA4BD,EAAI,IAAI,IAAKC,CAAe,EAC9DA,EAEP,QAAQ,KAAK,sBAAsBD,EAAI,IAAI,iCAAiC,CAEhF,OAASxiC,EAAO,CACd,QAAQ,KAAK,qCAAqCwiC,EAAI,IAAI,IAAKxiC,CAAK,CACtE,CAEJ,CAEA,OAAO,IACT,CAMA,SAASiiC,GAA0BO,EAAUhP,EAAuBwO,EAA+B,CAEjG,GAAI,MAAM,QAAQQ,CAAG,GAAKA,EAAI,QAAU,EAAG,CAEzC,GAAIR,GAAgBA,EAAa,KAAM,CACrC,MAAMP,EAAQjO,EAAM,OAAO,QAASgP,EAAK,CAAE,KAAMR,EAAa,KAAM,EACpE,eAAQ,KAAK,8BAA8BA,EAAa,IAAI,MAAOQ,CAAG,EAC/Df,CACT,CACA,OAAOe,CACT,CAEA,GAAI,OAAOA,GAAQ,UAAYA,IAAQ,KAAM,CAE3C,GAAI,MAAOA,GAAO,MAAOA,EAAK,CAC5B,MAAME,EAAS,CAACF,EAAI,EAAGA,EAAI,CAAC,EAE5B,GAAIR,GAAgBA,EAAa,KAAM,CACrC,MAAMP,EAAQjO,EAAM,OAAO,QAASkP,EAAQ,CAAE,KAAMV,EAAa,KAAM,EACvE,eAAQ,KAAK,8BAA8BA,EAAa,IAAI,MAAOU,CAAM,EAClEjB,CACT,CACA,OAAOiB,CACT,CAGA,GAAI,SAAUF,EACZ,GAAI,CAEF,GAAKhP,EAAc,SAAYA,EAAc,QAAQgP,EAAI,IAAI,EAAG,CAC9D,MAAMC,EAAmBjP,EAAc,QAAQgP,EAAI,IAAI,EACvD,GAAIC,EAEF,OAAIT,GAAgBA,EAAa,MAAQS,EAAgB,UACvDA,EAAgB,QAAQT,EAAa,IAAI,EACzC,QAAQ,KAAK,oBAAoBQ,EAAI,IAAI,YAAYR,EAAa,IAAI,EAAE,GAEnES,CAEX,CAGA,MAAMA,EAAkBjP,EAAM,YAAY,KAAMruB,GAAaA,EAAI,KAAOq9B,EAAI,IAAI,EAEhF,GAAIC,EACF,eAAQ,KAAK,4BAA4BD,EAAI,IAAI,IAAKC,CAAe,EAEjET,GAAgBA,EAAa,MAASS,EAAwB,UAC/DA,EAAwB,QAAQT,EAAa,IAAI,EAClD,QAAQ,KAAK,oBAAoBQ,EAAI,IAAI,YAAYR,EAAa,IAAI,EAAE,GAEnES,EAEP,QAAQ,KAAK,sBAAsBD,EAAI,IAAI,iCAAiC,CAEhF,OAASxiC,EAAO,CACd,QAAQ,KAAK,qCAAqCwiC,EAAI,IAAI,IAAKxiC,CAAK,CACtE,CAEJ,CAEA,OAAO,IACT,CChiCO,SAAS2iC,GACd5a,EACAzc,EAA8B,GACP,CACvB,KAAM,CACJ,QAAA0wB,EAAU,GACV,OAAA4G,EAAS,EAET,QAAAC,EAAU,CAAA,EACRv3B,EAGEw3B,EAAqB,CAAA,EA+D3B,GA7DA/a,EAAO,QAAQE,GAAS,CACtB,OAAQA,EAAM,KAAA,CACZ,IAAK,QACH6a,EAAU,KAAK7a,EAAM,QAAQ,EAC7B,MAEF,IAAK,OAEH,MAAMyZ,EAAaqB,GAAa9a,EAAM,MAAOF,CAAM,EAC7C6Z,EAAWmB,GAAa9a,EAAM,IAAKF,CAAM,EAC3C2Z,GAAYoB,EAAU,KAAKpB,CAAU,EACrCE,GAAUkB,EAAU,KAAKlB,CAAQ,EACrC,MAEF,IAAK,SAEH,MAAMC,EAAckB,GAAa9a,EAAM,OAAQF,CAAM,EAcrD,GAbI8Z,IACFiB,EAAU,KAAKjB,CAAW,EAEtB5Z,EAAM,SAAW,QACnB6a,EAAU,KACR,CAAE,EAAGjB,EAAY,EAAI5Z,EAAM,OAAQ,EAAG4Z,EAAY,CAAA,EAClD,CAAE,EAAGA,EAAY,EAAI5Z,EAAM,OAAQ,EAAG4Z,EAAY,CAAA,EAClD,CAAE,EAAGA,EAAY,EAAG,EAAGA,EAAY,EAAI5Z,EAAM,MAAA,EAC7C,CAAE,EAAG4Z,EAAY,EAAG,EAAGA,EAAY,EAAI5Z,EAAM,MAAA,CAAO,GAKtDA,EAAM,QAAS,CACjB,MAAM8Z,EAAegB,GAAa9a,EAAM,QAASF,CAAM,EACnDga,GAAce,EAAU,KAAKf,CAAY,CAC/C,CACA,MAEF,IAAK,UAEH9Z,EAAM,SAAS,QAAQG,GAAU,CAC/B,MAAMqZ,EAAQsB,GAAa3a,EAAQL,CAAM,EACrC0Z,GAAOqB,EAAU,KAAKrB,CAAK,CACjC,CAAC,EACD,MAEF,IAAK,OAEHqB,EAAU,KAAK7a,EAAM,QAAQ,EAE7B,MAAM+a,EAAa/a,EAAM,QAAQ,QAAUA,EAAM,UAAY,IAAO,GAC9Dgb,GAAchb,EAAM,UAAY,IAAM,GAC5C6a,EAAU,KACR,CAAE,EAAG7a,EAAM,SAAS,EAAI+a,EAAW,EAAG/a,EAAM,SAAS,CAAA,EACrD,CAAE,EAAGA,EAAM,SAAS,EAAI+a,EAAW,EAAG/a,EAAM,SAAS,CAAA,EACrD,CAAE,EAAGA,EAAM,SAAS,EAAG,EAAGA,EAAM,SAAS,EAAIgb,CAAA,EAC7C,CAAE,EAAGhb,EAAM,SAAS,EAAG,EAAGA,EAAM,SAAS,EAAIgb,CAAA,CAAW,EAE1D,KAAA,CAEN,CAAC,EAGGH,EAAU,SAAW,EACvB,MAAO,CACL,YAAa,CAAC,CAACD,EAASA,EAASA,EAAS,CAACA,CAAO,EAClD,OAAQ,CAAE,EAAG,EAAG,EAAG,CAAA,EACnB,MAAOA,EAAU,EACjB,OAAQA,EAAU,CAAA,EAKtB,MAAMlX,EAAO,KAAK,IAAI,GAAGmX,EAAU,IAAI/S,GAAKA,EAAE,CAAC,CAAC,EAC1CnE,EAAO,KAAK,IAAI,GAAGkX,EAAU,IAAI/S,GAAKA,EAAE,CAAC,CAAC,EAC1ClE,EAAO,KAAK,IAAI,GAAGiX,EAAU,IAAI/S,GAAKA,EAAE,CAAC,CAAC,EAC1CjE,EAAO,KAAK,IAAI,GAAGgX,EAAU,IAAI/S,GAAKA,EAAE,CAAC,CAAC,EAG1CmT,GAAWvX,EAAOC,GAAQ,EAC1BuX,GAAWtX,EAAOC,GAAQ,EAGhC,IAAIsX,EAAQ,KAAK,IAAIxX,EAAOD,EAAMkX,CAAO,EACrCje,EAAS,KAAK,IAAIkH,EAAOD,EAAMgX,CAAO,EAG1C,MAAMQ,EAAoB,IAAM,IAC1BC,EAAeF,EAAQxe,EAEzB,KAAK,IAAI0e,EAAeD,CAAiB,EAAI,KAC3CC,EAAeD,EAEjBze,EAASwe,EAAQC,EAGjBD,EAAQxe,EAASye,GAKrB,MAAME,EAAcH,GAAS,EAAIpH,GAAW4G,EAAS,EAC/CY,EAAe5e,GAAU,EAAIoX,GAAW4G,EAAS,EAGjD/Z,EAAOqa,EAAUK,EAAc,EAC/Bza,EAAMqa,EAAUK,EAAe,EAC/Bza,EAAQma,EAAUK,EAAc,EAChCva,EAASma,EAAUK,EAAe,EAGlCC,EAAqD,CAAC5a,EAAMC,EAAKC,EAAOC,CAAM,EAGpF,GAAI,QAAQ,IAAI,WAAa,cAAe,CAS1C,MAAM0a,EARmBZ,EAAU,IAAI/S,IAAM,CAC3C,EAAGA,EAAE,EACL,EAAGA,EAAE,EACL,QAASA,EAAE,GAAKlH,GAAQkH,EAAE,GAAKhH,EAC/B,QAASgH,EAAE,GAAKjH,GAAOiH,EAAE,GAAK/G,EAC9B,OAAQ+G,EAAE,GAAKlH,GAAQkH,EAAE,GAAKhH,GAASgH,EAAE,GAAKjH,GAAOiH,EAAE,GAAK/G,CAAA,EAC5D,EAEqC,OAAO+G,GAAK,CAACA,EAAE,MAAM,EACxD2T,EAAc,OAAS,GACzB,QAAQ,KAAK,yBAA0B,CACrC,YAAaD,EACb,cAAeC,EAAc,MAAM,EAAG,CAAC,EACvC,aAAcA,EAAc,MAAA,CAC7B,CAEL,CAEA,MAAO,CACL,YAAaD,EACb,OAAQ,CAAE,EAAGP,EAAS,EAAGC,CAAA,EACzB,MAAOI,EACP,OAAQC,CAAA,CAEZ,CAKO,SAAST,GAAaP,EAAUza,EAAkB,GAAkB,CACzE,GAAI,OAAOya,GAAQ,UAAYA,IAAQ,KAAM,CAE3C,GAAI,MAAOA,GAAO,MAAOA,EACvB,MAAO,CAAE,EAAGA,EAAI,EAAG,EAAGA,EAAI,CAAA,EAI5B,GAAI,SAAUA,EAAK,CACjB,MAAMC,EAAkB1a,EAAO,KAAKhK,GAAKA,EAAE,KAAOykB,EAAI,MAAQzkB,EAAE,OAAS,OAAO,EAChF,GAAI0kB,EACF,OAAOA,EAAgB,QAE3B,CACF,CACA,OAAO,IACT,CCzLO,SAASkB,GAAiB5b,EAAiB6b,EAAgB,QAAS,CACzE,QAAQ,MAAM,MAAMA,CAAK,YAAY,EAGrC,MAAMd,EAAsD,CAAA,EAgD5D,GA9CA/a,EAAO,QAAQE,GAAS,CACtB,OAAQA,EAAM,KAAA,CACZ,IAAK,QACH6a,EAAU,KAAK,CACb,EAAG7a,EAAM,SAAS,EAClB,EAAGA,EAAM,SAAS,EAClB,OAAQ,SAASA,EAAM,EAAE,EAAA,CAC1B,EACD,MAEF,IAAK,OACH6a,EAAU,KAAK,CACb,EAAG7a,EAAM,SAAS,EAClB,EAAGA,EAAM,SAAS,EAClB,OAAQ,QAAQA,EAAM,EAAE,EAAA,CACzB,EAED,MAAM+a,EAAa/a,EAAM,QAAQ,QAAUA,EAAM,UAAY,IAAO,GAC9Dgb,GAAchb,EAAM,UAAY,IAAM,GAC5C6a,EAAU,KACR,CAAE,EAAG7a,EAAM,SAAS,EAAI+a,EAAW,EAAG/a,EAAM,SAAS,EAAG,OAAQ,QAAQA,EAAM,EAAE,QAAA,EAChF,CAAE,EAAGA,EAAM,SAAS,EAAI+a,EAAW,EAAG/a,EAAM,SAAS,EAAG,OAAQ,QAAQA,EAAM,EAAE,OAAA,EAChF,CAAE,EAAGA,EAAM,SAAS,EAAG,EAAGA,EAAM,SAAS,EAAIgb,EAAY,OAAQ,QAAQhb,EAAM,EAAE,MAAA,EACjF,CAAE,EAAGA,EAAM,SAAS,EAAG,EAAGA,EAAM,SAAS,EAAIgb,EAAY,OAAQ,QAAQhb,EAAM,EAAE,SAAA,CAAU,EAE7F,MAEF,IAAK,UAEHA,EAAM,SAAS,QAAQ,CAACG,EAAQrc,IAAU,CACxC,MAAM01B,EAAQsB,GAAa3a,EAAQL,CAAM,EACrC0Z,GACFqB,EAAU,KAAK,CACb,EAAGrB,EAAM,EACT,EAAGA,EAAM,EACT,OAAQ,WAAWxZ,EAAM,EAAE,UAAUlc,CAAK,EAAA,CAC3C,CAEL,CAAC,EACD,KAAA,CAEN,CAAC,EAED,QAAQ,IAAI,cAAe+2B,CAAS,EAGhCA,EAAU,OAAS,EAAG,CACxB,MAAMnX,EAAO,KAAK,IAAI,GAAGmX,EAAU,IAAI/S,GAAKA,EAAE,CAAC,CAAC,EAC1CnE,EAAO,KAAK,IAAI,GAAGkX,EAAU,IAAI/S,GAAKA,EAAE,CAAC,CAAC,EAC1ClE,EAAO,KAAK,IAAI,GAAGiX,EAAU,IAAI/S,GAAKA,EAAE,CAAC,CAAC,EAC1CjE,EAAO,KAAK,IAAI,GAAGgX,EAAU,IAAI/S,GAAKA,EAAE,CAAC,CAAC,EAEhD,QAAQ,IAAI,YAAa,CACvB,KAAApE,EAAM,KAAAC,EAAM,KAAAC,EAAM,KAAAC,EAClB,MAAOF,EAAOD,EACd,OAAQG,EAAOD,CAAA,CAChB,CACH,CAGA,MAAMhoB,EAAS8+B,GAAqB5a,EAAQ,CAC1C,QAAS,GACT,OAAQ,EACR,QAAS,CAAA,CACV,EAED,eAAQ,IAAI,gBAAiBlkB,CAAM,EAEnC,QAAQ,SAAA,EAEDA,CACT,CC3EO,MAAMggC,GAAuCvoC,GAAU,CAC5D,KAAM,CACJ,OAAAysB,EACA,KAAA6R,EACA,cAAA0H,EACA,kBAAAC,EACA,MAAA6B,EAAQ,IACR,OAAAxe,EAAS,IACT,SAAAkf,EAAW,GACX,SAAAC,EAAW,GACX,UAAApmC,EAAY,GACZ,YAAA0iC,EACA,gBAAA2D,EAAkB,GAClB,mBAAAC,EACA,UAAAxb,EACA,kBAAAyb,EACA,kBAAAC,EACA,sBAAuBC,CAAA,EACrB9oC,EAGE+oC,EAAwBhe,EAAAA,QAAQ,IAAM,CAC1C,GAAIga,EACF,OAAOA,EAGT,GAAI2D,GAAmBjc,EAAO,OAAS,EACrC,GAAI,CAEE,QAAQ,IAAI,WAAa,eAC3B4b,GAAiB5b,EAAQ,4BAA4B,EAGvD,MAAMlkB,EAAS8+B,GAAqB5a,EAAQkc,CAAkB,EAC9D,eAAQ,IAAI,kCAAkC,EAC9C,QAAQ,IAAI,mBAAoBpgC,EAAO,WAAW,EAClD,QAAQ,IAAI,cAAeA,EAAO,MAAM,EACxC,QAAQ,IAAI,aAAcA,EAAO,KAAK,EACtC,QAAQ,IAAI,cAAeA,EAAO,MAAM,EACxC,QAAQ,IAAI,oBAAqBogC,CAAkB,EAC5CpgC,EAAO,WAChB,OAAS7D,EAAO,CACd,eAAQ,KAAK,wDAAyDA,CAAK,EACpE,CAAC,IAAK,GAAI,GAAI,GAAG,CAC1B,CAGF,MAAO,CAAC,IAAK,GAAI,GAAI,GAAG,CAC1B,EAAG,CAACqgC,EAAa2D,EAAiBjc,EAAQkc,CAAkB,CAAC,EAEvDK,EAAiBje,EAAAA,QAAQ,KAAO,CACpC,MAAO,OAAO+c,GAAU,SAAW,GAAGA,CAAK,KAAOA,EAClD,OAAQ,OAAOxe,GAAW,SAAW,GAAGA,CAAM,KAAOA,CAAA,GACnD,CAACwe,EAAOxe,CAAM,CAAC,EAEnB,aACGsY,GAAA,CACC,SAAAn/B,EAAAA,IAAC,MAAA,CACC,UAAW,wEAAwEJ,CAAS,GAC5F,MAAO2mC,EACP,cAAY,YACZ,KAAK,cACL,aAAW,SAEX,SAAAvmC,EAAAA,IAACyhC,GAAA,CACC,OAAAzX,EACA,KAAA6R,EACA,cAAA0H,EACA,kBAAAC,EACA,YAAa8C,EACb,SAAAP,EACA,SAAAC,EACA,UAAAtb,EACA,kBAAAyb,EACA,kBAAAC,CAAA,CAAA,CACF,CAAA,EAEJ,CAEJ,ECxFaI,GAA4C,CAAC,CACxD,OAAAxc,EACA,MAAAqb,EACA,OAAAxe,EACA,SAAAkf,EAAW,GACX,SAAAC,EAAW,GACX,YAAA1D,EACA,gBAAA2D,EACA,cAAA1C,EACA,UAAA3jC,EAAY,GAEZ,UAAA8qB,EACA,kBAAAyb,EACA,sBAAAM,EACA,kBAAAL,CACF,IAAM,CACJ,MAAM1E,EAAejO,EAAAA,OAAuB,IAAI,EAC1C,CAACkC,EAAeC,CAAgB,EAAIP,EAAAA,SAAS,CAAE,MAAO,IAAK,OAAQ,IAAK,EAG9ElN,EAAAA,UAAU,IAAM,CACd,MAAMgO,EAAa,IAAM,CACvB,GAAIuL,EAAa,QAAS,CACxB,KAAM,CAAE,YAAAtL,EAAa,aAAAsQ,CAAA,EAAiBhF,EAAa,QAC/CtL,EAAc,GAAKsQ,EAAe,GACpC9Q,EAAiB,CAAE,MAAOQ,EAAa,OAAQsQ,EAAc,CAEjE,CACF,EAEAvQ,EAAA,EAGA,OAAO,iBAAiB,SAAUA,CAAU,EAG5C,MAAMM,EAAiB,IAAI,eAAeN,CAAU,EACpD,OAAIuL,EAAa,SACfjL,EAAe,QAAQiL,EAAa,OAAO,EAGtC,IAAM,CACX,OAAO,oBAAoB,SAAUvL,CAAU,EAC/CM,EAAe,WAAA,CACjB,CACF,EAAG,CAAA,CAAE,EAGL,MAAM8P,EAAiB,CACrB,MAAOlB,EAAS,OAAOA,GAAU,SAAWA,EAAQ,GAAGA,CAAK,KAAQ,OACpE,OAAQxe,EAAU,OAAOA,GAAW,SAAWA,EAAS,GAAGA,CAAM,KAAQ,MAAA,EAG3E,OACE7mB,EAAAA,IAAC,MAAA,CACC,IAAK0hC,EACL,UAAW,qBAAqB9hC,CAAS,GACzC,MAAO2mC,EAEP,SAAAvmC,EAAAA,IAAC8lC,GAAA,CACC,OAAA9b,EACA,MAAO2L,EAAc,MACrB,OAAQA,EAAc,OACtB,SAAAoQ,EACA,SAAAC,EACA,YAAA1D,EACA,gBAAA2D,EACA,cAAA1C,EACA,KAAK,OACL,cAAY,YAEZ,UAAA7Y,EACA,kBAAAyb,EACA,sBAAAM,EACA,kBAAAL,CAAA,CAAA,CACF,CAAA,CAGN,EC9EaO,GAAoE,CAAC,CAChF,OAAAvrC,EACA,kBAAA65B,EACA,oBAAAC,EACA,QAAAC,EACA,cAAAV,EACA,YAAAC,EACA,WAAAK,EACA,UAAAn1B,EAAY,EACd,IAAM,CACJ,MAAMgnC,EAAyBnS,GAAiBr5B,EAAO,IAAI,eAAiB,UACtEyrC,EAAuBnS,GAAet5B,EAAO,IAAI,aAAe,IAChE0rC,EAAsB/R,GAAc35B,EAAO,IAAI,YAAc,IAG7D2rC,EAAyBvnC,GAAqB,CAClDy1B,IAAoBz1B,CAAQ,CAC9B,EAGMwnC,EAA0B,IAAM,CACpC9R,IAAA,CACF,EAGM+R,EAAehlC,GAAe,CAClCkzB,IAAUlzB,CAAK,CACjB,EAEE,eAAQ,MAAM,wCAAyC,CACrD,KAAM7G,EAAO,KACb,OAAQA,EAAO,OACf,KAAMA,EAAO,KACb,OAAQA,EAAO,OACf,qBAAsBA,EAAO,QAAQ,UAAU,OAC/C,mBAAoBA,EAAO,QAAQ,QAAQ,OAC3C,UAAWA,EAAO,UAClB,UAAWA,EAAO,UAClB,YAAaA,EAAO,YACpB,gBAAiBA,EAAO,YAAc,OAAO,KAAKA,EAAO,WAAW,EAAI,CAAA,EACxE,uBAAwBA,EAAO,aAAa,YAC5C,mBAAoBA,EAAO,aAAa,QACxC,mBAAoBA,EAAO,aAAa,QACxC,WAAY,OAAO,KAAKA,CAAM,CAAA,CAC/B,EAGD4E,EAAAA,IAAC,MAAA,CACC,UAAW,kCAAkCJ,CAAS,GACtD,MAAO,CACL,MAAO,OACP,QAAS,OACT,eAAgB,SAChB,WAAY,QAAA,EAEd,cAAY,qBAEZ,SAAAI,EAAAA,IAACw0B,GAAA,CACC,KAAMp5B,EAAO,KACb,OAAQA,EAAO,OACf,KAAMA,EAAO,KACb,OAAQA,EAAO,OACf,UAAWA,EAAO,UAClB,UAAWA,EAAO,UAClB,YAAaA,EAAO,YACpB,kBAAmB2rC,EACnB,oBAAqBC,EACrB,QAASC,EACT,cAAeL,EACf,YAAaC,EACb,WAAYC,EACZ,yBAA0B,GAC1B,2BAA4B,GAC5B,sBAAuB,IACvB,MAAM,OAAA,CAAA,CACR,CAAA,CAGN,EClEMI,GAAkD,CAAC,CACvD,QAAAn2B,EACA,OAAAo2B,EACA,OAAAC,EAAS,CAAA,CACX,IAAM,CACJ,KAAM,CACJ,SAAAC,EAAW,UACX,QAAAC,EAAU,UACV,YAAAC,EAAc,SAAA,EACZH,EAGJ,OAAIr2B,EAAQ,SAAWo2B,EAAO,QAC5B,QAAQ,KAAK,qDAAqD,EAC3D,MAIPxmC,EAAAA,KAAC,MAAA,CACC,UAAU,oBACV,MAAO,CACL,QAAS,eACT,OAAQ,aAAa4mC,CAAW,GAChC,aAAc,MACd,SAAU,SACV,WAAY,wBACZ,SAAU,OACV,WAAY,KAAA,EAGd,SAAA,CAAAvnC,EAAAA,IAAC,MAAA,CACC,MAAO,CACL,QAAS,OACT,aAAc,aAAaunC,CAAW,EAAA,EAGvC,SAAAx2B,EAAQ,IAAI,CAACiB,EAAQhE,IACpBhO,EAAAA,IAAC,MAAA,CAEC,MAAO,CACL,KAAM,EACN,QAAS,WACT,gBAAiBqnC,EACjB,WAAY,MACZ,UAAW,SACX,YAAar5B,EAAQ+C,EAAQ,OAAS,EAAI,aAAaw2B,CAAW,GAAK,OACvE,MAAO,SAAA,EAGR,SAAAv1B,CAAA,EAXIhE,CAAA,CAaR,CAAA,CAAA,EAEHhO,EAAAA,IAAC,MAAA,CACC,MAAO,CACL,QAAS,MAAA,EAGV,SAAAmnC,EAAO,IAAI,CAAC3qC,EAAOwR,IAClBhO,EAAAA,IAAC,MAAA,CAEC,MAAO,CACL,KAAM,EACN,QAAS,OACT,gBAAiBsnC,EACjB,UAAW,SACX,YAAat5B,EAAQm5B,EAAO,OAAS,EAAI,aAAaI,CAAW,GAAK,OACtE,MAAO,UACP,SAAU,OACV,WAAY,KAAA,EAGb,SAAA/qC,CAAA,EAZIwR,CAAA,CAcR,CAAA,CAAA,CACH,CAAA,CAAA,CAGN,ECrFaw5B,GAAkD,CAAC,CAC9D,QAAAj/B,EACA,cAAA02B,CACF,IAAM,CACJ,MAAMwI,EAAqB,CAACC,EAAqB15B,IAAkB,CAEjE,GAAI05B,EAAM,UAAY,GACpB,OAAO,KAGT,MAAMC,EAAY,GAAGD,EAAM,IAAI,IAAI15B,CAAK,GAElC45B,EAAqBC,GAAqB,CAC9C5I,IAAgB0I,EAAWE,CAAW,CACxC,EAEA,OAAQH,EAAM,KAAA,CACZ,IAAK,OACH,OACE1nC,EAAAA,IAACg/B,GAAA,CAEC,QAAS0I,EAAM,QACf,MAAOA,EAAM,MACb,cAAeE,CAAA,EAHVD,CAAA,EAMX,IAAK,UAEH,MAAMG,EAAeJ,EACrB,OACE1nC,EAAAA,IAACk/B,GAAA,CAEC,MAAO4I,EAAa,OAAS,CAAA,EAC7B,YAAaA,EAAa,YAC1B,MAAOJ,EAAM,KAAA,EAHRC,CAAA,EAMX,IAAK,QAEH,MAAMI,EAAaL,EACnB,OACE1nC,EAAAA,IAACwmC,GAAA,CAEC,OAAQuB,EAAW,QAAU,CAAA,EAC7B,MAAOA,EAAW,MAClB,OAAQA,EAAW,OACnB,SAAUA,EAAW,SACrB,SAAUA,EAAW,SACrB,YAAaA,EAAW,aAAa,YACrC,gBAAiB,CAACA,EAAW,aAAa,YAE1C,UAAWA,EAAW,UACtB,kBAAmBA,EAAW,kBAC9B,sBAAuBA,EAAW,sBAClC,kBAAmBA,EAAW,iBAAA,EAZzBJ,CAAA,EAeX,IAAK,cAEH,MAAMK,EAAmBN,EACzB,OACE1nC,EAAAA,IAAC47B,GAAA,CAEE,GAAGoM,EAAiB,KAAA,EADhBL,CAAA,EAIX,IAAK,kBAEH,MAAMM,EAAuBP,EAC7B,OACE1nC,EAAAA,IAACknC,GAAA,CAEE,GAAGe,EAAqB,KAAA,EADpBN,CAAA,EAIX,IAAK,oBAEH,MAAMO,EAAyBR,EAC/B,eAAQ,IAAI,+CAAgD,CAC1D,SAAUQ,EAAuB,SACjC,OAAQA,EAAuB,UAAU,OACzC,UAAW,CAAC,CAACA,EAAuB,UAAU,OAC9C,WAAYA,EAAuB,UAAU,OAAS,OAAO,KAAKA,EAAuB,SAAS,MAAM,EAAI,CAAA,EAC5G,aAAcA,EAAuB,UAAU,QAAQ,OACvD,2BAA4BA,EAAuB,UAAU,QAAQ,QAAQ,UAAU,OACvF,yBAA0BA,EAAuB,UAAU,QAAQ,QAAQ,QAAQ,OACnF,WAAYA,EAAuB,UAAU,QAAQ,KACrD,aAAcA,EAAuB,UAAU,QAAQ,OACvD,WAAYA,EAAuB,UAAU,QAAQ,KACrD,gBAAiBA,EAAuB,UAAU,QAAQ,SAAA,CAC3D,EAECloC,EAAAA,IAAC2mC,GAAA,CAEC,OAAQuB,EAAuB,SAAS,OACxC,kBAAoB1oC,GAAaooC,EAAkB,CAAE,KAAM,kBAAmB,SAAApoC,EAAU,EACxF,oBAAqB,IAAMooC,EAAkB,CAAE,KAAM,oBAAqB,EAC1E,QAAU3lC,GAAU2lC,EAAkB,CAAE,KAAM,QAAS,MAAA3lC,EAAO,CAAA,EAJzD0lC,CAAA,EAOX,QACE,OACE3nC,EAAAA,IAAC,MAAA,CAAoB,QAAS,IAAM4nC,EAAkB,CAAE,KAAM,OAAA,CAAS,EACpE,SAAAF,EAAM,OAAA,EADCC,CAEV,CAAA,CAGR,EAEA,OAAO3nC,EAAAA,IAAAiD,EAAAA,SAAA,CAAG,SAAAsF,EAAQ,IAAIk/B,CAAkB,EAAE,CAC5C,ECzGaU,GAcT,CAAC,CACH,KAAAnmC,EACA,MAAA87B,EAAQ,WACR,OAAAsK,EAAS,CAAE,KAAM,MAAA,EACjB,SAAAC,EAAW,CAAE,KAAM,SAAA,EACnB,MAAA1T,EAAQ,QACR,qBAAA2T,EACA,UAAA1oC,EAAY,GACZ,SAAAvB,CACF,IAAM,CAEJ,MAAMkqC,EAAc1K,GAAe77B,EAAM87B,CAAK,EAGxC0K,EAAe,CACnB,KAAMD,EACN,MAAAzK,EACA,OAAQyK,EAAY,QAAUH,EAC9B,SAAUG,EAAY,UAAYF,EAClC,MAAA1T,EACA,qBAAA2T,CAAA,EAIIG,EAAgBF,EAAY,QAAUH,EACtCM,GAAmB,IAAM,CAC7B,OAAQD,EAAc,KAAA,CACpB,IAAK,OACH,OAAOlK,GACT,IAAK,OACH,OAAOK,GAET,QACE,OAAOZ,EAAA,CAEb,GAAA,EAGM2K,GAAe,IAAM,CACzB,MAAMC,EAAY,CAChB,UAAAhpC,EACA,MAAA+0B,EACA,cAAe,uBAAA,EAGjB,OAAQ8T,EAAc,KAAA,CACpB,IAAK,OACH,MAAO,CACL,GAAGG,EACH,QAASH,EAAc,SAAW,EAClC,IAAKA,EAAc,KAAO,OAC1B,WAAYA,EAAc,aAAe,EAAA,EAE7C,IAAK,OACH,MAAO,CACL,GAAGG,EACH,UAAWH,EAAc,WAAa,WACtC,IAAKA,EAAc,KAAO,OAC1B,KAAMA,EAAc,OAAS,EAAA,EAGjC,QACE,MAAO,CACL,GAAGG,EACH,QAASH,EAAc,SAAW,OAClC,OAAQA,EAAc,SAAW,GACjC,OAAQA,EAAc,SAAW,EAAA,CACnC,CAEN,GAAA,EAEA,OACEzoC,EAAAA,IAAC49B,GAAkB,SAAlB,CAA2B,MAAO4K,EACjC,SAAAxoC,EAAAA,IAAC0oC,EAAA,CAAiB,GAAGC,EAClB,SAAAtqC,GACC2B,EAAAA,IAACwnC,GAAA,CACC,QAASe,EAAY,QACrB,OAAQA,EAAY,QAAUH,EAC9B,cAAeE,CAAA,CAAA,EAGrB,CAAA,CACF,CAEJ,EAGAH,GAAW,WAAanK,GACxBmK,GAAW,WAAa5J,GACxB4J,GAAW,WAAavJ,GACxBuJ,GAAW,YAAcnJ,GACzBmJ,GAAW,eAAiBjJ,GAC5BiJ,GAAW,aAAe3B,GAC1B2B,GAAW,yBAA2BxB,GACtCwB,GAAW,gBAAkBX,GCxFtB,MAAMqB,GAAeztC,GAAkD,CAC5E,KAAM,CAAE,UAAA0tC,EAAW,eAAAC,EAAgB,SAAAC,CAAA,EAAa5tC,EAG1C6tC,EAAU3gB,EAAAA,QAAQ,IAClBwgB,EAAU,MACLA,EAAU,MAI4C,CAC7D,SAAU,KACV,OAAQ,KACR,MAAO,IAAA,EAGYA,EAAU,IAAI,GAAKA,EAAU,KACjD,CAACA,EAAU,MAAOA,EAAU,IAAI,CAAC,EAG9BI,EAAW5gB,EAAAA,QAAQ,IAAM,CAC7B,GAAIwgB,EAAU,SACZ,OAAOA,EAAU,SAInB,MAAMK,EAA6B,CACjC,SAAU,qCACV,OAAQ,mCACR,MAAO,iCAAA,EAGT,OAAOA,EAAcL,EAAU,IAAI,GAAKK,EAAc,QACxD,EAAG,CAACL,EAAU,SAAUA,EAAU,IAAI,CAAC,EAGjCM,EAAe9gB,EAAAA,QAAQ,IACvBwgB,EAAU,aACLA,EAAU,aAGZ,qCACN,CAACA,EAAU,YAAY,CAAC,EAGrBO,EAAW/gB,EAAAA,QAAQ,IAAM,CAC7B,GAAI,CAACygB,EACH,MAAO,CAAA,EAGT,MAAMlS,EAAiC,CACrC,gBAAiBqS,EACjB,MAAOE,EACP,SAAU,iCACV,WAAY,iCAAA,EAGd,OAAIJ,EAEF,OAAO,OAAOnS,EAAW,CACvB,OAAQ,qCACR,aAAc,mDACd,MAAO,OACP,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,SAAU,WACV,OAAQ,CAAA,CACT,EAGD,OAAO,OAAOA,EAAW,CACvB,MAAO,6BACP,aAAc,4CACd,OAAQ,OACR,SAAU,WACV,KAAM,EACN,IAAK,EACL,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,YAAa,cACb,gBAAiB,QACjB,UAAW,cAAA,CACZ,EAGIA,CACT,EAAG,CAACkS,EAAgBG,EAAUE,EAAcJ,CAAQ,CAAC,EAG/CM,EAAehhB,EAAAA,QAAQ,IACvB,CAACygB,GAAkBC,EACd,CAAA,EAIF,CACL,YAAa,8DAAA,EAEd,CAACD,EAAgBC,CAAQ,CAAC,EAuB7B,MAAO,CACL,aArBmB1gB,EAAAA,QAAQ,IAAM,CACjC,GAAI,CAACygB,EACH,MAAO,GAGT,MAAMtkC,EAAU,CAAC,YAAY,EAG7B,OAAAA,EAAQ,KAAK,YAAYqkC,EAAU,IAAI,EAAE,EAGrCE,EACFvkC,EAAQ,KAAK,mBAAmB,EAEhCA,EAAQ,KAAK,oBAAoB,EAG5BA,EAAQ,KAAK,GAAG,CACzB,EAAG,CAACskC,EAAgBD,EAAU,KAAME,CAAQ,CAAC,EAI3C,SAAAK,EACA,aAAAC,EACA,QAAAL,EACA,SAAAC,EACA,aAAAE,CAAA,CAEJ,EC9IMG,GAAW,CACfC,EACAC,IACuC,CACvC,IAAIvuB,EAAiC,KAErC,MAAO,IAAI3E,IAAwB,CAC7B2E,GACF,aAAaA,CAAO,EAGtBA,EAAU,WAAW,IAAM,CACzBsuB,EAAK,GAAGjzB,CAAI,CACd,EAAGkzB,CAAI,CACT,CACF,EAWaC,GAAgB,CAC3BtuC,EAAuC,KACd,CAEzB,MAAMuuC,EAAa,OAAOvuC,GAAW,SAAWA,EAASA,EAAO,YAAc,IACxEwuC,EAAU,OAAOxuC,GAAW,SAAW,GAAOA,EAAO,UAAY,GAGjE,CAACyuC,EAAeC,CAAgB,EAAIzU,EAAAA,SAAiB,IACrD,OAAO,OAAW,IACb,OAAO,WAET,IACR,EAEK,CAAC2T,EAAUe,CAAW,EAAI1U,EAAAA,SAAkB,IAC5C,OAAO,OAAW,IACb,OAAO,WAAasU,EAEtB,EACR,EAGKK,EAAevW,EAAAA,OAAwB,IAAI,GAAK,EAGhDwW,EAAiBtW,EAAAA,YAAY,IAAM,CACvC,GAAI,OAAO,OAAW,IACpB,OAGF,MAAMlF,EAAW,OAAO,WAClByb,EAAczb,EAAWkb,EAE/BG,EAAiBrb,CAAQ,EACzBsb,EAAYG,CAAW,EAGvBF,EAAa,QAAQ,QAAQvzB,GAAY,CACvC,GAAI,CACFA,EAAA,CACF,OAASxU,EAAO,CACd,QAAQ,MAAM,4BAA6BA,CAAK,CAClD,CACF,CAAC,CACH,EAAG,CAAC0nC,CAAU,CAAC,EAGTQ,EAA0BxW,EAAAA,YAC9B4V,GAASU,EAAgB,GAAG,EAC5B,CAACA,CAAc,CAAA,EAIjB9hB,EAAAA,UAAU,IAAM,CACd,GAAI,GAACyhB,GAAW,OAAO,OAAW,KAKlC,OAAAK,EAAA,EAGA,OAAO,iBAAiB,SAAUE,CAAuB,EAGlD,IAAM,CACX,OAAO,oBAAoB,SAAUA,CAAuB,CAC9D,CACF,EAAG,CAACP,EAASO,EAAyBF,CAAc,CAAC,EAGrD,MAAMG,EAAoBzW,cAAald,IACrCuzB,EAAa,QAAQ,IAAIvzB,CAAQ,EAG1B,IAAM,CACXuzB,EAAa,QAAQ,OAAOvzB,CAAQ,CACtC,GACC,CAAA,CAAE,EAGC4zB,EAAuB1W,cAAald,GAAyB,CACjEuzB,EAAa,QAAQ,OAAOvzB,CAAQ,CACtC,EAAG,CAAA,CAAE,EAEL,MAAO,CACL,SAAAuyB,EACA,cAAAa,EACA,kBAAAO,EACA,qBAAAC,CAAA,CAEJ,EC5GaC,GAA4C,CAAC,CACxD,UAAAC,EACA,UAAAzB,EACA,eAAAC,EAAiB,GACjB,YAAAyB,EAAc,WACd,iBAAAC,EAAmB,IACnB,UAAA7qC,EAAY,GACZ,MAAA4C,EACA,SAAAnE,EACA,mBAAAqsC,CACF,IAAM,CAEJ,MAAMhM,EAAagL,GAAce,CAAgB,EAG3CE,EAAW9B,GAAY,CAC3B,UAAAC,EACA,eAAAC,EACA,SAAUrK,EAAW,QAAA,CACtB,EAGDvW,EAAAA,UAAU,IAAM,CACduiB,IAAqBhM,EAAW,QAAQ,CAC1C,EAAG,CAACA,EAAW,SAAUgM,CAAkB,CAAC,EAG5C,MAAMpmB,EAAqBgE,EAAAA,QAAQ,IAAM,CACvC,MAAM7jB,EAAU,CAAC,0BAA0B,EAE3C,OAAIskC,GACFtkC,EAAQ,KAAKkmC,EAAS,YAAY,EAGhC/qC,GACF6E,EAAQ,KAAK7E,CAAS,EAGpB8+B,EAAW,SACbj6B,EAAQ,KAAK,YAAY,EAEzBA,EAAQ,KAAK,aAAa,EAGrBA,EAAQ,KAAK,GAAG,CACzB,EAAG,CAACskC,EAAgB4B,EAAS,aAAc/qC,EAAW8+B,EAAW,QAAQ,CAAC,EAGpE6H,EAAiBje,EAAAA,QAAQ,IAAM,CACnC,MAAMuO,EAAY,CAAE,GAAGr0B,CAAA,EAEvB,OAAIumC,GAAkB,CAACrK,EAAW,SAEzB,CACL,GAAG7H,EACH,YAAa8T,EAAS,aAAa,WAAA,EAIhC9T,CACT,EAAG,CAACkS,EAAgBrK,EAAW,SAAUiM,EAAS,aAAcnoC,CAAK,CAAC,EAGhEooC,EAAoBtiB,EAAAA,QAAQ,IAAM,CACtC,GAAIkiB,IAAgB,YAAc,CAACD,EACjC,MAAO,GAGT,MAAM9lC,EAAU,CAAC8lC,EAAU,WAAa,EAAE,EAE1C,OAAIxB,GAEFtkC,EAAQ,KAAK,cAAc,EAGtBA,EAAQ,OAAO,OAAO,EAAE,KAAK,GAAG,CACzC,EAAG,CAAC+lC,EAAaD,GAAW,UAAWxB,CAAc,CAAC,EAEtD,OACEpoC,EAAAA,KAAC,MAAA,CACC,UAAW2jB,EACX,MAAOiiB,EACP,cAAY,2BACZ,gBAAeuC,EAAU,KACzB,mBAAkBC,EAClB,uBAAsBrK,EAAW,SAAW,SAAW,UAGtD,SAAA,CAAAqK,GAAkBD,EAAU,UAAY,IACvC9oC,EAAAA,IAAC,MAAA,CACC,UAAU,UACV,MAAO2qC,EAAS,SAChB,cAAY,UAEZ,SAAA3qC,EAAAA,IAAC,OAAA,CAAK,UAAU,eACb,WAAS,OAAA,CACZ,CAAA,CAAA,EAKHwqC,IAAgB,YAAcD,EAC7BvqC,EAAAA,IAACmoC,GAAA,CACE,GAAGoC,EACJ,UAAWK,CAAA,CAAA,EAIbvsC,CAAA,CAAA,CAAA,CAIR,EAGAisC,GAAa,YAAc,eC8CpB,MAAMO,GAAyD,CACpE,SAAU,CACR,KAAM,WACN,MAAO,KACP,QAAS,EAAA,EAEX,OAAQ,CACN,KAAM,SACN,MAAO,KACP,QAAS,EAAA,EAEX,MAAO,CACL,KAAM,QACN,MAAO,KACP,QAAS,EAAA,CAEb,EAKaC,GAA0B,CACrC,SAAU,qCACV,OAAQ,mCACR,MAAO,iCACT,EAKaC,GAA0C,CACrD,SAAU,KACV,OAAQ,KACR,MAAO,IACT,ECrNaC,GAAkD,CAAC,CAC9D,OAAAC,EACA,cAAAC,EACA,cAAAC,CACF,IAEIxqC,EAAAA,KAAC,MAAA,CAAI,UAAU,mBACb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,0BAA0B,SAAA,OAAI,QAC3C,MAAA,CAAI,UAAU,yBACZ,SAAAirC,EAAO,IAAKG,GACXzqC,EAAAA,KAAC,MAAA,CAEC,UAAW,cAAcwqC,IAAkBC,EAAM,GAAK,uBAAyB,EAAE,GACjF,MAAO,CAAE,gBAAiBA,EAAM,KAAA,EAChC,QAAS,IAAMF,IAAgBE,EAAM,EAAE,EAEvC,SAAA,CAAAprC,EAAAA,IAAC,MAAA,CAAI,UAAU,oBAAqB,SAAAorC,EAAM,MAAM,EAChDprC,EAAAA,IAAC,MAAA,CAAI,UAAU,mBAAoB,WAAM,KAAK,EAC9CA,EAAAA,IAAC,MAAA,CAAI,UAAU,0BAA2B,WAAM,WAAA,CAAY,CAAA,CAAA,EAPvDorC,EAAM,EAAA,CASd,CAAA,CACH,CAAA,EACF,EClCEC,GAAwC,CAAC,CAC7C,UAAAC,EACA,MAAAjG,EAAQ,IACR,OAAAxe,EAAS,GACX,IAAM,CAEJ,MAAM0kB,EAAuB,IACvBD,EAAU,SAAW,EAAU,GAE5BA,EACJ,IAAIE,GAAW,CAEd,GAAIA,EAAQ,SACV,MAAO,GAAGA,EAAQ,SAAS,CAAC,IAAIA,EAAQ,SAAS,CAAC,GAIpD,MAAMC,EAAS,KAAK,GAAK,EAAIH,EAAU,QAAQE,CAAO,EAAKF,EAAU,OAC/D3rC,EAAU6rC,EAAQ,MAAQA,EAAQ,SAAY,GAAK,GACnDhiB,EAAI,GAAK7pB,EAAS,KAAK,IAAI8rC,CAAK,EAChChiB,EAAI,GAAK9pB,EAAS,KAAK,IAAI8rC,CAAK,EAEtC,MAAO,GAAGjiB,CAAC,IAAIC,CAAC,EAClB,CAAC,EACA,KAAK,GAAG,EAIPiiB,EAA0B19B,GAAkB,CAChD,MAAMy9B,EAAS,KAAK,GAAK,EAAIz9B,EAAS,KAAK,IAAIs9B,EAAU,OAAQ,CAAC,EAC5DK,EAAK,GAAK,GAAK,KAAK,IAAIF,CAAK,EAC7BG,EAAK,GAAK,GAAK,KAAK,IAAIH,CAAK,EACnC,MAAO,CAAE,GAAAE,EAAI,GAAAC,CAAA,CACf,EAGMC,EAA0B79B,GAAkB,CAChD,MAAMy9B,EAAS,KAAK,GAAK,EAAIz9B,EAAS,KAAK,IAAIs9B,EAAU,OAAQ,CAAC,EAC5D9hB,EAAI,GAAK,GAAK,KAAK,IAAIiiB,CAAK,EAC5BhiB,EAAI,GAAK,GAAK,KAAK,IAAIgiB,CAAK,EAGlC,IAAIK,EAAa,SACjB,OAAIL,EAAQ,KAAK,GAAK,KAAQA,EAAQ,KAAK,GAAK,MAAMK,EAAa,SAC/DL,EAAQ,KAAK,GAAK,MAAQA,EAAQ,KAAK,GAAK,OAAMK,EAAa,OAE5D,CAAE,EAAAtiB,EAAG,EAAAC,EAAG,WAAAqiB,CAAA,CACjB,EAEA,OACEnrC,EAAAA,KAAC,MAAA,CACC,cAAY,cACZ,MAAA0kC,EACA,OAAAxe,EACA,QAAQ,cACR,UAAU,gBACV,oBAAoB,gBAGpB,SAAA,CAAA7mB,EAAAA,IAAC,SAAA,CACC,cAAY,eACZ,GAAG,KACH,GAAG,KACH,EAAE,IACF,KAAK,SAAA,CAAA,EAINsrC,EAAU,IAAI,CAACS,EAAG/9B,IAAU,CAC3B,KAAM,CAAE,GAAA29B,EAAI,GAAAC,GAAOF,EAAuB19B,CAAK,EAC/C,OACEhO,EAAAA,IAAC,OAAA,CAEC,cAAY,YACZ,GAAG,KACH,GAAG,KACH,GAAA2rC,EACA,GAAAC,EACA,OAAO,UACP,YAAY,KAAA,EAPP,QAAQ59B,CAAK,EAAA,CAUxB,CAAC,EAGAs9B,EAAU,OAAS,GAClBtrC,EAAAA,IAAC,UAAA,CACC,cAAY,gBACZ,OAAQurC,EAAA,EACR,KAAK,0BACL,OAAO,oBACP,YAAY,IACZ,SAAS,SAAA,CAAA,EAKZD,EAAU,IAAI,CAACE,EAASx9B,IAAU,CACjC,IAAIwb,EAAGC,EAEP,GAAI+hB,EAAQ,SACVhiB,EAAIgiB,EAAQ,SAAS,EACrB/hB,EAAI+hB,EAAQ,SAAS,MAChB,CACL,MAAMC,EAAS,KAAK,GAAK,EAAIz9B,EAASs9B,EAAU,OAC1C3rC,EAAU6rC,EAAQ,MAAQA,EAAQ,SAAY,GAAK,GACzDhiB,EAAI,GAAK7pB,EAAS,KAAK,IAAI8rC,CAAK,EAChChiB,EAAI,GAAK9pB,EAAS,KAAK,IAAI8rC,CAAK,CAClC,CAEA,OACEzrC,EAAAA,IAAC,SAAA,CAEC,cAAY,aACZ,GAAIwpB,EACJ,GAAIC,EACJ,EAAE,IACF,KAAM+hB,EAAQ,mBAAqB,gBAAkB,UAAY,SAAA,EAL5D,SAASA,EAAQ,IAAI,EAAA,CAQhC,CAAC,EAGAF,EAAU,IAAI,CAACE,EAASx9B,IAAU,CACjC,KAAM,CAAE,EAAAwb,EAAG,EAAAC,EAAG,WAAAqiB,CAAA,EAAeD,EAAuB79B,CAAK,EAEzD,OACEhO,EAAAA,IAAC,OAAA,CAEC,EAAAwpB,EACA,EAAAC,EACA,WAAAqiB,EACA,SAAS,IACT,KAAK,UACL,UAAU,UAET,SAAAN,EAAQ,IAAA,EARJ,SAASA,EAAQ,IAAI,EAAA,CAWhC,CAAC,CAAA,CAAA,CAAA,CAGP,EC7IaQ,GAAyC,CACpD,cAAe,KACf,sBAAuB,iEACvB,UAAW,CACT,CACE,KAAM,QACN,MAAO,IACP,SAAU,GACV,iBAAkB,cAClB,SAAU,CAAE,EAAG,GAAI,EAAG,IAAA,EACtB,eAAgB,4CAChB,mBAAoB,qBAAA,EAEtB,CACE,KAAM,OACN,MAAO,EACP,SAAU,GACV,iBAAkB,cAClB,SAAU,CAAE,EAAG,GAAI,EAAG,EAAA,EACtB,eAAgB,2CAChB,mBAAoB,gBAAA,EAEtB,CACE,KAAM,OACN,MAAO,EACP,SAAU,GACV,iBAAkB,cAClB,SAAU,CAAE,EAAG,GAAI,EAAG,EAAA,EACtB,eAAgB,4CAChB,mBAAoB,mBAAA,EAEtB,CACE,KAAM,MACN,MAAO,EACP,SAAU,GACV,iBAAkB,gBAClB,SAAU,CAAE,EAAG,GAAI,EAAG,EAAA,EACtB,eAAgB,oDAChB,mBAAoB,mBAAA,EAEtB,CACE,KAAM,MACN,MAAO,IACP,SAAU,GACV,iBAAkB,cAClB,SAAU,CAAE,EAAG,GAAI,EAAG,EAAA,EACtB,eAAgB,+CAChB,mBAAoB,qBAAA,EAEtB,CACE,KAAM,MACN,MAAO,IACP,SAAU,GACV,iBAAkB,cAClB,SAAU,CAAE,EAAG,GAAI,EAAG,EAAA,EACtB,eAAgB,6CAChB,mBAAoB,eAAA,CACtB,CAEJ,EAEO,MAAMC,EAAoB,CAC/B,OAAwB,aAAe,qBAEvC,aAAa,uBAAmD,CAC9D,GAAI,CAEF,OAAI,QAAQ,IAAI,WAAa,QAE3B,MAAM,IAAI,QAAQl3B,GAAW,WAAWA,EAAS,GAAG,CAAC,EAC9Ci3B,KAGU,MAAM9oB,GAAM,IAAsB,GAAG,KAAK,YAAY,aAAa,GACpE,IAEpB,OAASjhB,EAAO,CAGd,GAFA,QAAQ,MAAM,sCAAuCA,CAAK,EAEtD,QAAQ,IAAI,WAAa,OAC3B,MAAM,IAAI,MAAM,YAAY,EAG9B,OAAO+pC,EACT,CACF,CAEA,aAAa,eAAeE,EAIV,CAChB,GAAI,CAEF,MAAMhpB,GAAM,KAAK,GAAG,KAAK,YAAY,YAAagpB,CAAQ,CAC5D,OAASjqC,EAAO,CACd,cAAQ,MAAM,6BAA8BA,CAAK,EAC3C,IAAI,MAAM,QAAQ,CAC1B,CACF,CACF,CC1FO,MAAMkqC,GAAuBvS,GAAAA,OAA0B,CAACC,EAAKC,KAAS,CAC3E,KAAM,KACN,QAAS,GACT,MAAO,KAEP,UAAW,SAAY,CAErB,GAAI,CAAAA,EAAA,EAAM,QAEV,CAAAD,EAAI,CAAE,QAAS,GAAM,MAAO,KAAM,EAElC,GAAI,CACF,MAAMuS,EAAY,MAAMH,GAAoB,sBAAA,EAC5CpS,EAAI,CAAE,KAAMuS,EAAW,QAAS,GAAO,CACzC,OAASnqC,EAAO,CACd,MAAMsoB,EAAetoB,aAAiB,MAAQA,EAAM,QAAU,SAC9D43B,EAAI,CAAE,MAAOtP,EAAc,QAAS,GAAO,CAC7C,EACF,EAEA,QAAUvoB,GAA2B,CACnC63B,EAAI,CAAE,KAAA73B,EAAM,MAAO,KAAM,QAAS,GAAO,CAC3C,EAEA,SAAWC,GAAkB,CAC3B43B,EAAI,CAAE,MAAA53B,EAAO,QAAS,EAAA,CAAO,CAC/B,EAEA,MAAO,IAAM,CACX43B,EAAI,CAAE,KAAM,KAAM,QAAS,GAAO,MAAO,KAAM,CACjD,CACF,EAAE,EC1CIwS,GAAwD,CAAC,CAAE,QAAAb,KAAc,CAC7E,MAAMxX,EAAcwX,EAAQ,MAAQA,EAAQ,SAAY,IAExD,OACE7qC,EAAAA,KAAC,MAAA,CACC,UAAU,4BACV,eAAc6qC,EAAQ,KACtB,cAAY,yBAEZ,SAAA,CAAA7qC,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAX,EAAAA,IAAC,OAAA,CAAK,UAAU,4BAA6B,SAAAwrC,EAAQ,KAAK,EAC1D7qC,EAAAA,KAAC,OAAA,CAAK,UAAU,gBACb,SAAA,CAAA6qC,EAAQ,MAAM,IAAEA,EAAQ,QAAA,CAAA,CAC3B,CAAA,EACF,EAEAxrC,EAAAA,IAAC,MAAA,CACC,UAAU,wCACV,cAAY,qBAEZ,SAAAA,EAAAA,IAAC,MAAA,CACC,UAAW,GAAGwrC,EAAQ,gBAAgB,kDACtC,MAAO,CAAE,MAAO,GAAGxX,CAAU,GAAA,EAC7B,cAAY,qBACZ,KAAK,cACL,gBAAewX,EAAQ,MACvB,gBAAe,EACf,gBAAeA,EAAQ,SACvB,aAAY,GAAGA,EAAQ,IAAI,cAAcA,EAAQ,KAAK,WAAWA,EAAQ,QAAQ,EAAA,CAAA,CACnF,CAAA,CACF,CAAA,CAAA,CAGN,ECjCMc,GAAkE,CAAC,CACvE,sBAAAC,CACF,IAEIvsC,EAAAA,IAAC,MAAA,CACC,UAAU,mDACV,cAAY,eACZ,KAAK,SACL,aAAW,QAEX,SAAAW,EAAAA,KAAC,MAAA,CAAI,UAAU,mBACb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,gBACb,SAAAA,EAAAA,IAAC,IAAA,CACC,UAAU,+BACV,cAAY,iBACZ,cAAY,OACb,SAAA,WAAA,CAAA,EAGH,EAEAW,EAAAA,KAAC,MAAA,CAAI,UAAU,OACb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CACC,UAAU,sCACV,aAAY,EACb,SAAA,OAAA,CAAA,EAIDA,EAAAA,IAAC,IAAA,CACC,UAAU,6BACV,cAAY,sBAEX,SAAAusC,CAAA,CAAA,CACH,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,EClCAC,GAAwD,CAAC,CAAE,QAAAhB,EAAS,gBAAAiB,EAAkB,CAAA,KAAS,CAEnG,MAAMC,EAAeC,GAAwB,CAC3C,MAAMC,EAA2C,CAC/C,MAAS,SACT,KAAQ,SACR,KAAQ,SACR,IAAO,SACP,IAAO,SACP,IAAO,QAAA,EAIT,OAAOH,EAAgBE,CAAW,GAAKC,EAAiBD,CAAW,GAAK,MAC1E,EAEA,OACE3sC,EAAAA,IAACY,GAAAA,KAAA,CACC,UAAU,kFACV,eAAc4qC,EAAQ,KACtB,cAAY,sBACZ,YAAW,GACX,YAAW,GAEX,eAAC3qC,YAAA,CAAS,UAAU,MAClB,SAAAF,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAA,EAAAA,KAAC,KAAA,CACC,UAAU,wCACV,aAAY,EAEX,SAAA,CAAA6qC,EAAQ,KAAK,QAAA,CAAA,CAAA,EAGhBxrC,EAAAA,IAAC,IAAA,CACC,UAAU,2CACV,cAAY,6BAEX,SAAAwrC,EAAQ,cAAA,CAAA,EAGXxrC,EAAAA,IAACT,GAAAA,OAAA,CACC,GAAG,IACH,KAAMisC,EAAQ,mBACd,UAAU,aACV,KAAK,KACL,QAAQ,OACR,MAAM,UACN,WAAYxrC,EAAAA,IAAC6sC,GAAAA,WAAA,CAAW,UAAU,SAAA,CAAU,EAC5C,cAAY,sBACZ,aAAY,KAAKrB,EAAQ,IAAI,SAE5B,SAAAkB,EAAYlB,EAAQ,IAAI,CAAA,CAAA,CAC3B,CAAA,CACF,CAAA,CACF,CAAA,CAAA,CAGN,gMCtDMsB,GAAuC,IAAM,CACjD,KAAM,CAAE,KAAA9qC,EAAM,QAAAnC,EAAS,MAAAoC,EAAO,UAAA8qC,CAAA,EAAcZ,GAAA,EAM5C,OAJAhkB,EAAAA,UAAU,IAAM,CACd4kB,EAAA,CACF,EAAG,CAACA,CAAS,CAAC,EAEVltC,EAEAc,EAAAA,KAAC,MAAA,CACC,UAAU,qEACV,cAAY,kBAEZ,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,gEAAA,CAAiE,EAChFA,EAAAA,IAAC,OAAA,CAAK,UAAU,qBAAqB,SAAA,QAAA,CAAM,CAAA,CAAA,CAAA,EAK7CiC,EAEAtB,EAAAA,KAAC,MAAA,CACC,UAAU,gDACV,KAAK,QACL,YAAU,YAEV,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,oBACb,SAAAA,EAAAA,IAAC,IAAA,CACC,UAAU,0BACV,cAAY,OACb,SAAA,eAAA,CAAA,EAGH,EACAA,EAAAA,IAAC,KAAA,CAAG,UAAU,2CAA2C,SAAA,OAAI,EAC7DA,EAAAA,IAAC,IAAA,CAAE,UAAU,qBAAsB,SAAAiC,EAAM,EACzCjC,EAAAA,IAAC,SAAA,CACC,QAAS+sC,EACT,UAAU,0JACV,aAAW,SACZ,SAAA,IAAA,CAAA,CAED,CAAA,CAAA,EAKD/qC,EAaHrB,EAAAA,KAAC,MAAA,CACC,UAAU,oDACV,iBAAe,6BACf,KAAK,OACL,aAAW,YAGX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,kCAAkC,SAAA,UAAO,EACvDW,EAAAA,KAAC,OAAA,CACC,UAAU,6EACV,aAAY,SAASqB,EAAK,aAAa,GACxC,SAAA,CAAA,SACQA,EAAK,aAAA,CAAA,CAAA,CACd,EACF,EAGArB,EAAAA,KAAC,MAAA,CAAI,UAAWqsC,GAAO,gBAErB,SAAA,CAAArsC,EAAAA,KAAC,MAAA,CAAI,UAAWqsC,GAAO,aAErB,SAAA,CAAAhtC,EAAAA,IAAC,MAAA,CAAI,UAAWgtC,GAAO,eACrB,eAAC3B,GAAA,CAAW,UAAWrpC,EAAK,SAAA,CAAW,CAAA,CACzC,QAGC,MAAA,CAAI,UAAU,8CACZ,SAAAA,EAAK,UAAU,IAAIwpC,GAClBxrC,EAAAA,IAACqsC,GAAA,CAEC,QAAAb,CAAA,EADKA,EAAQ,IAAA,CAGhB,CAAA,CACH,CAAA,EACF,EAGA7qC,EAAAA,KAAC,MAAA,CAAI,UAAWqsC,GAAO,aAErB,SAAA,CAAAhtC,EAAAA,IAACssC,GAAA,CACC,sBAAuBtqC,EAAK,qBAAA,CAAA,EAI9BhC,EAAAA,IAAC,KAAA,CAAG,UAAU,4CAA4C,SAAA,SAE1D,QAEC,MAAA,CAAI,UAAU,wCACZ,SAAAgC,EAAK,UAAU,IAAIwpC,GAClBxrC,EAAAA,IAACwsC,GAAA,CAEC,QAAAhB,CAAA,EADKA,EAAQ,IAAA,CAGhB,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,CAAA,EArEAxrC,EAAAA,IAAC,MAAA,CACC,UAAU,gDACV,KAAK,SACL,YAAU,SAEV,SAAAA,EAAAA,IAAC,IAAA,CAAE,UAAU,gBAAgB,SAAA,MAAA,CAAI,CAAA,CAAA,CAmEzC,EChDaitC,GAAwC,CACnD,yBAA0B,KAC1B,wBAAyB,KACzB,6BAA8B,KAC9B,QAAW,IACb,EAGaC,GAAwC,CACnD,SAAY,MACZ,WAAc,KACd,SAAY,KACZ,UAAa,MACb,cAAe,KACjB,EAEaC,GAAuC,CAClD,SAAY,UACZ,WAAc,UACd,SAAY,UACZ,UAAa,UACb,cAAe,SACjB,ECpGaC,GAAiB,CAC5B,GAAI,WACJ,KAAM,KACN,MAAO,EACP,OAAQ,sCACR,MAAO,GACP,OAAQ,CAAC,KAAM,KAAM,IAAI,CAC3B,EAEaC,GAAqB,CAChC,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,MAAO,QAAS,IAAM,QAAQ,IAAI,aAAa,CAAA,EACjF,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,KAAM,QAAS,IAAM,QAAQ,IAAI,aAAa,CAAA,EAChF,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,MAAO,QAAS,IAAM,QAAQ,IAAI,aAAa,CAAA,EACjF,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,MAAO,QAAS,IAAM,QAAQ,IAAI,aAAa,CAAA,EACjF,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,MAAO,QAAS,IAAM,QAAQ,IAAI,aAAa,CAAA,EACjF,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,MAAO,QAAS,IAAM,QAAQ,IAAI,aAAa,CAAA,EACjF,CAAE,GAAI,YAAa,MAAO,OAAQ,OAAQ,MAAO,QAAS,IAAM,QAAQ,IAAI,cAAc,CAAA,EAC1F,CAAE,GAAI,aAAc,MAAO,OAAQ,OAAQ,MAAO,QAAS,IAAM,QAAQ,IAAI,cAAc,CAAA,EAC3F,CAAE,GAAI,YAAa,MAAO,OAAQ,OAAQ,MAAO,QAAS,IAAM,QAAQ,IAAI,cAAc,CAAA,EAC1F,CAAE,GAAI,aAAc,MAAO,OAAQ,OAAQ,MAAO,QAAS,IAAM,QAAQ,IAAI,cAAc,CAAA,CAC7F,EAGaC,GAAiB,0SCxBjBC,GAAyB,CACpC,GAAM,KACN,MAAS,UACT,MAAS,EACT,QAAW,KACX,MAAS,CACP,CACE,GAAM,SACN,MAAS,OACT,YAAe,iBACf,kBAAqB,KACrB,aAAgB,GAChB,eAAkB,yBAClB,QAAW,CACT,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,oBAAqB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,aAAc,YAAe,oDAAqD,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAChW,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,aAAc,YAAe,kCAAmC,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,wBAAyB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAClV,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,iBAAoB,YAAe,sBAAyB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAClN,CAAE,GAAM,gBAAiB,MAAS,gBAAiB,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,iBAAkB,YAAe,uBAAwB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,eAAgB,YAAe,uBAAwB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACtV,CAAE,GAAM,gBAAiB,MAAS,OAAQ,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,cAAe,YAAe,wBAAyB,SAAY,EAAG,WAAc,GAAK,CAAA,CAAE,CAChN,EAEF,CACE,GAAM,SAAU,MAAS,OAAQ,YAAe,iBAAkB,kBAAqB,KAAM,aAAgB,GAAI,eAAkB,yBACnI,QAAW,CACT,CAAE,GAAM,gBAAiB,MAAS,SAAU,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,cAAe,YAAe,6CAA8C,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACnO,CAAE,GAAM,gBAAiB,MAAS,UAAW,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,eAAgB,YAAe,mCAAoC,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAC3N,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,iBAAoB,YAAe,sBAAyB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAClN,CAAE,GAAM,gBAAiB,MAAS,OAAQ,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,UAAW,YAAe,kBAAmB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,YAAa,YAAe,gBAAiB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACvT,CAAE,GAAM,gBAAiB,MAAS,WAAY,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,aAAc,YAAe,kBAAmB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,iBAAkB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAC9T,CAAE,GAAM,gBAAiB,MAAS,OAAQ,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,cAAe,YAAe,sBAAuB,SAAY,EAAG,WAAc,GAAK,CAAA,CAAE,CAC9M,EAEF,CACE,GAAM,SAAU,MAAS,OAAQ,YAAe,iBAAkB,kBAAqB,KAAM,aAAgB,GAAI,eAAkB,yBACnI,QAAW,CACT,CAAE,GAAM,gBAAiB,MAAS,SAAU,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,SAAU,YAAe,mBAAoB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,iBAAkB,YAAe,kBAAmB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAChU,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,QAAS,YAAe,wBAAyB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACvM,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,SAAU,YAAe,kCAAmC,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,SAAU,YAAe,0CAA2C,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAC9V,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,aAAc,YAAe,6CAA8C,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACjO,CAAE,GAAM,gBAAiB,MAAS,UAAW,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,YAAa,YAAe,qBAAsB,SAAY,EAAG,WAAc,GAAK,CAAA,CAAE,CAC9M,EAEF,CACE,GAAM,SAAU,MAAS,SAAU,YAAe,2BAA4B,kBAAqB,KAAM,aAAgB,GAAI,eAAkB,wBAC/I,QAAW,CACT,CAAE,GAAM,gBAAiB,MAAS,WAAY,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,eAAgB,YAAe,wBAAyB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,aAAc,YAAe,4BAA6B,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACnV,CAAE,GAAM,gBAAiB,MAAS,SAAU,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,aAAc,YAAe,sBAAuB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,4BAA6B,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAC3U,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,YAAa,YAAe,qBAAsB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,UAAW,YAAe,+BAAgC,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAC1U,CAAE,GAAM,gBAAiB,MAAS,UAAW,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,SAAU,YAAe,2BAA4B,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,YAAa,YAAe,kBAAmB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,CAAE,CACxU,EAEF,CACE,GAAM,SAAU,MAAS,QAAS,YAAe,mBAAoB,kBAAqB,KAAM,aAAgB,GAAI,eAAkB,yBACtI,QAAW,CACT,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,6BAA8B,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,4BAA6B,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAC/U,CAAE,GAAM,gBAAiB,MAAS,cAAe,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,YAAa,YAAe,yBAA0B,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,UAAW,YAAe,0BAA2B,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAC/U,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,2BAA4B,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,cAAe,YAAe,yBAA0B,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,CAAE,CACjV,EAEF,CACE,GAAM,SAAU,MAAS,UAAW,YAAe,wBAAyB,kBAAqB,KAAM,aAAgB,GAAI,eAAkB,wBAC7I,QAAW,CACT,CAAE,GAAM,gBAAiB,MAAS,aAAc,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,SAAU,YAAe,uBAAwB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,SAAU,YAAe,wBAAyB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACtU,CAAE,GAAM,gBAAiB,MAAS,cAAe,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,SAAU,YAAe,6BAA8B,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,mBAAoB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAC1U,CAAE,GAAM,gBAAiB,MAAS,aAAc,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,UAAW,YAAe,oBAAqB,SAAY,EAAG,WAAc,IAAM,CAAE,GAAM,mBAAoB,MAAS,eAAgB,YAAe,mBAAoB,SAAY,EAAG,WAAc,IAAM,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,iBAAkB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAC1b,CAAE,GAAM,gBAAiB,MAAS,UAAW,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,UAAW,YAAe,oBAAqB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,eAAgB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,CAAE,CAC9T,EAEF,CACE,GAAM,SAAU,MAAS,WAAY,YAAe,sBAAuB,kBAAqB,KAAM,aAAgB,GAAI,eAAkB,yBAC5I,QAAW,CACT,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,wBAAyB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,OAAQ,YAAe,4BAA6B,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACtU,CAAE,GAAM,gBAAiB,MAAS,QAAS,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,WAAY,YAAe,2BAA4B,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAC7M,CAAE,GAAM,gBAAiB,MAAS,UAAW,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,aAAc,YAAe,kBAAmB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,MAAO,YAAe,yBAA0B,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAChU,CAAE,GAAM,gBAAiB,MAAS,UAAW,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,UAAW,YAAe,8BAA+B,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACjN,CAAE,GAAM,gBAAiB,MAAS,KAAM,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,QAAS,YAAe,iCAAkC,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,QAAS,YAAe,mBAAoB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACjU,CAAE,GAAM,gBAAiB,MAAS,KAAM,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,QAAS,YAAe,iCAAkC,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,QAAS,YAAe,mBAAoB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACjU,CAAE,GAAM,gBAAiB,MAAS,WAAY,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,SAAU,YAAe,cAAe,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,SAAU,YAAe,cAAe,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,CAAE,CACrT,EAEF,CACE,GAAM,SAAU,MAAS,WAAY,YAAe,sBAAuB,kBAAqB,KAAM,aAAgB,GAAI,eAAkB,yBAC5I,QAAW,CACT,CAAE,GAAM,gBAAiB,MAAS,YAAa,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,eAAgB,YAAe,iBAAkB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,eAAgB,YAAe,iBAAkB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACpU,CAAE,GAAM,gBAAiB,MAAS,YAAa,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,eAAgB,YAAe,qCAAsC,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,eAAgB,YAAe,qCAAsC,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EAC5W,CAAE,GAAM,gBAAiB,MAAS,WAAY,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,cAAe,YAAe,kBAAmB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,kBAAmB,YAAe,qCAAsC,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,CAAE,CAC9V,EAEF,CACE,GAAM,SAAU,MAAS,QAAS,YAAe,0BAA2B,kBAAqB,KAAM,aAAgB,EAAG,eAAkB,6BAC5I,QAAW,CACT,CAAE,GAAM,gBAAiB,MAAS,UAAW,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,aAAc,YAAe,qBAAsB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,YAAa,YAAe,iBAAkB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACjU,CAAE,GAAM,gBAAiB,MAAS,UAAW,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,aAAc,YAAe,qBAAsB,SAAY,EAAG,WAAc,EAAA,EAAM,CAAE,GAAM,mBAAoB,MAAS,YAAa,YAAe,iBAAkB,SAAY,EAAG,WAAc,EAAA,CAAK,CAAA,EACjU,CAAE,GAAM,gBAAiB,MAAS,OAAQ,SAAY,GAAI,eAAkB,CAAE,CAAE,GAAM,mBAAoB,MAAS,cAAe,YAAe,+BAAgC,SAAY,EAAG,WAAc,GAAK,CAAA,CAAE,CACvN,CACF,CAEJ,EAKavnB,GAAeqnB,GACfxoB,GAAWuoB,GCtExB,MAAMI,EAAc,CACV,QACA,MAER,YAAYx1B,EAAkB,UAAWjM,EAAgBuhC,GAAgB,CACvE,KAAK,QAAUt1B,EACf,KAAK,MAAQjM,CACf,CAEQ,gBAA8B,CACpC,MAAO,CACL,cAAiB,UAAU,KAAK,KAAK,GACrC,eAAgB,kBAAA,CAEpB,CAEA,MAAc,cAAc4C,EAAapB,EAAuB,GAAuB,CACrF,MAAMf,EAAW,MAAM,MAAMmC,EAAK,CAChC,GAAGpB,EACH,QAAS,CACP,GAAG,KAAK,eAAA,EACR,GAAGA,EAAQ,OAAA,CACb,CACD,EAED,GAAI,CAACf,EAAS,GACZ,MAAM,IAAI,MAAM,uBAAuBA,EAAS,MAAM,EAAE,EAG1D,OAAOA,CACT,CAGA,MAAM,cAAcihC,EAAuC,CAEzD,OADiB,MAAM,KAAK,cAAc,GAAG,KAAK,OAAO,oBAAoBA,CAAQ,EAAE,GACvE,KAAA,CAClB,CAGA,MAAM,qBAAqBC,EAA8C,CACvE,MAAM/+B,EAAM++B,EACR,GAAG,KAAK,OAAO,mBAAmB,mBAAmBA,CAAO,CAAC,aAC7D,GAAG,KAAK,OAAO,oCAGnB,OADiB,MAAM,KAAK,cAAc/+B,CAAG,GAC7B,KAAA,CAClB,CAGA,MAAM,gBAAgB8+B,EAAkB9qC,EAAwD,CAC9F,MAAMgM,EAAMhM,EACR,GAAG,KAAK,OAAO,oBAAoB8qC,CAAQ,UAAU9qC,CAAM,YAC3D,GAAG,KAAK,OAAO,oBAAoB8qC,CAAQ,YAG/C,OADiB,MAAM,KAAK,cAAc9+B,CAAG,GAC7B,KAAA,CAClB,CAGA,MAAM,0BACJhM,EACAgrC,EACuG,CASvG,OARiB,MAAM,KAAK,cAC1B,GAAG,KAAK,OAAO,kBAAkBhrC,CAAM,kBACvC,CACE,OAAQ,OACR,KAAM,KAAK,UAAUgrC,CAAe,CAAA,CACtC,GAGc,KAAA,CAClB,CAGA,MAAM,qBACJF,EACA9qC,EACAirC,EACA9rC,EACe,CACf,MAAM,KAAK,cACT,GAAG,KAAK,OAAO,oBAAoB2rC,CAAQ,UAAU9qC,CAAM,YAAYirC,CAAQ,YAC/E,CACE,OAAQ,OACR,KAAM,KAAK,UAAU,CAAE,OAAA9rC,EAAQ,CAAA,CACjC,CAEJ,CAGA,SAASiK,EAAqB,CAC5B,KAAK,MAAQA,CACf,CAGA,UAAmB,CACjB,OAAO,KAAK,KACd,CACF,CAGO,MAAM8hC,GAAgB,IAAIL,GC3B1B,MAAMM,WAAwB,KAAM,CACzC,YACEnhC,EACOL,EACAyhC,EACP,CACA,MAAMphC,CAAO,EAHN,KAAA,KAAAL,EACA,KAAA,cAAAyhC,EAGP,KAAK,KAAO,iBACd,CACF,CCxGO,MAAMC,EAAqC,CACxC,OAER,YAAY5yC,EAA6B,CACvC,KAAK,OAAS,CACZ,cAAe,GACf,SAAU,IACV,QAAS,KACT,WAAY,EACZ,WAAY,IACZ,GAAGA,CAAA,EAILyyC,GAAc,SAAS,KAAK,OAAO,KAAK,CAC1C,CAEA,MAAM,qBAAqBH,EAAiB7pB,EAAqD,CAC/F,GAAI,CACF,eAAQ,IAAI,uCAAuC6pB,CAAO,YAAY7pB,CAAM,EAAE,EAEjE,MAAM,KAAK,UAAU,IAChCgqB,GAAc,qBAAqBH,CAAO,CAAA,CAI9C,OAASzrC,EAAO,CACd,cAAQ,MAAM,gCAAiCA,CAAK,EAC9C,IAAI6rC,GACR,iBAAiB7rC,aAAiB,MAAQA,EAAM,QAAU,MAAM,GAChE,kCACAA,aAAiB,MAAQA,EAAQ,MAAA,CAErC,CACF,CAEA,MAAM,eAAe4hB,EAAmC,CACtD,GAAI,CACF,eAAQ,IAAI,oCAAoCA,CAAM,EAAE,EAIzB,CAC7B,GAAIA,EACJ,KAAM,OACN,MAAO,EACP,OAAQ,2BACR,OAAQ,CAAC,IAAI,CAAA,CAIjB,OAAS5hB,EAAO,CACd,cAAQ,MAAM,8BAA+BA,CAAK,EAC5C,IAAI6rC,GACR,eAAe7rC,aAAiB,MAAQA,EAAM,QAAU,MAAM,GAC9D,0BACAA,aAAiB,MAAQA,EAAQ,MAAA,CAErC,CACF,CAEA,MAAM,gBAAyC,CAC7C,GAAI,CACF,eAAQ,IAAI,0BAA0B,EAIC,CACrC,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,KAAA,EAClC,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,KAAA,CAAM,CAI5C,OAASA,EAAO,CACd,cAAQ,MAAM,8BAA+BA,CAAK,EAC5C,IAAI6rC,GACR,eAAe7rC,aAAiB,MAAQA,EAAM,QAAU,MAAM,GAC9D,0BACAA,aAAiB,MAAQA,EAAQ,MAAA,CAErC,CACF,CAEA,MAAM,qBAAqBsM,EAA6C,CACtE,GAAI,CACF,QAAQ,IAAI,0BAA2BA,CAAM,EAE7C,MAAM,KAAK,UAAU,IACnBs/B,GAAc,qBACZt/B,EAAO,SACPA,EAAO,OACPA,EAAO,SACPA,EAAO,MAAA,CACT,CAEJ,OAAStM,EAAO,CACd,cAAQ,MAAM,4BAA6BA,CAAK,EAC1C,IAAI6rC,GACR,aAAa7rC,aAAiB,MAAQA,EAAM,QAAU,MAAM,GAC5D,gCACAA,aAAiB,MAAQA,EAAQ,MAAA,CAErC,CACF,CAEA,MAAM,0BACJU,EACAgrC,EACuG,CACvG,GAAI,CACF,eAAQ,IAAI,oCAAoChrC,CAAM,GAAIgrC,CAAe,EAE1D,MAAM,KAAK,UAAU,IAClCE,GAAc,0BAA0BlrC,EAAQgrC,CAAe,CAAA,CAInE,OAAS1rC,EAAO,CACd,cAAQ,MAAM,8BAA+BA,CAAK,EAC5C,IAAI6rC,GACR,eAAe7rC,aAAiB,MAAQA,EAAM,QAAU,MAAM,GAC9D,sCACAA,aAAiB,MAAQA,EAAQ,MAAA,CAErC,CACF,CAKA,MAAc,UAAagsC,EAAyC,CAClE,IAAIC,EAEJ,QAASC,EAAU,EAAGA,GAAW,KAAK,OAAO,WAAaA,IACxD,GAAI,CACF,OAAO,MAAMF,EAAA,CACf,OAAShsC,EAAO,CACdisC,EAAYjsC,aAAiB,MAAQA,EAAQ,IAAI,MAAM,OAAOA,CAAK,CAAC,EAEhEksC,EAAU,KAAK,OAAO,aACxB,QAAQ,KAAK,yBAAyBA,CAAO,SAAUD,EAAU,OAAO,EACxE,MAAM,KAAK,MAAM,KAAK,OAAO,UAAW,EAE5C,CAGF,MAAMA,CACR,CAKQ,MAAME,EAA2B,CACvC,OAAO,IAAI,QAAQr5B,GAAW,WAAWA,EAASq5B,CAAE,CAAC,CACvD,CAKA,WAAiC,CAC/B,MAAO,CAAE,GAAG,KAAK,MAAA,CACnB,CACF,CChKO,MAAMC,EAAsC,CACzC,OAER,YAAYjzC,EAA8B,CACxC,KAAK,OAAS,CACZ,MAAO,IACP,cAAe,GACf,iBAAkB,GAClB,GAAGA,CAAA,CAEP,CAEA,MAAM,qBAAqBsyC,EAAiB7pB,EAAqD,CAI/F,GAHA,QAAQ,IAAI,0CAA0C6pB,CAAO,YAAY7pB,CAAM,EAAE,EACjF,MAAM,KAAK,cAAA,EAEP,KAAK,sBACP,cAAQ,IAAI,kCAAkC6pB,CAAO,YAAY7pB,CAAM,EAAE,EACnE,IAAIiqB,GACR,qBACA,sCAAA,EAIJ,eAAQ,IAAI,0CAA0CJ,CAAO,YAAY7pB,CAAM,EAAE,EAG/B,CAChD,OAAAA,EACA,SAAU6pB,EACV,YAAa,UACb,YAAa,EACb,WAAYH,GAAW,MAAM,OAC7B,eAAgB,EAChB,gBAAiB,GACjB,OAAQ,cACR,aAAc,IAAI,KAAA,EAAO,YAAA,EACzB,MAAOA,GAAW,MAAM,IAAI,CAAC9rC,EAAMuM,KAAW,CAC5C,OAAQvM,EAAK,GACb,MAAOA,EAAK,MACZ,YAAaA,EAAK,YAClB,eAAgBA,EAAK,eACrB,kBAAmBA,EAAK,kBACxB,aAAcA,EAAK,QAAQ,OAC3B,iBAAkBuM,EAAQ,EAAI,KAAK,MAAMvM,EAAK,QAAQ,OAAS,EAAG,EAAI,EACtE,mBAAoBuM,EAAQ,EAAI,GAAK,EACrC,OAAQA,EAAQ,EAAI,cAAgB,cACpC,aAAcA,EAAQ,MAAQ,KAAA,EAAO,cAAgB,OACrD,SAAUA,IAAU,EACpB,MAAO,sBAAsBvM,EAAK,EAAE,GACpC,KAAMwrC,GAAcxrC,EAAK,cAAc,GAAKwrC,GAAc,OAAA,EAC1D,CAAA,CAIN,CAEA,MAAM,eAAeppB,EAAmC,CAGtD,GAFA,MAAM,KAAK,cAAA,EAEP,KAAK,sBACP,MAAM,IAAIiqB,GACR,mBACA,8BAAA,EAIJ,eAAQ,IAAI,qCAAqCjqB,CAAM,EAAE,EAE1B,CAC7B,GAAIA,EACJ,KAAM,OACN,MAAO,EACP,OAAQ,2BACR,OAAQ,CAAC,IAAI,CAAA,CAIjB,CAEA,MAAM,gBAAyC,CAG7C,GAFA,MAAM,KAAK,cAAA,EAEP,KAAK,sBACP,MAAM,IAAIiqB,GACR,mBACA,8BAAA,EAIJ,eAAQ,IAAI,2BAA2B,EAEA,CACrC,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,KAAA,EAClC,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,KAAA,CAAM,CAI5C,CAEA,MAAM,qBAAqBv/B,EAA6C,CAGtE,GAFA,MAAM,KAAK,cAAA,EAEP,KAAK,sBACP,MAAM,IAAIu/B,GACR,iBACA,oCAAA,EAIJ,QAAQ,IAAI,2BAA4Bv/B,CAAM,EAG9C,QAAQ,IAAI,MAAMA,EAAO,QAAQ,WAAWA,EAAO,MAAM,EAAE,CAC7D,CAEA,MAAM,0BACJ5L,EACAgrC,EACuG,CAGvG,GAFA,MAAM,KAAK,cAAA,EAEP,KAAK,sBACP,MAAM,IAAIG,GACR,mBACA,0CAAA,EAIJ,eAAQ,IAAI,qCAAqCnrC,CAAM,GAAIgrC,CAAe,EAQnE,CACL,QAAS,GACT,QARcA,EAAgB,IAAIW,IAAW,CAC7C,SAAUA,EAAO,SACjB,QAAS,GACT,OAAQA,EAAO,MAAA,EACf,CAIA,CAEJ,CAKA,MAAc,eAA+B,CACvC,KAAK,OAAO,OAAS,KAAK,OAAO,MAAQ,GAC3C,MAAM,IAAI,QAAQv5B,GAAW,WAAWA,EAAS,KAAK,OAAO,KAAK,CAAC,CAEvE,CAKQ,qBAA+B,CACrC,OAAK,KAAK,OAAO,cAIV,KAAK,OAAA,GAAY,KAAK,OAAO,kBAAoB,IAH/C,EAIX,CAKA,WAAkC,CAChC,MAAO,CAAE,GAAG,KAAK,MAAA,CACnB,CAKA,eAAmC,CACjC,OAAOw4B,EACT,CAKA,gBAA2C,CACzC,MAAMgB,EAAwC,CAAA,EAC9C,OAAAhB,GAAW,MAAM,QAAQ9rC,GAAQ,CAC/B8sC,EAAY9sC,EAAK,EAAE,EAAIA,EAAK,QAAQ,IAAIR,IAAW,CACjD,GAAIA,EAAO,GACX,MAAOA,EAAO,MACd,SAAUA,EAAO,SACjB,eAAgBA,EAAO,eAAe,IAAIX,IAAS,CACjD,GAAGA,EACH,SAAU,CAAA,EACV,CAAA,EACF,CACJ,CAAC,EACMiuC,CACT,CACF,CCtMO,MAAMC,EAAkB,CAC7B,OAAe,UAAsC,IAAI,IAOzD,OAAO,iBAAiBjhC,EAAgD,CACtE,KAAM,CAAE,KAAApS,EAAM,OAAAC,EAAQ,sBAAAqzC,CAAA,EAA0BlhC,EAG1CmhC,EAAc,KAAK,eAAevzC,EAAMC,CAAM,EAGpD,GAAI,KAAK,UAAU,IAAIszC,CAAW,EAChC,OAAO,KAAK,UAAU,IAAIA,CAAW,EAGvC,IAAIC,EAEJ,OAAQxzC,EAAA,CACN,IAAK,MACHwzC,EAAa,IAAIX,GAAc5yC,CAA6B,EAC5D,MAEF,IAAK,OACHuzC,EAAa,IAAIN,GAAejzC,CAA8B,EAC9D,MAEF,IAAK,SACH,GAAI,CAACqzC,EACH,MAAM,IAAI,MAAM,uCAAuC,EAEzDE,EAAa,IAAIF,EAAsBrzC,CAAM,EAC7C,MAEF,QACE,MAAM,IAAI,MAAM,cAAcD,CAAI,EAAE,CAAA,CAIxC,YAAK,UAAU,IAAIuzC,EAAaC,CAAU,EAE1C,QAAQ,IAAI,mCAAmCxzC,CAAI,UAAUC,EAAO,IAAI,EAAE,EAEnEuzC,CACT,CAOA,OAAO,oBAAoBvzC,EAA4C,CACrE,OAAO,KAAK,iBAAiB,CAC3B,KAAM,MACN,OAAAA,CAAA,CACD,CACH,CAOA,OAAO,qBAAqBA,EAAwC,GAAoB,CACtF,OAAO,KAAK,iBAAiB,CAC3B,KAAM,OACN,OAAQ,CACN,KAAM,iBACN,GAAGA,CAAA,CACL,CACD,CACH,CAMA,OAAO,yBAAuC,CAE5C,MAAMwzC,EAAY,OAAO,OAAW,IAGpC,IAAIC,EAAgB,GAChBC,EAAS,GACTC,EAAU,GAEd,GAAI,CAEE,OAAO,QAAY,KAAe,QAAQ,KAC5CF,EAAgB,QAAQ,IAAI,WAAa,cACzCC,EAAS,QAAQ,IAAI,WAAa,OAClCC,EAAU,QAAQ,IAAI,qBAAuB,SAG7CF,EAAgB,GAChBE,EAAU,GAEd,OAAS9sC,EAAO,CAEd,QAAQ,KAAK,mBAAoBA,CAAK,EACtC4sC,EAAgB,GAChBE,EAAU,EACZ,CAGA,OAAIF,GAAiBC,GAAUC,EACtB,KAAK,qBAAqB,CAC/B,KAAM,wBACN,MAAO,GAAA,CACR,EAII,KAAK,oBAAoB,CAC9B,KAAM,uBACN,QAAS,UACT,MAAOH,GAAY,aAAa,QAAQ,WAAW,GAAK,EAAK,CAC9D,CACH,CAKA,OAAO,YAAmB,CACxB,KAAK,UAAU,MAAA,EACf,QAAQ,IAAI,kCAAkC,CAChD,CAKA,OAAO,wBAAiC,CACtC,OAAO,KAAK,UAAU,IACxB,CAKA,OAAe,eAAezzC,EAAcC,EAAkC,CAC5E,MAAO,GAAGD,CAAI,IAAIC,EAAO,IAAI,IAAI,KAAK,UAAUA,CAAM,CAAC,EACzD,CACF,CA0BO,SAAS4zC,IAAuC,CACrD,OAAOR,GAAkB,wBAAA,CAC3B,CC3KO,SAASS,GACd1hC,EAA+B,GACP,CACxB,KAAM,CACJ,WAAAohC,EAAaK,GAAA,EACb,iBAAAE,EAAmB,OACnB,cAAAC,EAAgB,CAAA,EAChB,YAAAC,EAAc,CAAA,EACd,MAAAza,EAAQ,CAAA,EACR,MAAA0a,EAAQ,GACR,eAAAC,EAAiB,EAAA,EACf/hC,EAiCJ,MA/BuC,CACrC,WAAAohC,EACA,iBAAAO,EACA,cAAe,CACb,uBAAwB,GACxB,UAAW,GACX,UAAW,GACX,WAAY,EACZ,WAAY,IACZ,GAAGC,CAAA,EAEL,YAAa,CACX,qBAAsB,GACtB,eAAgB,GAChB,eAAgB,IAChB,cAAe,GACf,SAAU,IACV,GAAGC,CAAA,EAEL,MAAO,CACL,aAAc,UACd,aAAc,MACd,QAAS,OACT,SAAU,OACV,eAAgB,GAChB,GAAGza,CAAA,EAEL,MAAA0a,EACA,eAAAC,CAAA,CAIJ,CA8EO,SAASC,GACdC,EACAC,EACwB,CACxB,MAAO,CACL,GAAGD,EACH,GAAGC,EACH,cAAe,CACb,GAAGD,EAAW,cACd,GAAGC,EAAe,aAAA,EAEpB,YAAa,CACX,GAAGD,EAAW,YACd,GAAGC,EAAe,WAAA,EAEpB,MAAO,CACL,GAAGD,EAAW,MACd,GAAGC,EAAe,KAAA,CACpB,CAEJ,CCnJO,MAAMC,GAA0BC,EAAAA,cAAkD,IAAI,EAEhFC,GAAsB,IAAM,CACvC,MAAM/nC,EAAUgoC,EAAAA,WAAWH,EAAuB,EAClD,GAAI,CAAC7nC,EACH,MAAM,IAAI,MAAM,kEAAkE,EAEpF,OAAOA,CACT,EAGaioC,GAAoE,CAAC,CAAE,SAAAzxC,EAAU,OAAQ0xC,KAAqB,CACzH,KAAM,CAAC30C,EAAQ40C,CAAS,EAAI3a,EAAAA,SAAS,IAAM4Z,GAA6Bc,CAAc,CAAC,EACjF,CAACE,EAAUC,CAAW,EAAI7a,EAAAA,SAA0B,IAAI,EACxD,CAAC8a,EAAaC,CAAc,EAAI/a,EAAAA,SAAwB,CAAA,CAAE,EAC1D,CAACgb,EAAWC,CAAY,EAAIjb,EAAAA,SAA4C,IAAI,EAC5E,CAACkb,EAASC,CAAU,EAAInb,EAAAA,SAAmC,CAAA,CAAE,EAC7D,CAACx1B,EAASklB,CAAU,EAAIsQ,EAAAA,SAAkB,EAAK,EAC/C,CAACpzB,EAAOqzB,CAAQ,EAAID,EAAAA,SAAwB,IAAI,EAChD,CAACjzB,EAAcquC,CAAe,EAAIpb,EAAAA,SAAwB,IAAI,EAC9D,CAAC3zB,EAAiBgvC,CAAkB,EAAIrb,EAAAA,SAAmB,CAAA,CAAE,EAE7Dsb,EAAehd,EAAAA,YAAY,MAAO+Z,EAAiB7pB,IAAmB,CAC1EkB,EAAW,EAAI,EACfuQ,EAAS,IAAI,EAEb,GAAI,CAGE,QAAQ,IAAI,WAAa,QAC3B,MAAM,IAAI,QAAQvgB,GAAW,WAAWA,EAAS,GAAG,CAAC,EAIvD,MAAMs7B,EAAY,MAAMj1C,EAAO,WAAW,qBAAqBsyC,EAAS7pB,CAAM,EAC9EysB,EAAaD,CAAS,EAGtB,MAAM9B,EAAwC,CAAA,EAC9ChB,GAAW,MAAM,QAAQ9rC,GAAQ,CAC/B8sC,EAAY9sC,EAAK,EAAE,EAAIA,EAAK,QAAQ,IAAIR,IAAW,CACjD,GAAIA,EAAO,GACX,MAAOA,EAAO,MACd,SAAUA,EAAO,SACjB,eAAgBA,EAAO,eAAe,IAAIX,IAAS,CACjD,GAAGA,EACH,SAAU,CAAA,EACV,CAAA,EACF,CACJ,CAAC,EACD,QAAQ,IAAI,uBAAwBiuC,CAAW,EAC/CiC,EAAWjC,CAAW,EAGtB,GAAI,CACF,MAAMqC,EAAc,MAAMx1C,EAAO,WAAW,eAAeyoB,CAAM,EACjEqsB,EAAYU,CAAW,CACzB,OAAS3uC,EAAO,CACd,QAAQ,KAAK,mBAAoBA,CAAK,EACtCiuC,EAAY,CACV,GAAIrsB,EACJ,KAAM,OACN,MAAO,EACP,OAAQ,2BACR,OAAQ,CAAC,IAAI,CAAA,CACd,CACH,CAGA,GAAI,CACF,MAAMgtB,EAAkB,MAAMz1C,EAAO,WAAW,eAAA,EAChDg1C,EAAeS,CAAe,CAChC,OAAS5uC,EAAO,CACd,QAAQ,KAAK,mBAAoBA,CAAK,EACtCmuC,EAAe,CACb,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,KAAA,EAClC,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,KAAA,CAAM,CACzC,CACH,CAEF,OAAS11B,EAAK,CAIZ,GAHA,QAAQ,MAAM,UAAWA,CAAG,EAGxBtf,EAAO,mBAAqB,OAAQ,CACtC,QAAQ,IAAI,oBAAoB,EAEhC,MAAM01C,EAAgB,CACpB,OAAAjtB,EACA,SAAU6pB,EACV,YAAa,UACb,YAAa,EACb,WAAYH,GAAW,MAAM,OAC7B,eAAgB,EAChB,gBAAiB,GACjB,OAAQ,cACR,aAAc,IAAI,KAAA,EAAO,YAAA,EACzB,MAAOA,GAAW,MAAM,IAAI,CAAC9rC,EAAMuM,KAAW,CAC5C,OAAQvM,EAAK,GACb,MAAOA,EAAK,MACZ,YAAaA,EAAK,YAClB,eAAgBA,EAAK,eACrB,kBAAmBA,EAAK,kBACxB,aAAcA,EAAK,QAAQ,OAC3B,iBAAkBuM,EAAQ,EAAI,KAAK,MAAMvM,EAAK,QAAQ,OAAS,EAAG,EAAI,EACtE,mBAAoBuM,EAAQ,EAAI,GAAK,EACrC,OAAQA,EAAQ,EAAI,cAAyB,cAC7C,aAAcA,EAAQ,MAAQ,KAAA,EAAO,cAAgB,OACrD,SAAUA,IAAU,EACpB,MAAO,sBAAsBvM,EAAK,EAAE,GACpC,KAAMwrC,GAAcxrC,EAAK,cAAc,GAAKwrC,GAAc,OAAA,EAC1D,CAAA,EAEJqD,EAAaQ,CAAa,EAG1B,MAAMvC,EAAwC,CAAA,EAC9ChB,GAAW,MAAM,QAAQ9rC,GAAQ,CAC/B8sC,EAAY9sC,EAAK,EAAE,EAAIA,EAAK,QAAQ,IAAIR,IAAW,CACjD,GAAIA,EAAO,GACX,MAAOA,EAAO,MACd,SAAUA,EAAO,SACjB,eAAgBA,EAAO,eAAe,IAAIX,IAAS,CACjD,GAAGA,EACH,SAAU,CAAA,EACV,CAAA,EACF,CACJ,CAAC,EACDkwC,EAAWjC,CAAW,EAGtB2B,EAAY,CACV,GAAIrsB,EACJ,KAAM,OACN,MAAO,EACP,OAAQ,2BACR,OAAQ,CAAC,IAAI,CAAA,CACd,EACDusB,EAAe,CACb,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,KAAA,EAClC,CAAE,GAAI,KAAM,MAAO,MAAO,OAAQ,KAAA,CAAM,CACzC,CACH,MAEE9a,EAAS5a,aAAe,MAAQA,EAAI,QAAU,QAAQ,EACtD41B,EAAa,IAAI,CAErB,QAAA,CACEvrB,EAAW,EAAK,CAClB,CACF,EAAG,CAAC3pB,CAAM,CAAC,EAEL21C,EAAepd,cAAaia,GAAqB,CACrD8C,EAAmBM,GACjBA,EAAK,SAASpD,CAAQ,EAClBoD,EAAK,OAAO7hC,GAAMA,IAAOy+B,CAAQ,EACjC,CAAC,GAAGoD,EAAMpD,CAAQ,CAAA,CAE1B,EAAG,CAAA,CAAE,EAGCqD,EAAgBtd,cAAahxB,GAA0B,CAC3D8tC,EAAgB9tC,CAAM,CACxB,EAAG,CAAA,CAAE,EAGCuuC,EAAevd,cAAawd,GAA6C,CAC7EnB,EAAUvW,GAAc8V,GAAa9V,EAAY0X,CAAO,CAAC,CAC3D,EAAG,CAAA,CAAE,EAGLhpB,EAAAA,UAAU,IAAM,CAKd,GAJA,QAAQ,IAAI,2BAA4BkoB,CAAS,EACjD,QAAQ,IAAI,oBAAqBA,GAAW,KAAK,EACjD,QAAQ,IAAI,4BAA6BA,GAAW,OAAO,MAAM,EAE7DA,GAAaA,EAAU,MAAM,OAAS,EAAG,CAC3C,QAAQ,IAAI,4BAA4B,EACxC,MAAMe,EAAaf,EAAU,MAAM,KAAK5uC,GAAQA,EAAK,QAAQ,EAC7D,QAAQ,IAAI,qBAAsB2vC,CAAU,EAC5C,MAAMC,EAAoBD,GAAY,QAAUf,EAAU,MAAM,CAAC,EAAE,OACnE,QAAQ,IAAI,+BAAgCgB,CAAiB,EAC7DZ,EAAgBY,CAAiB,EACjC,QAAQ,IAAI,8CAA+CA,CAAiB,CAC9E,MACE,QAAQ,IAAI,yDAAyD,CAEzE,EAAG,CAAChB,CAAS,CAAC,EAEd,MAAM7H,EAA4C,CAEhD,SAAAyH,EACA,YAAAE,EACA,UAAAE,EACA,QAAAE,EAGA,QAAA1wC,EACA,MAAAoC,EACA,aAAAG,EACA,gBAAAV,EAGA,OAAAtG,EACA,MAAOA,EAAO,MACd,qBAAsBA,EAAO,aAAa,qBAG1C,WAAA2pB,EACA,SAAAuQ,EACA,cAAA2b,EACA,aAAAF,EACA,aAAAJ,EACA,aAAAO,CAAA,EAGF,aACGxB,GAAwB,SAAxB,CAAiC,MAAOlH,EACtC,SAAAnqC,EACH,CAEJ,EC/NMizC,GAAmE,CAAC,CACxE,QAAA5D,EACA,OAAA7pB,EACA,cAAApjB,EACA,UAAAb,EACA,SAAU2xC,EACV,YAAaC,CACf,IAAM,CACJ,KAAM,CACJ,SAAUC,EACV,YAAaC,EACb,UAAArB,EACA,QAAAE,EACA,QAAA1wC,EACA,MAAAoC,EACA,aAAAG,EACA,gBAAAV,EACA,cAAAuvC,EACA,aAAAF,EACA,aAAAJ,CAAA,EACEf,GAAA,EAGEK,EAAWsB,GAAgBE,EAC3BtB,EAAcqB,GAAmBE,EAEvCvpB,EAAAA,UAAU,IAAM,CACd,QAAQ,IAAI,wEAAwE,EACpF,QAAQ,IAAI,WAAYulB,EAAS,UAAW7pB,CAAM,EAClD8sB,EAAajD,EAAS7pB,CAAM,CAC9B,EAAG,CAAC6pB,EAAS7pB,EAAQ8sB,CAAY,CAAC,EAGlCxoB,EAAAA,UAAU,IAAM,CACd,QAAQ,IAAI,6BAA8B/lB,CAAY,EACtD,QAAQ,IAAI,wBAAyBmuC,CAAO,EAG5C,MAAMoB,EAAgBtB,GAAW,OAAO,QAAa5uC,EAAK,SAAWW,CAAY,GAAK,KAChFwvC,EAAkBD,GAAiBvvC,GAAgBmuC,EAAQnuC,CAAY,EAAI,CAC/E,GAAIuvC,EAAc,OAClB,MAAOA,EAAc,MACrB,YAAaA,EAAc,YAC3B,kBAAmBA,EAAc,kBACjC,aAAcA,EAAc,aAC5B,eAAgBA,EAAc,eAC9B,QAASpB,EAAQnuC,CAAY,CAAA,EAC3B,KAEJ,QAAQ,IAAI,uBAAwBwvC,CAAe,CACrD,EAAG,CAACxvC,EAAcmuC,EAASF,CAAS,CAAC,EAGrC,MAAMsB,EAAgBtB,GAAW,OAAO,QAAa5uC,EAAK,SAAWW,CAAY,GAAK,KAGhFgvC,EAAaO,GAAiBvvC,GAAgBmuC,EAAQnuC,CAAY,EAAI,CAC1E,GAAIuvC,EAAc,OAClB,MAAOA,EAAc,MACrB,YAAaA,EAAc,YAC3B,kBAAmBA,EAAc,kBACjC,aAAcA,EAAc,aAC5B,eAAgBA,EAAc,eAC9B,QAASpB,EAAQnuC,CAAY,CAAA,EAC3B,KAEJ,OAAIvC,QAEC,MAAA,CAAI,UAAW,mCAAmCD,GAAa,EAAE,GAAI,cAAY,0BAChF,SAAAI,MAAC,OAAI,UAAU,kBAAkB,cAAY,kBAAkB,kBAE/D,EACF,EAIAiC,EAEAtB,OAAC,OAAI,UAAW,iCAAiCf,GAAa,EAAE,GAAI,cAAY,0BAC9E,SAAA,CAAAI,MAAC,MAAA,CAAI,UAAU,gBAAgB,cAAY,gBACxC,SAAAiC,EACH,EACAjC,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM2wC,EAAajD,EAAS7pB,CAAM,EAC3C,UAAU,eACX,SAAA,IAAA,CAAA,CAED,EACF,EAKFljB,EAAAA,KAAC,MAAA,CACC,UAAW,2BAA2Bf,GAAa,EAAE,GACrD,cAAY,0BAGZ,SAAA,CAAAI,EAAAA,IAAC,MAAA,CAAI,UAAU,cACb,SAAAA,EAAAA,IAAC4lB,GAAA,CACC,SAAUqqB,GAAY,OACtB,aAAcE,CAAA,CAAA,EAElB,EAGAnwC,EAAAA,IAAC,MAAA,CAAI,UAAU,eACb,SAAAA,EAAAA,IAAC+B,GAAA,CACC,KAAMsuC,EACN,aAAAjuC,EACA,aAAc6uC,EACd,QAAApxC,CAAA,CAAA,EAEJ,EAGAG,EAAAA,IAAC,MAAA,CAAI,UAAU,eACb,SAAAA,EAAAA,IAACwB,GAAA,CACC,KAAM4vC,EACN,gBAAA1vC,EACA,eAAgBqvC,EAChB,cAAetwC,IAAkB,IAAM,CAAE,GACzC,QAAAZ,CAAA,CAAA,CACF,CACF,CAAA,CAAA,CAAA,CAGN,EAGagyC,GAA6Dt0C,GAEtEyC,EAAAA,IAAC8vC,IAAyB,OAAQvyC,EAAM,OACtC,SAAAyC,EAAAA,IAACsxC,GAAA,CAA6B,GAAG/zC,CAAA,CAAO,CAAA,CAC1C,ECxIEu0C,GAAiB,CACrBC,EACAC,EACAC,EAAoB,KACO,CAE3B,GAAI,CAACF,EAAW,OACd,MAAO,CACL,QAAS,GACT,UAAW,GACX,aAAc,OAAA,EAKlB,MAAMG,EAAgB,WAAWH,CAAU,EAC3C,GAAI,MAAMG,CAAa,EACrB,MAAO,CACL,QAAS,GACT,UAAW,GACX,aAAc,UAAA,EAKlB,GAAIA,EAAgB,EAClB,MAAO,CACL,QAAS,GACT,UAAW,GACX,aAAc,SAAA,EAMlB,MAAMC,EADa,KAAK,IAAID,EAAgBF,CAAa,GACzBC,EAEhC,MAAO,CACL,QAAS,GACT,UAAAE,EACA,aAAcA,EAAY,OAAY,aAAA,CAE1C,EAOaC,GAA0B,IAC9BxY,GAAAA,OAAiC,CAACC,EAAKC,KAAS,CAErD,aAAc,WACd,WAAY,GACZ,UAAW,KACX,eAAgB,GAChB,YAAa,KACb,gBAAiB,KAGjB,eAAiBuY,GAAyC,CACxDxY,EAAI,CACF,YAAAwY,EACA,aAAc,WACd,WAAY,GACZ,UAAW,KACX,eAAgB,GAChB,gBAAiB,IAAA,CAClB,CACH,EAGA,iBAAmBC,GAAmB,CACpCzY,EAAI,CACF,WAAYyY,EACZ,gBAAiB,IAAA,CAClB,CACH,EAGA,aAAeA,GAAmB,CAChC,MAAMvyB,EAAQ+Z,EAAA,EAGd,GAAI,CAAC/Z,EAAM,YAAa,CACtB8Z,EAAI,CACF,gBAAiB,iBAAA,CAClB,EACD,MACF,CAGA,MAAMmY,EAAgBjyB,EAAM,YAAY,aAAa,OAASA,EAAM,YAAY,OAAO,MAGjFwyB,EAAmB,OAAOP,CAAa,EAGvCC,EAAYlyB,EAAM,YAAY,aAAa,WAAa,GACxDiR,EAAmB8gB,GAAeQ,EAAQC,EAAkBN,CAAS,EAE3E,GAAI,CAACjhB,EAAiB,QAAS,CAE7B6I,EAAI,CACF,WAAYyY,EACZ,gBAAiBthB,EAAiB,cAAgB,QAAA,CACnD,EACD,MACF,CAGA6I,EAAI,CACF,WAAYyY,EACZ,UAAWthB,EAAiB,UAC5B,eAAgB,GAChB,gBAAiB,KACjB,aAAcA,EAAiB,UAAY,UAAY,aAAA,CACxD,CACH,EAGA,aAAc,IAAM,CAClB6I,EAAI,CACF,aAAc,WACd,WAAY,GACZ,UAAW,KACX,eAAgB,GAChB,gBAAiB,IAAA,CAClB,CACH,EAGA,aAAc,IAAM,CAClBA,EAAI,CACF,aAAc,WACd,WAAY,GACZ,UAAW,KACX,eAAgB,GAChB,gBAAiB,IAAA,CAClB,CACH,CAAA,EACA,EAQS2Y,GAA8BJ,GAAA,EAK9BK,GAAkB,IACtBD,GAA6BzyB,GAAUA,EAAM,YAAY,EAMrD2yB,GAAgB,IACpBF,GAA6BzyB,GAAUA,EAAM,UAAU,EAMnD4yB,GAAuB,IAC3BH,GAA6BzyB,GAAUA,EAAM,SAAS,EAMlD6yB,GAA0B,IAC9BJ,GAA6BzyB,GAAUA,EAAM,cAAc,EAMvD8yB,GAAqB,IACzBL,GAA6BzyB,GAAUA,EAAM,eAAe,EAMxD+yB,GAAiB,IACrBN,GAA6BzyB,GAAUA,EAAM,WAAW,EAOpDgzB,GAAoB,IAC/BP,GACEjY,GAAAA,WAGIxa,IAAW,CACb,iBAAkBA,EAAM,iBACxB,aAAcA,EAAM,aACpB,aAAcA,EAAM,aACpB,aAAcA,EAAM,aACpB,eAAgBA,EAAM,cAAA,EACtB,CACJ,ECtMIizB,GAA2BrD,EAAAA,cAAgC,IAAI,EAmDxDsD,GAAuB,IAAM,CACxC,MAAMC,EAAQrD,EAAAA,WAAWmD,EAAwB,EACjD,GAAI,CAACE,EACH,MAAM,IAAI,MAAM,yDAAyD,EAE3E,OAAOA,CACT,EAKaC,GAA2B,IAAM,CAC5C,MAAMD,EAAQD,GAAA,EACRG,EAAWv0C,EAAM,YAAakhB,GAAoCA,EAAM,aAAc,EAAE,EAC9F,OAAOmzB,EAAME,CAAQ,CACvB,EAKaC,GAAyB,IAAM,CAC1C,MAAMH,EAAQD,GAAA,EACRG,EAAWv0C,EAAM,YAAakhB,GAAoCA,EAAM,WAAY,EAAE,EAC5F,OAAOmzB,EAAME,CAAQ,CACvB,EAcaE,GAAmC,IAAM,CACpD,MAAMJ,EAAQD,GAAA,EACRG,EAAWv0C,EAAM,YAAakhB,GAAoCA,EAAM,eAAgB,EAAE,EAChG,OAAOmzB,EAAME,CAAQ,CACvB,EAKaG,GAA8B,IAAM,CAC/C,MAAML,EAAQD,GAAA,EACRG,EAAWv0C,EAAM,YAAakhB,GAAoCA,EAAM,gBAAiB,EAAE,EACjG,OAAOmzB,EAAME,CAAQ,CACvB,EAeaI,GAA6B,IAC1BP,GAAA,EAEZ1Y,GAAAA,WAAYxa,IAAqC,CAC/C,iBAAkBA,EAAM,iBACxB,aAAcA,EAAM,aACpB,aAAcA,EAAM,aACpB,aAAcA,EAAM,aACpB,eAAgBA,EAAM,cAAA,EACtB,CAAA,ECtHO0yB,GAAkB,IAAM,CACnC,GAAI,CAEF,OAAOU,GAAA,CACT,MAAgB,CAEd,OAAOM,GAAA,CACT,CACF,EAMaf,GAAgB,IAAM,CACjC,GAAI,CACF,OAAOW,GAAA,CACT,MAAgB,CACd,OAAOK,GAAA,CACT,CACF,EAkBad,GAA0B,IAAM,CAC3C,GAAI,CACF,OAAOU,GAAA,CACT,MAAgB,CACd,OAAOK,GAAA,CACT,CACF,EAMad,GAAqB,IAAM,CACtC,GAAI,CACF,OAAOU,GAAA,CACT,MAAgB,CACd,OAAOK,GAAA,CACT,CACF,EAmBab,GAAoB,IAAM,CACrC,GAAI,CACF,OAAOS,GAAA,CACT,MAAgB,CACd,OAAOK,GAAA,CACT,CACF,ECjGaC,GAA8C,CAAC,CAC1D,YAAAzB,EACA,WAAAN,EACA,eAAAgC,EACA,eAAAC,EACA,eAAAC,EACA,gBAAA5b,CACF,IAAM,CACJ,MAAM6b,EAAgBnxC,GAAuB,CAC3CA,EAAE,eAAA,EACFixC,EAAejC,CAAU,CAC3B,EAEMoC,EAAsB33C,GAAkB,CAC5Cy3C,EAAez3C,CAAK,CACtB,EAEA,aACG,MAAA,CAAI,UAAU,2BACb,SAAAmE,EAAAA,KAAC,MAAA,CAAI,UAAU,sBAEb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,wBACb,SAAAA,EAAAA,IAACmoC,GAAA,CACC,KAAM,CACJ,GAAIkK,EAAY,GAChB,MAAOA,EAAY,MACnB,KAAMA,EAAY,KAClB,QAASA,EAAY,QAAQ,UAAU,OAC9BA,EAAY,QAAQ,UAAU,SAC9B,CAAA,CAAC,EAEZ,MAAM,WACN,OAAQ,CAAE,KAAM,OAAQ,QAAS,MAAO,OAAQ,GAAO,OAAQ,EAAA,CAAM,CAAA,EAEzE,EAGC0B,GACCpzC,EAAAA,KAAC,MAAA,CAAI,UAAU,wBACb,SAAA,CAAAA,EAAAA,KAAC,OAAA,CACC,SAAUuzC,EACV,UAAU,cAEV,SAAA,CAAAl0C,EAAAA,IAAC,QAAA,CAAM,UAAU,eAAe,SAAA,KAEhC,EACAA,EAAAA,IAAC,QAAA,CACC,KAAK,SACL,MAAO+xC,EACP,SAAWhvC,GAAMoxC,EAAmBpxC,EAAE,OAAO,KAAK,EAClD,UAAW,gBAAgBs1B,EAAkB,QAAU,QAAQ,GAC/D,YAAY,IACZ,SAAQ,EAAA,CAAA,EAEVr4B,EAAAA,IAAC,QAAK,UAAU,cACb,WAAY,UAAU,YAAcqyC,EAAY,UAAU,QAAA,CAC7D,EACAryC,EAAAA,IAACT,GAAA,CACC,KAAK,SACL,KAAK,KACL,UAAU,gBACX,SAAA,MAAA,CAAA,CAED,CAAA,CAAA,EAED84B,GACC13B,EAAAA,KAAC,MAAA,CAAI,UAAU,mBACb,SAAA,CAAAX,EAAAA,IAAC,QAAK,SAAA,IAAA,CAAE,EACRA,EAAAA,IAAC,QAAM,SAAAq4B,CAAA,CAAgB,CAAA,CAAA,CACzB,CAAA,CAAA,CAEJ,CAAA,CAAA,CAEJ,CAAA,CACF,CAEJ,EC1Ea+b,GAAgD,CAAC,CAC5D,YAAA/B,EACA,eAAAtJ,EAAiB,EACnB,IAAM,CACJ,QAAQ,IAAI,iCAAkCsJ,CAAW,EACzD,QAAQ,IAAI,qCAAsCA,GAAa,QAAQ,QAAQ,EAC/E,QAAQ,IAAI,2CAA4CA,GAAa,QAAQ,UAAU,KAAK,EAC5F,QAAQ,IAAI,6CAA8CA,GAAa,QAAQ,UAAU,OAAO,EAoChG,MAAMgC,GAjCyB,IAAM,CAEnC,MAAMC,EAAcjC,EAAY,QAAQ,QAAQ,MAChD,GAAIiC,GAAe,MAAM,QAAQA,CAAW,GAAKA,EAAY,OAAS,EACpE,eAAQ,IAAI,mCAAmC,EACxCA,EAIT,MAAMD,EAAgBhC,EAAY,QAAQ,QAAQ,QAClD,GAAIgC,GAAiB,MAAM,QAAQA,CAAa,GAAKA,EAAc,OAAS,EAC1E,eAAQ,IAAI,qCAAqC,EAC1CA,EAIT,MAAME,EAAgBlC,EAAY,QAAQ,UAAU,MACpD,GAAIkC,GAAiB,MAAM,QAAQA,CAAa,GAAKA,EAAc,OAAS,EAC1E,eAAQ,IAAI,qCAAqC,EAC1CA,EAIT,MAAMC,EAAkBnC,EAAY,QAAQ,UAAU,QACtD,OAAImC,GAAmB,MAAM,QAAQA,CAAe,GAAKA,EAAgB,OAAS,GAChF,QAAQ,IAAI,uCAAuC,EAC5CA,IAGT,QAAQ,IAAI,2BAA2B,EAChC,CAAA,EACT,GAEsB,EAGtB,GAAIH,EAAc,SAAW,EAAG,CAC9B,MAAMI,EACJz0C,EAAAA,IAAC,MAAA,CAAI,UAAU,0BACb,eAAC,IAAA,CAAE,UAAU,wBAAwB,SAAA,QAAA,CAAM,EAC7C,EAGF,OAAI+oC,EAEA/oC,EAAAA,IAACsqC,GAAA,CACC,YAAY,UACZ,UAAW,CAAE,KAAM,WAAY,MAAO,KAAM,QAAS,EAAA,EACrD,eAAgB,GAEf,SAAAmK,CAAA,CAAA,EAML9zC,EAAAA,KAAC,MAAA,CAAI,UAAU,4BACb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,wBAAwB,SAAA,KAEtC,EACCy0C,CAAA,EACH,CAEJ,CAGA,MAAMC,QACH,MAAA,CAAI,UAAU,0BAEZ,SAAAL,EAAc,IAAI,CAACM,EAAc3mC,IAAU,CAC1C,KAAM,CAAE,KAAA7S,EAAM,QAAAoN,EAAS,MAAA/F,EAAO,MAAAwlB,GAAU2sB,EAExC,OAAQx5C,EAAA,CACN,IAAK,OACH,OACE6E,EAAAA,IAAC,IAAA,CAEC,UAAU,6BACV,MAAAwC,EAEC,SAAA+F,CAAA,EAJIyF,CAAA,EAQX,IAAK,UACH,OACEhO,EAAAA,IAAC,MAAA,CAAgB,UAAU,gCACzB,SAAAA,EAAAA,IAACmoC,GAAA,CACC,KAAM,CACJ,GAAI,WAAWn6B,CAAK,GACpB,MAAOqkC,EAAY,MACnB,KAAMA,EAAY,KAClB,QAAS,CACP,CACE,KAAM,UACN,QAAA9pC,EACA,MAAOyf,GAAS,CAACzf,CAAO,CAAA,CAC1B,CACF,EAEF,OAAQ,CAAE,KAAM,MAAA,EAChB,UAAWwgC,EAAiB,eAAiB,EAAA,CAAA,GAfvC/6B,CAiBV,EAGJ,QACE,OACErN,EAAAA,KAAC,IAAA,CAAc,UAAU,8BAA8B,SAAA,CAAA,aAC1CxF,CAAA,CAAA,EADL6S,CAER,CAAA,CAGR,CAAC,CAAA,CACH,EAGF,OAAI+6B,EAEA/oC,EAAAA,IAACsqC,GAAA,CACC,YAAY,UACZ,UAAW,CAAE,KAAM,WAAY,MAAO,KAAM,QAAS,EAAA,EACrD,eAAgB,GAEf,SAAAoK,CAAA,CAAA,EAML/zC,EAAAA,KAAC,MAAA,CAAI,UAAU,4BAEb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,wBAAwB,SAAA,KAEtC,EACC00C,CAAA,EACH,CAEJ,ECtJaE,GAA4C,CAAC,CACxD,YAAAvC,EACA,WAAAN,EACA,eAAAhJ,EAAiB,EACnB,IAAM,CAEJ,MAAM2L,EACJ/zC,EAAAA,KAAC,MAAA,CAAI,UAAU,wBAEb,SAAA,CAAAX,MAAC,IAAA,CAAE,UAAU,yBACV,SAAAqyC,EAAY,UAAU,SACzB,EAGAryC,EAAAA,IAAC,MAAA,CAAI,UAAU,sBACb,SAAAA,EAAAA,IAACmoC,GAAA,CACC,KAAM,CACJ,GAAI,iBACJ,MAAOkK,EAAY,MACnB,KAAMA,EAAY,KAClB,QAASA,EAAY,QAAQ,UAAU,OAC5BA,EAAY,QAAQ,UAAU,SAC9B,CAAA,CAAC,EAEd,MAAM,WACN,OAAQ,CAAE,KAAM,MAAA,EAChB,UAAWtJ,EAAiB,eAAiB,EAAA,CAAA,EAEjD,EAGApoC,EAAAA,KAAC,IAAA,CAAE,UAAU,4BAA4B,SAAA,CAAA,SACjCX,EAAAA,IAAC,OAAA,CAAK,UAAU,kCACnB,SAAA+xC,CAAA,CACH,CAAA,CAAA,CACF,CAAA,EACF,EAGF,OAAIhJ,EAEA/oC,EAAAA,IAACsqC,GAAA,CACC,YAAY,UACZ,UAAW,CAAE,KAAM,SAAU,MAAO,KAAM,QAAS,EAAA,EACnD,eAAgB,GAEf,SAAAoK,CAAA,CAAA,EAML/zC,EAAAA,KAAC,MAAA,CAAI,UAAU,0BAEb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,sBAAsB,SAAA,KAEpC,EACC00C,CAAA,EACH,CAEJ,EClCMG,GAAgB7mC,GACL,CACb,CAAE,MAAO,6BAA8B,GAAI,yBAAA,EAC3C,CAAE,MAAO,4BAA6B,GAAI,wBAAA,EAC1C,CAAE,MAAO,2BAA4B,GAAI,uBAAA,CAAwB,EAErDA,EAAQ,CAAC,EAOZ8mC,GAAkD,CAAC,CAC9D,KAAA1gB,EACA,YAAAie,EACA,WAAA0C,CACF,IAAM,CACJ,KAAM,CAAE,MAAAC,EAAO,YAAAC,EAAa,YAAAC,CAAA,EAAgB9gB,EAAK,QAC3C+gB,EAAiB,CAAC,CAACD,EAGnBE,EAAYP,GAAaE,EAAa,CAAC,EAGvCM,EAAqB,CACzB,CACE,KAAM,OACN,QAASJ,EAAY,QAAQ,QAAS;AAAA,CAAI,EAAE,QAAQ,WAAY,EAAE,EAClE,MAAO,CACL,SAAU,sBACV,MAAO,2BACP,WAAY,2BAAA,CACd,CACF,EAGF,OACEt0C,EAAAA,KAAC,MAAA,CACC,UAAU,6BACV,MAAO,CACL,uBAAwBy0C,EAAU,MAClC,oBAAqBA,EAAU,EAAA,EAIjC,SAAA,CAAAz0C,EAAAA,KAAC,KAAA,CAAG,UAAU,yBACZ,SAAA,CAAAX,EAAAA,IAAC,OAAA,CAAK,UAAU,0BAA2B,SAAA+0C,EAAW,EACtD/0C,EAAAA,IAAC,QAAM,SAAAg1C,CAAA,CAAM,CAAA,EACf,EAGAr0C,EAAAA,KAAC,MAAA,CAAI,UAAU,2BACb,SAAA,CAAAX,EAAAA,IAACmoC,GAAA,CACC,KAAM,CACJ,GAAI,GAAG/T,EAAK,EAAE,eACd,MAAOie,EAAY,MACnB,KAAMA,EAAY,KAClB,QAASgD,CAAA,EAEX,OAAQ,CACN,KAAM,OACN,QAAS,OACT,OAAQ,GACR,OAAQ,EAAA,EAEV,UAAU,2BAAA,CAAA,EAIXF,GACCn1C,EAAAA,IAAC,MAAA,CAAI,UAAU,mCACZ,SAAAk1C,EAAY,OAAS,sBAAwBA,EAAY,QAAUA,EAAY,UAAU,QACxFl1C,EAAAA,IAAC2mC,GAAA,CACC,OAAQuO,EAAY,QAAUA,EAAY,UAAU,OACpD,kBAAoB11C,GAAa,QAAQ,IAAI,sBAAuBA,CAAQ,EAC5E,oBAAqB,IAAM,QAAQ,IAAI,oBAAoB,EAC3D,QAAUyC,GAAU,QAAQ,MAAM,4BAA6BA,CAAK,CAAA,CAAA,EAGtEjC,EAAAA,IAAC8lC,GAAA,CACC,OAAQoP,EAAY,QAAU,CAAA,EAC9B,MAAO,IACP,OAAQ,IACR,YAAaA,EAAY,aAAe,CAAC,IAAK,GAAI,GAAI,GAAG,EACzD,SAAUA,EAAY,UAAY,GAClC,SAAUA,EAAY,UAAY,GAClC,KAAK,OACL,UAAU,SAAA,CAAA,CACZ,CAEJ,CAAA,CAAA,CAEJ,CAAA,CAAA,CAAA,CAGN,EC+LO,SAASI,GACdC,EAC4B,CAC5B,OAAQA,EAA4B,QAAU,MAChD,CAKO,SAASC,GACdD,EACa,CACb,GAAID,GAAoBC,CAAW,EACjC,OAAOA,EAIT,GAAI,MAAM,QAAQA,CAAW,EAAG,CAE9B,GAAIA,EAAY,SAAW,EACzB,MAAO,CACL,MAAO,CAAA,EACP,YAAa,EACb,SAAU,eACV,eAAgB,CAAA,EAKpB,MAAME,EAAYF,EAAY,CAAC,EAI/B,GAHuBE,GAAaA,EAAU,UACvBA,EAAU,QAAQ,QAAU,QAAaA,EAAU,QAAQ,cAAgB,QAE9E,CAElB,MAAMC,EAA2BH,EAAY,IAAKnhB,IAAe,CAC/D,GAAIA,EAAK,GACT,KAAMA,EAAK,KACX,MAAOA,EAAK,QAAQ,OAAS,GAC7B,YAAaA,EAAK,QAAQ,aAAe,GACzC,YAAaA,EAAK,QAAQ,YAC1B,SAAUA,EAAK,QAAQ,SACvB,aAAcA,EAAK,QAAQ,aAC3B,WAAYA,EAAK,QAAQ,UAAA,EACzB,EAEF,MAAO,CACL,MAAAshB,EACA,YAAaA,EAAM,OACnB,SAAU,eACV,eAAgBA,EAAM,OAAS,EAAA,CAEnC,KAEE,OAAO,CACL,MAAOH,EACP,YAAaA,EAAY,OACzB,SAAU,eACV,eAAgBA,EAAY,OAAS,EAAA,CAG3C,CAGA,MAAO,CACL,MAAO,CAAA,EACP,YAAa,EACb,SAAU,eACV,eAAgB,CAAA,CAEpB,CC5XO,MAAMI,GAA0C,CAAC,CACtD,YAAAtD,EACA,eAAAtJ,EAAiB,EACnB,IAAM,CACJ,KAAM,CAAC6M,EAAmBC,CAAoB,EAAIxgB,EAAAA,SAAS,EAAK,EAE1DygB,EAAgBzD,GAAa,QAAQ,OAAO,OAASA,GAAa,QAAQ,OAAO,QACjF0D,EAAW,MAAM,QAAQD,CAAY,GAAKA,EAAa,OAAS,EAGhEE,EAAwB1tB,EAAAA,QAAQ,IACpCktB,GAAqBnD,EAAY,WAAW,EAC5C,CAACA,EAAY,WAAW,CAAA,EAEpB4D,EAAkBD,EAAsB,MAAM,OAAS,EAEvDE,EAA0B5tB,EAAAA,QAAQ,IACjC2tB,EAEED,EAAsB,MAAM,IAAK5hB,IAAU,CAChD,GAAGA,EACH,QAAS,CACP,MAAOA,EAAK,MACZ,YAAaA,EAAK,YAClB,YAAaA,EAAK,YAAc,CAC9B,GAAGA,EAAK,YACR,YAAcA,EAAK,YAAY,OAAS,SAAW,MAAM,QAAQA,EAAK,YAAY,WAAW,GAC3FA,EAAK,YAAY,YAAY,SAAW,EACtC,CACAA,EAAK,YAAY,YAAY,CAAC,EAC9BA,EAAK,YAAY,YAAY,CAAC,EAC9BA,EAAK,YAAY,YAAY,CAAC,EAC9BA,EAAK,YAAY,YAAY,CAAC,CAAA,EAE9B,CAAC,IAAK,GAAI,GAAI,GAAG,CAAA,EACnB,MAAA,CACN,EACA,EApB2B,CAAA,EAqB5B,CAAC6hB,EAAiBD,EAAsB,KAAK,CAAC,EAG3CtB,EACJ/zC,EAAAA,KAAC,MAAA,CAAI,UAAU,uBAEZ,SAAA,CAAAo1C,EACCp1C,EAAAA,KAAAsC,WAAA,CAEG,SAAA,CAAA,QAAQ,IAAI,iCAAkC6yC,CAAY,EAC1DA,GAAc,UAAU,CAACpO,EAAO15B,IAAU,CACrC05B,EAAM,OAAS,qBACjB,QAAQ,IAAI,4CAA4C15B,CAAK,MAAO,CAClE,KAAM05B,EAAM,KACZ,YAAa,CAAC,CAACA,EAAM,SACrB,SAAUA,EAAM,SAChB,UAAW,CAAC,CAACA,EAAM,OACnB,OAAQA,EAAM,OACd,UAAW,CAAC,CAACA,EAAM,OACnB,OAAQA,EAAM,OACd,aAAc,CAAC,CAACA,EAAM,UACtB,UAAWA,EAAM,SAAA,CAClB,CAEL,CAAC,EACD1nC,EAAAA,IAACmoC,GAAA,CACC,KAAM,CACJ,GAAI,cACJ,MAAOkK,EAAY,MACnB,KAAMA,EAAY,KAClB,QAASyD,CAAA,EAEX,MAAM,QACN,OAAQ,CAAE,KAAM,OAAQ,UAAW,WAAY,IAAK,MAAA,EACpD,UAAW/M,EAAiB,eAAiB,EAAA,CAAA,CAC/C,EACF,EAEA/oC,EAAAA,IAAC,MAAA,CAAI,UAAU,qBAAqB,SAAA,eAEpC,EAIFA,EAAAA,IAAC,MAAA,CAAI,UAAU,gCACb,SAAAA,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAAS,IAAM61C,EAAsB1R,GAAM,CAACA,CAAC,EAC7C,UAAU,sBAET,WAAoB,WAAa,UAAA,CAAA,EAEtC,EAGCyR,GACCj1C,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,8BAA8B,SAAA,SAE5C,EACCi2C,QACE,MAAA,CAAI,UAAU,6BACZ,SAAAC,EAAwB,IAAI,CAAC9hB,EAAMpmB,IAClChO,EAAAA,IAAC80C,GAAA,CAEC,KAAA1gB,EACA,YAAAie,EACA,WAAYrkC,EAAQ,CAAA,EAHfomB,EAAK,EAAA,CAKb,CAAA,CACH,QAEC,MAAA,CAAI,UAAU,qBAAqB,SAAA,UAAA,CAEpC,CAAA,CAAA,CAEJ,CAAA,EAEJ,EAGF,OAAI2U,EAEA/oC,EAAAA,IAACsqC,GAAA,CACC,YAAY,UACZ,UAAW,CAAE,KAAM,QAAS,MAAO,KAAM,QAAS,EAAA,EAClD,eAAgB,GAEf,SAAAoK,CAAA,CAAA,EAML/zC,EAAAA,KAAC,MAAA,CAAI,UAAU,yBAEb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,qBAAqB,SAAA,KAEnC,EACC00C,CAAA,EACH,CAEJ,EC/IayB,GAAoD,CAAC,CAChE,YAAA9D,EACA,WAAAN,EACA,eAAAqE,CACF,KACE,QAAQ,IAAI,mCAAoC/D,CAAW,EAC3D,QAAQ,IAAI,uCAAwCA,GAAa,QAAQ,QAAQ,EACjF,QAAQ,IAAI,6CAA8CA,GAAa,QAAQ,UAAU,KAAK,EAC9F,QAAQ,IAAI,+CAAgDA,GAAa,QAAQ,UAAU,OAAO,SAE/F,MAAA,CAEC,SAAA,CAAAryC,EAAAA,IAAC,OAAI,UAAU,2BACb,SAAAW,EAAAA,KAAC,MAAA,CAAI,UAAU,8BACb,SAAA,CAAAX,MAAC,MAAA,CAAI,UAAU,mBAAmB,cAAW,GAAC,SAAA,KAE9C,EAEAW,EAAAA,KAAC,MAAA,CAAI,UAAU,kDACb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,oBAAoB,SAAA,aAElC,EAEAW,EAAAA,KAAC,MAAA,CAAI,UAAU,0DACb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,uBAAuB,SAAA,SAAM,EAC5CA,EAAAA,IAAC,OAAI,UAAU,iCACb,eAAC,OAAA,CAAK,UAAU,uBACd,SAAAA,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,WAAY,wBACxB,SAAAqyC,EAAY,QAAQ,OAAS,IAAA,CAChC,EACF,CAAA,CACF,CAAA,CAAA,CACF,CAAA,EACF,EAEAryC,EAAAA,IAAC,MAAA,CAAI,UAAU,+BACb,SAAAA,EAAAA,IAACT,GAAA,CACC,QAAS62C,EACT,KAAK,KACL,UAAU,0BACX,SAAA,KAAA,CAAA,CAED,CACF,CAAA,CAAA,CACF,CAAA,CACF,EAGAz1C,EAAAA,KAAC,MAAA,CAAI,UAAU,2BACb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,uBAAuB,SAAA,OAErC,EAEAA,EAAAA,IAAC40C,GAAA,CACC,YAAAvC,EACA,WAAAN,CAAA,CAAA,EAIF/xC,EAAAA,IAACo0C,GAAA,CACC,YAAA/B,CAAA,CAAA,EAIFryC,EAAAA,IAAC21C,GAAA,CACC,YAAAtD,CAAA,CAAA,CACF,EACF,EAGAryC,EAAAA,IAAC,MAAA,CAAI,UAAU,0BACb,SAAAA,EAAAA,IAACT,GAAA,CACC,QAAS62C,EACT,KAAK,KACN,SAAA,KAAA,CAAA,CAED,CACF,CAAA,EACF,GC9ESC,GAA4C,CAAC,CACxD,YAAAhE,EACA,eAAA+D,CACF,IAEIz1C,EAAAA,KAAC,MAAA,CAAI,UAAU,0BAEb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,wBAAwB,SAAA,MAAG,EACzCA,EAAAA,IAAC,IAAA,CAAE,UAAU,8BAA8B,SAAA,SAAM,EAGjDA,EAAAA,IAAC,MAAA,CAAI,UAAU,2BACb,SAAAA,EAAAA,IAACmoC,GAAA,CACC,KAAM,CACJ,GAAI,kBACJ,MAAOkK,EAAY,MACnB,KAAMA,EAAY,KAElB,QAASA,EAAY,QAAQ,QAAQ,OAC5BA,EAAY,QAAQ,QAAQ,SAC5BA,EAAY,QAAQ,UAAU,OAC9BA,EAAY,QAAQ,UAAU,SAC9B,CACP,CACE,KAAM,OACN,QAAS,0BAAA,CACX,CACF,EAEF,MAAM,SACN,OAAQ,CAAE,KAAM,MAAA,CAAO,CAAA,EAE3B,EAGAryC,EAAAA,IAACT,GAAA,CACC,QAAS62C,EACT,KAAK,KACL,UAAU,cACX,SAAA,KAAA,CAAA,CAED,EACF,ECg1BSE,GAAmB,CAE9B,uBAAwB,yBASxB,sBAAuB,wBACvB,yBAA0B,0BAC5B,EC11BaC,GAAiD,CAC5D,WAAY,GACZ,cAAe,GACf,gBAAiB,QACjB,gBAAiB,GACjB,0BAA2B,GAC3B,kCAAmC,GACnC,kBAAmB,GACnB,4BAA6B,EAC/B,EC1BaA,GAAiD,CAC5D,WAAY,GACZ,cAAe,GACf,gBAAiB,QACjB,gBAAiB,GACjB,0BAA2B,GAC3B,kCAAmC,GACnC,kBAAmB,GACnB,4BAA6B,EAC/B,EA4EaC,GAAgB,CAC3B,aAAc,eACd,UAAW,YACX,aAAc,eACd,cAAe,gBACf,WAAY,aACZ,cAAe,gBACf,UAAW,YACX,uBAAwB,yBACxB,WAAY,YACd,EAoEaF,EAAmB,CAE9B,cAAe,gBACf,uBAAwB,yBAGxB,uBAAwB,yBACxB,uBAAwB,yBACxB,wBAAyB,0BACzB,iCAAkC,mCAClC,oBAAqB,sBACrB,wBAAyB,0BACzB,oBAAqB,sBACrB,qBAAsB,uBAGtB,sBAAuB,wBAGvB,yBAA0B,0BAC5B,EAOO,MAAMG,WAAqB,KAAM,CACtC,KACA,QAEA,YACEnqC,EACAK,EACA+pC,EACA,CACA,MAAM/pC,CAAO,EACb,KAAK,KAAO,eACZ,KAAK,KAAOL,EACZ,KAAK,QAAUoqC,CACjB,CACF,CChLO,MAAMC,GAAwB,CACnC,GAAI,4BACJ,MAAO,UACP,MAAO,EACP,KAAM,UACN,OAAQ,WACR,MAAO,qBACP,UAAW,oBACX,gBAAiB,CAAC,eAAe,EACjC,WAAY,EACZ,SAAU,CACR,MAAO,UACP,MAAO,YACP,KAAM,CAAC,QAAS,SAAS,CAAA,EAE3B,UAAW,CACT,SAAU,cACV,KAAM,EACN,OAAQ,EACR,SAAU,KACV,WAAY,KACZ,WAAY,KAAA,EAEd,OAAQ,CACN,SAAU,CAAE,QAAS,CAAA,EAAI,OAAQ,CAAE,KAAM,OAAO,EAChD,MAAO,CAAE,QAAS,CAAA,EAAI,OAAQ,CAAE,KAAM,OAAO,EAC7C,OAAQ,CAAE,QAAS,CAAA,EAAI,OAAQ,CAAE,KAAM,MAAA,CAAO,CAAE,EAElD,YAAa,CAAE,MAAO,EAAC,EACvB,OAAQ,CACN,MAAO,GACP,KAAM,MACN,YAAa,yCAAA,CAEjB,EASaC,GAA4C,CACvD,CAACN,EAAiB,aAAa,EAAG,SAClC,CAACA,EAAiB,sBAAsB,EAAG,SAC3C,CAACA,EAAiB,sBAAsB,EAAG,UAC3C,CAACA,EAAiB,sBAAsB,EAAG,UAC3C,CAACA,EAAiB,uBAAuB,EAAG,UAC5C,CAACA,EAAiB,mBAAmB,EAAG,UACxC,CAACA,EAAiB,uBAAuB,EAAG,UAC5C,CAACA,EAAiB,mBAAmB,EAAG,UACxC,CAACA,EAAiB,gCAAgC,EAAG,YACrD,CAACA,EAAiB,oBAAoB,EAAG,UACzC,CAACA,EAAiB,qBAAqB,EAAG,SAC1C,CAACA,EAAiB,wBAAwB,EAAG,QAC/C,EAyBaO,GAAyB,CACpC,wBAAyB,EACzB,oBAAqB,GAAK,KAC1B,oBAAqB,GACrB,4BAA6B,EAC/B,EASaC,GAAkB,CAC7B,SAAU,CACR,eACA,QACA,WACA,YACA,cACA,oBACA,YACA,mBACA,aACA,aACA,SACA,cACA,aAAA,EAEF,WAAY,CAAC,UAAU,EACvB,YAAa,CAAC,QAAS,OAAQ,kBAAkB,CACnD,EAKaC,GAAc,CAAC,WAAY,QAAS,SAAU,UAAU,EAwBxDC,GAAqB,CAChC,aAAc,0DACd,UAAW,sCACX,aAAc,yCACd,cAAe,0CACf,WAAY,uCACZ,cAAe,0CAEf,uBAAwB,kDACxB,WAAY,sCACd,EASaC,GAAsB,CACjC,KAAM,OACN,QAAS,UACT,MAAO,QACP,mBAAoB,oBACpB,aAAc,cACd,kBAAmB,iBACrB,EC/NaC,GAAyB,CAEpC,cAAe,CACb,OAAQ,CACN,QAAS,UACT,cAAe,UACf,MAAO,UACP,QAAS,UACT,aAAc,UACd,eAAgB,UAChB,gBAAiB,UACjB,iBAAkB,UAClB,aAAc,OACd,eAAgB,OAChB,iBAAkB,UAClB,mBAAoB,UACpB,gBAAiB,UACjB,aAAc,UACd,eAAgB,SAAA,EAElB,MAAO,CACL,cAAe,SACf,eAAgB,SAChB,KAAM,OACN,MAAO,OACP,QAAS,QAAA,EAEX,QAAS,CACP,MAAO,OACP,OAAQ,OACR,MAAO,OACP,KAAM,KAAA,EAER,SAAU,CACR,oBAAqB,EACrB,mBAAoB,EACpB,kBAAmB,IACnB,eAAgB,GAChB,cAAe,GACf,eAAgB,GAChB,YAAa,EACb,UAAW,CAAA,CACb,CAEJ,EAMaC,GAAyB,CAEpC,cAAe,CACb,QAAS,CACP,GAAI,UACJ,UAAW,wBACX,YAAa,2BACb,YAAa,kBACb,YAAa,+BAAA,EAEf,UAAW,CACT,GAAI,YACJ,UAAW,2BACX,YAAa,2BACb,YAAa,yBACb,YAAa,+BAAA,EAEf,YAAa,CACX,GAAI,cACJ,UAAW,wBACX,YAAa,0BACb,YAAa,yBACb,YAAa,+BAAA,EAEf,UAAW,CACT,GAAI,YACJ,UAAW,2BACX,YAAa,2BACb,YAAa,kBACb,YAAa,8BAAA,EAEf,MAAO,CACL,GAAI,QACJ,UAAW,cACX,YAAa,gBACb,YAAa,8BAAA,EAEf,QAAS,CACP,GAAI,UACJ,UAAW,kBACX,YAAa,2BACb,YAAa,uBACb,YAAa,+BAAA,EAEf,OAAQ,CACN,GAAI,SACJ,YAAa,yBACb,YAAa,gCACb,KAAM,uBAAA,EAER,aAAc,CACZ,GAAI,eACJ,MAAO,uBACP,SAAU,aAAA,EAEZ,mBAAoB,CAClB,GAAI,qBACJ,MAAO,uBACP,SAAU,uBACV,WAAY,MAAA,EAGd,eAAgB,CACd,GAAI,iBACJ,YAAa,gBACb,YAAa,+BACb,UAAW,aAAA,EAEb,eAAgB,CACd,GAAI,iBACJ,MAAO,uBACP,SAAU,eACV,WAAY,OACZ,UAAW,QAAA,EAEb,eAAgB,CACd,GAAI,iBACJ,UAAW,yBACX,YAAa,2BACb,YAAa,kBACb,YAAa,+BAAA,EAEf,gBAAiB,CACf,GAAI,kBACJ,UAAW,0BACX,YAAa,2BACb,YAAa,kBACb,YAAa,+BAAA,EAEf,YAAa,CACX,GAAI,cACJ,MAAO,gBACP,SAAU,eACV,WAAY,MAAA,CACd,CAEJ,EAMaC,GAA4B,CAEvC,iBAAkB,CAChB,eAAgB,CACd,GAAI,iBACJ,KAAM,UACN,SAAU,CAAC,CAAC,IAAK,GAAG,EAAG,CAAC,IAAK,GAAG,EAAG,CAAC,IAAK,GAAG,CAAC,EAC7C,SAAU,UACV,YAAa,OAAA,EAEf,eAAgB,CACd,GAAI,iBACJ,KAAM,WACN,SAAU,CAAC,CAAC,IAAK,GAAG,EAAG,CAAC,IAAK,GAAG,EAAG,CAAC,IAAK,GAAG,CAAC,EAC7C,SAAU,YACV,YAAa,OAAA,EAEf,qBAAsB,CACpB,GAAI,uBACJ,KAAM,WACN,SAAU,CAAC,CAAC,IAAK,GAAG,EAAG,CAAC,IAAK,GAAG,EAAG,CAAC,IAAK,GAAG,CAAC,EAC7C,SAAU,YACV,YAAa,OAAA,EAEf,UAAW,CACT,GAAI,YACJ,KAAM,YACN,WAAY,CAAE,MAAO,IAAK,OAAQ,GAAA,EAClC,SAAU,UACV,YAAa,IAAA,EAEf,cAAe,CACb,GAAI,gBACJ,KAAM,gBACN,SAAU,CAAC,CAAC,IAAK,GAAG,EAAG,CAAC,IAAK,GAAG,EAAG,CAAC,IAAK,GAAG,EAAG,CAAC,GAAI,GAAG,CAAC,EACxD,SAAU,YACV,YAAa,OAAA,EAGf,gBAAiB,CACf,GAAI,kBACJ,KAAM,UACN,UAAW,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,IAAK,CAAC,CAAC,EAC5B,SAAU,UACV,YAAa,QAAA,EAEf,cAAe,CACb,GAAI,gBACJ,KAAM,UACN,UAAW,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAG,GAAG,CAAC,EAC5B,SAAU,UACV,YAAa,QAAA,EAEf,WAAY,CACV,GAAI,aACJ,KAAM,UACN,UAAW,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,IAAK,CAAC,CAAC,EAC5B,SAAU,QACV,YAAa,QAAA,EAGf,YAAa,CACX,GAAI,cACJ,KAAM,QACN,SAAU,CAAC,GAAI,EAAE,EACjB,SAAU,eACV,YAAa,SAAA,EAEf,aAAc,CACZ,GAAI,eACJ,KAAM,QACN,SAAU,CAAC,GAAI,EAAE,EACjB,SAAU,UACV,YAAa,OAAA,EAEf,aAAc,CACZ,GAAI,eACJ,KAAM,QACN,SAAU,CAAC,EAAG,CAAC,EACf,SAAU,UACV,YAAa,OAAA,EAEf,aAAc,CACZ,GAAI,eACJ,KAAM,QACN,SAAU,CAAC,EAAG,CAAC,EACf,SAAU,YACV,YAAa,OAAA,EAGf,cAAe,CACb,GAAI,gBACJ,KAAM,UACN,SAAU,CAAC,CAAC,IAAK,GAAG,EAAG,CAAC,IAAK,GAAG,EAAG,CAAC,IAAK,GAAG,CAAC,EAC7C,SAAU,iBACV,YAAa,QAAA,CACf,CAEJ,EAMaC,GAA0B,CAErC,eAAgB,CACd,KAAM,CACJ,GAAI,OACJ,KAAM,OACN,QAAS,iBACT,MAAO,OAAA,EAET,kBAAmB,CACjB,GAAI,oBACJ,KAAM,WACN,QAAS,iBACT,UAAW,QAAA,EAEb,gBAAiB,CACf,GAAI,kBACJ,KAAM,WACN,QAAS,kBACT,UAAW,OAAA,EAEb,UAAW,CACT,GAAI,YACJ,KAAM,OACN,QAAS,EACT,QAAS,iBAAA,CACX,CAEJ,EAMaC,GAAiC,CAE5C,sBAAuB,CACrB,cAAe,CACb,GAAI,gBACJ,KAAM,WACN,MAAO,IACP,OAAQ,CAAC,EAAG,CAAC,EACb,YAAa,SAAA,EAEf,eAAgB,CACd,GAAI,iBACJ,KAAM,WACN,MAAO,GACP,OAAQ,CAAC,EAAG,CAAC,EACb,YAAa,SAAA,EAEf,YAAa,CACX,GAAI,cACJ,KAAM,cACN,GAAI,EACJ,GAAI,EACJ,YAAa,MAAA,EAEf,MAAO,CACL,GAAI,QACJ,KAAM,QACN,OAAQ,EACR,OAAQ,CAAC,EAAG,CAAC,EACb,YAAa,MAAA,CACf,CAEJ,EAMaC,GAAiC,CAE5C,mBAAoB,CAClB,kBAAmB,CACjB,GAAI,oBACJ,OAAQ,CACN,SAAU,CAAC,EAAG,EAAE,EAChB,OAAQ,GACR,YAAa,aACb,IAAK,EACL,IAAK,EACL,KAAM,GAAA,EAER,kBAAmB,CACjB,QAAS,GACT,OAAQ,EACR,OAAQ,CAAC,KAAM,MAAO,MAAO,MAAO,IAAI,EACxC,eAAgB,EAAA,EAElB,SAAU,IACV,OAAQ,cACR,YAAa,QAAA,EAEf,gBAAiB,CACf,GAAI,kBACJ,OAAQ,CACN,SAAU,CAAC,GAAI,CAAC,EAChB,OAAQ,GACR,YAAa,WACb,IAAK,EACL,IAAK,EACL,KAAM,GAAA,EAER,kBAAmB,CACjB,QAAS,GACT,OAAQ,EACR,OAAQ,CAAC,KAAM,MAAO,MAAO,MAAO,IAAI,EACxC,eAAgB,EAAA,EAElB,SAAU,IACV,OAAQ,cACR,YAAa,QAAA,CACf,CAEJ,EAMaC,GAA6B,CAExC,kBAAmB,CACjB,QAAS,CACP,GAAI,UACJ,QAAS,EACT,QAAS,EACT,YAAa,CAAC,EAAG,EAAG,GAAI,CAAC,EACzB,gBAAiB,GACjB,SAAU,GACV,SAAU,GACV,YAAa,QAAA,EAEf,SAAU,CACR,GAAI,WACJ,QAAS,EACT,QAAS,EACT,YAAa,CAAC,GAAI,GAAI,GAAI,EAAE,EAC5B,gBAAiB,GACjB,SAAU,GACV,SAAU,GACV,SAAU,EACV,YAAa,iBAAA,CACf,CAEJ,EASaC,GAA2B,CACtC,aAAcP,GAAuB,cACrC,aAAcC,GAAuB,cACrC,gBAAiBC,GAA0B,iBAC3C,cAAeC,GAAwB,eACvC,qBAAsBC,GAA+B,sBAErD,qBAAsBC,GAA+B,mBACrD,iBAAkBA,GAA+B,mBACjD,iBAAkBC,GAA2B,iBAC/C,EC7ZO,SAASE,IAA6B,CAC3C,QAAQ,MAAM,wCAAyC,CACrD,gCAAiC,CAAC,CAACH,GACnC,sBAAuBA,GAA+B,mBAAqB,OAAO,KAAKA,GAA+B,kBAAkB,EAAI,CAAA,CAAC,CAC9I,EAID,MAAMI,EAAoBJ,GAA+B,mBAEzD,MAAO,CACL,aAAcL,GAAuB,cACrC,aAAcC,GAAuB,cACrC,gBAAiBC,GAA0B,iBAC3C,cAAeC,GAAwB,eACvC,qBAAsBC,GAA+B,sBAErD,qBAAsBK,EACtB,iBAAkBA,EAClB,iBAAkBH,GAA2B,iBAAA,CAEjD,CC5BO,MAAMI,EAAoB,CAI/B,OAAO,WAAWnT,EAAsB,CACtC,OAAOuS,GAAmB,aAAa,KAAKvS,CAAG,CACjD,CAKA,OAAO,QAAQA,EAAa58B,EAAgC,CAC1D,GAAI,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAM,IAAI,MAAM,gBAAgBA,CAAG,EAAE,EAIvC,MAAMx3B,EAAOw3B,EAAI,UAAU,CAAC,EAC5B,OAAO,KAAK,YAAYx3B,EAAMpF,EAAQ,YAAY,CACpD,CAKA,OAAe,YAAYoF,EAAckF,EAAkC,CACzE,MAAM6V,EAAQ/a,EAAK,MAAM,GAAG,EAC5B,IAAI4qC,EAAe1lC,EAEnB,UAAWoW,KAAQP,EAAO,CACxB,GAA6B6vB,GAAY,KACvC,MAAM,IAAI,MAAM,cAAc5qC,CAAI,OAAOsb,CAAI,OAAO,EAGtD,GAAI,OAAOsvB,GAAY,SACrB,MAAM,IAAI,MAAM,aAAa5qC,CAAI,KAAKsb,CAAI,QAAQ,EAGpDsvB,EAAUA,EAAQtvB,CAAI,CACxB,CAEA,GAAIsvB,IAAY,OACd,MAAM,IAAI,MAAM,YAAY5qC,CAAI,EAAE,EAGpC,OAAO4qC,CACT,CAKA,OAAO,aAAaC,EAAgBjwC,EAAgD,CAClF,MAAMkwC,EAA+B,CAAA,EAErC,UAAWtT,KAAOqT,EAChB,GAAI,KAAK,WAAWrT,CAAG,EACrB,GAAI,CACFsT,EAAQtT,CAAG,EAAI,KAAK,QAAQA,EAAK58B,CAAO,CAC1C,OAAS5F,EAAO,CAEd,QAAQ,KAAK,aAAawiC,CAAG,GAAIxiC,CAAK,CACxC,CAIJ,OAAO81C,CACT,CAKA,OAAO,uBAAuB3wC,EAAoB,CAChD,MAAM0wC,EAAiB,CAAA,EAEjBE,EAAYx7C,GAAe,CAC3B,OAAOA,GAAU,SACf,KAAK,WAAWA,CAAK,GACvBs7C,EAAK,KAAKt7C,CAAK,EAER,MAAM,QAAQA,CAAK,EAC5BA,EAAM,QAAQw7C,CAAQ,EACb,OAAOx7C,GAAU,UAAYA,IAAU,MAChD,OAAO,OAAOA,CAAK,EAAE,QAAQw7C,CAAQ,CAEzC,EAEA,OAAAA,EAAS5wC,CAAG,EACL0wC,CACT,CAKA,OAAO,uBACL1wC,EACAS,EACAowC,EACK,CACL,MAAMC,EAAW17C,GAAoB,CACnC,GAAI,OAAOA,GAAU,SAAU,CAE7B,GAAI,KAAK,WAAWA,CAAK,EACvB,GAAI,CACF,OAAO,KAAK,QAAQA,EAAOqL,CAAO,CACpC,OAAS5F,EAAO,CACd,GAAIg2C,EACF,OAAOA,EAAUz7C,CAAK,EAExB,MAAMyF,CACR,CAKF,MAAMk2C,EAAa,yDAEnB,IAAI9pC,EACAhF,EAAY,EAChB,MAAM2e,EAAkB,CAAA,EAExB,MAAQ3Z,EAAQ8pC,EAAW,KAAK37C,CAAK,KAAO,MAAM,CAE5C6R,EAAM,MAAQhF,GAChB2e,EAAM,KAAKxrB,EAAM,UAAU6M,EAAWgF,EAAM,KAAK,CAAC,EAGpD,MAAMtC,EAAQsC,EAAM,CAAC,EACrB,GAAI,CACF,MAAMmzB,EAAW,KAAK,QAAQz1B,EAAOlE,CAAO,EAC5CmgB,EAAM,KAAK,OAAOwZ,CAAQ,CAAC,CAC7B,MAAgB,CACVyW,EACFjwB,EAAM,KAAK,OAAOiwB,EAAUlsC,CAAK,CAAC,CAAC,EAGnCic,EAAM,KAAKjc,CAAK,CAEpB,CAEA1C,EAAYgF,EAAM,MAAQtC,EAAM,MAClC,CAQA,OALI1C,EAAY7M,EAAM,QACpBwrB,EAAM,KAAKxrB,EAAM,UAAU6M,CAAS,CAAC,EAInC2e,EAAM,OAAS,EACVA,EAAM,KAAK,EAAE,EAGfxrB,CACT,KAAA,IAAW,MAAM,QAAQA,CAAK,EAC5B,OAAOA,EAAM,IAAI07C,CAAO,EAC1B,GAAW,OAAO17C,GAAU,UAAYA,IAAU,KAAM,CACtD,MAAMsJ,EAA8B,CAAA,EACpC,SAAW,CAACxK,EAAKoK,CAAG,IAAK,OAAO,QAAQlJ,CAAK,EAC3CsJ,EAAOxK,CAAG,EAAI48C,EAAQxyC,CAAG,EAE3B,OAAOI,CACT,EACA,OAAOtJ,CACT,EAEA,OAAO07C,EAAQ9wC,CAAG,CACpB,CACF,CAKO,SAASgxC,IAA4B,CAC1C,MAAO,CACL,KAAM5B,GAAc,aACpB,WAAYoB,GAAoB,WAAW,KAAKA,EAAmB,EACnE,QAASA,GAAoB,QAAQ,KAAKA,EAAmB,CAAA,CAEjE,CCjLO,MAAMS,EAAoB,CAI/B,OAAO,WAAW5T,EAAa58B,EAAqC,CAClE,GAAI,OAAO48B,GAAQ,UAAYA,EAAI,SAAW,EAC5C,MAAO,GAuBT,GAnBIuS,GAAmB,aAAa,KAAKvS,CAAG,GAMnB,CACvB,wBACA,0BACA,uBACA,2BACA,0BACA,yBACA,wBACA,yBACA,sBACA,qBAAA,EAGmB,KAAK7S,GAAWA,EAAQ,KAAK6S,CAAG,CAAC,EACpD,MAAO,GAIT,GAAI58B,GAAWA,EAAQ,gBAAiB,CAEtC,IAAIywC,EACJ,MAAMjqC,EAAQo2B,EAAI,MAAMuS,GAAmB,YAAY,EACvD,OAAI3oC,EACFiqC,EAAejqC,EAAM,CAAC,EAEtBiqC,EAAe7T,EAEV6T,KAAgBzwC,EAAQ,eACjC,CAYA,MAR2B,CACzB,iBAAkB,iBAAkB,uBACpC,YAAa,gBAAiB,kBAAmB,gBACjD,aAAc,cAAe,eAAgB,eAC7C,eAAgB,gBAAiB,iBACjC,eAAgB,iBAAkB,aAAc,eAChD,gBAAA,EAEwB,SAAS48B,CAAG,CACxC,CAKA,OAAe,uBAAuBpa,EAAaxiB,EAAgC,CAUjF,GATA,QAAQ,MAAM,iDAAkD,CAC9D,MAAOwiB,EACP,MAAOA,GAAU,OAAOA,GAAW,UAAY,SAAUA,EACzD,QAASA,GAAQ,KACjB,WAAY,CAAC,CAACxiB,EAAQ,gBACtB,WAAY,EAAAA,EAAQ,kBAAkBwiB,GAAQ,IAAI,CAAW,CAC9D,EAGGA,GAAU,OAAOA,GAAW,UAAY,SAAUA,EAAQ,CAC5D,MAAMkuB,EAAUluB,EAAO,KACvB,GAAIxiB,EAAQ,iBAAmBA,EAAQ,gBAAgB0wC,CAAO,EAAG,CAC/D,MAAM7U,EAAQ77B,EAAQ,gBAAgB0wC,CAAO,EAE7C,GAAI7U,EAAM,SACR,eAAQ,MAAM,YAAY6U,CAAO,gBAAiB7U,EAAM,QAAQ,EACzD,CAACA,EAAM,SAAS,EAAGA,EAAM,SAAS,CAAC,EAE5C,GAAI,MAAOA,GAAS,MAAOA,EACzB,eAAQ,MAAM,YAAY6U,CAAO,WAAY,CAAE,EAAG7U,EAAM,EAAG,EAAGA,EAAM,CAAA,CAAG,EAChE,CAACA,EAAM,EAAGA,EAAM,CAAC,CAE5B,CACA,eAAQ,KAAK,aAAa6U,CAAO,EAAE,EAC5BluB,CACT,CAGA,OAAI,MAAM,QAAQA,CAAM,GAAKA,EAAO,SAAW,EACtCA,EACEA,GAAU,OAAOA,GAAW,UAAY,MAAOA,GAAU,MAAOA,EAClE,CAACA,EAAO,EAAGA,EAAO,CAAC,EAGrBA,CACT,CAKA,OAAO,QAAQoa,EAAa58B,EAAgC,CAC1D,GAAI,CAAC,KAAK,WAAW48B,EAAK58B,CAAO,EAC/B,MAAM,IAAI,MAAM,cAAc48B,CAAG,EAAE,EAIrC,IAAI6T,EACJ,MAAMjqC,EAAQo2B,EAAI,MAAMuS,GAAmB,YAAY,EACnD3oC,EAEFiqC,EAAejqC,EAAM,CAAC,EAGtBiqC,EAAe7T,EAGjB,QAAQ,MAAM,wCAAwCA,CAAG,oBAAoB6T,CAAY,GAAG,EAC5F,QAAQ,MAAM,gCAAiC,OAAO,KAAKzwC,EAAQ,iBAAmB,CAAA,CAAE,CAAC,EAEzF,MAAM2wC,EAAW3wC,EAAQ,gBAAgBywC,CAAY,EAErD,GAAI,CAACE,EACH,cAAQ,MAAM,gCAAgCF,CAAY,MAAOzwC,EAAQ,eAAe,EAClF,IAAI,MAAM,YAAYywC,CAAY,EAAE,EAG5C,QAAQ,MAAM,uBAAwB,CACpC,KAAMA,EACN,KAAME,EAAS,KACf,YAAa,aAAcA,EAC3B,cAAeA,EAAS,SAAWA,EAAS,SAAS,OAAS,EAC9D,aAAc,cAAeA,EAC7B,UAAWA,EAAS,UACpB,iBAAkB,MAAM,QAAQA,EAAS,SAAS,EAClD,gBAAiBA,EAAS,UAAYA,EAAS,UAAU,OAAS,EAClE,aAAc,OAAO,KAAKA,CAAQ,CAAA,CACnC,EAGD,MAAMC,EAAe,CAAE,GAAGD,CAAA,EAG1B,OAAIC,EAAa,UAAY,MAAM,QAAQA,EAAa,QAAQ,IAC9DA,EAAa,SAAWA,EAAa,SAAS,IAAKpuB,GAAgB,CACjE,GAAI,CAEF,OAAIA,GAAU,OAAOA,GAAW,UAAY,SAAUA,EAC7C,KAAK,uBAAuBA,EAAQxiB,CAAO,EAEhD,MAAM,QAAQwiB,CAAM,GAAKA,EAAO,SAAW,EAEtCA,EACEA,GAAU,OAAOA,GAAW,UAAY,MAAOA,GAAU,MAAOA,EAElE,CAACA,EAAO,EAAGA,EAAO,CAAC,EAGrBA,CACT,OAASpoB,EAAO,CACd,eAAQ,KAAK,YAAaA,CAAK,EAExBooB,CACT,CACF,CAAC,EACD,QAAQ,MAAM,qCAAqCouB,EAAa,SAAS,MAAM,GAAI,CACjF,eAAgBA,EAAa,SAAS,MAAM,EAAG,CAAC,EAAE,IAAI,CAACtU,EAAQ78B,KAAe,CAAE,MAAOA,EAAG,MAAO68B,EAAG,QAAS,MAAM,QAAQA,CAAC,EAAG,OAAQ,MAAM,QAAQA,CAAC,EAAIA,EAAE,OAAS,OAAQ,CAAA,CAC9K,GAICsU,EAAa,WAAa,MAAM,QAAQA,EAAa,SAAS,IAChEA,EAAa,UAAYA,EAAa,UAAU,IAAK/U,GAAe,CAClE,GAAI,CACF,OAAIA,GAAS,OAAOA,GAAU,UAAY,SAAUA,EAC3C,KAAK,uBAAuBA,EAAO77B,CAAO,EAE/C,MAAM,QAAQ67B,CAAK,GAAKA,EAAM,SAAW,EACpCA,EACEA,GAAS,OAAOA,GAAU,UAAY,MAAOA,GAAS,MAAOA,EAC/D,CAACA,EAAM,EAAGA,EAAM,CAAC,EAEnBA,CACT,OAASzhC,EAAO,CACd,eAAQ,KAAK,YAAaA,CAAK,EACxByhC,CACT,CACF,CAAC,GAII+U,CACT,CAKA,OAAO,SAAShU,EAAa58B,EAAoC,CAC/D,GAAI,CAAC,KAAK,WAAW48B,EAAK58B,CAAO,EAC/B,MAAO,GAIT,IAAIywC,EACJ,MAAMjqC,EAAQo2B,EAAI,MAAMuS,GAAmB,YAAY,EACvD,OAAI3oC,EAEFiqC,EAAejqC,EAAM,CAAC,EAGtBiqC,EAAe7T,EAGV6T,KAAgBzwC,EAAQ,eACjC,CAKA,OAAO,0BAA0BA,EAAqC,CACpE,OAAO,OAAO,KAAKA,EAAQ,eAAe,CAC5C,CAKA,OAAO,iBAAiB48B,EAAa58B,EAAgC,CACnE,MAAM2wC,EAAW,KAAK,QAAQ/T,EAAK58B,CAAO,EAG1C,GAAI2wC,EAAS,UAAY3wC,EAAQ,aAAa2wC,EAAS,QAAQ,EAAG,CAChE,MAAMh2C,EAAQqF,EAAQ,aAAa2wC,EAAS,QAAQ,EACpD,MAAO,CACL,GAAGA,EACH,MAAO,CAAE,GAAGh2C,CAAA,CAAM,CAEtB,CAEA,OAAOg2C,CACT,CAKA,OAAO,aAAaV,EAAgBjwC,EAAgD,CAClF,MAAMkwC,EAA+B,CAAA,EAErC,UAAWtT,KAAOqT,EAChB,GAAI,KAAK,WAAWrT,CAAG,EACrB,GAAI,CACFsT,EAAQtT,CAAG,EAAI,KAAK,QAAQA,EAAK58B,CAAO,CAC1C,OAAS5F,EAAO,CACd,QAAQ,KAAK,aAAawiC,CAAG,GAAIxiC,CAAK,CACxC,CAIJ,OAAO81C,CACT,CAKA,OAAO,oBAAoBxvC,EAA0B,CACnD,MAAMuvC,EAAiB,CAAA,EAEjBE,EAAY5wC,GAAa,CAC7B,GAAI,GAACA,GAAO,OAAOA,GAAQ,UAK3B,CAAIA,EAAI,aAAe,OAAOA,EAAI,aAAgB,UAChD0wC,EAAK,KAAK1wC,EAAI,WAAW,EAIvB,MAAM,QAAQA,EAAI,MAAM,GAC1BA,EAAI,OAAO,QAAS8iB,GAAe,CAC7BA,EAAM,aAAe,OAAOA,EAAM,aAAgB,UACpD4tB,EAAK,KAAK5tB,EAAM,WAAW,CAE/B,CAAC,EAIH,UAAW1tB,KAAS,OAAO,OAAO4K,CAAG,EAC/B,MAAM,QAAQ5K,CAAK,EACrBA,EAAM,QAAQw7C,CAAQ,EACbx7C,GAAS,OAAOA,GAAU,UACnCw7C,EAASx7C,CAAK,EAGpB,EAEA,OAAAw7C,EAASzvC,CAAO,EACT,CAAC,GAAG,IAAI,IAAIuvC,CAAI,CAAC,CAC1B,CACF,CAKO,SAASY,IAA4B,CAC1C,MAAO,CACL,KAAMlC,GAAc,aACpB,WAAY6B,GAAoB,WAAW,KAAKA,EAAmB,EACnE,QAASA,GAAoB,QAAQ,KAAKA,EAAmB,EAC7D,SAAUA,GAAoB,SAAS,KAAKA,EAAmB,CAAA,CAEnE,CCxTO,MAAMM,EAAqB,CAIhC,OAAO,WAAWlU,EAAsB,CACtC,OAAI,OAAOA,GAAQ,UAAYA,EAAI,SAAW,EACrC,GAILuS,GAAmB,cAAc,KAAKvS,CAAG,EACpC,GAKmB,CAAC,gBAAiB,iBAAkB,aAAa,EAClD,SAASA,CAAG,CACzC,CAKA,OAAO,QAAQA,EAAa58B,EAAgC,CAC1D,GAAI,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAM,IAAI,MAAM,cAAcA,CAAG,EAAE,EAIrC,IAAImU,EACJ,MAAMvqC,EAAQo2B,EAAI,MAAMuS,GAAmB,aAAa,EAUxD,GATI3oC,EAEFuqC,EAAgBvqC,EAAM,CAAC,EAGvBuqC,EAAgBnU,EAId58B,EAAQ,sBAAwBA,EAAQ,qBAAqB+wC,CAAa,EAC5E,MAAO,CAAE,GAAG/wC,EAAQ,qBAAqB+wC,CAAa,CAAA,EAIxD,MAAMC,EAAoB,CACxB,cAAe,CAAE,KAAM,WAAY,MAAO,IAAK,OAAQ,CAAC,EAAG,CAAC,CAAA,EAC5D,eAAgB,CAAE,KAAM,WAAY,MAAO,GAAI,OAAQ,CAAC,EAAG,CAAC,CAAA,EAC5D,YAAa,CAAE,KAAM,cAAe,GAAI,EAAG,GAAI,CAAA,CAAE,EAGnD,GAAIA,EAAkBD,CAA+C,EACnE,MAAO,CAAE,GAAGC,EAAkBD,CAA+C,CAAA,EAG/E,MAAM,IAAI,MAAM,YAAYA,CAAa,EAAE,CAC7C,CAKA,OAAO,SAASnU,EAAa58B,EAAoC,CAC/D,GAAI,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAO,GAIT,IAAImU,EACJ,MAAMvqC,EAAQo2B,EAAI,MAAMuS,GAAmB,aAAa,EAUxD,OATI3oC,EAEFuqC,EAAgBvqC,EAAM,CAAC,EAGvBuqC,EAAgBnU,EAId58B,EAAQ,sBAAwBA,EAAQ,qBAAqB+wC,CAAa,EACrE,GAIiB,CAAC,gBAAiB,iBAAkB,aAAa,EAClD,SAASA,CAAa,CACjD,CAKA,OAAO,eAAeJ,EAAevvB,EAAqB,CACxD,GAAI,CAACA,GAAa,CAACuvB,EACjB,OAAOA,EAGT,MAAM1yC,EAAS,CAAE,GAAG0yC,CAAA,EAEpB,OAAQvvB,EAAU,KAAA,CAChB,IAAK,WACHnjB,EAAO,SAAW,KAAK,cAAc0yC,EAAS,SAAUvvB,EAAU,MAAOA,EAAU,MAAM,EACzF,MACF,IAAK,cACHnjB,EAAO,SAAW,KAAK,iBAAiB0yC,EAAS,SAAUvvB,EAAU,GAAIA,EAAU,EAAE,EACrF,MACF,IAAK,QACHnjB,EAAO,SAAW,KAAK,WAAW0yC,EAAS,SAAUvvB,EAAU,OAAQA,EAAU,MAAM,EACvF,MACF,QACE,QAAQ,KAAK,YAAYA,EAAU,IAAI,EAAE,CAAA,CAG7C,OAAOnjB,CACT,CAKA,OAAe,cAAcujB,EAA8BoiB,EAAex7B,EAA8C,CACtH,GAAI,CAACoZ,GAAY,CAAC,MAAM,QAAQA,CAAQ,EACtC,OAAOA,EAGT,KAAM,CAACyvB,EAAIC,CAAE,EAAI9oC,EACX+oC,EAAOvN,EAAQ,KAAK,GAAM,IAC1B9e,EAAM,KAAK,IAAIqsB,CAAG,EAClBpsB,EAAM,KAAK,IAAIosB,CAAG,EAExB,OAAO3vB,EAAS,IAAI,CAAC,CAACG,EAAGC,CAAC,IAAM,CAC9B,MAAMgD,EAAKjD,EAAIsvB,EACTpsB,EAAKjD,EAAIsvB,EACf,MAAO,CACLD,EAAKrsB,EAAKE,EAAMD,EAAKE,EACrBmsB,EAAKtsB,EAAKG,EAAMF,EAAKC,CAAA,CAEzB,CAAC,CACH,CAKA,OAAe,iBAAiBtD,EAA8BoD,EAAYC,EAAgC,CACxG,MAAI,CAACrD,GAAY,CAAC,MAAM,QAAQA,CAAQ,EAC/BA,EAGFA,EAAS,IAAI,CAAC,CAACG,EAAGC,CAAC,IAAM,CAACD,EAAIiD,EAAIhD,EAAIiD,CAAE,CAAC,CAClD,CAKA,OAAe,WAAWrD,EAA8B4vB,EAAgBhpC,EAA8C,CACpH,GAAI,CAACoZ,GAAY,CAAC,MAAM,QAAQA,CAAQ,EACtC,OAAOA,EAGT,KAAM,CAACyvB,EAAIC,CAAE,EAAI9oC,EACjB,OAAOoZ,EAAS,IAAI,CAAC,CAACG,EAAGC,CAAC,IAAM,CAC9B,MAAMgD,EAAKjD,EAAIsvB,EACTpsB,EAAKjD,EAAIsvB,EACf,MAAO,CACLD,EAAKrsB,EAAKwsB,EACVF,EAAKrsB,EAAKusB,CAAA,CAEd,CAAC,CACH,CAKA,OAAO,aAAanB,EAAgBjwC,EAAgD,CAClF,MAAMkwC,EAA+B,CAAA,EAErC,UAAWtT,KAAOqT,EAChB,GAAI,KAAK,WAAWrT,CAAG,EACrB,GAAI,CACFsT,EAAQtT,CAAG,EAAI,KAAK,QAAQA,EAAK58B,CAAO,CAC1C,OAAS5F,EAAO,CACd,QAAQ,KAAK,aAAawiC,CAAG,GAAIxiC,CAAK,CACxC,CAIJ,OAAO81C,CACT,CAKA,OAAO,qBAAqBxvC,EAA0B,CACpD,MAAMuvC,EAAiB,CAAA,EAEjBE,EAAY5wC,GAAa,CAC7B,GAAI,GAACA,GAAO,OAAOA,GAAQ,UAK3B,CAAIA,EAAI,cAAgB,OAAOA,EAAI,cAAiB,UAClD0wC,EAAK,KAAK1wC,EAAI,YAAY,EAIxB,MAAM,QAAQA,EAAI,eAAe,GACnCA,EAAI,gBAAgB,QAAS6hB,GAAmB,CAC1CA,EAAU,cAAgB,OAAOA,EAAU,cAAiB,UAC9D6uB,EAAK,KAAK7uB,EAAU,YAAY,CAEpC,CAAC,EAIH,UAAWzsB,KAAS,OAAO,OAAO4K,CAAG,EAC/B,MAAM,QAAQ5K,CAAK,EACrBA,EAAM,QAAQw7C,CAAQ,EACbx7C,GAAS,OAAOA,GAAU,UACnCw7C,EAASx7C,CAAK,EAGpB,EAEA,OAAAw7C,EAASzvC,CAAO,EACT,CAAC,GAAG,IAAI,IAAIuvC,CAAI,CAAC,CAC1B,CACF,CAKO,SAASoB,IAA6B,CAC3C,MAAO,CACL,KAAM1C,GAAc,cACpB,WAAYmC,GAAqB,WAAW,KAAKA,EAAoB,EACrE,QAASA,GAAqB,QAAQ,KAAKA,EAAoB,EAC/D,SAAUA,GAAqB,SAAS,KAAKA,EAAoB,CAAA,CAErE,CC3OO,MAAMQ,EAAiB,CAI5B,OAAO,WAAW1U,EAAsB,CACtC,OAAI,OAAOA,GAAQ,UAAYA,EAAI,SAAW,EACrC,GAILuS,GAAmB,UAAU,KAAKvS,CAAG,EAChC,GAKe,CACtB,UAAW,YAAa,cAAe,YAAa,QAAS,UAC7D,SAAU,eAAgB,qBAAsB,iBAChD,iBAAkB,iBAAkB,kBAAmB,aAAA,EAElC,SAASA,CAAG,CACrC,CAKA,OAAO,QAAQA,EAAa58B,EAAgC,CAC1D,GAAI,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAM,IAAI,MAAM,cAAcA,CAAG,EAAE,EAIrC,IAAI2U,EACJ,MAAM/qC,EAAQo2B,EAAI,MAAMuS,GAAmB,SAAS,EAChD3oC,EAEF+qC,EAAY/qC,EAAM,CAAC,EAGnB+qC,EAAY3U,EAGd,MAAM4U,EAAcxxC,EAAQ,aAAauxC,CAAS,EAElD,GAAI,CAACC,EACH,MAAM,IAAI,MAAM,YAAYD,CAAS,EAAE,EAIzC,OAAO,KAAK,mBAAmBC,EAAaxxC,CAAO,CACrD,CAKA,OAAe,mBAAmBwxC,EAAkBxxC,EAAgC,CAClF,MAAMyxC,EAAqC,CAAE,GAAGD,CAAA,EAGhD,SAAW,CAAC/9C,EAAKkB,CAAK,IAAK,OAAO,QAAQ68C,CAAW,EACnD,GAAI,OAAO78C,GAAU,UAEnB,GAAIo7C,GAAoB,WAAWp7C,CAAK,EACtC,GAAI,CACF88C,EAAch+C,CAAG,EAAIs8C,GAAoB,QAAQp7C,EAAOqL,CAAO,CACjE,OAAS5F,EAAO,CACd,QAAQ,KAAK,iBAAiB3G,CAAG,IAAIkB,CAAK,GAAIyF,CAAK,EAEnDq3C,EAAch+C,CAAG,EAAIkB,CACvB,OAEOA,GAAS,OAAOA,GAAU,WAEnC88C,EAAch+C,CAAG,EAAI,KAAK,mBAAmBkB,EAAOqL,CAAO,GAI/D,OAAOyxC,CACT,CAKA,OAAO,SAAS7U,EAAa58B,EAAoC,CAC/D,GAAI,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAO,GAIT,IAAI2U,EACJ,MAAM/qC,EAAQo2B,EAAI,MAAMuS,GAAmB,SAAS,EACpD,OAAI3oC,EAEF+qC,EAAY/qC,EAAM,CAAC,EAGnB+qC,EAAY3U,EAGP2U,KAAavxC,EAAQ,YAC9B,CAKA,OAAO,WAAW2wC,EAAeh2C,EAAiB,CAChD,GAAI,CAACg2C,GAAY,CAACh2C,EAChB,OAAOg2C,EAGT,MAAM1yC,EAAS,CAAE,GAAG0yC,CAAA,EAGpB,OAAA1yC,EAAO,MAAQA,EAAO,MAAQ,CAAE,GAAGA,EAAO,MAAO,GAAGtD,GAAU,CAAE,GAAGA,CAAA,EAG7C,CAAC,cAAe,cAAe,gBAAiB,MAAM,EAC9D,QAAQyG,GAAQ,CACxBzG,EAAMyG,CAAI,IAAM,SAClBnD,EAAOmD,CAAI,EAAIzG,EAAMyG,CAAI,EAE7B,CAAC,EAEMnD,CACT,CAKA,OAAO,aAAagyC,EAAgBjwC,EAAgD,CAClF,MAAMkwC,EAA+B,CAAA,EAErC,UAAWtT,KAAOqT,EAChB,GAAI,KAAK,WAAWrT,CAAG,EACrB,GAAI,CACFsT,EAAQtT,CAAG,EAAI,KAAK,QAAQA,EAAK58B,CAAO,CAC1C,OAAS5F,EAAO,CACd,QAAQ,KAAK,aAAawiC,CAAG,GAAIxiC,CAAK,CACxC,CAIJ,OAAO81C,CACT,CAKA,OAAO,iBAAiBxvC,EAA0B,CAChD,MAAMuvC,EAAiB,CAAA,EAEjBE,EAAY5wC,GAAa,CAC7B,GAAI,GAACA,GAAO,OAAOA,GAAQ,UAK3B,CAAIA,EAAI,UAAY,OAAOA,EAAI,UAAa,UAC1C0wC,EAAK,KAAK1wC,EAAI,QAAQ,EAIpBA,EAAI,OAAS,OAAOA,EAAI,OAAU,UAEhCA,EAAI,MAAM,UAAY,OAAOA,EAAI,MAAM,UAAa,UACtD0wC,EAAK,KAAK1wC,EAAI,MAAM,QAAQ,EAK5B,MAAM,QAAQA,EAAI,MAAM,GAC1BA,EAAI,OAAO,QAAS8iB,GAAe,CAC7BA,EAAM,UAAY,OAAOA,EAAM,UAAa,UAC9C4tB,EAAK,KAAK5tB,EAAM,QAAQ,EAEtBA,EAAM,OAASA,EAAM,MAAM,UAAY,OAAOA,EAAM,MAAM,UAAa,UACzE4tB,EAAK,KAAK5tB,EAAM,MAAM,QAAQ,CAElC,CAAC,EAIH,UAAW1tB,KAAS,OAAO,OAAO4K,CAAG,EAC/B,MAAM,QAAQ5K,CAAK,EACrBA,EAAM,QAAQw7C,CAAQ,EACbx7C,GAAS,OAAOA,GAAU,UACnCw7C,EAASx7C,CAAK,EAGpB,EAEA,OAAAw7C,EAASzvC,CAAO,EACT,CAAC,GAAG,IAAI,IAAIuvC,CAAI,CAAC,CAC1B,CAKA,OAAO,oBAA0B,CAC/B,MAAO,CACL,UAAW,UACX,YAAa,GACb,YAAa,UACb,YAAa,CAAA,CAEjB,CACF,CAKO,SAASyB,IAAyB,CACvC,MAAO,CACL,KAAM/C,GAAc,UACpB,WAAY2C,GAAiB,WAAW,KAAKA,EAAgB,EAC7D,QAASA,GAAiB,QAAQ,KAAKA,EAAgB,EACvD,SAAUA,GAAiB,SAAS,KAAKA,EAAgB,CAAA,CAE7D,CC3NO,MAAMK,EAAkB,CAI7B,OAAO,WAAW/U,EAAsB,CACtC,OAAI,OAAOA,GAAQ,UAAYA,EAAI,SAAW,EACrC,GAILuS,GAAmB,WAAW,KAAKvS,CAAG,EACjC,GAKgB,CACvB,OAAQ,WAAY,aAAc,OAAQ,QAC1C,oBAAqB,sBAAuB,UAAA,EAItB,SAASA,CAAG,CACtC,CAKA,OAAO,QAAQA,EAAa58B,EAAgC,CAC1D,GAAI,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAM,IAAI,MAAM,cAAcA,CAAG,EAAE,EAIrC,IAAIgV,EACJ,MAAMprC,EAAQo2B,EAAI,MAAMuS,GAAmB,UAAU,EASrD,GARI3oC,EACForC,EAAaprC,EAAM,CAAC,EAGpBorC,EAAahV,EAIX58B,EAAQ,eAAiBA,EAAQ,cAAc4xC,CAAU,EAAG,CAC9D,MAAMC,EAAe7xC,EAAQ,cAAc4xC,CAAU,EACrD,OAAO,KAAK,oBAAoBC,EAAc7xC,CAAO,CACvD,CAGA,MAAM8xC,EAAiB,CACrB,KAAM,CAAE,KAAM,OAAQ,QAAS,OAAQ,MAAO,OAAA,EAC9C,SAAU,CAAE,KAAM,WAAY,QAAS,OAAQ,UAAW,OAAA,EAC1D,WAAY,CAAE,KAAM,aAAc,QAAS,OAAQ,UAAW,QAAA,CAAS,EAGzE,GAAIA,EAAeF,CAAyC,EAC1D,MAAO,CAAE,GAAGE,EAAeF,CAAyC,CAAA,EAGtE,MAAM,IAAI,MAAM,YAAYA,CAAU,EAAE,CAC1C,CAKA,OAAe,oBAAoBC,EAAmB7xC,EAAgC,CACpF,MAAM+xC,EAAsC,CAAE,GAAGF,CAAA,EAGjD,SAAW,CAACp+C,EAAKkB,CAAK,IAAK,OAAO,QAAQk9C,CAAY,EACpD,GAAI,OAAOl9C,GAAU,UAEnB,GAAIo7C,GAAoB,WAAWp7C,CAAK,EACtC,GAAI,CACFo9C,EAAet+C,CAAG,EAAIs8C,GAAoB,QAAQp7C,EAAOqL,CAAO,CAClE,OAAS5F,EAAO,CACd,QAAQ,KAAK,iBAAiB3G,CAAG,IAAIkB,CAAK,GAAIyF,CAAK,EAEnD23C,EAAet+C,CAAG,EAAIkB,CACxB,OAEOA,GAAS,OAAOA,GAAU,WAEnCo9C,EAAet+C,CAAG,EAAI,KAAK,oBAAoBkB,EAAOqL,CAAO,GAIjE,OAAO+xC,CACT,CAKA,OAAO,SAASnV,EAAa58B,EAAoC,CAC/D,GAAI,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAO,GAIT,IAAIgV,EACJ,MAAMprC,EAAQo2B,EAAI,MAAMuS,GAAmB,UAAU,EASrD,OARI3oC,EACForC,EAAaprC,EAAM,CAAC,EAGpBorC,EAAahV,EAIX58B,EAAQ,eAAiBA,EAAQ,cAAc4xC,CAAU,EACpD,GAIc,CAAC,OAAQ,WAAY,YAAY,EAClC,SAASA,CAAU,CAC3C,CAKA,OAAO,YAAYI,EAAkBzR,EAAkB,CACrD,GAAI,CAACyR,GAAe,CAACzR,EACnB,OAAOyR,EAGT,MAAM/zC,EAAS,CAAE,GAAG+zC,CAAA,EAGpB,OAAI/zC,EAAO,OACTA,EAAO,OAAS,CAAE,GAAGA,EAAO,OAAQ,GAAGsiC,CAAA,EAEvCtiC,EAAO,OAAS,CAAE,GAAGsiC,CAAA,EAGhBtiC,CACT,CAKA,OAAO,aAAagyC,EAAgBjwC,EAAgD,CAClF,MAAMkwC,EAA+B,CAAA,EAErC,UAAWtT,KAAOqT,EAChB,GAAI,KAAK,WAAWrT,CAAG,EACrB,GAAI,CACFsT,EAAQtT,CAAG,EAAI,KAAK,QAAQA,EAAK58B,CAAO,CAC1C,OAAS5F,EAAO,CACd,QAAQ,KAAK,aAAawiC,CAAG,GAAIxiC,CAAK,CACxC,CAIJ,OAAO81C,CACT,CAKA,OAAO,kBAAkB+B,EAAuC,CAC9D,MAAMhC,EAAiB,CAAA,EAEvB,UAAWha,KAAS,OAAO,OAAOgc,CAAM,EAStC,GARIhc,EAAM,QAAUA,EAAM,OAAO,MAAQ,OAAOA,EAAM,OAAO,MAAS,UAEhE,KAAK,YAAYA,EAAM,OAAO,IAAI,GACpCga,EAAK,KAAKha,EAAM,OAAO,IAAI,EAK3BA,EAAM,QAAU,OAAOA,EAAM,QAAW,SAC1C,UAAWthC,KAAS,OAAO,OAAOshC,EAAM,MAAM,EACxC,OAAOthC,GAAU,UAAY,KAAK,YAAYA,CAAK,GACrDs7C,EAAK,KAAKt7C,CAAK,EAMvB,MAAO,CAAC,GAAG,IAAI,IAAIs7C,CAAI,CAAC,CAC1B,CAKA,OAAe,YAAYt7C,EAAwB,CACjD,OAAOw6C,GAAmB,WAAW,KAAKx6C,CAAK,CACjD,CAKA,OAAO,qBAA2B,CAChC,MAAO,CACL,KAAM,OACN,QAAS,OACT,MAAO,OAAA,CAEX,CACF,CAKO,SAASu9C,IAA0B,CACxC,MAAO,CACL,KAAMvD,GAAc,WACpB,WAAYgD,GAAkB,WAAW,KAAKA,EAAiB,EAC/D,QAASA,GAAkB,QAAQ,KAAKA,EAAiB,EACzD,SAAUA,GAAkB,SAAS,KAAKA,EAAiB,CAAA,CAE/D,CChNO,MAAMQ,EAAqB,CAKhC,OAAO,WAAWvV,EAAsB,CACtC,OAAI,OAAOA,GAAQ,UAAYA,EAAI,SAAW,EACrC,GAKFuS,GAAmB,cAAc,KAAKvS,CAAG,CAClD,CAUA,OAAO,QAAQA,EAAa58B,EAA4C,CACtE,GAAI,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAM,IAAIgS,GACRH,EAAiB,wBACjB,cAAc7R,CAAG,EAAA,EAKrB,MAAMp2B,EAAQo2B,EAAI,MAAMuS,GAAmB,aAAa,EAExD,GAAI,CAAC3oC,EAEH,MAAM,IAAIooC,GACRH,EAAiB,wBACjB,aAAa7R,CAAG,EAAA,EAKpB,MAAMwV,EAAoB5rC,EAAM,CAAC,EAG3B6rC,EAAYryC,EAAQ,mBAAmBoyC,CAAiB,EAE9D,GAAI,CAACC,EACH,MAAM,IAAIzD,GACRH,EAAiB,wBACjB,YAAY2D,CAAiB,EAAA,EAKjC,OAAO,KAAK,uBAAuBA,EAAmBC,EAAWryC,CAAO,CAC1E,CAYA,OAAe,uBACbsyC,EACAD,EACAE,EACiB,CAEjB,GAAI,CAACF,EAAU,YAAc,CAAC,MAAM,QAAQA,EAAU,UAAU,EAC9D,MAAM,IAAIzD,GACRH,EAAiB,wBACjB,aAAa6D,CAAW,mBAAA,EAK5B,MAAMlpB,EAAaipB,EAAU,WAAW,IAAI,CAACjxB,EAAWjb,IAAU,CAEhE,GAAI,CAACib,EAAU,GACb,MAAM,IAAIwtB,GACRH,EAAiB,wBACjB,QAAQ6D,CAAW,gBAAgBnsC,CAAK,YAAA,EAI5C,GAAI,CAACib,EAAU,KACb,MAAM,IAAIwtB,GACRH,EAAiB,wBACjB,QAAQ6D,CAAW,gBAAgBnsC,CAAK,cAAA,EAI5C,GAAI,CAACib,EAAU,cAAgB,CAAC,MAAM,QAAQA,EAAU,YAAY,EAClE,MAAM,IAAIwtB,GACRH,EAAiB,wBACjB,QAAQ6D,CAAW,gBAAgBnsC,CAAK,sBAAA,EAK5C,GAAIib,EAAU,aAAa,SAAW,EACpC,MAAM,IAAIwtB,GACRH,EAAiB,wBACjB,QAAQ6D,CAAW,gBAAgBnsC,CAAK,qBAAA,EAK5Cib,EAAU,aAAa,QAAQ,CAACoZ,EAASgY,IAAe,CACtD,GAAI,OAAOhY,GAAY,UAAYA,EAAQ,KAAA,IAAW,GACpD,MAAM,IAAIoU,GACRH,EAAiB,wBACjB,QAAQ6D,CAAW,gBAAgBnsC,CAAK,kBAAkBqsC,CAAU,gBAAA,CAG1E,CAAC,EAGD,MAAMC,EAAiBhZ,GAAqBrY,EAAU,MAAM,EAGtD8Z,EAAc,KAAK,UAAU9Z,EAAU,MAAM,EAAE,SAAS,eAAe,EAE7E,MAAO,CACL,GAAIA,EAAU,GACd,KAAMA,EAAU,KAChB,OAAQqxB,EACR,aAAcrxB,EAAU,aACxB,YAAA8Z,CAAA,CAEJ,CAAC,EAGKwX,EAAkC,CACtC,GAAIJ,EACJ,QAASD,EAAU,QACnB,WAAAjpB,EACA,cAAeipB,EAAU,eAAiB,CAAA,EAC1C,gBAAiBA,EAAU,eAAA,EAIvBM,EAAa/vB,GAAwB8vB,CAAc,EACzD,GAAI,CAACC,EAAW,MACd,MAAM,IAAI/D,GACRH,EAAiB,wBACjB,aAAa6D,CAAW;AAAA,EAAKK,EAAW,QAAQ,KAAK;AAAA,CAAI,CAAC,EAAA,EAI9D,OAAOD,CACT,CASA,OAAO,SAAS9V,EAAa58B,EAAoC,CAC/D,GAAI,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAO,GAIT,IAAIwV,EACJ,MAAM5rC,EAAQo2B,EAAI,MAAMuS,GAAmB,aAAa,EAExD,OAAI3oC,EAEF4rC,EAAoB5rC,EAAM,CAAC,EAG3B4rC,EAAoBxV,EAKDwV,KAAsBpyC,EAAQ,kBAAoB,CAAA,EAGzE,CASA,OAAO,aAAaiwC,EAAgBjwC,EAA4D,CAC9F,MAAMkwC,EAA2C,CAAA,EAEjD,UAAWtT,KAAOqT,EAChB,GAAI,KAAK,WAAWrT,CAAG,EACrB,GAAI,CACFsT,EAAQtT,CAAG,EAAI,KAAK,QAAQA,EAAK58B,CAAO,CAC1C,OAAS5F,EAAO,CACd,QAAQ,KAAK,aAAawiC,CAAG,GAAIxiC,CAAK,CAExC,CAIJ,OAAO81C,CACT,CAQA,OAAO,qBAAqBxvC,EAA0B,CACpD,MAAMuvC,EAAiB,CAAA,EAEjBE,EAAY5wC,GAAa,CAC7B,GAAI,GAACA,GAAO,OAAOA,GAAQ,UAK3B,CAAIA,EAAI,cAAgB,OAAOA,EAAI,cAAiB,UAClD0wC,EAAK,KAAK1wC,EAAI,YAAY,EAIxBA,EAAI,aAAa,cAAgB,OAAOA,EAAI,YAAY,cAAiB,UAC3E0wC,EAAK,KAAK1wC,EAAI,YAAY,YAAY,EAIxC,UAAW5K,KAAS,OAAO,OAAO4K,CAAG,EAC/B,MAAM,QAAQ5K,CAAK,EACrBA,EAAM,QAAQw7C,CAAQ,EACbx7C,GAAS,OAAOA,GAAU,UACnCw7C,EAASx7C,CAAK,EAGpB,EAEA,OAAAw7C,EAASzvC,CAAO,EAET,CAAC,GAAG,IAAI,IAAIuvC,CAAI,CAAC,CAC1B,CACF,CAKO,SAAS2C,IAA6B,CAC3C,MAAO,CACL,KAAMjE,GAAc,cACpB,WAAYwD,GAAqB,WAAW,KAAKA,EAAoB,EACrE,QAASA,GAAqB,QAAQ,KAAKA,EAAoB,EAC/D,SAAUA,GAAqB,SAAS,KAAKA,EAAoB,CAAA,CAErE,CCrPO,MAAMU,EAAkB,CAO7B,OAAO,WAAWjW,EAAsB,CACtC,OAAI,OAAOA,GAAQ,UAAYA,EAAI,SAAW,EACrC,GAMFuS,GAAmB,WAAW,KAAKvS,CAAG,GACtC,2BAA2B,KAAKA,CAAG,CAC5C,CAUA,OAAO,QAAQA,EAAa58B,EAAyC,CASnE,GARA,QAAQ,MAAM,uCAAwC,CACpD,IAAA48B,EACA,WAAY,CAAC,CAAC58B,EACd,YAAa,OAAO,KAAKA,GAAW,CAAA,CAAE,EACtC,yBAA0BA,EAAQ,qBAAuB,OAAO,KAAKA,EAAQ,oBAA2B,EAAI,CAAA,EAC5G,qBAAsBA,EAAQ,iBAAmB,OAAO,KAAKA,EAAQ,gBAAuB,EAAI,CAAA,CAAC,CAClG,EAEG,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAM,IAAIgS,GACRH,EAAiB,qBACjB,cAAc7R,CAAG,EAAA,EAQrB,MAAMp2B,EAAQo2B,EAAI,MAAMuS,GAAmB,UAAU,EAC/C2D,EAAiBtsC,EAAQA,EAAM,CAAC,EAAIo2B,EAK1C,IAAIyV,EAAYryC,EAAQ,uBAAuB8yC,CAAqB,EA0BpE,MAvBI,CAACT,GAAaryC,EAAQ,mBACxBqyC,EAAaryC,EAAQ,iBAAyB8yC,CAAc,GAI1D,CAACT,GAAazC,IAA0B,uBAC1CyC,EAAazC,GAAyB,qBAA6BkD,CAAc,GAI/E,CAACT,GAAazC,IAA0B,mBAC1CyC,EAAazC,GAAyB,iBAAyBkD,CAAc,GAG/E,QAAQ,MAAM,uCAAwC,CACpD,eAAAA,EACA,aAAc,CAAC,CAACT,EAChB,UAAAA,EACA,qBAAsBryC,EAAQ,qBAC9B,iBAAkBA,EAAQ,iBAC1B,iBAAkB,CAAC,CAAC4vC,EAAA,CACrB,EAEIyC,EAUE,KAAK,2BAA2BS,EAAgBT,CAAS,GAT9D,QAAQ,KAAK,eAAeS,CAAc,SAAS,EAE5C,CACL,GAAGC,GACH,GAAID,CAAA,EAMV,CASA,OAAe,2BACbE,EACAX,EACc,CAEd,GAAI,CAACA,EAAU,OACb,MAAM,IAAIzD,GACRH,EAAiB,qBACjB,aAAauE,CAAQ,eAAA,EAIzB,KAAM,CAAE,OAAAlwB,GAAWuvB,EAGbY,EAAiB,CAAC,WAAY,SAAU,cAAe,MAAO,MAAO,MAAM,EACjF,UAAW5oB,KAAS4oB,EAClB,GAAI,EAAE5oB,KAASvH,GACb,MAAM,IAAI8rB,GACRH,EAAiB,qBACjB,QAAQuE,CAAQ,gBAAgB3oB,CAAK,KAAA,EAM3C,GAAI,CAAC,MAAM,QAAQvH,EAAO,QAAQ,GAAKA,EAAO,SAAS,SAAW,EAChE,MAAM,IAAI8rB,GACRH,EAAiB,qBACjB,QAAQuE,CAAQ,iCAAA,EAKpB,GAAIlwB,EAAO,cAAgB,cAAgBA,EAAO,cAAgB,WAChE,MAAM,IAAI8rB,GACRH,EAAiB,qBACjB,QAAQuE,CAAQ,qDAAA,EAKpB,GAAIlwB,EAAO,KAAOA,EAAO,IACvB,MAAM,IAAI8rB,GACRH,EAAiB,qBACjB,QAAQuE,CAAQ,+BAAA,EAIpB,GAAIlwB,EAAO,MAAQ,EACjB,MAAM,IAAI8rB,GACRH,EAAiB,qBACjB,QAAQuE,CAAQ,uBAAA,EAKpB,MAAO,CACL,GAAIA,EACJ,OAAQ,CACN,SAAUlwB,EAAO,SACjB,OAAQA,EAAO,OACf,YAAaA,EAAO,YACpB,IAAKA,EAAO,IACZ,IAAKA,EAAO,IACZ,KAAMA,EAAO,IAAA,EAEf,kBAAmBuvB,EAAU,kBAC7B,SAAUA,EAAU,SACpB,OAAQA,EAAU,OAClB,YAAaA,EAAU,WAAA,CAE3B,CASA,OAAO,SAASzV,EAAa58B,EAAoC,CAC/D,GAAI,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAO,GAOT,MAAMp2B,EAAQo2B,EAAI,MAAMuS,GAAmB,UAAU,EAC/C2D,EAAiBtsC,EAAQA,EAAM,CAAC,EAAIo2B,EAIxC,OAAAkW,KAAoB9yC,EAAQ,sBAAgC,CAAA,IAC5D8yC,KAAoB9yC,EAAQ,kBAA4B,CAAA,GAInD,EACT,CASA,OAAO,aAAaiwC,EAAgBjwC,EAAyD,CAC3F,MAAMkwC,EAAwC,CAAA,EAE9C,UAAWtT,KAAOqT,EAChB,GAAI,KAAK,WAAWrT,CAAG,EACrB,GAAI,CACFsT,EAAQtT,CAAG,EAAI,KAAK,QAAQA,EAAK58B,CAAO,CAC1C,OAAS5F,EAAO,CACd,QAAQ,KAAK,aAAawiC,CAAG,GAAIxiC,CAAK,CAExC,CAIJ,OAAO81C,CACT,CAQA,OAAO,kBAAkBxvC,EAA0B,CACjD,MAAMuvC,EAAiB,CAAA,EAEjBE,EAAY5wC,GAAa,CAC7B,GAAI,GAACA,GAAO,OAAOA,GAAQ,UAK3B,CAAIA,EAAI,WAAa,OAAOA,EAAI,WAAc,UAC5C0wC,EAAK,KAAK1wC,EAAI,SAAS,EAIrBA,EAAI,aAAa,WAAa,OAAOA,EAAI,YAAY,WAAc,UACrE0wC,EAAK,KAAK1wC,EAAI,YAAY,SAAS,EAIrC,UAAW5K,KAAS,OAAO,OAAO4K,CAAG,EAC/B,MAAM,QAAQ5K,CAAK,EACrBA,EAAM,QAAQw7C,CAAQ,EACbx7C,GAAS,OAAOA,GAAU,UACnCw7C,EAASx7C,CAAK,EAGpB,EAEA,OAAAw7C,EAASzvC,CAAO,EAET,CAAC,GAAG,IAAI,IAAIuvC,CAAI,CAAC,CAC1B,CACF,CAKA,MAAM8C,GAAsC,CAC1C,GAAI,iBACJ,OAAQ,CACN,SAAU,CAAC,EAAG,EAAE,EAChB,OAAQ,GACR,YAAa,aACb,IAAK,EACL,IAAK,EACL,KAAM,GAAA,EAER,kBAAmB,CACjB,QAAS,GACT,OAAQ,EACR,OAAQ,CAAC,KAAM,MAAO,MAAO,MAAO,IAAI,EACxC,eAAgB,EAAA,EAElB,SAAU,IACV,OAAQ,cACR,YAAa,kBACf,EAKO,SAASG,IAA0B,CACxC,MAAO,CACL,KAAMvE,GAAc,WACpB,WAAYkE,GAAkB,WAAW,KAAKA,EAAiB,EAC/D,QAASA,GAAkB,QAAQ,KAAKA,EAAiB,EACzD,SAAUA,GAAkB,SAAS,KAAKA,EAAiB,CAAA,CAE/D,CCxUO,MAAMM,EAA6B,CAIxC,OAAO,WAAWvW,EAAsB,CACtC,OAAI,OAAOA,GAAQ,UAAYA,EAAI,SAAW,EACrC,GAMFuS,GAAmB,uBAAuB,KAAKvS,CAAG,GAClD,2BAA2B,KAAKA,CAAG,CAC5C,CAKA,OAAO,QACLA,EACA58B,EACAozC,EACyB,CACzB,GAAI,CAAC,KAAK,WAAWxW,CAAG,EACtB,MAAM,IAAI,MAAM,gBAAgBA,CAAG,EAAE,EAOvC,MAAMp2B,EAAQo2B,EAAI,MAAMuS,GAAmB,sBAAsB,EAC3DkE,EAAW7sC,EAAQA,EAAM,CAAC,EAAIo2B,EAEpC,QAAQ,MAAM,iDAAiDA,CAAG,OAAOyW,CAAQ,GAAI,CACnF,4BAA6B,CAAC,CAACrzC,EAAQ,yBACvC,WAAYA,EAAQ,yBAA2B,OAAO,KAAKA,EAAQ,wBAAwB,EAAI,CAAA,CAAC,CACjG,EAGD,MAAMzM,EAASyM,EAAQ,2BAA2BqzC,CAAQ,EAE1D,GAAI,CAAC9/C,EACH,MAAM,IAAIq7C,GACRH,EAAiB,iCACjB,cAAc4E,CAAQ,GACtB,CAAE,UAAWzW,EAAK,SAAAyW,EAAU,iBAAkBrzC,EAAQ,yBAA2B,OAAO,KAAKA,EAAQ,wBAAwB,EAAI,CAAA,CAAC,CAAE,EAIxI,QAAQ,MAAM,cAAezM,CAAM,EAGnC,MAAM0K,EAASm1C,EAAW,KAAK,cAAc7/C,EAAQ6/C,CAAQ,EAAI,CAAE,GAAG7/C,CAAA,EAEtE,eAAQ,MAAM,eAAgB0K,CAAM,EAE7BA,CACT,CAKA,OAAe,cACbikB,EACAkxB,EACyB,CACzB,MAAMn1C,EAAS,CAAE,GAAGikB,CAAA,EAGpB,SAAW,CAACzuB,EAAKkB,CAAK,IAAK,OAAO,QAAQy+C,CAAQ,EAC5Cz+C,IAAU,SACXsJ,EAAexK,CAAG,EAAIkB,GAK3B,OAAIy+C,EAAS,SACXn1C,EAAO,OAAS,CACd,OAAQ,CAAC,GAAIA,EAAO,QAAQ,QAAU,CAAA,CAAG,EACzC,SAAU,CAAC,GAAIA,EAAO,QAAQ,UAAY,CAAA,CAAG,CAAA,EAG3Cm1C,EAAS,OAAO,SAClBn1C,EAAO,OAAO,OAASm1C,EAAS,OAAO,QAErCA,EAAS,OAAO,WAClBn1C,EAAO,OAAO,SAAWm1C,EAAS,OAAO,WAIzCA,EAAS,YACXn1C,EAAO,UAAY,CACjB,GAAGA,EAAO,UACV,GAAGm1C,EAAS,SAAA,GAITn1C,CACT,CAKA,OAAO,SAAS2+B,EAAa58B,EAAoC,CAC/D,GAAI,CAAC,KAAK,WAAW48B,CAAG,EACtB,MAAO,GAOT,MAAMp2B,EAAQo2B,EAAI,MAAMuS,GAAmB,sBAAsB,EAC3DkE,EAAW7sC,EAAQA,EAAM,CAAC,EAAIo2B,EAEpC,MAAO,CAAC,CAAC58B,EAAQ,2BAA2BqzC,CAAQ,CACtD,CAKA,OAAO,aACLpD,EACAjwC,EACAszC,EACyC,CACzC,MAAMpD,EAAmD,CAAA,EAEzD,UAAWtT,KAAOqT,EAChB,GAAI,KAAK,WAAWrT,CAAG,GAAK,KAAK,SAASA,EAAK58B,CAAO,EACpD,GAAI,CACF,MAAMozC,EAAWE,IAAY1W,CAAG,EAChCsT,EAAQtT,CAAG,EAAI,KAAK,QAAQA,EAAK58B,EAASozC,CAAQ,CACpD,OAASh5C,EAAO,CACd,QAAQ,KAAK,eAAewiC,CAAG,GAAIxiC,CAAK,CAC1C,CAIJ,OAAO81C,CACT,CAKA,OAAO,wBAAwBpD,EAAkC,CAC/D,MAAI,CAACA,GAAgB,OAAOA,GAAiB,SACpC,KAGLA,EAAa,sBAAwB,OAAOA,EAAa,sBAAyB,SAC7EA,EAAa,qBAGf,IACT,CAKA,OAAO,yBAAyByG,EAAyB,CACvD,MAAMtD,EAAiB,CAAA,EAEvB,UAAWpQ,KAAS0T,EAAQ,CAC1B,MAAM3W,EAAM,KAAK,wBAAwBiD,CAAK,EAC1CjD,GACFqT,EAAK,KAAKrT,CAAG,CAEjB,CAEA,MAAO,CAAC,GAAG,IAAI,IAAIqT,CAAI,CAAC,CAC1B,CACF,CAKO,SAASuD,IAAqC,CACnD,MAAO,CACL,KAAM7E,GAAc,uBACpB,WAAYwE,GAA6B,WAAW,KAAKA,EAA4B,EACrF,QAASA,GAA6B,QAAQ,KAAKA,EAA4B,EAC/E,SAAUA,GAA6B,SAAS,KAAKA,EAA4B,CAAA,CAErF,CC1JO,MAAMM,GAAqD,CAEhE,YAAa9E,GAAc,aAG3B,SAAUA,GAAc,UAGxB,UAAWA,GAAc,WAGzB,SAAUA,GAAc,UAGxB,aAAcA,GAAc,cAG5B,aAAcA,GAAc,cAG5B,cAAeA,GAAc,UAG7B,qBAAsBA,GAAc,uBAGpC,UAAWA,GAAc,WAGzB,KAAMA,GAAc,YACtB,EAOO,MAAM+E,EAAmB,CAkB9B,OAAO,YAAYn0C,EAAgC,CACjD,MAAM0wC,EAA6B,CAAA,EAC7B0D,MAAW,IAEXxD,EAAYx7C,GAAe,CAC/B,GAAI,GAACA,GAAS,OAAOA,GAAU,UAK/B,SAAW,CAAClB,EAAKoK,CAAG,IAAK,OAAO,QAAQlJ,CAAK,EAAG,CAE9C,GAAIlB,KAAOggD,GAAqB,CAE9B,GAAI,OAAO51C,GAAQ,SAAU,CAC3B,MAAMvK,EAAOmgD,GAAoBhgD,CAAG,EAC9BmgD,EAAW,GAAGngD,CAAG,IAAIoK,CAAG,GAGzB81C,EAAK,IAAIC,CAAQ,IACpBD,EAAK,IAAIC,CAAQ,EACjB3D,EAAK,KAAK,CACR,IAAKpyC,EACL,KAAAvK,EACA,KAAMG,EACN,MAAOoK,EACP,UAAWpK,EACX,SAAAmgD,CAAA,CACqB,EAE3B,CAEA,QACF,CAGA,GAAI,OAAO/1C,GAAQ,SAAU,CACZ,KAAK,oBAAoBA,CAAG,EACpC,QAAQqG,GAAS,CAEtB,MAAM0vC,EAAW,QAAQ1vC,CAAK,GACzByvC,EAAK,IAAIC,CAAQ,IACpBD,EAAK,IAAIC,CAAQ,EACjB3D,EAAK,KAAK,CACR,IAAK/rC,EACL,KAAMyqC,GAAc,aACpB,KAAM,OACN,MAAOzqC,EACP,UAAW,OACX,SAAA0vC,CAAA,CACqB,EAE3B,CAAC,EACD,QACF,CAGA,GAAI,MAAM,QAAQ/1C,CAAG,EAAG,CACtBA,EAAI,QAAQpF,GAAQ03C,EAAS13C,CAAI,CAAC,EAClC,QACF,CAGI,OAAOoF,GAAQ,UACjBsyC,EAAStyC,CAAG,CAEhB,CACF,EAEA,OAAAsyC,EAAS5wC,CAAG,EAEL0wC,CACT,CAcA,OAAe,oBAAoB1yC,EAAuB,CACxD,MAAM+M,EAAmB,CAAA,EAOnBupC,EAAQ,oDAEd,IAAIrtC,EACJ,MAAQA,EAAQqtC,EAAM,KAAKt2C,CAAG,KAAO,MACnC+M,EAAO,KAAK9D,EAAM,CAAC,CAAC,EAGtB,OAAO8D,CACT,CAQA,OAAO,eAAe/K,EAIpB,CACA,MAAM0wC,EAAiB,KAAK,YAAY1wC,CAAG,EAAE,IAAIq9B,GAAOA,EAAI,GAAG,EACzDkX,EAAsC,CAAA,EAEtCC,EAAep/C,GAAe,CAClC,GAAI,GAACA,GAAS,OAAOA,GAAU,UAI/B,SAAW,CAAClB,EAAKoK,CAAG,IAAK,OAAO,QAAQlJ,CAAK,EACvClB,KAAOggD,GACTK,EAAYrgD,CAAG,GAAKqgD,EAAYrgD,CAAG,GAAK,GAAK,EACpC,OAAOoK,GAAQ,UACxBk2C,EAAYl2C,CAAG,CAGrB,EAEA,OAAAk2C,EAAYx0C,CAAG,EAER,CACL,UAAW0wC,EAAK,OAChB,WAAY,IAAI,IAAIA,CAAI,EAAE,KAC1B,YAAA6D,CAAA,CAEJ,CACF,CCnMO,MAAME,EAAiB,CACpB,UAAwB,CAAA,EAEhC,aAAc,CACZ,KAAK,yBAAA,CACP,CAKQ,0BAA2B,CACjC,KAAK,SAASzD,IAA2B,EACzC,KAAK,SAASM,IAA2B,EACzC,KAAK,SAASQ,IAA4B,EAC1C,KAAK,SAASK,IAAwB,EACtC,KAAK,SAASQ,IAAyB,EACvC,KAAK,SAASU,IAA4B,EAC1C,KAAK,SAASM,IAAyB,EACvC,KAAK,SAASM,IAAoC,CACpD,CAKA,SAASS,EAA0B,CACjC,KAAK,UAAU,KAAKA,CAAQ,CAC9B,CAKA,iBAA8B,CAC5B,MAAO,CAAC,GAAG,KAAK,SAAS,CAC3B,CAKA,kBAAkB3gD,EAA2C,CAC3D,OAAO,KAAK,UAAU,KAAK2gD,GAAYA,EAAS,OAAS3gD,CAAI,CAC/D,CAKA,kBAAkBspC,EAAmC,CACnD,OAAO,KAAK,UAAU,QAAiBqX,EAAS,WAAWrX,CAAG,CAAC,CACjE,CAUA,QAAQA,EAA0B58B,EAAgC,CAEhE,GAAI,OAAO48B,GAAQ,SAAU,CAE3B,MAAMqX,EAAW,KAAK,kBAAkBrX,EAAI,IAAI,EAChD,GAAI,CAACqX,EACH,MAAM,IAAI,MAAM,UAAUrX,EAAI,IAAI,OAAO,EAG3C,GAAI,CAEF,OAAOqX,EAAS,QAAQrX,EAAI,MAAO58B,CAAO,CAC5C,OAAS5F,EAAO,CACd,MAAM,IAAI,MACR,OAAOwiC,EAAI,IAAI,OAAOA,EAAI,QAAQ,QAAQxiC,CAAK,EAAA,CAEnD,CACF,CAIA,MAAM85C,EAAoB,KAAK,UAAU,UAAmBD,EAAS,WAAWrX,CAAG,CAAC,EAEpF,GAAIsX,EAAkB,SAAW,EAC/B,MAAM,IAAI,MAAM,eAAetX,CAAG,EAAE,EAItC,UAAWqX,KAAYC,EACrB,GAAI,CAEF,OADeD,EAAS,QAAQrX,EAAK58B,CAAO,CAE9C,OAAS5F,EAAO,CAEd,QAAQ,MAAM,OAAO65C,EAAS,IAAI,OAAOrX,CAAG,OAAQxiC,CAAK,EACzD,QACF,CAIF,MAAM,IAAI,MAAM,iBAAiBwiC,CAAG,EAAE,CACxC,CAKA,aAAaqT,EAA6BjwC,EAAgD,CACxF,MAAMkwC,EAA+B,CAAA,EAErC,UAAWtT,KAAOqT,EAChB,GAAI,CAEF,MAAMhyC,EAAS,KAAK,QAAQ2+B,EAAK58B,CAAO,EAElCvM,EAAM,OAAOmpC,GAAQ,SAAWA,EAAMA,EAAI,SAChDsT,EAAQz8C,CAAG,EAAIwK,CACjB,OAAS7D,EAAO,CACd,MAAM3G,EAAM,OAAOmpC,GAAQ,SAAWA,EAAMA,EAAI,SAChD,QAAQ,KAAK,WAAWnpC,CAAG,GAAI2G,CAAK,CACtC,CAGF,OAAO81C,CACT,CAWA,uBAAuB3wC,EAAgC,CACrD,GAAI,CAEF,OAAOm0C,GAAmB,YAAYn0C,CAAG,CAC3C,OAASnF,EAAO,CACd,eAAQ,KAAK,2BAA4BA,CAAK,EAEvC,CAAA,CACT,CACF,CAUA,eAAemF,EAAoB,CAEjC,OADuB,KAAK,uBAAuBA,CAAG,EAChC,IAAIq9B,GAAOA,EAAI,QAAQ,CAC/C,CASA,qBAAqBr9B,EAAoB,CACvC,MAAM0wC,EAAiB,CAAA,EAGjBE,EAAYx7C,GAAe,CAC/B,GAAI,GAACA,GAAS,OAAOA,GAAU,UAI/B,SAAW,CAAClB,EAAKoK,CAAG,IAAK,OAAO,QAAQlJ,CAAK,EAE3C,GAAIlB,EAAI,SAAS,KAAK,GAAK,OAAOoK,GAAQ,SACxCoyC,EAAK,KAAKpyC,CAAG,UACJ,OAAOA,GAAQ,UAAYA,EAAI,SAAS,GAAG,EAAG,CAEvD,MAAMyM,EAASzM,EAAI,MAAM,mDAAmD,EACxEyM,GAAQ2lC,EAAK,KAAK,GAAG3lC,CAAM,CACjC,MAAW,MAAM,QAAQzM,CAAG,EAC1BA,EAAI,QAAQpF,GAAQ03C,EAAS13C,CAAI,CAAC,EACzB,OAAOoF,GAAQ,UACxBsyC,EAAStyC,CAAG,CAGlB,EAEA,OAAAsyC,EAAS5wC,CAAG,EACL,CAAC,GAAG,IAAI,IAAI0wC,CAAI,CAAC,CAC1B,CAMA,SAASrT,EAAa58B,EAAoC,CACxD,MAAMi0C,EAAW,KAAK,kBAAkBrX,CAAG,EAC3C,GAAI,CAACqX,EACH,MAAO,GAGT,GAAIA,EAAS,SACX,OAAOA,EAAS,SAASrX,EAAK58B,CAAO,EAIvC,GAAI,CACF,OAAAi0C,EAAS,QAAQrX,EAAK58B,CAAO,EACtB,EACT,MAAQ,CACN,MAAO,EACT,CACF,CACF,CAKO,SAASm0C,IAAkD,CAChE,OAAO,IAAIH,EACb,CCrPO,MAAMI,EAAiB,CAI5B,OAAO,UACLtH,EACA9sC,EACAzM,EAGI,CAAA,EACC,CACL,KAAM,CACJ,0BAAA8gD,EAA4B,GAC5B,WAAAC,EAAa,EAAA,EACX/gD,EAEJ,QAAQ,MAAM,yDAA0D,CACtE,UAAWu5C,EAAa,KACxB,UAAW,MAAM,QAAQA,EAAa,MAAM,EAC5C,YAAaA,EAAa,OAASA,EAAa,OAAO,OAAS,EAChE,0BAAAuH,EACA,WAAAC,EACA,oBAAqB,OAAO,KAAKt0C,EAAQ,iBAAmB,CAAA,CAAE,CAAA,CAC/D,EAED,QAAQ,MAAM,0DAA2D,CACvE,UAAW8sC,EAAa,KACxB,UAAW,MAAM,QAAQA,EAAa,MAAM,EAC5C,YAAaA,EAAa,OAASA,EAAa,OAAO,OAAS,EAChE,0BAAAuH,EACA,WAAAC,CAAA,CACD,EAGGxH,EAAa,QAAU,MAAM,QAAQA,EAAa,MAAM,GAC1D,QAAQ,KAAK,4CAA4CA,EAAa,OAAO,MAAM,KAAMA,EAAa,OAAO,IAAK30B,IAAY,CAC5H,GAAIA,EAAE,GACN,KAAMA,EAAE,KACR,YAAaA,EAAE,YACf,SAAUA,EAAE,QAAA,EACZ,CAAC,EAIL,MAAMgT,EAAc,CAClB,GAAG2hB,EACH,KAAMsC,GAAoB,KAAA,EAI5B,GAAI,CAACiF,EACH,OAAOlpB,EAGT,GAAI,CAsBF,GApBIA,EAAY,WACdA,EAAY,YAAc,KAAK,mBAAmBA,EAAY,SAAUnrB,CAAO,EAC/E,OAAOmrB,EAAY,UAIjB,MAAM,QAAQA,EAAY,MAAM,IAClC,QAAQ,MAAM,qCAAqCA,EAAY,OAAO,MAAM,EAAE,EAC9EA,EAAY,OAASA,EAAY,OAAO,IAAI,CAAC9I,EAAYlc,KACvD,QAAQ,MAAM,gBAAgBA,CAAK,KAAM,CACvC,GAAIkc,EAAM,GACV,YAAaA,EAAM,YACnB,SAAUA,EAAM,SAChB,KAAM,OAAO,KAAKA,CAAK,CAAA,CACxB,EACM,KAAK,eAAeA,EAAOriB,EAAS,CAAE,WAAAs0C,EAAY,EAC1D,GAICnpB,EAAY,SAAU,CACxB,GAAI,CACF,MAAMxwB,EAAQ22C,GAAiB,QAAQnmB,EAAY,SAAUnrB,CAAO,EACpEmrB,EAAY,MAAQxwB,CACtB,OAASP,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,aAAa+wB,EAAY,QAAQ,GAAI/wB,CAAK,CACzD,CACA,OAAO+wB,EAAY,QACrB,CAGA,GAAIA,EAAY,aAAc,CAC5B,QAAQ,KAAK,sCAAsCA,EAAY,YAAY,EAAE,EAC7E,GAAI,CAEF,MAAMopB,EAAgBppB,EAAY,aAAa,WAAW,eAAe,EACrEA,EAAY,aACZ,gBAAgBA,EAAY,YAAY,GACtCqpB,EAAkBrC,GAAqB,QAAQoC,EAAev0C,CAAO,EAC3E,QAAQ,KAAK,cAAe,CAC1B,YAAaw0C,EAAgB,GAC7B,eAAgBA,EAAgB,WAAW,OAC3C,WAAY,CAAC,CAACA,EAAgB,QAC9B,cAAeA,EAAgB,QAC/B,iBAAkB,CAAC,CAACA,EAAgB,cACpC,mBAAoBA,EAAgB,eAAe,QAAU,CAAA,CAC9D,EAGDrpB,EAAY,UAAYqpB,EAGpBrpB,EAAY,uBACd,QAAQ,KAAK,6CAA6C,EAC1D,OAAOA,EAAY,qBAEvB,OAAS/wB,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,eAAe+wB,EAAY,YAAY,GAAI/wB,CAAK,CAE/D,CACA,OAAO+wB,EAAY,YACrB,MAAWA,EAAY,YAErB,QAAQ,KAAK,gCAAiC,CAC5C,YAAaA,EAAY,UAAU,GACnC,eAAgBA,EAAY,UAAU,YAAY,QAAU,CAAA,CAC7D,EAGGA,EAAY,UAAU,YAAc,MAAM,QAAQA,EAAY,UAAU,UAAU,EACpF,QAAQ,KAAK,6BAA6BA,EAAY,UAAU,WAAW,MAAM,EAAE,GAEnF,QAAQ,KAAK,kCAAkC,EAE/C,OAAOA,EAAY,YAIvB,OAAOA,CACT,OAAS/wB,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,eAAQ,KAAK,UAAWA,CAAK,EACtB+wB,CACT,CACF,CAKA,OAAe,eACb9I,EACAriB,EACAzM,EAAmC,CAAA,EAC9B,CACL,KAAM,CAAE,WAAA+gD,EAAa,EAAA,EAAU/gD,EAC/B,QAAQ,MAAM,sDAAuD,CACnE,QAAS8uB,EAAM,GACf,UAAWA,EAAM,KACjB,eAAgB,gBAAiBA,EACjC,YAAaA,EAAM,YACnB,YAAa,aAAcA,EAC3B,SAAUA,EAAM,SAChB,aAAc,OAAO,KAAKA,CAAK,EAC/B,oBAAqB,OAAO,KAAKriB,EAAQ,iBAAmB,CAAA,CAAE,CAAA,CAC/D,GAGGqiB,EAAM,KAAO,aAAeA,EAAM,KAAO,gBAC3C,QAAQ,MAAM,WAAWA,EAAM,EAAE,IAAK,CACpC,GAAIA,EAAM,GACV,KAAMA,EAAM,KACZ,YAAaA,EAAM,YACnB,SAAUA,EAAM,SAChB,UAAWA,EAAM,UACjB,iBAAkB,MAAM,QAAQA,EAAM,SAAS,CAAA,CAChD,EAGH,IAAI6O,EAAmB,CAAE,GAAG7O,CAAA,EAGxBA,EAAM,OAAS,SACjB,QAAQ,KAAK,wCAAwCA,EAAM,EAAE,IAAK,CAChE,GAAIA,EAAM,GACV,KAAMA,EAAM,KACZ,SAAUA,EAAM,SAChB,aAAc,OAAOA,EAAM,SAC3B,gBAAiB,MAAM,QAAQA,EAAM,QAAQ,EAC7C,UAAW,OAAO,KAAKA,CAAK,CAAA,CAC7B,EAGH,GAAI,CAEF,GAAI6O,EAAiB,YAAa,CAChC,QAAQ,KAAK,+CAA+CA,EAAiB,WAAW,cAAcA,EAAiB,EAAE,GAAI,CAC3H,QAASA,EAAiB,GAC1B,UAAWA,EAAiB,KAC5B,YAAaA,EAAiB,YAC9B,0BAA2B,CAAC,CAAClxB,EAAQ,gBACrC,mBAAoBA,EAAQ,gBAAkB,OAAO,KAAKA,EAAQ,eAAe,EAAI,CAAA,CAAC,CACvF,EACD,GAAI,CACF,MAAM2wC,EAAWH,GAAoB,QAAQtf,EAAiB,YAAalxB,CAAO,EAClF,QAAQ,KAAK,4BAA4BkxB,EAAiB,WAAW,IAAK,CACxE,KAAMyf,EAAS,KACf,YAAa,aAAcA,EAC3B,SAAUA,EAAS,SACnB,YAAa,aAAcA,EAC3B,SAAUA,EAAS,SACnB,aAAc,cAAeA,EAC7B,UAAWA,EAAS,UACpB,iBAAkB,MAAM,QAAQA,EAAS,SAAS,EAClD,aAAc,OAAO,KAAKA,CAAQ,CAAA,CACnC,EAED,MAAM8D,EAAevjB,EAAiB,KAChCwjB,EAAkBxjB,EAAiB,QAEnCyjB,EAAc,CAAE,GAAGzjB,CAAA,EACzB,OAAO,OAAOA,EAAkByf,CAAQ,EAExCzf,EAAiB,GAAK7O,EAAM,GAExBoyB,IAAiB,SACnBvjB,EAAiB,KAAOujB,GAEtBC,IAAoB,SACtBxjB,EAAiB,QAAUwjB,GAE7B,QAAQ,KAAK,sBAAsBxjB,EAAiB,EAAE,IAAK,CACzD,KAAMA,EAAiB,KACvB,SAAUA,EAAiB,SAC3B,gBAAiB,MAAM,QAAQA,EAAiB,QAAQ,EACxD,eAAgBA,EAAiB,SAAWA,EAAiB,SAAS,OAAS,YAC/E,SAAUA,EAAiB,SAC3B,UAAWA,EAAiB,UAC5B,iBAAkB,MAAM,QAAQA,EAAiB,SAAS,EAC1D,qBAAsB,OAAO,KAAKA,CAAgB,CAAA,CACnD,EAGD,MAAM0jB,EAAe1jB,EAAiB,KACtC,IAAI2jB,EAAsB,GAI1B,MAAMC,EAAmB90C,EAAQ,gBAAgBkxB,EAAiB,WAAW,EAW7E,GAVA,QAAQ,KAAK,qBAAsB,CACjC,YAAaA,EAAiB,YAC9B,uBAAwB,CAAC,CAAC4jB,EAC1B,qBAAsBA,GAAkB,KACxC,qBAAsBA,EAAmB,OAAO,KAAKA,CAAgB,EAAI,CAAA,EACzE,YAAaA,GAAoB,aAAcA,EAC/C,gBAAiBA,GAAoB,MAAM,QAAQA,EAAiB,QAAQ,EAC5E,eAAgBA,GAAkB,UAAU,OAC5C,2BAA4B,OAAO,KAAK90C,EAAQ,iBAAmB,CAAA,CAAE,CAAA,CACtE,EACG80C,GAAoBA,EAAiB,UAAY,MAAM,QAAQA,EAAiB,QAAQ,EAAG,CAiD7F,GAhDA,QAAQ,KAAK,8BAA+B,CAC1C,iBAAkBA,EAAiB,SACnC,aAAc,cAAeA,EAC7B,UAAWA,EAAiB,UAC5B,SAAU,UAAWA,EACrB,MAAOA,EAAiB,KAAA,CACzB,EAGI5jB,EAAiB,iBACpBA,EAAiB,eAAiB,CAAA,GAIpC4jB,EAAiB,SAAS,QAAQ,CAACtyB,EAAarc,IAAkB,CAOhE,GANA,QAAQ,KAAK,iBAAiBA,CAAK,IAAK,CACtC,OAAAqc,EACA,SAAUA,GAAU,OAAOA,GAAW,SACtC,aAAcA,GAAU,OAAOA,GAAW,UAAY,SAAUA,EAChE,QAASA,GAAQ,IAAA,CAClB,EACGA,GAAU,OAAOA,GAAW,UAAY,SAAUA,EAAQ,CAC5D,MAAMkuB,EAAUluB,EAAO,KAEvB,GADA,QAAQ,KAAK,sBAAsBkuB,CAAO,4BAA4B,EAClE1wC,EAAQ,iBAAmBA,EAAQ,gBAAgB0wC,CAAO,EAAG,CAC/D,MAAMqE,EAAkB/0C,EAAQ,gBAAgB0wC,CAAO,EACvD,QAAQ,KAAK,mBAAmBA,CAAO,IAAKqE,CAAe,EACvDA,EAAgB,MACb7jB,EAAiB,eAAe/qB,CAAK,IACxC+qB,EAAiB,eAAe/qB,CAAK,EAAI,CAAA,GAE3C+qB,EAAiB,eAAe/qB,CAAK,EAAE,KAAO4uC,EAAgB,KAC9D,QAAQ,KAAK,gBAAgB5uC,CAAK,OAAO4uC,EAAgB,IAAI,EAAE,GAE/D,QAAQ,KAAK,UAAUrE,CAAO,WAAW,CAE7C,MACE,QAAQ,KAAK,mCAAmCA,CAAO,EAAE,CAE7D,MACE,QAAQ,KAAK,QAAQvqC,CAAK,UAAU,CAExC,CAAC,EAGG2uC,EAAiB,YAAc,SACjC5jB,EAAiB,eAAe,UAAY4jB,EAAiB,WAE3DA,EAAiB,OAAS,OAAOA,EAAiB,OAAU,SAAU,CACxE,MAAM9W,EAAQ8W,EAAiB,MAC3B9W,EAAM,QAAU,MAAM,QAAQA,EAAM,MAAM,GAAKA,EAAM,OAAO,QAAU,IACxE9M,EAAiB,eAAe,OAAS8M,EAAM,QAE7CA,EAAM,WAAa,SACrB9M,EAAiB,eAAe,SAAW8M,EAAM,UAE/CA,EAAM,QACR9M,EAAiB,eAAe,MAAQ8M,EAAM,OAE5CA,EAAM,UACR9M,EAAiB,eAAe,QAAU8M,EAAM,SAE9CA,EAAM,UACR9M,EAAiB,eAAe,QAAU8M,EAAM,QAEpD,CAEA,QAAQ,KAAK,uBAAwB9M,EAAiB,cAAc,CACtE,CAuBA,GArBI0jB,IAAiB,WAAaA,IAAiB,OACjDC,EAAsB,cAAe3jB,GAAoB,MAAM,QAAQA,EAAiB,SAAS,EACxF0jB,IAAiB,QAC1BC,EAAsB,aAAc3jB,GAAoBA,EAAiB,WAAa,OAC7E0jB,IAAiB,WAAaA,IAAiB,YAAcA,IAAiB,aAAeA,IAAiB,gBACvHC,EAAsB,aAAc3jB,GAAoB,MAAM,QAAQA,EAAiB,QAAQ,EAG/F2jB,EAAuB,aAAc3jB,GAAoB,MAAM,QAAQA,EAAiB,QAAQ,GAC7F,cAAeA,GAAoB,MAAM,QAAQA,EAAiB,SAAS,GAC3E,aAAcA,GAAoBA,EAAiB,WAAa,OAGhE2jB,IACH,QAAQ,MAAM,2CAA2C3jB,EAAiB,EAAE,WAAW0jB,CAAY,qCAAqC,EACxI,QAAQ,MAAM,oBAAqB,OAAO,KAAKjE,CAAQ,CAAC,EACxD,QAAQ,MAAM,oBAAqBA,EAAS,IAAI,EAChD,QAAQ,MAAM,4BAA6B,OAAO,KAAKzf,CAAgB,CAAC,GAItEyf,EAAS,SAAU,CACrB,QAAQ,MAAM,oCAAoCA,EAAS,QAAQ,EAAE,EACrE,MAAMh2C,EAAQ22C,GAAiB,QAAQX,EAAS,SAAU3wC,CAAO,EACjE,QAAQ,MAAM,cAAerF,CAAK,EAClCu2B,EAAiB,MAAQv2B,CAC3B,CACF,OAASP,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,MAAM,eAAe82B,EAAiB,WAAW,GAAI92B,CAAK,EAClE,QAAQ,MAAM,gBAAgB82B,EAAiB,EAAE,WAAWA,EAAiB,IAAI,EAAE,EACnF,QAAQ,MAAM,mCAAoClxB,EAAQ,gBAAkB,OAAO,KAAKA,EAAQ,eAAe,EAAI,WAAW,CAChI,CACA,OAAOkxB,EAAiB,WAC1B,CAGA,GAAIA,EAAiB,SAAU,CAC7B,QAAQ,MAAM,oCAAoCA,EAAiB,QAAQ,eAAeA,EAAiB,EAAE,EAAE,EAC/G,GAAI,CACF,MAAMv2B,EAAQ22C,GAAiB,QAAQpgB,EAAiB,SAAUlxB,CAAO,EACzE,QAAQ,MAAM,cAAerF,CAAK,EAGlC,KAAM,CAAE,GAAIq6C,EAAS,GAAGC,GAAmBt6C,EAC3Cu2B,EAAmB,CACjB,GAAGA,EACH,GAAG+jB,EAEH,MAAO,CACL,GAAG/jB,EAAiB,MACpB,GAAGv2B,CAAA,CACL,CAEJ,OAASP,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,eAAe82B,EAAiB,QAAQ,GAAI92B,CAAK,EAE9D,OAAO82B,EAAiB,KAC1B,CACA,OAAOA,EAAiB,QAC1B,CA6BA,GA1BI,MAAM,QAAQA,EAAiB,eAAe,IAChDA,EAAiB,gBAAkBA,EAAiB,gBAAgB,IACjE9P,GAAmB,KAAK,mBAAmBA,EAAWphB,EAAS,CAAE,WAAAs0C,EAAY,CAAA,GAK9EpjB,EAAiB,OAAS,OAAOA,EAAiB,OAAU,WAC9DA,EAAiB,MAAQ,KAAK,eAAeA,EAAiB,MAAOlxB,CAAO,GAI9E,QAAQ,KAAK,sCAAsCkxB,EAAiB,EAAE,IAAK,CACzE,KAAMA,EAAiB,KACvB,aAAc,cAAeA,EAC7B,UAAWA,EAAiB,UAC5B,iBAAkB,MAAM,QAAQA,EAAiB,SAAS,EAC1D,gBAAiBA,EAAiB,UAAYA,EAAiB,UAAU,OAAS,EAClF,UAAW,OAAO,KAAKA,CAAgB,CAAA,CACxC,EAGDA,EAAmB,KAAK,wBAAwBA,EAAkBlxB,CAAO,EAIrEkxB,EAAiB,OAAS,WAAa,MAAM,QAAQA,EAAiB,SAAS,GAAKA,EAAiB,UAAU,QAAU,EAAG,CAC9H,QAAQ,KAAK,qCAAqCA,EAAiB,EAAE,IAAK,CACxE,aAAcA,EAAiB,KAC/B,UAAWA,EAAiB,SAAA,CAC7B,EACDA,EAAiB,KAAO,OAGxB,MAAM4K,EAAa,KAAK,sBAAsB5K,EAAiB,UAAU,CAAC,EAAGlxB,CAAO,EAC9Eg8B,EAAW,KAAK,sBAAsB9K,EAAiB,UAAU,CAAC,EAAGlxB,CAAO,EAG9E,MAAM,QAAQ87B,CAAU,GAAKA,EAAW,QAAU,EACpD5K,EAAiB,MAAQ,CAAE,EAAG4K,EAAW,CAAC,EAAG,EAAGA,EAAW,CAAC,CAAA,EACnDA,GAAc,OAAOA,GAAe,UAAY,MAAOA,GAAc,MAAOA,EACrF5K,EAAiB,MAAQ4K,EAGzB5K,EAAiB,MAAQA,EAAiB,UAAU,CAAC,EAGnD,MAAM,QAAQ8K,CAAQ,GAAKA,EAAS,QAAU,EAChD9K,EAAiB,IAAM,CAAE,EAAG8K,EAAS,CAAC,EAAG,EAAGA,EAAS,CAAC,CAAA,EAC7CA,GAAY,OAAOA,GAAa,UAAY,MAAOA,GAAY,MAAOA,EAC/E9K,EAAiB,IAAM8K,EAEvB9K,EAAiB,IAAMA,EAAiB,UAAU,CAAC,EAGrD,OAAOA,EAAiB,SAC1B,CAGA,eAAQ,KAAK,kDAAkDA,EAAiB,EAAE,KAAKA,EAAiB,IAAI,KAAM,CAChH,GAAIA,EAAiB,GACrB,KAAMA,EAAiB,KACvB,YAAa,aAAcA,EAC3B,SAAUA,EAAiB,SAC3B,gBAAiB,MAAM,QAAQA,EAAiB,QAAQ,EACxD,eAAgBA,EAAiB,SAAWA,EAAiB,SAAS,OAAS,EAC/E,kBAAmB,mBAAoBA,EACvC,eAAgBA,EAAiB,eACjC,mBAAoBA,EAAiB,eAAiB,OAAO,KAAKA,EAAiB,cAAc,EAAI,CAAA,EACrG,YAAa,aAAcA,EAC3B,SAAUA,EAAiB,SAC3B,SAAU,UAAWA,EACrB,MAAOA,EAAiB,MACxB,OAAQ,QAASA,EACjB,IAAKA,EAAiB,IACtB,aAAc,cAAeA,EAC7B,UAAWA,EAAiB,UAC5B,eAAgB,gBAAiBA,EACjC,YAAaA,EAAiB,YAC9B,KAAM,OAAO,KAAKA,CAAgB,CAAA,CACnC,EAEMA,CACT,OAAS92B,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,eAAQ,KAAK,YAAaA,CAAK,EACxB82B,CACT,CACF,CAKA,OAAe,sBAAsBgkB,EAAel1C,EAAoB,CACtE,GAAI,CAACk1C,GAAY,OAAOA,GAAa,SACnC,OAAOA,EAIT,GAAI,SAAUA,EAAU,CACtB,MAAMxE,EAAUwE,EAAS,KACzB,GAAIl1C,GAAWA,EAAQ,iBAAmBA,EAAQ,gBAAgB0wC,CAAO,EAAG,CAC1E,MAAM7U,EAAQ77B,EAAQ,gBAAgB0wC,CAAO,EAE7C,GAAI7U,EAAM,SACR,OAAOA,EAAM,SAGf,GAAI,MAAOA,GAAS,MAAOA,EACzB,OAAOA,CAEX,CAEA,OAAOqZ,CACT,CAGA,GAAI,gBAAiBA,EAAU,CAC7B,MAAMxE,EAAUwE,EAAS,YACzB,GAAIl1C,GAAWA,EAAQ,iBAAmBA,EAAQ,gBAAgB0wC,CAAO,EAAG,CAC1E,MAAM7U,EAAQ77B,EAAQ,gBAAgB0wC,CAAO,EAC7C,GAAI7U,EAAM,SACR,OAAOA,EAAM,SAEf,GAAI,MAAOA,GAAS,MAAOA,EACzB,OAAOA,CAEX,CACA,OAAOqZ,CACT,CAEA,OAAOA,CACT,CAKA,OAAe,wBAAwB7yB,EAAYriB,EAAoB,CACrE,GAAI,CAACqiB,GAAS,OAAOA,GAAU,SAC7B,OAAOA,EAGT,QAAQ,KAAK,+DAAgE,CAC3E,GAAIA,EAAM,GACV,KAAMA,EAAM,KACZ,YAAa,aAAcA,EAC3B,gBAAiB,MAAM,QAAQA,EAAM,QAAQ,EAC7C,eAAgBA,EAAM,SAAWA,EAAM,SAAS,OAAS,YACzD,UAAW,OAAO,KAAKA,CAAK,CAAA,CAC7B,EAED,MAAM8yB,EAAiB,CAAE,GAAG9yB,CAAA,EAG5B,GAAI8yB,EAAe,UACjB,GAAI,MAAM,QAAQA,EAAe,QAAQ,GAAKA,EAAe,SAAS,QAAU,EAC9E,QAAQ,KAAK,8CAA8CA,EAAe,EAAE,IAAK,CAC/E,QAASA,EAAe,GACxB,cAAeA,EAAe,SAC9B,YAAa,CAAE,EAAGA,EAAe,SAAS,CAAC,EAAG,EAAGA,EAAe,SAAS,CAAC,CAAA,CAAE,CAC7E,EACDA,EAAe,SAAW,CACxB,EAAGA,EAAe,SAAS,CAAC,EAC5B,EAAGA,EAAe,SAAS,CAAC,CAAA,UAErB,OAAOA,EAAe,UAAa,SAAU,CAEtD,MAAMC,EAAmB,KAAK,sBAAsBD,EAAe,SAAUn1C,CAAO,EAChFo1C,GAAoB,OAAOA,GAAqB,WAClDD,EAAe,SAAWC,EAE9B,EAIF,GAAI,MAAM,QAAQD,EAAe,QAAQ,EAAG,CAE1C,MAAME,EAAsBF,EAAe,eAAiB,CAAE,GAAGA,EAAe,cAAA,EAAmB,CAAA,EAoDnG,GAnDA,QAAQ,KAAK,iDAAkD,CAC7D,YAAa,CAAC,CAACA,EAAe,eAC9B,aAAcA,EAAe,eAAiB,OAAO,KAAKA,EAAe,cAAc,EAAI,CAAA,EAC3F,mBAAoB,OAAO,KAAKE,CAAc,CAAA,CAC/C,EAEDF,EAAe,SAAWA,EAAe,SAAS,IAAI,CAAC3yB,EAAarc,IAAkB,CAEpF,MAAMmvC,EAAiB,KAAK,sBAAsB9yB,EAAQxiB,CAAO,EAGjE,IAAI+0C,EAAuB,KAC3B,GAAIvyB,GAAU,OAAOA,GAAW,UAAY,SAAUA,EAAQ,CAC5D,MAAMkuB,EAAUluB,EAAO,KACnBxiB,GAAWA,EAAQ,iBAAmBA,EAAQ,gBAAgB0wC,CAAO,IACvEqE,EAAkB/0C,EAAQ,gBAAgB0wC,CAAO,EACjD,QAAQ,KAAK,iCAAiCA,CAAO,cAAcvqC,CAAK,IAAK,CAC3E,aAAc,cAAe4uC,EAC7B,UAAWA,EAAgB,UAC3B,SAAU,UAAWA,EACrB,UAAWA,EAAgB,MAAQ,OAAO,KAAKA,EAAgB,KAAK,EAAI,MAAA,CACzE,EAGGA,EAAgB,OACbM,EAAelvC,CAAK,IACvBkvC,EAAelvC,CAAK,EAAI,CAAA,GAE1BkvC,EAAelvC,CAAK,EAAE,KAAO4uC,EAAgB,MAGnD,CAEA,OAAI,MAAM,QAAQO,CAAc,GAAKA,EAAe,QAAU,EACrD,CACL,EAAGA,EAAe,CAAC,EACnB,EAAGA,EAAe,CAAC,CAAA,EAInBA,GAAkB,OAAOA,GAAmB,UAAY,MAAOA,GAAkB,MAAOA,EACnFA,GAGL9yB,GAAU,OAAOA,GAAW,WAAa,SAAUA,GAAU,gBAAiBA,GACzEA,EAGX,CAAC,EAGG2yB,EAAe,YAAc,QAAaA,EAAe,MAAO,CAElE,MAAMI,EAAqB,CACzB,UAAWJ,EAAe,YAAc,OAAYA,EAAe,UAAY,EAAA,EAIjF,GAAIA,EAAe,OAAS,OAAOA,EAAe,OAAU,SAAU,CACpE,MAAMnX,EAAQmX,EAAe,MAGzBnX,EAAM,QAAU,MAAM,QAAQA,EAAM,MAAM,GAAKA,EAAM,OAAO,QAAU,IACxEuX,EAAc,OAASvX,EAAM,QAE3BA,EAAM,WAAa,SACrBuX,EAAc,SAAWvX,EAAM,UAE7BA,EAAM,QACRuX,EAAc,MAAQvX,EAAM,OAE1BA,EAAM,UACRuX,EAAc,QAAUvX,EAAM,SAE5BA,EAAM,UACRuX,EAAc,QAAUvX,EAAM,QAElC,CAKA,MAAMwX,EAAoB,CAAE,GAAGD,CAAA,EAG/B,UAAW9hD,KAAO4hD,EACX,MAAM,OAAO5hD,CAAG,CAAC,IAEf+hD,EAAa/hD,CAAG,IACnB+hD,EAAa/hD,CAAG,EAAI,CAAA,GAEtB,OAAO,OAAO+hD,EAAa/hD,CAAG,EAAG4hD,EAAe5hD,CAAG,CAAC,GAIxD0hD,EAAe,eAAiBK,EAChC,QAAQ,KAAK,6CAA6CL,EAAe,EAAE,IAAKK,CAAY,CAC9F,MAAW,OAAO,KAAKH,CAAc,EAAE,OAAS,IAE9CF,EAAe,eAAiBE,EAChC,QAAQ,KAAK,sCAAsCF,EAAe,EAAE,IAAKE,CAAc,EAE3F,CA0BA,GAvBI,MAAM,QAAQF,EAAe,SAAS,IACxCA,EAAe,UAAYA,EAAe,UAAU,IAAK73B,GAAkB,CAEzE,MAAMm4B,EAAmB,KAAK,sBAAsBn4B,EAAUtd,CAAO,EAErE,OAAI,MAAM,QAAQy1C,CAAgB,GAAKA,EAAiB,QAAU,EACzD,CACL,EAAGA,EAAiB,CAAC,EACrB,EAAGA,EAAiB,CAAC,CAAA,EAGrBA,GAAoB,OAAOA,GAAqB,UAAY,MAAOA,GAAoB,MAAOA,EACzFA,GAGLn4B,GAAY,OAAOA,GAAa,WAAa,SAAUA,GAAY,gBAAiBA,GAC/EA,EAGX,CAAC,GAIC,MAAM,QAAQ63B,EAAe,MAAM,GAAKA,EAAe,OAAO,QAAU,EAC1EA,EAAe,OAAS,CACtB,EAAGA,EAAe,OAAO,CAAC,EAC1B,EAAGA,EAAe,OAAO,CAAC,CAAA,UAEnBA,EAAe,QAAU,OAAOA,EAAe,QAAW,SAAU,CAE7E,MAAMO,EAAiB,KAAK,sBAAsBP,EAAe,OAAQn1C,CAAO,EAC5E01C,GAAkB,OAAOA,GAAmB,WAC9CP,EAAe,OAASO,EAE5B,CAGA,GAAIP,EAAe,OACjB,GAAI,MAAM,QAAQA,EAAe,KAAK,GAAKA,EAAe,MAAM,QAAU,EACxEA,EAAe,MAAQ,CACrB,EAAGA,EAAe,MAAM,CAAC,EACzB,EAAGA,EAAe,MAAM,CAAC,CAAA,UAElB,OAAOA,EAAe,OAAU,SAAU,CACnD,MAAMQ,EAAgB,KAAK,sBAAsBR,EAAe,MAAOn1C,CAAO,EAC1E21C,GAAiB,OAAOA,GAAkB,WAC5CR,EAAe,MAAQQ,EAE3B,EAGF,GAAIR,EAAe,KACjB,GAAI,MAAM,QAAQA,EAAe,GAAG,GAAKA,EAAe,IAAI,QAAU,EACpEA,EAAe,IAAM,CACnB,EAAGA,EAAe,IAAI,CAAC,EACvB,EAAGA,EAAe,IAAI,CAAC,CAAA,UAEhB,OAAOA,EAAe,KAAQ,SAAU,CACjD,MAAMS,EAAc,KAAK,sBAAsBT,EAAe,IAAKn1C,CAAO,EACtE41C,GAAe,OAAOA,GAAgB,WACxCT,EAAe,IAAMS,EAEzB,EAIF,SAAW,CAACniD,EAAKkB,CAAK,IAAK,OAAO,QAAQwgD,CAAc,EAClD,MAAM,QAAQxgD,CAAK,EACrBwgD,EAAe1hD,CAAG,EAAIkB,EAAM,IAAK8D,GAC/B,OAAOA,GAAS,SAAW,KAAK,wBAAwBA,EAAMuH,CAAO,EAAIvH,CAAA,EAElE9D,GAAS,OAAOA,GAAU,WACnCwgD,EAAe1hD,CAAG,EAAI,KAAK,wBAAwBkB,EAAOqL,CAAO,GAIrE,OAAOm1C,CACT,CAKA,OAAe,mBACb/zB,EACAphB,EACAzM,EAAmC,CAAA,EAC9B,CACL,KAAM,CAAE,WAAA+gD,EAAa,EAAA,EAAU/gD,EACzBsiD,EAAuB,CAAE,GAAGz0B,CAAA,EAGlC,GAAIy0B,EAAqB,aAAc,CACrC,GAAI,CACF,MAAMC,EAAehF,GAAqB,QAAQ+E,EAAqB,aAAc71C,CAAO,EAC5F,OAAO,OAAO61C,EAAsBC,CAAY,CAClD,OAAS17C,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,WAAWy7C,EAAqB,YAAY,GAAIz7C,CAAK,CACpE,CACA,OAAOy7C,EAAqB,YAC9B,CAEA,OAAOA,CACT,CAKA,OAAe,eAAe7X,EAAYh+B,EAAgC,CACxE,MAAM+1C,EAAmB,CAAE,GAAG/X,CAAA,EAG9B,GAAI+X,EAAiB,SAAU,CAC7B,GAAI,CACF,MAAMp7C,EAAQ22C,GAAiB,QAAQyE,EAAiB,SAAU/1C,CAAO,EACzE+1C,EAAiB,MAAQp7C,CAC3B,OAASP,EAAO,CACd,QAAQ,KAAK,aAAa27C,EAAiB,QAAQ,GAAI37C,CAAK,CAC9D,CACA,OAAO27C,EAAiB,QAC1B,CAEA,OAAOA,CACT,CAKA,OAAe,mBAAmBC,EAAkBh2C,EAAgC,CAElF,GAAIA,EAAQ,kBAAoBA,EAAQ,iBAAiBg2C,CAAQ,EAC/D,OAAOh2C,EAAQ,iBAAiBg2C,CAAQ,EAI1C,MAAMC,EAAkB,CACtB,QAAS,CACP,QAAS,EACT,QAAS,EACT,YAAa,CAAC,EAAG,EAAG,GAAI,CAAC,EACzB,gBAAiB,GACjB,SAAU,GACV,SAAU,EAAA,EAEZ,SAAU,CACR,QAAS,EACT,QAAS,EACT,YAAa,CAAC,GAAI,GAAI,GAAI,EAAE,EAC5B,gBAAiB,GACjB,SAAU,GACV,SAAU,GACV,SAAU,CAAA,CACZ,EAGF,OAAOA,EAAgBD,CAAwC,GAAKC,EAAgB,OACtF,CAKA,OAAO,SAASnJ,EAA6B,CAC3C,MAAMjpB,EAAmB,CAAA,EAEzB,OAAKipB,GAKDA,EAAa,OAASsC,GAAoB,OAC5CvrB,EAAO,KAAK,0BAA0BipB,EAAa,IAAI,GAAG,EAGvD,MAAM,QAAQA,EAAa,MAAM,EAE3BA,EAAa,OAAO,SAAW,GACxCjpB,EAAO,KAAK,qBAAqB,EAFjCA,EAAO,KAAK,mBAAmB,EAK1BA,IAdLA,EAAO,KAAK,WAAW,EAChBA,EAcX,CAKA,OAAO,eACLqyB,EACAl2C,EACAzM,EAGI,CAAA,EACG,CACP,OAAO2iD,EACJ,OAAOrW,GAASA,EAAM,OAASuP,GAAoB,KAAK,EACxD,OAAa,KAAK,UAAUvP,EAAO7/B,EAASzM,CAAM,CAAC,CACxD,CACF,CAKO,SAAS4iD,IAAyB,CACvC,MAAO,CACL,KAAM/G,GAAoB,MAC1B,UAAWgF,GAAiB,UAAU,KAAKA,EAAgB,EAC3D,SAAUA,GAAiB,SAAS,KAAKA,EAAgB,CAAA,CAE7D,CCh4BO,MAAMgC,EAA6B,CAIxC,OAAe,gBAAgBj0B,EAAiD,CAC9E,GAAI,CAACA,GAAU,OAAOA,GAAW,SAC/B,MAAO,CAAE,OAAQ,GAAI,SAAU,CAAA,CAAC,EAIlC,MAAM/V,EAAa,CACjB,OAAQ,MAAM,QAAQ+V,EAAO,MAAM,EAAIA,EAAO,OAAS,CAAA,EACvD,SAAU,MAAM,QAAQA,EAAO,QAAQ,EAAIA,EAAO,SAAW,CAAA,CAAC,EAGhE,eAAQ,MAAM,mDAAoD,CAChE,YAAaA,EACb,WAAA/V,EACA,UAAW,MAAM,QAAQ+V,EAAO,MAAM,EACtC,YAAa,MAAM,QAAQA,EAAO,QAAQ,EAC1C,aAAc/V,EAAW,OAAO,OAChC,eAAgBA,EAAW,SAAS,MAAA,CACrC,EAEMA,CACT,CAKA,OAAO,UACL0gC,EACA9sC,EACAzM,EAGI,CAAA,EACC,CACL,KAAM,CACJ,0BAAA8gD,EAA4B,GAC5B,WAAAC,EAAa,EAAA,EACX/gD,EAGJ,GAAIu5C,EAAa,qBAAsB,CACrC,QAAQ,MAAM,uDAAwD,CACpE,qBAAsBA,EAAa,qBACnC,YAAa,CAAC,CAACA,EAAa,QAAA,CAC7B,EAED,GAAI,CACF,GAAIuH,EAA2B,CAE7B,QAAQ,MAAM,4DAA6DvH,EAAa,oBAAoB,EAC5G,MAAM4F,EAAiBS,GAA6B,QAClDrG,EAAa,qBACb9sC,EACA8sC,EAAa,QAAA,EAGf,QAAQ,MAAM,mDAAoD4F,CAAc,EAChF,QAAQ,MAAM,wDAAyD,OAAO,KAAKA,GAAkB,CAAA,CAAE,CAAC,EAGxG,MAAMvnB,EAAc,CAClB,KAAMikB,GAAoB,mBAC1B,SAAU,CACR,cAAe,qBACf,OAAQsD,CAAA,CACV,EAGF,eAAQ,MAAM,0BAA2BvnB,EAAY,SAAS,MAAM,EAGhEA,EAAY,SAAS,QAAU,OAAOA,EAAY,SAAS,QAAW,WACxE,QAAQ,MAAM,yBAAyB,EACvCA,EAAY,SAAS,OAAS,KAAK,gBAAgBA,EAAY,SAAS,OAAQnrB,EAAS,CAAE,WAAAs0C,CAAA,CAAY,GAGzG,QAAQ,MAAM,uDAAwDnpB,CAAW,EACjF,QAAQ,MAAM,gEAAiEA,EAAY,SAAS,MAAM,EACnGA,CACT,KAEE,gBAAQ,KAAK,uBAAuB,EAC7B,CACL,KAAMikB,GAAoB,mBAC1B,SAAU,CACR,cAAe,qBACf,OAAQ,CACN,KAAM,EACN,OAAQ,EACR,KAAM,KACN,SAAU,UACV,OAAQ,CAAE,OAAQ,GAAI,SAAU,CAAA,CAAC,EACjC,UAAW,CAAE,KAAM,YAAa,WAAY,CAAA,CAAC,CAAE,CACjD,CACF,CAGN,OAASh1C,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,MAAM,gBAAiBA,CAAK,EACpC,QAAQ,MAAM,kBAAmB0yC,CAAY,EAC7C,QAAQ,MAAM,sCAAuC9sC,EAAQ,wBAAwB,CAEvF,CACF,CAGA,MAAMkiB,EAAO4qB,EAAa,MAAQA,EAAa,QAAQ,MAAQ9sC,EAAQ,WAAW,MAAQ,EACpFgf,EAAS8tB,EAAa,QAAUA,EAAa,QAAQ,QAAU9sC,EAAQ,WAAW,QAAU,EAC5FpG,EAAOkzC,EAAa,MAAQA,EAAa,QAAQ,MAAQ9sC,EAAQ,WAAW,UAAY,KAGxFmrB,EAAc,CAClB,GAAG2hB,EACH,KAAMsC,GAAoB,mBAE1B,SAAU,CACR,cAAe,qBACf,OAAQ,CAEN,KAAAltB,EACA,OAAAlD,EACA,KAAAplB,EAEA,GAAIkzC,EAAa,QAAU,CAAA,EAE3B,OAAQ,KAAK,gBAAgBA,EAAa,QAAUA,EAAa,QAAQ,MAAM,EAC/E,UAAWA,EAAa,WAAaA,EAAa,QAAQ,WAAa,CAAA,EACvE,UAAWA,EAAa,WAAaA,EAAa,QAAQ,WAAa,CAAA,EACvE,YAAaA,EAAa,aAAeA,EAAa,QAAQ,aAAe,CAAA,CAAC,CAChF,CACF,EA6BF,GAzBA,QAAQ,MAAM,qDAAsD,CAClE,eAAgB3hB,EAAY,UAAU,OACtC,qBAAsBA,EAAY,UAAU,QAAQ,QAAQ,UAAU,OACtE,mBAAoBA,EAAY,UAAU,QAAQ,QAAQ,QAAQ,OAClE,KAAMA,EAAY,UAAU,QAAQ,KACpC,OAAQA,EAAY,UAAU,QAAQ,OACtC,KAAMA,EAAY,UAAU,QAAQ,KACpC,eAAgB,CAAC,CAAC2hB,EAAa,YAC/B,YAAaA,EAAa,YAC1B,gBAAiB,CAAC,CAACA,EAAa,aAChC,aAAcA,EAAa,aAC3B,qBAAsBA,CAAA,CACvB,EAGD,OAAO3hB,EAAY,OACnB,OAAOA,EAAY,KACnB,OAAOA,EAAY,OACnB,OAAOA,EAAY,KACnB,OAAOA,EAAY,OACnB,OAAOA,EAAY,UACnB,OAAOA,EAAY,UACnB,OAAOA,EAAY,YAGf,CAACkpB,EACH,OAAOlpB,EAGT,GAAI,CAEF,GAAIA,EAAY,YAAa,CAC3B,GAAI,CACF,MAAMwlB,EAAWH,GAAoB,QAAQrlB,EAAY,YAAanrB,CAAO,EAS7E,GANKmrB,EAAY,SAAS,SACxBA,EAAY,SAAS,OAAS,CAAA,GAEhC,OAAO,OAAOA,EAAY,SAAS,OAAQwlB,CAAQ,EAG/CA,EAAS,SAAU,CACrB,MAAMh2C,EAAQ22C,GAAiB,QAAQX,EAAS,SAAU3wC,CAAO,EACjEmrB,EAAY,SAAS,OAAO,MAAQxwB,CACtC,CACF,OAASP,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,eAAe+wB,EAAY,WAAW,GAAI/wB,CAAK,CAC9D,CACA,OAAO+wB,EAAY,WACrB,CAGA,GAAIA,EAAY,aAAc,CAC5B,GAAI,CACF,MAAM/J,EAAY0vB,GAAqB,QAAQ3lB,EAAY,aAAcnrB,CAAO,EAG3EmrB,EAAY,SAAS,SACxBA,EAAY,SAAS,OAAS,CAAA,GAK3BA,EAAY,SAAS,OAAO,YAC/BA,EAAY,SAAS,OAAO,UAAY,CAAA,GAI1C,OAAO,OAAOA,EAAY,SAAS,OAAO,UAAW/J,CAAS,CAChE,OAAShnB,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,eAAe+wB,EAAY,YAAY,GAAI/wB,CAAK,CAC/D,CACA,OAAO+wB,EAAY,YACrB,CAsBA,GAjBA,QAAQ,MAAM,gEAAiE,CAC7E,YAAa,CAAC,CAACA,EAAY,SAC3B,UAAW,CAAC,CAACA,EAAY,UAAU,OACnC,WAAYA,EAAY,UAAU,OAAS,OAAOA,EAAY,SAAS,OAAS,YAChF,eAAgBA,EAAY,UAAU,OAAS,OAAOA,EAAY,SAAS,QAAW,SAAW,GACjG,WAAYA,EAAY,UAAU,OAAS,OAAO,KAAKA,EAAY,SAAS,MAAM,EAAI,CAAA,CAAC,CACxF,EAEGA,EAAY,UAAU,QAAU,OAAOA,EAAY,SAAS,QAAW,UACzE,QAAQ,MAAM,+DAA+D,EAC7EA,EAAY,SAAS,OAAS,KAAK,gBAAgBA,EAAY,SAAS,OAAQnrB,EAAS,CAAE,WAAAs0C,CAAA,CAAY,EACvG,QAAQ,MAAM,iEAAiE,GAE/E,QAAQ,MAAM,uEAAuE,EAInFnpB,EAAY,SAAU,CACxB,GAAI,CACF,MAAMxwB,EAAQ22C,GAAiB,QAAQnmB,EAAY,SAAUnrB,CAAO,EAC/DmrB,EAAY,SAAS,SACxBA,EAAY,SAAS,OAAS,CAAA,GAEhCA,EAAY,SAAS,OAAO,MAAQxwB,CACtC,OAASP,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,eAAe+wB,EAAY,QAAQ,GAAI/wB,CAAK,CAC3D,CACA,OAAO+wB,EAAY,QACrB,CAGA,GAAIA,EAAY,aAAc,CAC5B,GAAI,CACF,MAAMqpB,EAAkB,KAAK,uBAC3BrpB,EAAY,aACZnrB,EACA,CAAE,WAAAs0C,CAAA,CAAW,EAEVnpB,EAAY,SAAS,SACxBA,EAAY,SAAS,OAAS,CAAA,GAEhCA,EAAY,SAAS,OAAO,UAAY,CACtC,GAAGqpB,EACH,GAAIrpB,EAAY,SAAS,OAAO,WAAa,CAAA,CAAC,CAElD,OAAS/wB,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,eAAe+wB,EAAY,YAAY,GAAI/wB,CAAK,CAC/D,CACA,OAAO+wB,EAAY,YACrB,CAGA,GAAIA,EAAY,UAAW,CACzB,GAAI,CACF,MAAMkrB,EAAexD,GAAkB,QACrC1nB,EAAY,UACZnrB,CAAA,EAEGmrB,EAAY,SAAS,SACxBA,EAAY,SAAS,OAAS,CAAA,GAEhCA,EAAY,SAAS,OAAO,UAAY,CACtC,GAAGkrB,EACH,GAAIlrB,EAAY,SAAS,OAAO,WAAa,CAAA,CAAC,CAElD,OAAS/wB,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,eAAe+wB,EAAY,SAAS,GAAI/wB,CAAK,CAC5D,CACA,OAAO+wB,EAAY,SACrB,CAGA,GAAIA,EAAY,SAAU,CACxB,QAAQ,MAAM,2DAA4D,CACxE,SAAUA,EAAY,SACtB,kBAAmB,CAAC,CAACA,EAAY,UAAU,OAC3C,mBAAoBA,EAAY,UAAU,QAAQ,WAAA,CACnD,EACD,GAAI,CACF,MAAMnI,EAAc,KAAK,mBACvBmI,EAAY,SACZnrB,EACA,CAAE,WAAAs0C,CAAA,CAAW,EAEf,QAAQ,MAAM,uBAAwBtxB,CAAW,EAC5CmI,EAAY,SAAS,SACxBA,EAAY,SAAS,OAAS,CAAA,GAEhCA,EAAY,SAAS,OAAO,YAAc,CACxC,GAAGnI,EACH,GAAImI,EAAY,SAAS,OAAO,aAAe,CAAA,CAAC,EAElD,QAAQ,MAAM,uCAAwCA,EAAY,SAAS,OAAO,WAAW,CAC/F,OAAS/wB,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,eAAe+wB,EAAY,QAAQ,GAAI/wB,CAAK,CAC3D,CACA,OAAO+wB,EAAY,QACrB,CAGA,GAAIA,EAAY,UAAU,QAAQ,aAAe,OAAOA,EAAY,SAAS,OAAO,aAAgB,SAAU,CAC5G,MAAMnI,EAAcmI,EAAY,SAAS,OAAO,aAC5C,CAACnI,EAAY,aAAe,CAAC,MAAM,QAAQA,EAAY,WAAW,GAAKA,EAAY,YAAY,SAAW,KAC5G,QAAQ,MAAM,mEAAmE,EACjFA,EAAY,YAAc,CAAC,EAAG,EAAG,GAAI,CAAC,EACtCA,EAAY,QAAUA,EAAY,SAAW,EAC7CA,EAAY,QAAUA,EAAY,SAAW,EAC7CA,EAAY,gBAAkBA,EAAY,iBAAmB,GAC7DA,EAAY,SAAWA,EAAY,UAAY,GAC/CA,EAAY,SAAWA,EAAY,UAAY,GAC/CA,EAAY,YAAcA,EAAY,aAAe,SAEzD,CAGA,eAAQ,MAAM,sDAAuD,CACnE,KAAMmI,EAAY,KAClB,eAAgBA,EAAY,UAAU,OACtC,qBAAsBA,EAAY,UAAU,QAAQ,QAAQ,UAAU,OACtE,mBAAoBA,EAAY,UAAU,QAAQ,QAAQ,QAAQ,OAClE,KAAMA,EAAY,UAAU,QAAQ,KACpC,OAAQA,EAAY,UAAU,QAAQ,OACtC,KAAMA,EAAY,UAAU,QAAQ,KACpC,aAAc,CAAC,CAACA,EAAY,UAAU,QAAQ,UAC9C,UAAWA,EAAY,UAAU,QAAQ,UACzC,aAAc,CAAC,CAACA,EAAY,UAAU,QAAQ,UAC9C,UAAWA,EAAY,UAAU,QAAQ,UACzC,eAAgB,CAAC,CAACA,EAAY,UAAU,QAAQ,YAChD,YAAaA,EAAY,UAAU,QAAQ,WAAA,CAC5C,EAEMA,CACT,OAAS/wB,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,eAAQ,KAAK,YAAaA,CAAK,EACxB+wB,CACT,CACF,CAKA,OAAe,gBACb53B,EACAyM,EACAs2C,EAA0C,CAAA,EACrC,CACL,KAAM,CAAE,WAAAhC,EAAa,EAAA,EAAUgC,EACzBC,EAAoB,CAAE,GAAGhjD,CAAA,EAGzBijD,EAA+C,CAAA,EAmErD,GAhEID,EAAkB,SACpB,QAAQ,MAAM,4DAA4D,EAC1E,QAAQ,MAAM,8BAA+BA,EAAkB,MAAM,EACjEA,EAAkB,OAAO,SAC3B,QAAQ,MAAM,uBAAuBA,EAAkB,OAAO,OAAO,MAAM,IAAI,EAC/EA,EAAkB,OAAO,OAASA,EAAkB,OAAO,OAAO,IAAI,CAACl0B,EAAYlc,IAAkB,CACnG,QAAQ,MAAM,uBAAuBA,CAAK,KAAM,CAC9C,GAAIkc,EAAM,GACV,KAAMA,EAAM,KACZ,eAAgB,CAAC,CAACA,EAAM,YACxB,YAAaA,EAAM,YACnB,UAAW,OAAO,KAAKA,CAAK,CAAA,CAC7B,EACD,MAAM8I,EAAc,KAAK,eAAe9I,EAAOriB,EAAS,CAAE,WAAAs0C,EAAY,EAGtE,OAAIjyB,EAAM,aAAe8I,EAAY,KACnCqrB,EAAqBn0B,EAAM,WAAW,EAAI8I,EAAY,GACtD,QAAQ,MAAM,0BAA0B9I,EAAM,WAAW,iBAAiB8I,EAAY,EAAE,SAAS,GAGnG,QAAQ,MAAM,yBAAyBhlB,CAAK,KAAM,CAChD,GAAIglB,EAAY,GAChB,KAAMA,EAAY,KAClB,eAAgB,CAAC,CAACA,EAAY,YAC9B,YAAaA,EAAY,YACzB,YAAa,CAAC,CAACA,EAAY,SAC3B,SAAUA,EAAY,QAAA,CACvB,EACMA,CACT,CAAC,GAECorB,EAAkB,OAAO,WAC3B,QAAQ,MAAM,yBAAyBA,EAAkB,OAAO,SAAS,MAAM,IAAI,EACnFA,EAAkB,OAAO,SAAWA,EAAkB,OAAO,SAAS,IAAI,CAACl0B,EAAYlc,IAAkB,CACvG,QAAQ,MAAM,yBAAyBA,CAAK,KAAM,CAChD,GAAIkc,EAAM,GACV,KAAMA,EAAM,KACZ,eAAgB,CAAC,CAACA,EAAM,YACxB,YAAaA,EAAM,YACnB,UAAW,OAAO,KAAKA,CAAK,CAAA,CAC7B,EACD,MAAM8I,EAAc,KAAK,eAAe9I,EAAOriB,EAAS,CAAE,WAAAs0C,EAAY,EAGtE,OAAIjyB,EAAM,aAAe8I,EAAY,KACnCqrB,EAAqBn0B,EAAM,WAAW,EAAI8I,EAAY,GACtD,QAAQ,MAAM,0BAA0B9I,EAAM,WAAW,iBAAiB8I,EAAY,EAAE,SAAS,GAGnG,QAAQ,MAAM,2BAA2BhlB,CAAK,KAAM,CAClD,GAAIglB,EAAY,GAChB,KAAMA,EAAY,KAClB,eAAgB,CAAC,CAACA,EAAY,YAC9B,YAAaA,EAAY,YACzB,YAAa,CAAC,CAACA,EAAY,SAC3B,SAAUA,EAAY,QAAA,CACvB,EACMA,CACT,CAAC,IAKDorB,EAAkB,UAAW,CAE/B,GAAIA,EAAkB,UAAU,aAC9B,GAAI,CACF,MAAME,EAAoB3F,GAAqB,QAC7CyF,EAAkB,UAAU,aAC5Bv2C,CAAA,EAGFu2C,EAAkB,UAAY,CAC5B,GAAGE,EACH,GAAGF,EAAkB,UACrB,aAAc,MAAA,EAEhB,QAAQ,MAAM,kFAAmF,CAC/F,qBAAsBA,EAAkB,UAAU,aAClD,kBAAAE,EACA,gBAAiBF,EAAkB,SAAA,CACpC,CACH,OAASn8C,EAAO,CACd,GAAIk6C,EAAY,MAAMl6C,EACtB,QAAQ,KAAK,sBAAsBm8C,EAAkB,UAAU,YAAY,GAAIn8C,CAAK,CACtF,CAIFm8C,EAAkB,UAAY,KAAK,yBACjCA,EAAkB,UAClBC,CAAA,EAGE,MAAM,QAAQD,EAAkB,UAAU,UAAU,IACtD,QAAQ,MAAM,oEAAqE,CACjF,iBAAkBA,EAAkB,UAAU,WAAW,OACzD,WAAYA,EAAkB,UAAU,UAAA,CACzC,EACDA,EAAkB,UAAU,WAAaA,EAAkB,UAAU,WAAW,IAC9E,CAACG,EAAoBvwC,IAAkB,CAWrC,GAVA,QAAQ,MAAM,mBAAmBA,CAAK,KAAM,CAC1C,KAAM,OAAOuwC,EACb,SAAU,OAAOA,GAAkB,SACnC,SAAU,OAAOA,GAAkB,UAAYA,IAAkB,KACjE,cAAAA,EACA,gBAAiBA,GAAiB,OAAOA,GAAkB,UAAY,iBAAkBA,EACzF,aAAcA,GAAiB,OAAOA,GAAkB,SAAWA,EAAc,aAAe,MAAA,CACjG,EAGG,OAAOA,GAAkB,SAAU,CAErC,GADA,QAAQ,MAAM,gBAAgBvwC,CAAK,UAAU,EACzCuwC,EAAc,WAAW,eAAe,EAAG,CAC7C,MAAMhG,EAAUgG,EAAc,QAAQ,gBAAiB,EAAE,EACzD,QAAQ,MAAM,2BAA2BhG,CAAO,EAAE,EAClD,GAAI,CACF,MAAM/W,EAAWmX,GAAqB,QAAQJ,EAAS1wC,CAAO,EAC9D,QAAQ,MAAM,gBAAgBmG,CAAK,UAAWwzB,CAAQ,EACtD,MAAMvtB,EAAa,KAAK,yBAAyButB,EAAU6c,CAAoB,EAC/E,eAAQ,MAAM,gBAAgBrwC,CAAK,UAAWiG,CAAU,EACjDA,CACT,OAAShS,EAAO,CACd,GAAIk6C,EAAY,MAAMl6C,EACtB,eAAQ,KAAK,sBAAsBs2C,CAAO,GAAIt2C,CAAK,EAC5Cs8C,CACT,CACF,CAEA,GAAI,CACF,MAAM/c,EAAWmX,GAAqB,QAAQ4F,EAAe12C,CAAO,EAEpE,OADmB,KAAK,yBAAyB25B,EAAU6c,CAAoB,CAEjF,OAASp8C,EAAO,CACd,GAAIk6C,EAAY,MAAMl6C,EACtB,eAAQ,KAAK,sBAAsBs8C,CAAa,GAAIt8C,CAAK,EAClDs8C,CACT,CACF,SAESA,GAAiB,OAAOA,GAAkB,UAAYA,EAAc,aAAc,CACzF,MAAMhG,EAAUgG,EAAc,aAC9B,QAAQ,MAAM,gBAAgBvwC,CAAK,mBAAmBuqC,CAAO,EAAE,EAC/D,GAAI,CACF,MAAM+F,EAAoB3F,GAAqB,QAAQJ,EAAS1wC,CAAO,EACvE,QAAQ,MAAM,gBAAgBmG,CAAK,UAAWswC,CAAiB,EAE/D,MAAMp1C,EAAS,CACb,GAAGo1C,EACH,GAAGC,EACH,aAAc,MAAA,EAEhB,QAAQ,MAAM,gBAAgBvwC,CAAK,SAAU9E,CAAM,EACnD,MAAM+K,EAAa,KAAK,yBAAyB/K,EAAQm1C,CAAoB,EAC7E,eAAQ,MAAM,gBAAgBrwC,CAAK,UAAWiG,CAAU,EACjDA,CACT,OAAShS,EAAO,CACd,GAAIk6C,EAAY,MAAMl6C,EACtB,eAAQ,KAAK,sBAAsBs2C,CAAO,GAAIt2C,CAAK,EAC5Cs8C,CACT,CACF,SAESA,GAAiB,OAAOA,GAAkB,SACjD,eAAQ,MAAM,gBAAgBvwC,CAAK,cAAc,EAC1C,KAAK,yBAAyBuwC,EAAeF,CAAoB,EAE1E,eAAQ,MAAM,gBAAgBrwC,CAAK,eAAgBuwC,CAAa,EACzDA,CACT,CAAA,EAGN,CA6CA,GAzCIH,EAAkB,UAAY,OAAOA,EAAkB,UAAa,WACtEA,EAAkB,SAAW,KAAK,kBAChCA,EAAkB,SAClBv2C,EACA,CAAE,WAAAs0C,CAAA,CAAW,GAKb,MAAM,QAAQiC,EAAkB,eAAe,IACjDA,EAAkB,gBAAkBA,EAAkB,gBAAgB,IACnEG,GAAuB,CACtB,GAAIA,EAAc,aAChB,GAAI,CACF,MAAMt1B,EAAY0vB,GAAqB,QAAQ4F,EAAc,aAAc12C,CAAO,EAClF,MAAO,CACL,GAAG02C,EACH,GAAGt1B,EACH,aAAc,MAAA,CAElB,OAAShnB,EAAO,CACd,GAAIk6C,EAAY,MAAMl6C,EACtB,eAAQ,KAAK,wBAAwBs8C,EAAc,YAAY,GAAIt8C,CAAK,EACjEs8C,CACT,CAEF,OAAOA,CACT,CAAA,GAKAH,EAAkB,OAAS,OAAOA,EAAkB,OAAU,WAChEA,EAAkB,MAAQ,KAAK,eAC7BA,EAAkB,MAClBv2C,EACA,CAAE,WAAAs0C,CAAA,CAAW,GAKbiC,EAAkB,aAAc,CAClC,GAAI,CACF,MAAM/B,EAAkB,KAAK,uBAC3B+B,EAAkB,aAClBv2C,EACA,CAAE,WAAAs0C,CAAA,CAAW,EAEfiC,EAAkB,UAAY,CAC5B,GAAG/B,EAEH,GAAI+B,EAAkB,WAAa,CAAA,CAAC,CAExC,OAASn8C,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,aAAam8C,EAAkB,YAAY,GAAIn8C,CAAK,CACnE,CACA,OAAOm8C,EAAkB,YAC3B,CAGA,GAAIA,EAAkB,UAAW,CAC/B,QAAQ,MAAM,gEAAiE,CAC7E,UAAWA,EAAkB,UAC7B,wBAAyB,CAAC,CAACv2C,EAAQ,qBACnC,wBAAyBA,EAAQ,qBAAuB,OAAO,KAAKA,EAAQ,oBAAoB,EAAI,CAAA,CAAC,CACtG,EACD,GAAI,CAEF,MAAM22C,EAAkB,CACtB,GAAG/G,GACH,GAAG5vC,EAEH,qBAAsBA,EAAQ,sBAAwB4vC,GAAyB,oBAAA,EAE3EyG,EAAexD,GAAkB,QACrC0D,EAAkB,UAClBI,CAAA,EAEFJ,EAAkB,UAAY,CAC5B,GAAGF,EAEH,GAAIE,EAAkB,WAAa,CAAA,CAAC,CAExC,OAASn8C,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,aAAam8C,EAAkB,SAAS,GAAIn8C,CAAK,CAChE,CACA,OAAOm8C,EAAkB,SAC3B,CAGA,GAAIA,EAAkB,SAAU,CAC9B,QAAQ,MAAM,yEAA0E,CACtF,SAAUA,EAAkB,SAC5B,mBAAoBA,EAAkB,WAAA,CACvC,EACD,GAAI,CACF,MAAMvzB,EAAc,KAAK,mBACvBuzB,EAAkB,SAClBv2C,EACA,CAAE,WAAAs0C,CAAA,CAAW,EAEf,QAAQ,MAAM,gCAAiCtxB,CAAW,EAC1DuzB,EAAkB,YAAc,CAC9B,GAAGvzB,EAEH,GAAIuzB,EAAkB,aAAe,CAAA,CAAC,EAExC,QAAQ,MAAM,yCAA0CA,EAAkB,WAAW,CACvF,OAASn8C,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,aAAam8C,EAAkB,QAAQ,GAAIn8C,CAAK,CAC/D,CACA,OAAOm8C,EAAkB,QAC3B,CAEA,OAAOA,CACT,CAKA,OAAe,yBACbn1B,EACAo1B,EACK,CACL,GAAI,CAACp1B,GAAa,OAAOA,GAAc,SACrC,OAAOA,EAGT,QAAQ,MAAM,+DAAgE,CAC5E,YAAaA,EAAU,GACvB,cAAeA,EAAU,KACzB,eAAgB,CAAC,CAACA,EAAU,YAC5B,YAAaA,EAAU,YACvB,yBAA0Bo1B,EAAuB,OAAO,KAAKA,CAAoB,EAAI,CAAA,EACrF,qBAAAA,CAAA,CACD,EAED,MAAMpqC,EAAa,CAAE,GAAGgV,CAAA,EASxB,OALI,CAAChV,EAAW,MAAQA,EAAW,QAAUA,EAAW,OAAO,OAC7DA,EAAW,KAAOA,EAAW,OAAO,MAI9BA,EAAW,KAAA,CACjB,IAAK,WAEH,GAAIA,EAAW,OAAQ,CAIrB,GAHAA,EAAW,SAAW,CAAE,GAAGA,EAAW,MAAA,EAGlCA,EAAW,SAAS,QAAU,OAAOA,EAAW,SAAS,QAAW,SAAU,CAChF,MAAMkY,EAASlY,EAAW,SAAS,OAC/B,MAAOkY,GAAU,MAAOA,IAC1BlY,EAAW,SAAS,OAAS,CAACkY,EAAO,EAAGA,EAAO,CAAC,EAEpD,CAGA,OAAOlY,EAAW,MACpB,CACA,MAEF,IAAK,cACCA,EAAW,SACbA,EAAW,YAAc,CAAE,GAAGA,EAAW,MAAA,EAEzC,OAAOA,EAAW,QAEpB,MAEF,IAAK,QACH,GAAIA,EAAW,OAAQ,CAIrB,GAHAA,EAAW,MAAQ,CAAE,GAAGA,EAAW,MAAA,EAG/BA,EAAW,MAAM,QAAU,OAAOA,EAAW,MAAM,QAAW,SAAU,CAC1E,MAAMkY,EAASlY,EAAW,MAAM,OAC5B,MAAOkY,GAAU,MAAOA,IAC1BlY,EAAW,MAAM,OAAS,CAACkY,EAAO,EAAGA,EAAO,CAAC,EAEjD,CAGA,OAAOlY,EAAW,MACpB,CACA,MAEF,IAAK,YAECA,EAAW,QAAU,MAAM,QAAQA,EAAW,OAAO,UAAU,IACjEA,EAAW,UAAYA,EAAW,OAAO,WAAW,IAAKme,GACvD,KAAK,yBAAyBA,EAAGisB,CAAoB,CAAA,EAGvD,OAAOpqC,EAAW,QAEpB,MAEF,QAEE,GAAIA,EAAW,OAAQ,CAErB,KAAM,CAAE,KAAA9Y,EAAM,GAAGsjD,CAAA,EAAsBxqC,EAAW,OAClD,OAAO,OAAOA,EAAYwqC,CAAiB,EAC3C,OAAOxqC,EAAW,MACpB,CAAA,CAIJ,GAAIA,EAAW,aAAeoqC,EAAsB,CAClD,MAAMK,EAAsBzqC,EAAW,YACvC,IAAI0qC,EAGJ,GAAIN,EAAqBK,CAAmB,EAC1CC,EAAgBN,EAAqBK,CAAmB,EACxD,QAAQ,MAAM,6EAA8E,CAC1F,SAAUA,EACV,OAAQC,EACR,KAAM,OAAA,CACP,MAGE,CAEH,MAAMC,EAAc,OAAO,KAAKP,CAAoB,EAAE,KAAK5Z,GAAO,CAMhE,GAJIA,EAAI,WAAWia,EAAsB,GAAG,GAAKja,IAAQia,GAIrDja,EAAI,SAASia,CAAmB,EAClC,MAAO,GAGT,MAAMG,EAAWpa,EAAI,MAAM,GAAG,EACxBqa,EAAcJ,EAAoB,MAAM,GAAG,EACjD,OAAOG,EAAS,KAAKt2B,GAAQu2B,EAAY,SAASv2B,CAAI,CAAC,CACzD,CAAC,EAEGq2B,IACFD,EAAgBN,EAAqBO,CAAW,EAChD,QAAQ,MAAM,8EAA+E,CAC3F,SAAUF,EACV,YAAaE,EACb,OAAQD,EACR,KAAM,WAAA,CACP,EAEL,CAEIA,EACF1qC,EAAW,YAAc0qC,EAEzB,QAAQ,MAAM,6EAA8E,CAC1F,SAAUD,EACV,qBAAAL,EACA,QAAS,sCAAA,CACV,CAEL,CAGA,OAAIp1B,EAAU,aAAe,CAAChV,EAAW,cACvCA,EAAW,YAAcgV,EAAU,aAMrC,QAAQ,MAAM,4DAA6D,CACzE,MAAOA,EACP,OAAQhV,EACR,YAAa,CAAC,CAACA,EAAW,SAC1B,eAAgB,CAAC,CAACA,EAAW,YAC7B,SAAU,CAAC,CAACA,EAAW,MACvB,aAAc,CAAC,CAACA,EAAW,SAAA,CAC5B,EAEMA,CACT,CAGA,OAAe,eACbiW,EACAriB,EACAzM,EAAmC,CAAA,EAC9B,CACL,QAAQ,MAAM,yBAA0B,CACtC,QAAS8uB,EAAM,GACf,UAAWA,EAAM,KACjB,eAAgB,CAAC,CAACA,EAAM,YACxB,YAAaA,EAAM,YACnB,YAAa,CAAC,CAACA,EAAM,SACrB,SAAUA,EAAM,SAChB,UAAW,OAAO,KAAKA,CAAK,EAC5B,0BAA2B,CAAC,CAACriB,EAAQ,gBACrC,0BAA2BA,EAAQ,gBAAkB,OAAO,KAAKA,EAAQ,eAAe,EAAI,CAAA,CAAC,CAC9F,EAED,KAAM,CAAE,WAAAs0C,EAAa,EAAA,EAAU/gD,EACzB29B,EAAmB,CAAE,GAAG7O,CAAA,EAE9B,GAAI6O,EAAiB,YAAa,CAChC,QAAQ,MAAM,qCAAsCA,EAAiB,WAAW,EAChF,QAAQ,MAAM,8CAA+ClxB,EAAQ,eAAe,EACpF,QAAQ,MAAM,mDAAoDA,EAAQ,gBAAkB,OAAO,KAAKA,EAAQ,eAAe,EAAI,EAAE,EACrI,GAAI,CACF,QAAQ,MAAM,mDAAmD,EACjE,MAAM2wC,EAAWH,GAAoB,QAAQtf,EAAiB,YAAalxB,CAAO,EAClF,QAAQ,MAAM,oCAAqC2wC,CAAQ,EAC3D,OAAO,OAAOzf,EAAkByf,CAAQ,EACxC,QAAQ,MAAM,iCAAkCzf,CAAgB,EAE5DA,EAAiB,UAAY,MAAM,QAAQA,EAAiB,QAAQ,GACtE,QAAQ,MAAM,2BAA4B,CACxC,MAAOA,EAAiB,SAAS,OACjC,OAAQA,EAAiB,SAAS,MAAM,EAAG,CAAC,EAAE,IAAI,CAACoL,EAAQ78B,KAAe,CACxE,MAAOA,EACP,MAAO68B,EACP,QAAS,MAAM,QAAQA,CAAC,EACxB,OAAQ,MAAM,QAAQA,CAAC,EAAIA,EAAE,OAAS,KAAA,EACtC,CAAA,CACH,CAEL,OAASliC,EAAO,CAEd,GADA,QAAQ,MAAM,uCAAwCA,CAAK,EACvDk6C,EAAY,MAAMl6C,EACtB,QAAQ,KAAK,0BAA0B82B,EAAiB,WAAW,GAAI92B,CAAK,CAC9E,CACA,OAAO82B,EAAiB,YACxB,QAAQ,MAAM,8CAA+CA,CAAgB,CAC/E,CAEA,GAAIA,EAAiB,SAAU,CAC7B,GAAI,CACF,MAAMv2B,EAAQ22C,GAAiB,QAAQpgB,EAAiB,SAAUlxB,CAAO,EACzEkxB,EAAiB,MAAQv2B,CAC3B,OAASP,EAAO,CACd,GAAIk6C,EAAY,MAAMl6C,EACtB,QAAQ,KAAK,uBAAuB82B,EAAiB,QAAQ,GAAI92B,CAAK,CACxE,CACA,OAAO82B,EAAiB,QAC1B,CAqCA,GAlCKA,EAAiB,WACpBA,EAAiB,SAAW,CAAA,GAI1B,CAACA,EAAiB,SAAS,IAAMA,EAAiB,KACpDA,EAAiB,SAAS,GAAKA,EAAiB,IAK9CA,EAAiB,YAAc,SACjCA,EAAiB,SAAS,UAAYA,EAAiB,UAEvD,OAAOA,EAAiB,WAGtBA,EAAiB,QAEf,OAAOA,EAAiB,OAAU,SACpCA,EAAiB,SAAS,MAAQA,EAAiB,MAAM,MAAQA,EAAiB,SAAS,IAAM,GACxF,OAAOA,EAAiB,OAAU,WAC3CA,EAAiB,SAAS,MAAQA,EAAiB,OAGrD,OAAOA,EAAiB,OAItBA,EAAiB,SAAS,WAAa,CAACA,EAAiB,SAAS,OAASA,EAAiB,SAAS,KACvGA,EAAiB,SAAS,MAAQA,EAAiB,SAAS,IAI1DA,EAAiB,SAAS,GAAI,CAChC,MAAM5pB,EAAK4pB,EAAiB,SAAS,GAAG,YAAA,EACpC5pB,EAAG,SAAS,MAAM,EACpB4pB,EAAiB,SAAS,cAAgB,OACjC5pB,EAAG,SAAS,OAAO,EAC5B4pB,EAAiB,SAAS,cAAgB,QAG1CA,EAAiB,SAAS,cAAgBA,EAAiB,SAAS,EAExE,CAGA,GAAIA,EAAiB,OAAS,SAAWA,EAAiB,SAAU,CAClE,QAAQ,MAAM,qCAAsC,CAClD,QAASA,EAAiB,UAAU,GACpC,SAAUA,EAAiB,SAC3B,aAAcA,EAAiB,IAAA,CAChC,EAGD,MAAMoM,EAAUpM,EAAiB,SAAS,EACpCqM,EAAUrM,EAAiB,SAAS,EACpCp5B,EAAS,GAEfo5B,EAAiB,KAAO,SACxBA,EAAiB,SAAW,CAC1B,CAACoM,EAASC,CAAO,EACjB,CAACD,EAAUxlC,EAAQylC,CAAO,CAAA,EAI5B,OAAOrM,EAAiB,SAExB,QAAQ,MAAM,uCAAwC,CACpD,QAASA,EAAiB,KAC1B,SAAUA,EAAiB,QAAA,CAC5B,CACH,CAEA,OAAOA,CACT,CAKA,OAAe,kBACbyf,EACA3wC,EACAzM,EAAmC,CAAA,EAC9B,CACL,KAAM,CAAE,WAAA+gD,EAAa,EAAA,EAAU/gD,EACzB2jD,EAAsB,CAAE,GAAGvG,CAAA,EAGjC,GAAIuG,EAAoB,YAAa,CACnC,GAAI,CACF,MAAMC,EAAmB3G,GAAoB,QAAQ0G,EAAoB,YAAal3C,CAAO,EAC7F,OAAO,OAAOk3C,EAAqBC,CAAgB,CACrD,OAAS/8C,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,aAAa88C,EAAoB,WAAW,GAAI98C,CAAK,CACpE,CACA,OAAO88C,EAAoB,WAC7B,CAEA,OAAOA,CACT,CAKA,OAAe,mBACb91B,EACAphB,EACAzM,EAAmC,CAAA,EAC9B,CACL,KAAM,CAAE,WAAA+gD,EAAa,EAAA,EAAU/gD,EACzBsiD,EAAuB,CAAE,GAAGz0B,CAAA,EAGlC,GAAIy0B,EAAqB,aAAc,CACrC,GAAI,CACF,MAAMY,EAAoB3F,GAAqB,QAAQ+E,EAAqB,aAAc71C,CAAO,EACjG,OAAO,OAAO61C,EAAsBY,CAAiB,CACvD,OAASr8C,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,aAAay7C,EAAqB,YAAY,GAAIz7C,CAAK,CACtE,CACA,OAAOy7C,EAAqB,YAC9B,CAEA,OAAOA,CACT,CAKA,OAAe,eACbl7C,EACAqF,EACAzM,EAAmC,CAAA,EAC9B,CACL,KAAM,CAAE,WAAA+gD,EAAa,EAAA,EAAU/gD,EACzB6jD,EAAmB,CAAE,GAAGz8C,CAAA,EAG9B,GAAIy8C,EAAiB,SAAU,CAC7B,GAAI,CACF,MAAM3F,EAAgBH,GAAiB,QAAQ8F,EAAiB,SAAUp3C,CAAO,EACjF,OAAO,OAAOo3C,EAAkB3F,CAAa,CAC/C,OAASr3C,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,aAAag9C,EAAiB,QAAQ,GAAIh9C,CAAK,CAC9D,CACA,OAAOg9C,EAAiB,QAC1B,CAEA,OAAOA,CACT,CAKA,OAAe,uBACbC,EACAr3C,EACAzM,EAAmC,CAAA,EAC9B,CACL,KAAM,CAAE,WAAA+gD,EAAa,EAAA,EAAU/gD,EAE/B,GAAI,CAAC8jD,GAAgB,OAAOA,GAAiB,SAAU,CACrD,GAAI/C,EACF,MAAM,IAAI,MAAM,YAAY+C,CAAY,EAAE,EAE5C,eAAQ,KAAK,YAAYA,CAAY,EAAE,EAChC,CAAA,CACT,CAEA,GAAI,CAEF,MAAM3G,EAAU2G,EAAa,QAAQ,gBAAiB,EAAE,EAGxD,GAAIr3C,EAAQ,sBAAwBA,EAAQ,qBAAqB0wC,CAAO,EACtE,MAAO,CAAE,GAAG1wC,EAAQ,qBAAqB0wC,CAAO,CAAA,EAIlD,GAAI4D,EACF,MAAM,IAAI,MAAM,YAAY5D,CAAO,EAAE,EAIvC,MAAM4G,EAAiB,KAAK,2BAA2B5G,CAAO,EAC9D,eAAQ,KAAK,wBAAwBA,CAAO,EAAE,EACvC4G,CACT,OAASl9C,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,eAAQ,KAAK,aAAai9C,CAAY,GAAIj9C,CAAK,EACxC,CAAA,CACT,CACF,CAKA,OAAe,mBACb47C,EACAh2C,EACAzM,EAAmC,CAAA,EAC9B,CACL,KAAM,CAAE,WAAA+gD,EAAa,EAAA,EAAU/gD,EAE/B,GAAI,CAACyiD,GAAY,OAAOA,GAAa,SAAU,CAC7C,GAAI1B,EACF,MAAM,IAAI,MAAM,YAAY0B,CAAQ,EAAE,EAExC,eAAQ,KAAK,YAAYA,CAAQ,EAAE,EAC5B,CAAA,CACT,CAEA,GAAI,CAEF,MAAMtF,EAAUsF,EAAS,QAAQ,YAAa,EAAE,EAWhD,GATA,QAAQ,MAAM,sDAAuD,CACnE,SAAAA,EACA,QAAAtF,EACA,2BAA4B,CAAC,CAAC1wC,EAAQ,iBACtC,2BAA4BA,EAAQ,iBAAmB,OAAO,KAAKA,EAAQ,gBAAgB,EAAI,CAAA,EAC/F,gBAAiBA,EAAQ,kBAAoB,CAAC,CAACA,EAAQ,iBAAiB0wC,CAAO,CAAA,CAChF,EAGG1wC,EAAQ,kBAAoBA,EAAQ,iBAAiB0wC,CAAO,EAAG,CACjE,MAAMn9C,EAAS,CAAE,GAAGyM,EAAQ,iBAAiB0wC,CAAO,CAAA,EACpD,eAAQ,MAAM,iBAAkBn9C,CAAM,EAC/BA,CACT,CAGA,GAAI+gD,EACF,MAAM,IAAI,MAAM,YAAY5D,CAAO,EAAE,EAIvC,MAAM4G,EAAiB,KAAK,uBAAuB5G,CAAO,EAC1D,eAAQ,KAAK,wBAAwBA,CAAO,EAAE,EAC9C,QAAQ,MAAM,eAAgB4G,CAAc,EACrCA,CACT,OAASl9C,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,eAAQ,KAAK,aAAa47C,CAAQ,GAAI57C,CAAK,EACpC,CAAA,CACT,CACF,CAKA,OAAe,2BAA2Bs2C,EAAsB,CAC9D,MAAM6G,EAAuC,CAC3C,kBAAmB,CACjB,GAAI,oBACJ,OAAQ,CACN,SAAU,CAAC,EAAG,EAAE,EAChB,OAAQ,GACR,YAAa,aACb,IAAK,EACL,IAAK,EACL,KAAM,GAAA,EAER,kBAAmB,CACjB,QAAS,GACT,OAAQ,EACR,OAAQ,CAAC,KAAM,MAAO,MAAO,MAAO,IAAI,EACxC,eAAgB,EAAA,EAElB,SAAU,IACV,OAAQ,cACR,YAAa,QAAA,EAEf,gBAAiB,CACf,GAAI,kBACJ,OAAQ,CACN,SAAU,CAAC,GAAI,CAAC,EAChB,OAAQ,GACR,YAAa,WACb,IAAK,EACL,IAAK,EACL,KAAM,GAAA,EAER,kBAAmB,CACjB,QAAS,GACT,OAAQ,EACR,OAAQ,CAAC,KAAM,MAAO,MAAO,MAAO,IAAI,EACxC,eAAgB,EAAA,EAElB,SAAU,IACV,OAAQ,cACR,YAAa,QAAA,CACf,EAGF,OAAOA,EAAgB7G,CAAO,GAAK6G,EAAgB,iBACrD,CAKA,OAAe,uBAAuB7G,EAAsB,CAC1D,MAAM6G,EAAuC,CAC3C,QAAS,CACP,GAAI,UACJ,QAAS,EACT,QAAS,EACT,YAAa,CAAC,EAAG,EAAG,GAAI,CAAC,EACzB,gBAAiB,GACjB,SAAU,GACV,SAAU,GACV,YAAa,QAAA,EAEf,SAAU,CACR,GAAI,WACJ,QAAS,EACT,QAAS,EACT,YAAa,CAAC,GAAI,GAAI,GAAI,EAAE,EAC5B,gBAAiB,GACjB,SAAU,GACV,SAAU,GACV,SAAU,EACV,YAAa,iBAAA,CACf,EAGF,OAAOA,EAAgB7G,CAAO,GAAK6G,EAAgB,OACrD,CAKA,OAAO,SAASzK,EAA6B,CAC3C,MAAMjpB,EAAmB,CAAA,EAEzB,OAAKipB,GAKDA,EAAa,OAASsC,GAAoB,oBAC5CvrB,EAAO,KAAK,wCAAwCipB,EAAa,IAAI,GAAG,EAGtE,CAACA,EAAa,QAAU,OAAOA,EAAa,QAAW,SAEpDA,EAAa,aAChBjpB,EAAO,KAAK,kCAAkC,EAG5C,CAACipB,EAAa,OAAO,UAAY,CAACA,EAAa,aACjDjpB,EAAO,KAAK,kCAAkC,EAI3CA,IAnBLA,EAAO,KAAK,aAAa,EAClBA,EAmBX,CAKA,OAAO,eACLqyB,EACAl2C,EACAzM,EAGI,CAAA,EACG,CACP,OAAO2iD,EACJ,OAAOrW,GAASA,EAAM,OAASuP,GAAoB,kBAAkB,EACrE,OAAa,KAAK,UAAUvP,EAAO7/B,EAASzM,CAAM,CAAC,CACxD,CACF,CAKO,SAASikD,IAAqC,CACnD,MAAO,CACL,KAAMpI,GAAoB,mBAC1B,UAAWgH,GAA6B,UAAU,KAAKA,EAA4B,EACnF,SAAUA,GAA6B,SAAS,KAAKA,EAA4B,CAAA,CAErF,CCtzCO,MAAMqB,EAAgB,CAI3B,OAAO,cACL3K,EACA9sC,EACAzM,EAGI,CAAA,EACC,CACL,KAAM,CACJ,0BAAA8gD,EAA4B,GAC5B,WAAAC,EAAa,EAAA,EACX/gD,EAEJ,QAAQ,MAAM,0CAA0Cu5C,EAAa,IAAI,aAAaA,EAAa,SAAS,UAAU,EAAG,EAAE,CAAC,iBAAiBA,EAAa,QAAQ,+BAA+BuH,CAAyB,EAAE,EAG5N,MAAMlpB,EAAc,CAClB,GAAG2hB,EACH,KAAMsC,GAAoB,IAAA,EAI5B,GAAI,CAACiF,EACH,OAAOlpB,EAGT,GAAI,CAYF,GAVI,OAAOA,EAAY,SAAY,WACjCA,EAAY,QAAU,KAAK,mBAAmBA,EAAY,QAASnrB,EAAS,CAAE,WAAAs0C,EAAY,GAIxFnpB,EAAY,OAAS,OAAOA,EAAY,OAAU,WACpDA,EAAY,MAAQ,KAAK,aAAaA,EAAY,MAAOnrB,EAAS,CAAE,WAAAs0C,EAAY,GAI9EnpB,EAAY,SAAU,CACxB,QAAQ,MAAM,iCAAiCA,EAAY,QAAQ,EAAE,EACrE,GAAI,CAEF,MAAMxwB,EAAQ22C,GAAiB,QAAQnmB,EAAY,SAAUnrB,CAAO,EACpE,QAAQ,MAAM,0BAA2BrF,CAAK,EAC9CwwB,EAAY,MAAQ,CAAE,GAAGA,EAAY,MAAO,GAAGxwB,CAAA,EAC/C,QAAQ,MAAM,cAAewwB,EAAY,KAAK,CAChD,OAAS/wB,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,aAAa+wB,EAAY,QAAQ,GAAI/wB,CAAK,CACzD,CACA,OAAO+wB,EAAY,QACrB,CAEA,OAAOA,CACT,OAAS/wB,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,eAAQ,KAAK,UAAWA,CAAK,EACtB+wB,CACT,CACF,CAKA,OAAO,iBACL2hB,EACA9sC,EACAzM,EAGI,CAAA,EACC,CACL,KAAM,CACJ,0BAAA8gD,EAA4B,GAC5B,WAAAC,EAAa,EAAA,EACX/gD,EAGE43B,EAAc,CAClB,GAAG2hB,EACH,KAAMsC,GAAoB,OAAA,EAI5B,GAAI,CAACiF,EACH,OAAOlpB,EAGT,GAAI,CAOF,GALIA,EAAY,OAAS,OAAOA,EAAY,OAAU,WACpDA,EAAY,MAAQ,KAAK,aAAaA,EAAY,MAAOnrB,EAAS,CAAE,WAAAs0C,EAAY,GAI9EnpB,EAAY,SAAU,CACxB,GAAI,CAEF,MAAMxwB,EAAQ22C,GAAiB,QAAQnmB,EAAY,SAAUnrB,CAAO,EACpEmrB,EAAY,MAAQ,CAAE,GAAGA,EAAY,MAAO,GAAGxwB,CAAA,CACjD,OAASP,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,aAAa+wB,EAAY,QAAQ,GAAI/wB,CAAK,CACzD,CACA,OAAO+wB,EAAY,QACrB,CAEA,OAAOA,CACT,OAAS/wB,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,eAAQ,KAAK,UAAWA,CAAK,EACtB+wB,CACT,CACF,CAKA,OAAe,mBACbusB,EACA13C,EACAzM,EAAmC,CAAA,EAC3B,CACR,KAAM,CAAE,WAAA+gD,EAAa,EAAA,EAAU/gD,EAG/B,GAFA,QAAQ,MAAM,sDAAsDmkD,CAAI,sBAAsBA,EAAK,SAAS,GAAG,CAAC,EAAE,EAE9G,CAACA,EAAK,SAAS,GAAG,EACpB,eAAQ,MAAM,iDAAiDA,CAAI,GAAG,EAC/DA,EAQT,IAAIz5C,EAASy5C,EACTlxC,EACJ,MAAMmxC,EAAc,2DAEpB,MAAQnxC,EAAQmxC,EAAY,KAAKD,CAAI,KAAO,MAAM,CAChD,MAAME,EAAYpxC,EAAM,CAAC,EACnBpB,EAAOoB,EAAM,CAAC,EAEpB,QAAQ,MAAM,aAAaoxC,CAAS,UAAUxyC,CAAI,EAAE,EACpD,GAAI,CAEF,MAAMu0B,EAAWoW,GAAoB,QAAQ6H,EAAW53C,CAAO,EAC/D,QAAQ,MAAM,WAAW43C,CAAS,OAAOje,CAAQ,EAAE,EAGnD17B,EAASA,EAAO,QAAQ25C,EAAW,OAAOje,CAAQ,CAAC,CACrD,OAASv/B,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,iBAAiBw9C,CAAS,GAAIx9C,CAAK,CAElD,CACF,CAEA,eAAQ,MAAM,uCAAuCs9C,CAAI,gBAAgBz5C,CAAM,GAAG,EAC3EA,CACT,CAKA,OAAe,aACbtD,EACAqF,EACAzM,EAAmC,CAAA,EAC9B,CACL,KAAM,CAAE,WAAA+gD,EAAa,EAAA,EAAU/gD,EAE/B,GAAI,CACF,OAAOw8C,GAAoB,uBACzBp1C,EACAqF,EACC48B,GAAQ,CACP,GAAI0X,EACF,MAAM,IAAI,MAAM,YAAY1X,CAAG,EAAE,EAEnC,eAAQ,KAAK,YAAYA,CAAG,EAAE,EACvBA,CACT,CAAA,CAEJ,OAASxiC,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,eAAQ,KAAK,UAAWA,CAAK,EACtBO,CACT,CACF,CAKA,OAAO,aAAamyC,EAA6B,CAC/C,MAAMjpB,EAAmB,CAAA,EAEzB,OAAKipB,GAKDA,EAAa,OAASsC,GAAoB,MAC5CvrB,EAAO,KAAK,yBAAyBipB,EAAa,IAAI,GAAG,GAGvDA,EAAa,UAAY,QAAaA,EAAa,UAAY,OACjEjpB,EAAO,KAAK,oBAAoB,EAG3BA,IAZLA,EAAO,KAAK,WAAW,EAChBA,EAYX,CAKA,OAAO,gBAAgBipB,EAA6B,CAClD,MAAMjpB,EAAmB,CAAA,EAEzB,OAAKipB,GAKDA,EAAa,OAASsC,GAAoB,SAC5CvrB,EAAO,KAAK,4BAA4BipB,EAAa,IAAI,GAAG,GAG1DA,EAAa,UAAY,QAAaA,EAAa,UAAY,OACjEjpB,EAAO,KAAK,oBAAoB,EAG3BA,IAZLA,EAAO,KAAK,WAAW,EAChBA,EAYX,CAKA,OAAO,mBACLqyB,EACAl2C,EACAzM,EAGI,CAAA,EACG,CACP,OAAO2iD,EACJ,OAAOrW,GAASA,EAAM,OAASuP,GAAoB,IAAI,EACvD,OAAa,KAAK,cAAcvP,EAAO7/B,EAASzM,CAAM,CAAC,CAC5D,CAKA,OAAO,sBACL2iD,EACAl2C,EACAzM,EAGI,CAAA,EACG,CACP,OAAO2iD,EACJ,OAAOrW,GAASA,EAAM,OAASuP,GAAoB,OAAO,EAC1D,OAAa,KAAK,iBAAiBvP,EAAO7/B,EAASzM,CAAM,CAAC,CAC/D,CACF,CAKO,SAASskD,IAAwB,CACtC,MAAO,CACL,KAAMzI,GAAoB,KAC1B,UAAWqI,GAAgB,cAAc,KAAKA,EAAe,EAC7D,SAAUA,GAAgB,aAAa,KAAKA,EAAe,CAAA,CAE/D,CAKO,SAASK,IAA2B,CACzC,MAAO,CACL,KAAM1I,GAAoB,QAC1B,UAAWqI,GAAgB,iBAAiB,KAAKA,EAAe,EAChE,SAAUA,GAAgB,gBAAgB,KAAKA,EAAe,CAAA,CAElE,CCjSO,MAAMM,EAAoB,CACvB,iBAA6C,IAErD,aAAc,CACZ,KAAK,4BAAA,CACP,CAKQ,6BAA8B,CACpC,KAAK,SAAS5B,IAAwB,EACtC,KAAK,SAASqB,IAAoC,EAClD,KAAK,SAASK,IAAuB,EACrC,KAAK,SAASC,IAA0B,CAC1C,CAKA,SAASE,EAAgC,CACvC,KAAK,aAAa,IAAIA,EAAY,KAAMA,CAAW,CACrD,CAKA,oBAAoC,CAClC,OAAO,MAAM,KAAK,KAAK,aAAa,QAAQ,CAC9C,CAKA,eAAe1kD,EAAuC,CACpD,OAAO,KAAK,aAAa,IAAIA,CAAI,CACnC,CAKA,UACEw5C,EACA9sC,EACAzM,EAGI,CAAA,EACC,CACL,GAAI,CAACu5C,GAAgB,CAACA,EAAa,KACjC,MAAM,IAAI,MAAM,eAAe,EAGjC,MAAMkL,EAAc,KAAK,eAAelL,EAAa,IAAI,EACzD,OAAKkL,GAKL,QAAQ,MAAM,2CAA2ClL,EAAa,IAAI,wBAAwBkL,EAAY,IAAI,gCAAgCzkD,EAAO,yBAAyB,EAAE,EAC7KykD,EAAY,UAAUlL,EAAc9sC,EAASzM,CAAM,IALxD,QAAQ,MAAM,eAAeu5C,EAAa,IAAI,EAAE,EACzCA,EAKX,CAKA,eACEoJ,EACAl2C,EACAzM,EAGI,CAAA,EACG,CACP,OAAO2iD,EAAc,IAAIrW,GAAS,KAAK,UAAUA,EAAO7/B,EAASzM,CAAM,CAAC,CAC1E,CAOA,eACE0iC,EACAj2B,EACAzM,EAGI,CAAA,EAC4B,CAEhC,MAAM0kD,EAAehiB,EAAM,OAASA,EAAM,QAE1C,GAAI,CAACA,GAAS,CAAC,MAAM,QAAQgiB,CAAY,EACvC,MAAO,CAAE,MAAO,CAAA,EAAI,OAAQhiB,GAAO,MAAA,EAGrC,MAAMiiB,EAAqB,KAAK,eAAeD,EAAcj4C,EAASzM,CAAM,EAG5E,IAAI4kD,EAAoBliB,EAAM,OAC9B,GAAIA,EAAM,QAAU,OAAOA,EAAM,QAAW,SAE1CkiB,EAAoB,KAAK,wBAAwBliB,EAAM,OAAQj2B,EAASzM,CAAM,UACrE,OAAO0iC,EAAM,QAAW,UAAYA,EAAM,OAAO,WAAW,YAAY,EAEjF,GAAI,CACFkiB,EAAoBxG,GAAkB,QAAQ1b,EAAM,OAAQj2B,CAAO,CACrE,OAAS5F,EAAO,CACd,GAAI7G,EAAO,WACT,MAAM6G,EAER,QAAQ,KAAK,aAAa67B,EAAM,MAAM,GAAI77B,CAAK,EAC/C+9C,EAAoBliB,EAAM,MAC5B,CAGF,MAAO,CACL,MAAOiiB,EACP,OAAQC,CAAA,CAEZ,CAKQ,wBACN5X,EACAvgC,EACAzM,EAIK,CACL,GAAI,CAACgtC,GAAU,CAAChtC,EAAO,0BACrB,OAAOgtC,EAIT,GAAI,OAAOA,GAAW,UAAYA,EAAO,WAAW,YAAY,EAC9D,GAAI,CACF,OAAOoR,GAAkB,QAAQpR,EAAQvgC,CAAO,CAClD,OAAS5F,EAAO,CACd,GAAI7G,EAAO,WACT,MAAM6G,EAER,eAAQ,KAAK,aAAammC,CAAM,GAAInmC,CAAK,EAClCmmC,CACT,CAIF,GAAI,OAAOA,GAAW,SAAU,CAE9B,GAAIA,EAAO,WAAa,OAAOA,EAAO,WAAc,SAClD,GAAI,CAEF,MAAM6X,EAAkB,aAAa7X,EAAO,SAAS,GAC/CwR,EAAiBJ,GAAkB,QAAQyG,EAAiBp4C,CAAO,EAEnE,CAAE,UAAAq4C,EAAW,GAAGC,CAAA,EAAe/X,EACrC,MAAO,CAAE,GAAGwR,EAAgB,GAAGuG,CAAA,CACjC,OAASl+C,EAAO,CACd,GAAI7G,EAAO,WACT,MAAM6G,EAER,QAAQ,KAAK,aAAammC,EAAO,SAAS,GAAInmC,CAAK,CAErD,CAGF,MAAM23C,EAAsB,MAAM,QAAQxR,CAAM,EAAI,CAAA,EAAK,CAAA,EAEzD,SAAW,CAAC9sC,EAAKkB,CAAK,IAAK,OAAO,QAAQ4rC,CAAM,EAC9C,GAAI,OAAO5rC,GAAU,UAAYA,EAAM,WAAW,YAAY,EAC5D,GAAI,CACFo9C,EAAet+C,CAAG,EAAIk+C,GAAkB,QAAQh9C,EAAOqL,CAAO,CAChE,OAAS5F,EAAO,CACd,GAAI7G,EAAO,WACT,MAAM6G,EAER,QAAQ,KAAK,aAAazF,CAAK,GAAIyF,CAAK,EACxC23C,EAAet+C,CAAG,EAAIkB,CACxB,SACS,OAAOA,GAAU,UAAYA,EAAM,WAAW,GAAG,EAE1D,GAAI,CACFo9C,EAAet+C,CAAG,EAAIs8C,GAAoB,QAAQp7C,EAAOqL,CAAO,CAClE,OAAS5F,EAAO,CACd,GAAI7G,EAAO,WACT,MAAM6G,EAER,QAAQ,KAAK,iBAAiB3G,CAAG,IAAIkB,CAAK,GAAIyF,CAAK,EACnD23C,EAAet+C,CAAG,EAAIkB,CACxB,MACSA,GAAS,OAAOA,GAAU,SACnCo9C,EAAet+C,CAAG,EAAI,KAAK,wBAAwBkB,EAAOqL,EAASzM,CAAM,EAEzEw+C,EAAet+C,CAAG,EAAIkB,EAI1B,OAAOo9C,CACT,CAEA,OAAOxR,CACT,CAOA,gBACE0R,EACAjyC,EACAzM,EAGI,CAAA,EAC4C,CAChD,MAAMglD,EAAoE,CAAA,EAE1E,SAAW,CAACC,EAAWviB,CAAK,IAAK,OAAO,QAAQgc,CAAM,EACpDsG,EAAkBC,CAAS,EAAI,KAAK,eAAeviB,EAAOj2B,EAASzM,CAAM,EAG3E,OAAOglD,CACT,CAKA,SAASzL,EAA6B,CACpC,GAAI,CAACA,GAAgB,CAACA,EAAa,KACjC,MAAO,CAAC,eAAe,EAGzB,MAAMkL,EAAc,KAAK,eAAelL,EAAa,IAAI,EACzD,MAAI,CAACkL,GAAe,CAACA,EAAY,SACxB,CAAA,EAGFA,EAAY,SAASlL,CAAY,CAC1C,CAKA,cAAcoJ,EAA+D,CAC3E,OAAOA,EAAc,IAAIrW,IAAU,CACjC,MAAAA,EACA,OAAQ,KAAK,SAASA,CAAK,CAAA,EAC3B,CACJ,CACF,CAKO,SAAS4Y,IAAwD,CACtE,OAAO,IAAIV,EACb,CCvRO,MAAMW,EAAe,CAI1B,OAAO,SACLC,EACAjzC,EAGI,GACwD,CAC5D,KAAM,CAAE,WAAA4uC,EAAa,GAAO,mBAAAsE,EAAqB,IAAUlzC,EACrDme,EAAmB,CAAA,EACnBC,EAAqB,CAAA,EAG3B,MAAI,CAAC60B,GAAS,OAAOA,GAAU,UAC7B90B,EAAO,KAAK,WAAW,EAChB,CAAE,QAAS,GAAO,OAAAA,EAAQ,SAAAC,CAAA,IAInC,KAAK,uBAAuB60B,EAAO90B,EAAQC,EAAU,CAAE,mBAAA80B,EAAoB,EAG3E,KAAK,mBAAmBD,EAAO90B,EAAQC,CAAQ,EAG/C,KAAK,eAAe60B,EAAO90B,EAAQC,CAAQ,EAG3C,KAAK,kBAAkB60B,EAAO90B,EAAQC,CAAQ,EAG9C,KAAK,mBAAmB60B,EAAO90B,EAAQC,CAAQ,EAG3CwwB,GACF,KAAK,mBAAmBqE,EAAO90B,EAAQC,CAAQ,EAG1C,CACL,QAASD,EAAO,SAAW,EAC3B,OAAAA,EACA,SAAAC,CAAA,EAEJ,CAKA,OAAe,uBACb60B,EACA90B,EACAC,EACApe,EACM,CACN,KAAM,CAAE,mBAAAkzC,GAAuBlzC,EAG/B,UAAW2kB,KAAS4kB,GAAgB,SAC9B0J,EAAMtuB,CAAK,IAAM,QACnBxG,EAAO,KAAK,WAAWwG,CAAK,EAAE,EAKlC,GAAIsuB,EAAM,WACR,UAAWtuB,KAAS4kB,GAAgB,WAC9B0J,EAAM,WAAWtuB,CAAK,IAAM,QAC9BxG,EAAO,KAAK,sBAAsBwG,CAAK,EAAE,EAM/C,GAAIsuB,EAAM,YACR,UAAWtuB,KAAS4kB,GAAgB,YAC9B0J,EAAM,YAAYtuB,CAAK,IAAM,QAC/BxG,EAAO,KAAK,uBAAuBwG,CAAK,EAAE,CAIlD,CAKA,OAAe,mBACbsuB,EACA90B,EACAC,EACM,CAEe,CAAC,eAAgB,QAAS,WAAY,YAAa,cAAe,oBAAqB,WAAW,EAC1G,QAAQuG,GAAS,CACxBsuB,EAAMtuB,CAAK,IAAM,QAAa,OAAOsuB,EAAMtuB,CAAK,GAAM,UACxDxG,EAAO,KAAK,GAAGwG,CAAK,UAAU,CAElC,CAAC,EAGoB,CAAC,aAAc,UAAW,YAAa,YAAa,UAAU,EACtE,QAAQA,GAAS,CACxBsuB,EAAMtuB,CAAK,IAAM,QAAa,OAAOsuB,EAAMtuB,CAAK,GAAM,UACxDxG,EAAO,KAAK,GAAGwG,CAAK,SAAS,CAEjC,CAAC,EAGGsuB,EAAM,mBAAqB,QAAa,CAAC,MAAM,QAAQA,EAAM,gBAAgB,GAC/E90B,EAAO,KAAK,yBAAyB,EAIlB,CAAC,WAAY,aAAc,cAAe,QAAQ,EAC1D,QAAQwG,GAAS,CACxBsuB,EAAMtuB,CAAK,IAAM,SAAc,OAAOsuB,EAAMtuB,CAAK,GAAM,UAAY,MAAM,QAAQsuB,EAAMtuB,CAAK,CAAC,IAC/FxG,EAAO,KAAK,GAAGwG,CAAK,SAAS,CAEjC,CAAC,CACH,CAKA,OAAe,eACbsuB,EACA90B,EACAC,EACM,CACN,GAAI,CAAC60B,EAAM,QAAU,OAAOA,EAAM,QAAW,SAAU,CACrD90B,EAAO,KAAK,eAAe,EAC3B,MACF,CAGA,MAAMg1B,EAAiB,CAAC,WAAY,QAAS,QAAQ,EACrD,UAAWL,KAAaK,EACjBF,EAAM,OAAOH,CAAS,GACzB30B,EAAO,KAAK,WAAW20B,CAAS,EAAE,EAKtC,SAAW,CAACA,EAAWviB,CAAK,IAAK,OAAO,QAAQ0iB,EAAM,MAAM,EAAG,CAC7D,GAAI,CAAC1iB,GAAS,OAAOA,GAAU,SAAU,CACvCpS,EAAO,KAAK,MAAM20B,CAAS,SAAS,EACpC,QACF,CAEA,MAAMM,EAAW7iB,EAGZ,MAAM,QAAQ6iB,EAAS,OAAO,GACjCj1B,EAAO,KAAK,MAAM20B,CAAS,mBAAmB,EAI5CM,EAAS,SAAW,QAAa,OAAOA,EAAS,QAAW,UAC9Dj1B,EAAO,KAAK,MAAM20B,CAAS,kBAAkB,EAI1CtJ,GAAY,SAASsJ,CAAgB,GACxC10B,EAAS,KAAK,YAAY00B,CAAS,EAAE,CAEzC,CACF,CAKA,OAAe,kBACbG,EACA90B,EACAC,EACM,CACN,GAAI,CAAC60B,EAAM,YAAc,OAAOA,EAAM,YAAe,SACnD,OAGF,MAAMI,EAAYJ,EAAM,WAGH,CAAC,OAAQ,SAAU,SAAU,QAAS,OAAO,EACrD,QAAQtuB,GAAS,CACxB0uB,EAAU1uB,CAAK,IAAM,QAAa,OAAO0uB,EAAU1uB,CAAK,GAAM,UAChExG,EAAO,KAAK,cAAcwG,CAAK,SAAS,CAE5C,CAAC,EAGoB,CAAC,WAAY,aAAc,WAAY,QAAS,WAAY,aAAc,aAAc,WAAW,EAC3G,QAAQA,GAAS,CACxB0uB,EAAU1uB,CAAK,IAAM,QAAa,OAAO0uB,EAAU1uB,CAAK,GAAM,UAChExG,EAAO,KAAK,cAAcwG,CAAK,UAAU,CAE7C,CAAC,EAGG0uB,EAAU,YAAc,QAAa,OAAOA,EAAU,WAAc,UACtEl1B,EAAO,KAAK,6BAA6B,EAGvCk1B,EAAU,UAAY,QAAa,OAAOA,EAAU,SAAY,UAClEl1B,EAAO,KAAK,2BAA2B,EAIrCk1B,EAAU,OAAS,CAAC,CAAC,iBAAkB,iBAAkB,YAAa,QAAQ,EAAE,SAASA,EAAU,KAAK,GAC1Gj1B,EAAS,KAAK,YAAYi1B,EAAU,KAAK,EAAE,CAE/C,CAKA,OAAe,mBACbJ,EACA90B,EACAC,EACM,CACN,GAAI,CAAC60B,EAAM,aAAe,OAAOA,EAAM,aAAgB,SACrD,OAGF,MAAMK,EAAaL,EAAM,YAGrB,OAAOK,EAAW,OAAU,UAC9Bn1B,EAAO,KAAK,0BAA0B,EAGpC,OAAOm1B,EAAW,MAAS,UAC7Bn1B,EAAO,KAAK,0BAA0B,EAGpC,OAAOm1B,EAAW,kBAAqB,UACzCn1B,EAAO,KAAK,sCAAsC,EAIhDm1B,EAAW,QAAU,SACnBA,EAAW,MAAQ,GACrBl1B,EAAS,KAAK,6BAA6B,EAEzCk1B,EAAW,MAAQ,KACrBl1B,EAAS,KAAK,4BAA4B,EAGhD,CAKA,OAAe,mBACb60B,EACA90B,EACAC,EACM,CAiBN,GAfK60B,EAAM,gBACT70B,EAAS,KAAK,wBAAwB,EAInC60B,EAAM,gBACT70B,EAAS,KAAK,wBAAwB,EAIpC60B,EAAM,kBAAoBA,EAAM,iBAAiB,SAAW,GAC9D70B,EAAS,KAAK,uBAAuB,EAInC60B,EAAM,OACR,SAAW,CAACH,EAAWviB,CAAK,IAAK,OAAO,QAAQ0iB,EAAM,MAAM,EAAG,CAC7D,MAAMG,EAAW7iB,EACb6iB,EAAS,SAAWA,EAAS,QAAQ,SAAW,GAClDh1B,EAAS,KAAK,MAAM00B,CAAS,iBAAiB,CAElD,CAEJ,CAKA,OAAO,cAAcG,EAAqB,CACxC,GAAI,CAACA,GAAS,OAAOA,GAAU,SAC7B,MAAO,GAIT,MAAMM,EAAiB,CAAC,eAAgB,QAAS,aAAc,SAAU,aAAa,EACtF,UAAW5uB,KAAS4uB,EAClB,GAAIN,EAAMtuB,CAAK,IAAM,OACnB,MAAO,GAIX,MAAO,EACT,CAKA,OAAO,iBACLsuB,EACAjzC,EAGI,GACiD,CACrD,KAAM,CAAE,WAAA4uC,EAAa,GAAO,oBAAA4E,EAAsB,IAAUxzC,EACtDitC,EAAa,KAAK,SAASgG,EAAO,CAAE,WAAArE,EAAY,EAEtD,IAAI6E,EAAcR,EAElB,OAAIO,GAAuB,CAACvG,EAAW,UAErCwG,EAAc,CAAE,GAAGR,CAAA,EACG,CAAC,YAAa,cAAe,WAAW,EAChD,QAAQtuB,GAAS,CACzBA,KAAS8uB,GACX,OAAOA,EAAY9uB,CAAK,CAE5B,CAAC,GAGI,CACL,KAAM8uB,EACN,OAAQxG,EAAW,OACnB,SAAUA,EAAW,QAAA,CAEzB,CACF,CClVO,MAAMyG,EAAgB,CAI3B,OAAO,SACLC,EACA3zC,EAGI,GACwD,CAC5D,KAAM,CAAE,WAAA4uC,EAAa,GAAO,kBAAAgF,EAAoB,IAAS5zC,EACnDme,EAAmB,CAAA,EACnBC,EAAqB,CAAA,EAG3B,MAAI,CAACu1B,GAAU,OAAOA,GAAW,UAC/Bx1B,EAAO,KAAK,WAAW,EAChB,CAAE,QAAS,GAAO,OAAAA,EAAQ,SAAAC,CAAA,IAInC,KAAK,uBAAuBu1B,EAAQx1B,EAAQC,CAAQ,EAGpD,KAAK,mBAAmBu1B,EAAQx1B,EAAQC,CAAQ,EAG5Cw1B,GACF,KAAK,eAAeD,EAAQx1B,EAAQC,CAAQ,EAI9C,KAAK,kBAAkBu1B,EAAQx1B,EAAQC,CAAQ,EAG/C,KAAK,eAAeu1B,EAAQx1B,EAAQC,CAAQ,EAG5C,KAAK,oBAAoBu1B,EAAQx1B,EAAQC,CAAQ,EAG7CwwB,GACF,KAAK,mBAAmB+E,EAAQx1B,EAAQC,CAAQ,EAG3C,CACL,QAASD,EAAO,SAAW,EAC3B,OAAAA,EACA,SAAAC,CAAA,EAEJ,CAKA,OAAe,uBACbu1B,EACAx1B,EACAC,EACM,CACN,MAAMmvB,EAAiB,CACrB,KAAM,QAAS,QAAS,OAAQ,SAAU,QAAS,YACnD,kBAAmB,aAAc,WAAY,YAAa,SAAU,QAAA,EAGtE,UAAW5oB,KAAS4oB,EACdoG,EAAOhvB,CAAK,IAAM,QACpBxG,EAAO,KAAK,WAAWwG,CAAK,EAAE,CAGpC,CAKA,OAAe,mBACbgvB,EACAx1B,EACAC,EACM,CAEe,CAAC,KAAM,QAAS,OAAQ,SAAU,QAAS,WAAW,EAC9D,QAAQuG,GAAS,CACxBgvB,EAAOhvB,CAAK,IAAM,QAAa,OAAOgvB,EAAOhvB,CAAK,GAAM,UAC1DxG,EAAO,KAAK,GAAGwG,CAAK,UAAU,CAElC,CAAC,EAGGgvB,EAAO,QAAU,QAAa,OAAOA,EAAO,OAAU,UACxDx1B,EAAO,KAAK,cAAc,EAGxBw1B,EAAO,aAAe,QAAa,OAAOA,EAAO,YAAe,UAClEx1B,EAAO,KAAK,mBAAmB,EAI7Bw1B,EAAO,kBAAoB,QAAa,CAAC,MAAM,QAAQA,EAAO,eAAe,GAC/Ex1B,EAAO,KAAK,wBAAwB,EAIjB,CAAC,WAAY,YAAa,SAAU,QAAQ,EACpD,QAAQwG,GAAS,CACxBgvB,EAAOhvB,CAAK,IAAM,SAAc,OAAOgvB,EAAOhvB,CAAK,GAAM,UAAY,MAAM,QAAQgvB,EAAOhvB,CAAK,CAAC,IAClGxG,EAAO,KAAK,GAAGwG,CAAK,SAAS,CAEjC,CAAC,CACH,CAMA,OAAe,eACbgvB,EACAx1B,EACAC,EACM,CACN,GAAI,CAACu1B,EAAO,QAAU,OAAOA,EAAO,QAAW,SAAU,CACvDx1B,EAAO,KAAK,eAAe,EAC3B,MACF,CAGA,MAAMg1B,EAAiB,CAAC,WAAY,QAAS,QAAQ,EACrD,UAAWL,KAAaK,EACjBQ,EAAO,OAAOb,CAAS,GAC1B30B,EAAO,KAAK,WAAW20B,CAAS,EAAE,EAKtC,SAAW,CAACA,EAAWviB,CAAK,IAAK,OAAO,QAAQojB,EAAO,MAAM,EAAG,CAC9D,GAAI,CAACpjB,GAAS,OAAOA,GAAU,SAAU,CACvCpS,EAAO,KAAK,MAAM20B,CAAS,SAAS,EACpC,QACF,CAEA,MAAMM,EAAW7iB,EAIXsjB,EAAeT,EAAS,OAASA,EAAS,QAE3C,MAAM,QAAQS,CAAY,EAGpBA,EAAa,SAAW,GACjCz1B,EAAS,KAAK,MAAM00B,CAAS,UAAU,EAFvC30B,EAAO,KAAK,MAAM20B,CAAS,mCAAmC,EAM5DM,EAAS,SAAW,QAAa,OAAOA,EAAS,QAAW,UAC9Dj1B,EAAO,KAAK,MAAM20B,CAAS,kBAAkB,EAI1CtJ,GAAY,SAASsJ,CAAgB,GACxC10B,EAAS,KAAK,YAAY00B,CAAS,EAAE,CAEzC,CACF,CAKA,OAAe,kBACba,EACAx1B,EACAC,EACM,CACN,GAAI,CAACu1B,EAAO,WAAa,OAAOA,EAAO,WAAc,SAAU,CAC7Dx1B,EAAO,KAAK,kBAAkB,EAC9B,MACF,CAEA,MAAMk1B,EAAYM,EAAO,WAGrBN,EAAU,WAAa,QAAa,OAAOA,EAAU,UAAa,WACpEl1B,EAAO,KAAK,4BAA4B,EAIrB,CAAC,OAAQ,SAAU,SAAU,QAAS,OAAO,EACrD,QAAQwG,GAAS,CACxB0uB,EAAU1uB,CAAK,IAAM,QAAa,OAAO0uB,EAAU1uB,CAAK,GAAM,UAChExG,EAAO,KAAK,aAAawG,CAAK,SAAS,CAE3C,CAAC,EAGoB,CAAC,aAAc,WAAY,QAAS,WAAY,aAAc,aAAc,WAAW,EAC/F,QAAQA,GAAS,CACxB0uB,EAAU1uB,CAAK,IAAM,QAAa,OAAO0uB,EAAU1uB,CAAK,GAAM,UAChExG,EAAO,KAAK,aAAawG,CAAK,UAAU,CAE5C,CAAC,EAGG0uB,EAAU,YAAc,QAAa,OAAOA,EAAU,WAAc,UACtEl1B,EAAO,KAAK,4BAA4B,EAGtCk1B,EAAU,UAAY,QAAa,OAAOA,EAAU,SAAY,UAClEl1B,EAAO,KAAK,0BAA0B,CAE1C,CAKA,OAAe,eACbw1B,EACAx1B,EACAC,EACM,CACN,GAAI,CAACu1B,EAAO,QAAU,OAAOA,EAAO,QAAW,SAAU,CACvDx1B,EAAO,KAAK,eAAe,EAC3B,MACF,CAEA,MAAM4mB,EAAS4O,EAAO,OAGlB,OAAO5O,EAAO,OAAU,UAC1B5mB,EAAO,KAAK,qBAAqB,EAG/B,OAAO4mB,EAAO,MAAS,UACzB5mB,EAAO,KAAK,qBAAqB,EAG/B,OAAO4mB,EAAO,aAAgB,UAChC5mB,EAAO,KAAK,4BAA4B,EAItC4mB,EAAO,QAAU,SACfA,EAAO,MAAQ,GACjB3mB,EAAS,KAAK,wBAAwB,EAEpC2mB,EAAO,MAAQ,KACjB3mB,EAAS,KAAK,uBAAuB,EAG3C,CAKA,OAAe,oBACbu1B,EACAx1B,EACAC,EACM,CACN,GAAIu1B,EAAO,cAAgB,OAAW,CAEpCx1B,EAAO,KAAK,mBAAmB,EAC/B,MACF,CAGA,GAAI,OAAOw1B,EAAO,aAAgB,SAAU,CAC1Cx1B,EAAO,KAAK,uBAAuB,EACnC,MACF,CAGI,MAAM,QAAQw1B,EAAO,WAAW,GAC9BA,EAAO,YAAY,SAAW,GAChCv1B,EAAS,KAAK,kBAAkB,EAGlCu1B,EAAO,YAAY,QAAQ,CAAC9sB,EAAWpmB,IAAkB,EACnD,CAAComB,GAAQ,OAAOA,GAAS,WAC3B1I,EAAO,KAAK,eAAe1d,CAAK,UAAU,CAE9C,CAAC,GAGMkzC,EAAO,YAAY,QAAU,OACpCx1B,EAAO,KAAK,2BAA2B,EAC7B,MAAM,QAAQw1B,EAAO,YAAY,KAAK,GAChDx1B,EAAO,KAAK,0BAA0B,CAE1C,CAKA,OAAe,mBACbw1B,EACAx1B,EACAC,EACM,CA4BN,GA1BIu1B,EAAO,IAAM,OAAOA,EAAO,IAAO,WAC/BA,EAAO,GAAG,SAAS,GAAG,GACzBv1B,EAAS,KAAK,wBAAwB,GAKtCu1B,EAAO,QAAU,SACfA,EAAO,MAAQ,GAAKA,EAAO,MAAQ,KACrCv1B,EAAS,KAAK,WAAWu1B,EAAO,KAAK,gBAAgB,EAKrDA,EAAO,aAAe,SACpBA,EAAO,WAAa,GAAKA,EAAO,WAAa,IAC/Cv1B,EAAS,KAAK,gBAAgBu1B,EAAO,UAAU,aAAa,EAK5DA,EAAO,iBAAmBA,EAAO,gBAAgB,SAAW,GAC9Dv1B,EAAS,KAAK,sBAAsB,EAIlCu1B,EAAO,UAAY,OAAOA,EAAO,UAAa,SAAU,CAC1D,MAAM1vB,EAAW0vB,EAAO,UACpB,CAAC1vB,EAAS,OAAS,OAAOA,EAAS,OAAU,WAC/C7F,EAAS,KAAK,wBAAwB,GAEpC,CAAC6F,EAAS,OAAS,OAAOA,EAAS,OAAU,WAC/C7F,EAAS,KAAK,wBAAwB,GAEpC,CAAC6F,EAAS,MAAQ,CAAC,MAAM,QAAQA,EAAS,IAAI,IAChD7F,EAAS,KAAK,sBAAsB,CAExC,CACF,CAKA,OAAO,cAAcu1B,EAAsB,CACzC,GAAI,CAACA,GAAU,OAAOA,GAAW,SAC/B,MAAO,GAIT,MAAMJ,EAAiB,CAAC,KAAM,QAAS,YAAa,SAAU,QAAQ,EACtE,UAAW5uB,KAAS4uB,EAClB,GAAII,EAAOhvB,CAAK,IAAM,OACpB,MAAO,GAiBX,MAZI,SAAOgvB,EAAO,OAAU,UAIxBA,EAAO,WAAa,OAAOA,EAAO,WAAc,UAIhDA,EAAO,QAAU,OAAOA,EAAO,QAAW,UAI1CA,EAAO,QAAU,OAAOA,EAAO,QAAW,SAKhD,CAKA,OAAO,+BAA+BA,EAAgD,CAEpF,OADmB,KAAK,SAASA,EAAQ,CAAE,WAAY,GAAO,kBAAmB,GAAO,EACtE,OACpB,CACF,CCnXO,MAAMG,EAAkB,CAI7B,OAAO,cACLb,EACAjzC,EAGI,GACc,CAClB,KAAM,CAAE,QAAAke,EAAS,OAAAC,EAAQ,SAAAC,CAAA,EAAa40B,GAAe,SAASC,EAAOjzC,CAAO,EAE5E,MAAO,CACL,QAAAke,EACA,OAAAC,EACA,SAAAC,EACA,UAAW,KAAK,IAAA,CAAI,CAExB,CAKA,OAAO,eACLu1B,EACA3zC,EAGI,GACc,CAClB,KAAM,CAAE,QAAAke,EAAS,OAAAC,EAAQ,SAAAC,CAAA,EAAas1B,GAAgB,SAASC,EAAQ3zC,CAAO,EAE9E,MAAO,CACL,QAAAke,EACA,OAAAC,EACA,SAAAC,EACA,UAAW,KAAK,IAAA,CAAI,CAExB,CAKA,OAAO,iBACL60B,EACAU,EACA3zC,EAGI,CAAA,EAKJ,CACA,KAAM,CAAE,gBAAA+zC,EAAkB,GAAO,iBAAAC,EAAmB,IAAUh0C,EAExDi0C,EAAc,KAAK,cAAchB,EAAO,CAAE,WAAYc,EAAiB,EACvEG,EAAe,KAAK,eAAeP,EAAQ,CAAE,WAAYK,EAAkB,EAG3EG,EAAY,CAAC,GAAGF,EAAY,OAAQ,GAAGC,EAAa,MAAM,EAC1DE,EAAc,CAAC,GAAGH,EAAY,SAAU,GAAGC,EAAa,QAAQ,EAEhEG,EAAU,CACd,QAASJ,EAAY,SAAWC,EAAa,QAC7C,OAAQC,EACR,SAAUC,CAAA,EAGZ,MAAO,CACL,MAAOH,EACP,OAAQC,EACR,QAAAG,CAAA,CAEJ,CAKA,OAAO,mBAAmBpB,EAAqB,CAC7C,OAAOD,GAAe,cAAcC,CAAK,CAC3C,CAKA,OAAO,oBAAoBU,EAAsB,CAC/C,OAAOD,GAAgB,cAAcC,CAAM,CAC7C,CAKA,OAAO,kBACLl/C,EACA7G,EACAoS,EAAe,CAAA,EACT,CACN,MAAMzH,EAAS3K,IAAS,QACpB,KAAK,cAAc6G,EAAMuL,CAAO,EAChC,KAAK,eAAevL,EAAMuL,CAAO,EAErC,QAAQ,MAAM,GAAGpS,EAAK,YAAA,CAAa,OAAO,EAC1C,QAAQ,IAAI,QAAQ2K,EAAO,QAAU,OAAS,MAAM,EAAE,EAElDA,EAAO,OAAO,OAAS,IACzB,QAAQ,MAAM,OAAO,EACrBA,EAAO,OAAO,QAAQ7D,GAAS,QAAQ,IAAI,OAAOA,CAAK,EAAE,CAAC,EAC1D,QAAQ,SAAA,GAGN6D,EAAO,SAAS,OAAS,IAC3B,QAAQ,MAAM,QAAQ,EACtBA,EAAO,SAAS,QAAQ+7C,GAAW,QAAQ,IAAI,OAAOA,CAAO,EAAE,CAAC,EAChE,QAAQ,SAAA,GAGV,QAAQ,SAAA,CACV,CACF,CCpIO,MAAMC,EAAe,CAI1B,OAAO,qBAAqB16C,EAAoB,CAC9C,MAAM0wC,EAAiB,CAAA,EAEjBE,EAAYx7C,GAAe,CAC3B,OAAOA,GAAU,SACnBs7C,EAAK,KAAKt7C,CAAK,EACN,MAAM,QAAQA,CAAK,EAC5BA,EAAM,QAAQw7C,CAAQ,EACbx7C,GAAS,OAAOA,GAAU,UACnC,OAAO,OAAOA,CAAK,EAAE,QAAQw7C,CAAQ,CAEzC,EAEA,OAAAA,EAAS5wC,CAAG,EACL,CAAC,GAAG,IAAI,IAAI0wC,CAAI,CAAC,CAC1B,CAKA,OAAO,qBAAqBA,EAAgBjwC,EAAwD,CAClG,MAAMk6C,EAA2C,CAC/C,CAACvL,GAAc,YAAY,EAAG,CAAA,EAC9B,CAACA,GAAc,SAAS,EAAG,CAAA,EAC3B,CAACA,GAAc,YAAY,EAAG,CAAA,EAC9B,CAACA,GAAc,aAAa,EAAG,CAAA,EAC/B,CAACA,GAAc,UAAU,EAAG,CAAA,CAAC,EAGzBwL,EAAmB,IAAInG,GAE7B,UAAWpX,KAAOqT,EAAM,CACtB,MAAMgE,EAAWkG,EAAiB,kBAAkBvd,CAAG,EACnDqX,GACFiG,EAAYjG,EAAS,IAAI,EAAE,KAAKrX,CAAG,CAEvC,CAEA,OAAOsd,CACT,CAKA,OAAO,uBACLjK,EACAjwC,EACA0F,EAGI,CAAA,EACiB,CACrB,KAAM,CAAE,WAAA4uC,EAAa,GAAO,UAAAlE,CAAA,EAAc1qC,EACpCy0C,EAAmB,IAAInG,GACvB9D,EAA+B,CAAA,EAErC,UAAWtT,KAAOqT,EAAM,CACtB,MAAMgE,EAAWkG,EAAiB,kBAAkBvd,CAAG,EACvD,GAAIqX,EACF,GAAI,CACF/D,EAAQtT,CAAG,EAAIqX,EAAS,QAAQrX,EAAK58B,CAAO,CAC9C,OAAS5F,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAER,QAAQ,KAAK,WAAWwiC,CAAG,GAAIxiC,CAAK,EAChCg2C,IACFF,EAAQtT,CAAG,EAAIwT,EAAUxT,CAAG,EAEhC,CAEJ,CAEA,OAAOsT,CACT,CAKA,OAAO,kBACL3wC,EACAS,EACA0F,EAII,CAAA,EACC,CACL,KAAM,CAAE,WAAA4uC,EAAa,GAAO,UAAAlE,EAAW,SAAAgK,EAAW,IAAO10C,EACnDy0C,EAAmB,IAAInG,GAIvBqG,MAA0B,IAAI,CAClC,cAAe,WAAY,eAC3B,YAAa,WAAY,eACzB,gBAAiB,WAAY,WAC7B,YAAa,SAAU,QAAS,MAEhC,OAAQ,QAAS,WAAY,UAAW,cAAe,QACvD,WAAY,SAAU,OAAQ,KAAM,OAAQ,QAC5C,SAAU,WAAY,SAAU,WAAY,UAC5C,YAAa,YAAa,cAAe,eAEzC,cAAe,YAAa,gBAC5B,kBAAmB,gBAAiB,YAAa,WACjD,SAAU,WAAY,SAAU,YAAa,cAC7C,QAAS,QAAS,YAAa,aAAc,mBAC7C,iBAAkB,YAAa,UAAW,UAAW,WACrD,WAAY,aAAc,aAAc,OAAQ,SAChD,cAAe,QAAS,WAAY,aAAc,SAAA,CACnD,EAEKhK,EAAU,CAAC17C,EAAY2lD,EAAgB,EAAGC,IAA4B,CAC1E,GAAID,EAAQF,EACV,eAAQ,KAAK,eAAeA,CAAQ,EAAE,EAC/BzlD,EAGT,GAAI,OAAOA,GAAU,SAAU,CAE7B,GAAI4lD,GAAaF,EAAoB,IAAIE,CAAS,EAEhD,eAAQ,KAAK,eAAeA,CAAS,aAAa5lD,CAAK,GAAG,EACnDA,EAMT,GAAI,EADsBA,EAAM,WAAW,GAAG,GAAKA,EAAM,SAAS,MAAM,GAGtE,OAAOA,EAGT,MAAMs/C,EAAWkG,EAAiB,kBAAkBxlD,CAAK,EACzD,GAAIs/C,EACF,GAAI,CACF,OAAOA,EAAS,QAAQt/C,EAAOqL,CAAO,CACxC,OAAS5F,EAAO,CACd,GAAIk6C,EACF,MAAMl6C,EAGR,OADA,QAAQ,KAAK,WAAWzF,CAAK,GAAIyF,CAAK,EAClCg2C,EACKA,EAAUz7C,CAAK,EAEjBA,CACT,CAEF,OAAOA,CACT,KAAA,IAAW,MAAM,QAAQA,CAAK,EAC5B,OAAOA,EAAM,IAAI8D,GAAQ43C,EAAQ53C,EAAM6hD,EAAQ,EAAG,MAAS,CAAC,EAC9D,GAAW3lD,GAAS,OAAOA,GAAU,SAAU,CAC7C,MAAMsJ,EAA8B,CAAA,EACpC,SAAW,CAACxK,EAAKoK,CAAG,IAAK,OAAO,QAAQlJ,CAAK,EAC3CsJ,EAAOxK,CAAG,EAAI48C,EAAQxyC,EAAKy8C,EAAQ,EAAG7mD,CAAG,EAE3C,OAAOwK,CACT,EACA,OAAOtJ,CACT,EAEA,OAAO07C,EAAQ9wC,CAAG,CACpB,CAKA,OAAO,wBACL0wC,EACAjwC,EAMA,CACA,MAAMm6C,EAAmB,IAAInG,GACvBwG,EAAQ,CACZ,MAAOvK,EAAK,OACZ,SAAU,EACV,OAAQ,EACR,OAAQ,CAAA,CAAC,EAIX,OAAO,OAAOtB,EAAa,EAAE,QAAQr7C,GAAQ,CAC3CknD,EAAM,OAAOlnD,CAAI,EAAI,CAAE,MAAO,EAAG,SAAU,EAAG,OAAQ,CAAA,CACxD,CAAC,EAED,QAAQ,IAAI,yCAA0C28C,EAAK,MAAM,EACjE,UAAWrT,KAAOqT,EAAM,CACtB,QAAQ,IAAI,WAAYrT,CAAG,EAC3B,MAAMqX,EAAWkG,EAAiB,kBAAkBvd,CAAG,EACvD,GAAIqX,EAAU,CACZ,MAAM3gD,EAAO2gD,EAAS,KACtBuG,EAAM,OAAOlnD,CAAI,EAAE,QACnB,QAAQ,IAAI,kBAAkBA,CAAI,EAAE,EAEpC,GAAI,CACF,MAAM2K,EAASg2C,EAAS,QAAQrX,EAAK58B,CAAO,EAC5C,QAAQ,IAAI,cAAc48B,CAAG,MAAO3+B,CAAM,EAC1Cu8C,EAAM,WACNA,EAAM,OAAOlnD,CAAI,EAAE,UACrB,OAAS8G,EAAO,CACd,QAAQ,MAAM,cAAcwiC,CAAG,GAAIxiC,CAAK,EACxCogD,EAAM,SACNA,EAAM,OAAOlnD,CAAI,EAAE,QACrB,CACF,MACE,QAAQ,IAAI,cAAcspC,CAAG,EAAE,CAEnC,CAEA,OAAO4d,CACT,CAKA,OAAO,qBAAqB5d,EAAa58B,EAAoC,CAE3E,MAAMi0C,EADmB,IAAID,GAAA,EACK,kBAAkBpX,CAAG,EACvD,GAAI,CAACqX,EACH,MAAO,GAGT,GAAIA,EAAS,SACX,OAAOA,EAAS,SAASrX,EAAK58B,CAAO,EAGvC,GAAI,CACF,OAAAi0C,EAAS,QAAQrX,EAAK58B,CAAO,EACtB,EACT,MAAQ,CACN,MAAO,EACT,CACF,CAKA,OAAO,iBAAiB48B,EAAuB,CAC7C,GAAIA,EAAI,WAAW,GAAG,EACpB,OAAOA,EAAI,UAAU,CAAC,EAAE,MAAM,GAAG,EAInC,MAAMp2B,EAAQo2B,EAAI,MAAM,eAAe,EACvC,OAAIp2B,EACK,CAACA,EAAM,CAAC,EAAGA,EAAM,CAAC,CAAC,EAGrB,CAACo2B,CAAG,CACb,CAKA,OAAO,gBAAgBtpC,EAAqB8R,EAAwB,CAClE,OAAQ9R,EAAA,CACN,KAAKq7C,GAAc,aACjB,MAAO,IAAIvpC,EAAK,KAAK,GAAG,CAAC,GAC3B,KAAKupC,GAAc,UACjB,MAAO,YAAYvpC,EAAK,CAAC,CAAC,GAC5B,KAAKupC,GAAc,aACjB,MAAO,eAAevpC,EAAK,CAAC,CAAC,GAC/B,KAAKupC,GAAc,cACjB,MAAO,gBAAgBvpC,EAAK,CAAC,CAAC,GAChC,KAAKupC,GAAc,WACjB,MAAO,aAAavpC,EAAK,CAAC,CAAC,GAC7B,QACE,OAAOA,EAAK,KAAK,GAAG,CAAA,CAE1B,CAKA,OAAO,wBAAwB7F,EAAoB,CACjD,MAAM0wC,EAAiB,CAAA,EAEjBE,EAAW,CAACx7C,EAAYyQ,EAAiB,CAAA,IAAO,CACpD,GAAI,OAAOzQ,GAAU,SACnBs7C,EAAK,KAAK,GAAG7qC,EAAK,KAAK,GAAG,CAAC,IAAIzQ,CAAK,EAAE,UAC7B,MAAM,QAAQA,CAAK,EAC5BA,EAAM,QAAQ,CAAC8D,EAAM0N,IAAU,CAC7BgqC,EAAS13C,EAAM,CAAC,GAAG2M,EAAM,IAAIe,CAAK,GAAG,CAAC,CACxC,CAAC,UACQxR,GAAS,OAAOA,GAAU,SACnC,SAAW,CAAClB,EAAKoK,CAAG,IAAK,OAAO,QAAQlJ,CAAK,EAC3Cw7C,EAAStyC,EAAK,CAAC,GAAGuH,EAAM3R,CAAG,CAAC,CAGlC,EAEA,OAAA08C,EAAS5wC,CAAG,EACL0wC,CACT,CACF,CCjTO,MAAMwK,EAAmB,CACtB,UAA0C,IAC1C,MAA0B,CAChC,UAAW,EACX,wBAAyB,EACzB,mBAAoB,EACpB,eAAgB,EAChB,YAAa,EACb,eAAgB,CAAA,EAEV,YAAsB,EAE9B,aAAc,CACZ,KAAK,oBAAA,CACP,CAKA,UAAUxlD,EAAoB,CAC5B,KAAK,MAAM,IAAIA,EAAM,CACnB,KAAAA,EACA,UAAW,YAAY,IAAA,CAAI,CAC5B,CACH,CAKA,QAAQA,EAAoB,CAC1B,MAAMylD,EAAO,KAAK,MAAM,IAAIzlD,CAAI,EAChC,GAAI,CAACylD,EAAM,CACT,QAAQ,KAAK,YAAYzlD,CAAI,EAAE,EAC/B,MACF,CAEA,MAAM0lD,EAAU,YAAY,IAAA,EACtBC,EAAWD,EAAUD,EAAK,UAEhCA,EAAK,QAAUC,EACfD,EAAK,SAAWE,EAGhB,KAAK,YAAY3lD,EAAM2lD,CAAQ,CACjC,CAKQ,YAAY3lD,EAAc2lD,EAAwB,CACxD,OAAQ3lD,EAAA,CACN,IAAK,uBACH,KAAK,MAAM,wBAA0B2lD,EACrC,MACF,IAAK,iBACH,KAAK,MAAM,mBAAqBA,EAChC,MACF,IAAK,aACH,KAAK,MAAM,eAAiBA,EAC5B,MACF,IAAK,QACH,KAAK,MAAM,UAAYA,EACvB,KAAA,CAEN,CAKQ,qBAA4B,CAC9B,OAAO,YAAgB,KAAgB,YAAoB,SAC7D,KAAK,YAAe,YAAoB,OAAO,eAEnD,CAKQ,mBAA0B,CAChC,GAAI,OAAO,YAAgB,KAAgB,YAAoB,OAAQ,CACrE,MAAMC,EAAa,YAAoB,OAAO,eAC9C,KAAK,MAAM,YAAcA,EAAY,KAAK,WAC5C,CACF,CAKA,kBAAkBC,EAAqB,CACrC,KAAK,MAAM,eAAiBA,CAC9B,CAKA,UAA6B,CAC3B,YAAK,kBAAA,EACE,CAAE,GAAG,KAAK,KAAA,CACnB,CAKA,UAA8B,CAC5B,OAAO,MAAM,KAAK,KAAK,MAAM,QAAQ,CACvC,CAKA,kBAA4D,CAC1D,MAAMh3B,EAAqB,CAAA,EAG3B,OAAI,KAAK,MAAM,mBAAqBkrB,GAAuB,6BACzDlrB,EAAS,KAAK,WAAW,KAAK,MAAM,mBAAmB,QAAQ,CAAC,CAAC,aAAakrB,GAAuB,2BAA2B,KAAK,EAGnI,KAAK,MAAM,mBAAqBA,GAAuB,yBACzDlrB,EAAS,KAAK,WAAW,KAAK,MAAM,mBAAmB,QAAQ,CAAC,CAAC,aAAakrB,GAAuB,uBAAuB,KAAK,EAI/H,KAAK,MAAM,YAAcA,GAAuB,qBAClDlrB,EAAS,KAAK,YAAY,KAAK,MAAM,YAAc,MAAM,QAAQ,CAAC,CAAC,aAAakrB,GAAuB,oBAAsB,IAAI,KAAK,EAIpI,KAAK,MAAM,eAAiBA,GAAuB,oBAAsB,IAC3ElrB,EAAS,KAAK,WAAW,KAAK,MAAM,cAAc,WAAW,EAGxD,CACL,OAAQA,EAAS,SAAW,EAC5B,SAAAA,CAAA,CAEJ,CAKA,OAAc,CACZ,KAAK,MAAM,MAAA,EACX,KAAK,MAAQ,CACX,UAAW,EACX,wBAAyB,EACzB,mBAAoB,EACpB,eAAgB,EAChB,YAAa,EACb,eAAgB,CAAA,EAElB,KAAK,oBAAA,CACP,CACF,CC3JO,MAAMi3B,EAAY,CAIvB,OAAO,UAAUp3C,EAAaD,EAAkB,CAC9C,GAAIA,IAAW,MAAQ,OAAOA,GAAW,SACvC,OAAOA,EAGT,GAAI,MAAM,QAAQA,CAAM,EACtB,OAAK,MAAM,QAAQC,CAAM,EAGlBA,EAAO,IAAI,CAAClL,EAAM0N,IACvBA,EAAQzC,EAAO,OAAS,KAAK,UAAUjL,EAAMiL,EAAOyC,CAAK,CAAC,EAAI1N,CAAA,EAHvD,CAAC,GAAGiL,CAAM,EAOrB,MAAMzF,EAAS,CAAE,GAAG0F,CAAA,EACpB,SAAW,CAAClQ,EAAKkB,CAAK,IAAK,OAAO,QAAQ+O,CAAM,EAC1C/O,IAAU,SAIVlB,KAAOwK,GAAU,OAAOA,EAAOxK,CAAG,GAAM,UAAY,OAAOkB,GAAU,SACvEsJ,EAAOxK,CAAG,EAAI,KAAK,UAAUwK,EAAOxK,CAAG,EAAGkB,CAAK,EAE/CsJ,EAAOxK,CAAG,EAAIkB,GAIlB,OAAOsJ,CACT,CAKA,OAAO,UAAUsC,EAAQC,EAAiB,CACxC,GAAID,IAAMC,EACR,MAAO,GAWT,GARI,OAAOD,GAAM,OAAOC,GAIpB,OAAOD,GAAM,UAAYA,IAAM,MAAQC,IAAM,MAI7C,MAAM,QAAQD,CAAC,IAAM,MAAM,QAAQC,CAAC,EACtC,MAAO,GAGT,GAAI,MAAM,QAAQD,CAAC,EACjB,OAAIA,EAAE,SAAWC,EAAE,OACV,GAEFD,EAAE,MAAM,CAAC9H,EAAM0N,IAAU,KAAK,UAAU1N,EAAM+H,EAAE2F,CAAK,CAAC,CAAC,EAGhE,MAAM60C,EAAQ,OAAO,KAAKz6C,CAAC,EACrB06C,EAAQ,OAAO,KAAKz6C,CAAC,EAE3B,OAAIw6C,EAAM,SAAWC,EAAM,OAClB,GAGFD,EAAM,MAAMvnD,GACXA,KAAO+M,EAGN,KAAK,UAAUD,EAAE9M,CAAG,EAAG+M,EAAE/M,CAAG,CAAC,EAF3B,EAGV,CACH,CAKA,OAAO,QAAQ8L,EAAU6F,EAAyB/B,EAAoB,OAAgB,CACpF,MAAM63C,EAAY,MAAM,QAAQ91C,CAAI,EAAIA,EAAOA,EAAK,MAAM,GAAG,EAC7D,IAAI4qC,EAAUzwC,EAEd,UAAW9L,KAAOynD,EAAW,CAC3B,GAAIlL,GAAY,MAAiC,OAAOA,GAAY,SAClE,OAAO3sC,EAIT,MAAM83C,EAAa1nD,EAAI,MAAM,aAAa,EAC1C,GAAI0nD,GAAc,MAAM,QAAQnL,CAAO,EAAG,CACxC,MAAM7pC,EAAQ,SAASg1C,EAAW,CAAC,EAAG,EAAE,EACxCnL,EAAUA,EAAQ7pC,CAAK,CACzB,MACE6pC,EAAUA,EAAQv8C,CAAG,CAEzB,CAEA,OAAOu8C,IAAY,OAAYA,EAAU3sC,CAC3C,CAKA,OAAO,QAAQ9D,EAAU6F,EAAyBzQ,EAAiB,CACjE,MAAMumD,EAAY,MAAM,QAAQ91C,CAAI,EAAIA,EAAOA,EAAK,MAAM,GAAG,EACvDnH,EAAS,MAAM,QAAQsB,CAAG,EAAI,CAAC,GAAGA,CAAG,EAAI,CAAE,GAAGA,CAAA,EACpD,IAAIywC,EAAU/xC,EAEd,QAASwB,EAAI,EAAGA,EAAIy7C,EAAU,OAAS,EAAGz7C,IAAK,CAC7C,MAAMhM,EAAMynD,EAAUz7C,CAAC,EACjB07C,EAAa1nD,EAAI,MAAM,aAAa,EAE1C,GAAI0nD,GAAc,MAAM,QAAQnL,CAAO,EAAG,CACxC,MAAM7pC,EAAQ,SAASg1C,EAAW,CAAC,EAAG,EAAE,EACpCnL,EAAQ7pC,CAAK,IAAM,SACrB6pC,EAAQ7pC,CAAK,EAAI,CAAA,GAEnB6pC,EAAUA,EAAQ7pC,CAAK,CACzB,KAAO,CACL,GAAI6pC,EAAQv8C,CAAG,IAAM,OAAW,CAE9B,MAAM2nD,EADUF,EAAUz7C,EAAI,CAAC,EACA,MAAM,aAAa,EAClDuwC,EAAQv8C,CAAG,EAAI2nD,EAAiB,CAAA,EAAK,CAAA,CACvC,CACApL,EAAUA,EAAQv8C,CAAG,CACvB,CACF,CAEA,MAAM4nD,EAAUH,EAAUA,EAAU,OAAS,CAAC,EACxCI,EAAiBD,EAAQ,MAAM,aAAa,EAElD,GAAIC,GAAkB,MAAM,QAAQtL,CAAO,EAAG,CAC5C,MAAM7pC,EAAQ,SAASm1C,EAAe,CAAC,EAAG,EAAE,EAC5CtL,EAAQ7pC,CAAK,EAAIxR,CACnB,MACEq7C,EAAQqL,CAAO,EAAI1mD,EAGrB,OAAOsJ,CACT,CAKA,OAAO,WAAWs9C,EAAiB,KAAc,CAC/C,MAAO,GAAGA,CAAM,IAAI,KAAK,IAAA,CAAK,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,OAAO,EAAG,CAAC,CAAC,EAC3E,CAKA,OAAO,SACL5Z,EACA6Z,EAC0B,CAC1B,IAAIC,EAAW,EACf,MAAO,IAAI/sC,IAAgB,CACzB,MAAMX,EAAM,KAAK,IAAA,EACbA,EAAM0tC,GAAYD,IACpBC,EAAW1tC,EACX4zB,EAAK,GAAGjzB,CAAI,EAEhB,CACF,CAKA,OAAO,SACLizB,EACA6Z,EAC0B,CAC1B,IAAIE,EACJ,MAAO,IAAIhtC,IAAgB,CACzB,aAAagtC,CAAS,EACtBA,EAAY,WAAW,IAAM/Z,EAAK,GAAGjzB,CAAI,EAAG8sC,CAAK,CACnD,CACF,CAKA,OAAO,YAAY/tC,EAAekuC,EAAmB,EAAW,CAC9D,GAAIluC,IAAU,EAAG,MAAO,UAExB,MAAM4tB,EAAI,KACJugB,EAAKD,EAAW,EAAI,EAAIA,EACxBE,EAAQ,CAAC,QAAS,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAI,EAEhE,EAAI,KAAK,MAAM,KAAK,IAAIpuC,CAAK,EAAI,KAAK,IAAI4tB,CAAC,CAAC,EAElD,OAAO,YAAY5tB,EAAQ,KAAK,IAAI4tB,EAAG,CAAC,GAAG,QAAQugB,CAAE,CAAC,EAAI,IAAMC,EAAM,CAAC,CACzE,CAKA,OAAO,mBAAmBt8C,EAAkB,CAC1C,MAAMu8C,MAAc,IAEdC,EAAapnD,GACbmnD,EAAQ,IAAInnD,CAAK,EACZ,EAGL,OAAOA,GAAU,SAEZA,EAAM,OAAS,EACb,OAAOA,GAAU,SACnB,EACE,OAAOA,GAAU,UACnB,EACEA,GAAU,KACZ,EACE,MAAM,QAAQA,CAAK,GAC5BmnD,EAAQ,IAAInnD,CAAK,EACVA,EAAM,OAAO,CAAC6D,EAAaC,IAASD,EAAMujD,EAAUtjD,CAAI,EAAG,CAAC,GAC1D,OAAO9D,GAAU,UAC1BmnD,EAAQ,IAAInnD,CAAK,EACV,OAAO,OAAOA,CAAK,EAAE,OAAO,CAAC6D,EAAaC,IAASD,EAAMujD,EAAUtjD,CAAI,EAAG,CAAC,GAG7E,EAGT,OAAOsjD,EAAUx8C,CAAG,CACtB,CACF,CClNO,MAAMy8C,EAAgB,CACnB,OACA,iBACA,iBACA,oBACA,mBAER,YAAYzoD,EAA4B,GAAI,CAC1C,KAAK,OAAS,CAAE,GAAGm7C,GAA6B,GAAGn7C,CAAA,EACnD,KAAK,iBAAmBs8C,GAAA,EACxB,KAAK,iBAAmBsE,GAAA,EACxB,KAAK,oBAAsBsE,GAAA,EAC3B,KAAK,mBAAqB,IAAIgC,EAChC,CAKA,MAAMwB,EAAkD,CACtD,QAAQ,MAAM,8CAA+C,CAC3D,aAAcA,GAAW,aACzB,kBAAmB,CAAC,CAACA,GAAW,gBAChC,kBAAmBA,GAAW,gBAAkB,OAAO,KAAKA,EAAU,eAAe,EAAI,CAAA,EACzF,UAAW,CAAC,CAACA,GAAW,OACxB,UAAWA,GAAW,OAAS,OAAO,KAAKA,EAAU,MAAM,EAAI,CAAA,CAAC,CACjE,EAED,KAAK,mBAAmB,UAAU,OAAO,EAEzC,GAAI,CAEF,KAAK,mBAAmB,UAAU,YAAY,EAC9C,MAAMC,EAAkB,KAAK,cAAcD,CAAS,EACpD,GAAI,CAACC,EAAgB,SAAW,KAAK,OAAO,WAC1C,MAAM,IAAItN,GACRH,EAAiB,cACjBM,GAAeN,EAAiB,aAAa,EAC7C,CAAE,OAAQyN,EAAgB,MAAA,CAAO,EAGrC,KAAK,mBAAmB,QAAQ,YAAY,EAG5C,KAAK,mBAAmB,UAAU,qBAAqB,EACvD,MAAMC,EAAW,KAAK,kBAAkBF,CAAS,EACjD,KAAK,mBAAmB,QAAQ,qBAAqB,EAGrD,IAAIG,EAAeD,EACf,KAAK,OAAO,4BACd,KAAK,mBAAmB,UAAU,sBAAsB,EACxDC,EAAe,KAAK,kBAAkBD,CAAQ,EAC9C,KAAK,mBAAmB,QAAQ,sBAAsB,GAIxD,KAAK,mBAAmB,UAAU,sBAAsB,EAEpD,CAAC,KAAK,iBAAiB,WAAaC,EAAa,YACnD,KAAK,iBAAiB,UAAYA,EAAa,WAEjD,MAAMC,EAAkB,KAAK,gBAAgBD,CAAY,EACzD,KAAK,mBAAmB,QAAQ,sBAAsB,EAGtD,KAAK,mBAAmB,UAAU,mBAAmB,EACrD,MAAME,EAAmB,KAAK,eAAeD,CAAe,EAC5D,GAAI,CAACC,EAAiB,SAAW,KAAK,OAAO,WAC3C,MAAM,IAAI1N,GACRH,EAAiB,yBACjBM,GAAeN,EAAiB,wBAAwB,EACxD,CAAE,OAAQ6N,EAAiB,MAAA,CAAO,EAGtC,KAAK,mBAAmB,QAAQ,mBAAmB,EAGnD,KAAK,mBAAmB,QAAQ,OAAO,EACvC,QAAQ,MAAM,gDAAiDD,CAAe,EAC9E,QAAQ,MAAM,uCAAwCA,EAAgB,SAAS,EAC/E,QAAQ,MAAM,mDAAoDA,EAAgB,WAAW,UAAU,EACvG,MAAMp+C,EAAS,KAAK,YAAYo+C,EAAiB,CAC/C,gBAAAH,EACA,iBAAAI,EACA,cAAeJ,EAAgB,SAC/B,eAAgBI,EAAiB,QAAA,EAChCL,CAAS,EAEZ,eAAQ,MAAM,mCAAoCh+C,EAAO,KAAK,SAAS,EACvE,QAAQ,MAAM,+CAAgDA,EAAO,KAAK,WAAW,UAAU,EACxFA,CAET,OAAS7D,EAAO,CAKd,GAJA,KAAK,mBAAmB,QAAQ,OAAO,EAInC,KAAK,OAAO,WACd,MAAMA,EAIR,GAAI,KAAK,OAAO,gBACd,eAAQ,KAAK,eAAgBA,CAAK,EAC3B,KAAK,qBAAqB6hD,EAAW7hD,CAAK,EAGnD,MAAMA,CACR,CACF,CAKQ,cAAc6hD,EAA4E,CAChG,OAAOzC,GAAkB,cAAcyC,EAAW,CAChD,WAAY,KAAK,OAAO,YAAc,KAAK,OAAO,kBAAoB,QAAA,CACvE,CACH,CAKQ,oCAAoCA,EAAyC,CAEnF,GAAI,CAACA,EAAW,CACd,QAAQ,MAAM,wEAAwE,EACtF,MACF,CAGK,KAAK,iBAAiB,kBACzB,KAAK,iBAAiB,gBAAkB,CAAA,GAErC,KAAK,iBAAiB,uBACzB,KAAK,iBAAiB,qBAAuB,CAAA,GAI3CA,EAAU,iBAAmB,OAAOA,EAAU,iBAAoB,UACpE,QAAQ,MAAM,iCAAkC,OAAO,KAAKA,EAAU,eAAe,CAAC,EAEtF,OAAO,QAAQA,EAAU,eAAe,EAAE,QAAQ,CAAC,CAACxoD,EAAK4uB,CAAK,IAAM,CAClE,GAAIA,GAAS,OAAOA,GAAU,SAAU,CACtC,QAAQ,MAAM,kCAAkC5uB,CAAG,IAAK,CACtD,GAAI4uB,EAAM,GACV,KAAMA,EAAM,KACZ,aAAc,cAAeA,EAC7B,UAAWA,EAAM,UACjB,iBAAkB,MAAM,QAAQA,EAAM,SAAS,EAC/C,UAAW,OAAO,KAAKA,CAAK,CAAA,CAC7B,EAED,MAAM8yB,EAAiB,KAAK,gCAAgC9yB,CAAK,EACjE,QAAQ,MAAM,QAAQ5uB,CAAG,IAAK,CAAE,KAAM4uB,EAAM,KAAM,SAAUA,EAAM,SAAU,SAAUA,EAAM,SAAU,EACtG,KAAK,iBAAiB,gBAAgB5uB,CAAG,EAAI0hD,CAC/C,CACF,CAAC,EACD,QAAQ,MAAM,sCAAuC,OAAO,KAAK,KAAK,iBAAiB,eAAe,CAAC,GAEvG,QAAQ,MAAM,2CAA2C,EAIvD8G,EAAU,uBAAyB,OAAOA,EAAU,uBAA0B,UAEhF,OAAO,QAAQA,EAAU,qBAAqB,EAAE,QAAQ,CAAC,CAACxoD,EAAK2tB,CAAS,IAAM,CAC5E,GAAIA,GAAa,OAAOA,GAAc,SAAU,CAE9C,MAAMm7B,EAAqB,KAAK,sCAAsCn7B,CAAS,EAC/E,KAAK,iBAAiB,qBAAqB3tB,CAAG,EAAI8oD,CACpD,CACF,CAAC,EAKCN,EAAU,QAAU,OAAOA,EAAU,QAAW,UAClD,OAAO,OAAOA,EAAU,MAAM,EAAE,QAAShmB,GAAe,CAClDA,GAASA,EAAM,SAAW,MAAM,QAAQA,EAAM,OAAO,GACvDA,EAAM,QAAQ,QAAS6W,GAAsB,CAEvCA,EAAa,OAAS,SAAWA,EAAa,QAChD,KAAK,kCAAkCA,EAAa,MAAM,CAE9D,CAAC,CAEL,CAAC,CAEL,CAMQ,yCAAyCmP,EAAyC,CAExF,GAAI,CAACA,EAAW,CACd,QAAQ,MAAM,6EAA6E,EAC3F,MACF,CAGK,KAAK,iBAAiB,2BACzB,KAAK,iBAAiB,yBAA2B,CAAA,GAI/CA,EAAU,4BAA8B,OAAOA,EAAU,4BAA+B,UAC1F,QAAQ,MAAM,4CAA6C,OAAO,KAAKA,EAAU,0BAA0B,CAAC,EAE5G,OAAO,QAAQA,EAAU,0BAA0B,EAAE,QAAQ,CAAC,CAACxoD,EAAKF,CAAM,IAAM,CAC1EA,GAAU,OAAOA,GAAW,WAC9B,QAAQ,MAAM,6CAA6CE,CAAG,IAAK,CACjE,GAAIF,EAAO,GACX,SAAUA,EAAO,SACjB,QAAS,SAAUA,EACnB,UAAW,WAAYA,EACvB,UAAW,WAAYA,EACvB,aAAc,cAAeA,CAAA,CAC9B,EACD,KAAK,iBAAiB,yBAA0BE,CAAG,EAAIF,EAE3D,CAAC,EACD,QAAQ,MAAM,+CAAgD,OAAO,KAAK,KAAK,iBAAiB,wBAAwB,CAAC,GAEzH,QAAQ,MAAM,sDAAsD,CAExE,CAMQ,iCAAiC0oD,EAAyC,CAEhF,GAAI,CAACA,EAAW,CACd,QAAQ,MAAM,qEAAqE,EACnF,MACF,CAGK,KAAK,iBAAiB,mBACzB,KAAK,iBAAiB,iBAAmB,CAAA,GAIvCA,EAAU,mBAAqB,OAAOA,EAAU,mBAAsB,UACxE,QAAQ,MAAM,mCAAoC,OAAO,KAAKA,EAAU,iBAAiB,CAAC,EAE1F,OAAO,QAAQA,EAAU,iBAAiB,EAAE,QAAQ,CAAC,CAACxoD,EAAKF,CAAM,IAAM,CACjEA,GAAU,OAAOA,GAAW,WAC9B,QAAQ,MAAM,oCAAoCE,CAAG,IAAK,CACxD,GAAKF,EAAe,GACpB,YAAcA,EAAe,YAC7B,cAAe,eAAgBA,EAC/B,iBAAkB,kBAAmBA,CAAA,CACtC,EACD,KAAK,iBAAiB,iBAAkBE,CAAG,EAAIF,EAEnD,CAAC,EACD,QAAQ,MAAM,uCAAwC,OAAO,KAAK,KAAK,iBAAiB,gBAAgB,CAAC,GAEzG,QAAQ,MAAM,6CAA6C,CAE/D,CAKQ,gCAAgC8uB,EAAiB,CACvD,GAAI,CAACA,GAAS,OAAOA,GAAU,SAC7B,OAAOA,EAGT,QAAQ,MAAM,uDAAwD,CACpE,GAAIA,EAAM,GACV,KAAMA,EAAM,KACZ,aAAc,cAAeA,EAC7B,UAAWA,EAAM,UACjB,iBAAkB,MAAM,QAAQA,EAAM,SAAS,EAC/C,gBAAiBA,EAAM,UAAYA,EAAM,UAAU,OAAS,CAAA,CAC7D,EAED,MAAM8yB,EAAiB,CAAE,GAAG9yB,CAAA,EAGxB8yB,EAAe,OAAS,YAC1B,QAAQ,MAAM,2CAA2CA,EAAe,IAAM,SAAS,EAAE,EACzFA,EAAe,KAAO,QAIpB,MAAM,QAAQA,EAAe,QAAQ,GAAKA,EAAe,SAAS,QAAU,IAC9EA,EAAe,SAAW,CACxB,EAAGA,EAAe,SAAS,CAAC,EAC5B,EAAGA,EAAe,SAAS,CAAC,CAAA,GAK5B,MAAM,QAAQA,EAAe,QAAQ,IACvCA,EAAe,SAAWA,EAAe,SAAS,IAAK3yB,GACjD,MAAM,QAAQA,CAAM,GAAKA,EAAO,QAAU,EACrC,CACL,EAAGA,EAAO,CAAC,EACX,EAAGA,EAAO,CAAC,CAAA,EAIRA,CACR,GAIC,MAAM,QAAQ2yB,EAAe,SAAS,GACxC,QAAQ,MAAM,qCAAqCA,EAAe,IAAM,SAAS,IAAK,CACpF,gBAAiBA,EAAe,UAAU,OAC1C,cAAeA,EAAe,UAAU,CAAC,EACzC,kBAAmB,OAAOA,EAAe,UAAU,CAAC,EACpD,qBAAsB,MAAM,QAAQA,EAAe,UAAU,CAAC,CAAC,CAAA,CAChE,EACDA,EAAe,UAAYA,EAAe,UAAU,IAAI,CAAC73B,EAAenX,IAClE,MAAM,QAAQmX,CAAQ,GAAKA,EAAS,QAAU,EACzC,CACL,EAAGA,EAAS,CAAC,EACb,EAAGA,EAAS,CAAC,CAAA,GAGjB,QAAQ,MAAM,cAAcnX,CAAK,iBAAkBmX,CAAQ,EACpDA,EACR,EAGG63B,EAAe,OAAS,WAAa,MAAM,QAAQA,EAAe,SAAS,GAAKA,EAAe,UAAU,SAAW,IACtH,QAAQ,MAAM,2CAA2CA,EAAe,IAAM,SAAS,EAAE,EACzFA,EAAe,KAAO,OACtBA,EAAe,MAAQA,EAAe,UAAU,CAAC,EACjDA,EAAe,IAAMA,EAAe,UAAU,CAAC,EAE/C,OAAOA,EAAe,YAEf,cAAeA,GACxB,QAAQ,MAAM,YAAYA,EAAe,IAAM,SAAS,gCAAiC,CACvF,UAAWA,EAAe,UAC1B,cAAe,OAAOA,EAAe,SAAA,CACtC,EAIH,SAAW,CAAC1hD,EAAKkB,CAAK,IAAK,OAAO,QAAQwgD,CAAc,EAClD,MAAM,QAAQxgD,CAAK,EACrBwgD,EAAe1hD,CAAG,EAAIkB,EAAM,IAAK8D,GAE3BA,GAAQ,OAAOA,GAAS,UAAY,SAAUA,EACzCA,EAEF,OAAOA,GAAS,SAAW,KAAK,gCAAgCA,CAAI,EAAIA,CAChF,EACQ9D,GAAS,OAAOA,GAAU,WAE/B,SAAUA,EACZwgD,EAAe1hD,CAAG,EAAIkB,EAEtBwgD,EAAe1hD,CAAG,EAAI,KAAK,gCAAgCkB,CAAK,GAKtE,eAAQ,MAAM,gDAAgD0tB,EAAM,EAAE,IAAK,CACzE,KAAM8yB,EAAe,KACrB,aAAc,cAAeA,EAC7B,UAAWA,EAAe,UAC1B,iBAAkB,MAAM,QAAQA,EAAe,SAAS,EACxD,gBAAiBA,EAAe,UAAYA,EAAe,UAAU,OAAS,EAC9E,KAAM,OAAO,KAAKA,CAAc,CAAA,CACjC,EAEMA,CACT,CAKQ,sCAAsC/zB,EAAqB,CACjE,GAAI,CAACA,GAAa,OAAOA,GAAc,SACrC,OAAOA,EAGT,MAAMm7B,EAAqB,CAAE,GAAGn7B,CAAA,EAGhC,GAAIm7B,EAAmB,QAAUA,EAAmB,OAAO,OAAQ,CACjE,MAAMj4B,EAASi4B,EAAmB,OAAO,OAGrCj4B,GAAU,OAAOA,GAAW,UAAY,MAAOA,GAAU,MAAOA,IAClEi4B,EAAmB,OAAO,OAAS,CAACj4B,EAAO,EAAGA,EAAO,CAAC,EAI1D,CAGA,SAAW,CAAC7wB,EAAKkB,CAAK,IAAK,OAAO,QAAQ4nD,CAAkB,EACtD,MAAM,QAAQ5nD,CAAK,EACrB4nD,EAAmB9oD,CAAG,EAAIkB,EAAM,IAAK8D,GACnC,OAAOA,GAAS,SAAW,KAAK,sCAAsCA,CAAI,EAAIA,CAAA,EAEvE9D,GAAS,OAAOA,GAAU,WACnC4nD,EAAmB9oD,CAAG,EAAI,KAAK,sCAAsCkB,CAAK,GAI9E,OAAO4nD,CACT,CAKQ,kCAAkCp6B,EAAqB,CACxD,MAAM,QAAQA,CAAM,GAEzBA,EAAO,QAASE,GAAe,CAC7B,GAAIA,GAASA,EAAM,OAAS,SAAWA,EAAM,UAAY,MAAM,QAAQA,EAAM,QAAQ,GAAKA,EAAM,SAAS,QAAU,EAAG,CAEpH,MAAMm6B,EAAUn6B,EAAM,IAAM,SAASA,EAAM,SAAS,CAAC,CAAC,IAAIA,EAAM,SAAS,CAAC,CAAC,GAC3E,KAAK,iBAAiB,gBAAgBm6B,CAAO,EAAI,CAC/C,KAAM,QACN,SAAU,CACR,EAAGn6B,EAAM,SAAS,CAAC,EACnB,EAAGA,EAAM,SAAS,CAAC,CAAA,CACrB,CAEJ,CACF,CAAC,CACH,CAKQ,kBAAkB45B,EAAwC,CAEhE,GAAI,CAACA,EACH,eAAQ,MAAM,sDAAsD,EAC7D,CACL,GAAI,uBACJ,MAAO,OACP,MAAO,EACP,KAAM,OACN,OAAQ,OACR,MAAO,OACP,UAAW,OACX,gBAAiB,CAAA,EACjB,WAAY,EACZ,SAAU,CAAA,EACV,UAAW,CAAE,SAAU,EAAA,EACvB,OAAQ,CAAE,SAAU,CAAE,MAAO,CAAA,GAAM,MAAO,CAAE,MAAO,CAAA,GAAM,OAAQ,CAAE,MAAO,CAAA,EAAG,EAC7E,YAAa,CAAE,MAAO,EAAC,EACvB,OAAQ,CAAE,MAAO,EAAG,KAAM,GAAI,YAAa,EAAA,CAAG,EAKlD,KAAK,oCAAoCA,CAAS,EAGlD,KAAK,yCAAyCA,CAAS,EAGvD,KAAK,iCAAiCA,CAAS,EAG/C,MAAM9wB,EAAmB,CACvB,GAAI8wB,EAAU,cAAgBlB,GAAY,WAAW,UAAU,EAC/D,MAAOkB,EAAU,MACjB,MAAO,KAAK,WAAWA,EAAU,QAAQ,EACzC,KAAMA,EAAU,UAChB,OAAQA,EAAU,YAClB,MAAOA,EAAU,kBACjB,UAAWA,EAAU,UACrB,gBAAiBA,EAAU,kBAAoB,CAAA,EAC/C,WAAYA,EAAU,YAAc,EACpC,SAAU,KAAK,kBAAkBA,CAAS,EAC1C,YAAaA,EAAU,YACvB,OAAQ,KAAK,yBAAyBA,EAAU,MAAM,EACtD,OAAQ,KAAK,gBAAgBA,EAAU,WAAW,EAClD,YAAa,KAAK,oBAAoBA,EAAU,WAAW,CAAA,EAItC,CACrB,UAAW,YAAa,YAAa,gBAAiB,WACtD,aAAc,aAAc,QAAA,EAGf,QAAQ5xB,GAAS,CACzB4xB,EAAkB5xB,CAAK,IAAM,SAC/Bc,EAAoBd,CAAK,EAAK4xB,EAAkB5xB,CAAK,EAE1D,CAAC,EAID,QAAQ,MAAM,+CAAgD4xB,EAAU,UAAU,EAClF,MAAMlD,EAAY,KAAK,mBAAmBkD,EAAU,UAAU,EAC9D,eAAQ,MAAM,oDAAqDlD,CAAS,EAC5E,QAAQ,MAAM,+CAAgDA,GAAW,UAAU,EACnF,KAAK,iBAAiB,UAAYA,EAClC5tB,EAAY,UAAY4tB,EACxB,QAAQ,MAAM,oDAAqD5tB,EAAY,SAAS,EAGxFA,EAAY,YAAc,KAAK,qBAAqB8wB,EAAU,WAAW,EAElE9wB,CACT,CAKQ,WAAW0a,EAAyB,CAC1C,MAAMr/B,EAAQq/B,EAAQ,MAAM,QAAQ,EACpC,OAAOr/B,EAAQ,SAASA,EAAM,CAAC,EAAG,EAAE,EAAI,CAC1C,CAKQ,kBAAkBy1C,EAAwC,CAChE,OAAIA,EAAU,UAAY,OAAOA,EAAU,UAAa,SAC/CA,EAAU,SAGZ,CACL,MAAOA,EAAU,WAAa,UAC9B,MAAOA,EAAU,mBAAqB,YACtC,KAAMA,EAAU,kBAAoB,CAAC,SAAS,CAAA,CAElD,CAKQ,mBAAmBlD,EAAqB,CAE9C,GADA,QAAQ,MAAM,qCAAsCA,CAAS,EACzD,CAACA,GAAa,OAAOA,GAAc,SACrC,eAAQ,MAAM,8DAA8D,EACrE,CAAE,SAAU,EAAA,EAGrB,MAAM5tB,EAAc,CAAE,GAAG4tB,CAAA,EACzB,eAAQ,MAAM,2CAA4C5tB,CAAW,EAGjEA,EAAY,WAAa,QAAaA,EAAY,UAAY,SAChEA,EAAY,SAAWA,EAAY,SAIjCA,EAAY,WAAa,SAC3BA,EAAY,SAAW,IAGzB,QAAQ,MAAM,oCAAqCA,CAAW,EACvDA,CACT,CAOQ,yBAAyB8mB,EAAkB,CACjD,GAAI,CAACA,GAAU,OAAOA,GAAW,SAC/B,MAAO,CACL,SAAU,CAAE,MAAO,EAAC,EACpB,MAAO,CAAE,MAAO,EAAC,EACjB,OAAQ,CAAE,MAAO,CAAA,CAAC,CAAE,EAIxB,MAAMsG,EAAyC,CAAA,EAI/C,MADuB,CAAC,WAAY,QAAS,QAAQ,EACtC,QAAQC,GAAa,CAClC,GAAIvG,EAAOuG,CAAS,EAAG,CACrB,MAAMviB,EAAQgc,EAAOuG,CAAS,EAExBiE,EAAaxmB,EAAM,OAASA,EAAM,SAAW,CAAA,EACnDsiB,EAAkBC,CAAS,EAAI,CAC7B,GAAGviB,EACH,MAAOwmB,CAAA,EAGLxmB,EAAM,UAAY,QACpB,OAAOsiB,EAAkBC,CAAS,EAAE,OAExC,MACED,EAAkBC,CAAS,EAAI,CAAE,MAAO,CAAA,CAAC,CAE7C,CAAC,EAGsB,CAAC,UAAU,EACnB,QAAQA,GAAa,CAClC,GAAIvG,EAAOuG,CAAS,EAAG,CACrB,MAAMviB,EAAQgc,EAAOuG,CAAS,EAExBiE,EAAaxmB,EAAM,OAASA,EAAM,SAAW,CAAA,EACnDsiB,EAAkBC,CAAS,EAAI,CAC7B,GAAGviB,EACH,MAAOwmB,CAAA,EAGLxmB,EAAM,UAAY,QACpB,OAAOsiB,EAAkBC,CAAS,EAAE,OAExC,CACF,CAAC,EAEMD,CACT,CAKQ,qBAAqB7K,EAAuB,CAQlD,GAPA,QAAQ,MAAM,kCAAmC,CAC/C,eAAgB,CAAC,CAACA,EAClB,QAAS,MAAM,QAAQA,CAAW,EAClC,SAAUA,GAAeA,EAAY,OAAS,MAAM,QAAQA,EAAY,KAAK,EAC7E,WAAYA,GAAeA,EAAY,MAAQA,EAAY,MAAM,OAAS,CAAA,CAC3E,EAEG,CAACA,EACH,MAAO,CAAE,MAAO,EAAC,EAInB,GAAI,MAAM,QAAQA,CAAW,EAC3B,MAAO,CAAE,MAAOA,CAAA,EAIlB,GAAIA,EAAY,OAAS,MAAM,QAAQA,EAAY,KAAK,EAAG,CACzD,QAAQ,MAAM,uCAAuCA,EAAY,MAAM,MAAM,QAAQ,EAErF,MAAMgP,EAAmBhP,EAAY,MAAM,IAAI,CAACnhB,EAAWpmB,KACzD,QAAQ,MAAM,UAAUA,CAAK,oBAAoB,CAAC,CAAComB,EAAK,WAAW,EAAE,EAC9D,KAAK,yBAAyBA,CAAI,EAC1C,EACD,MAAO,CACL,GAAGmhB,EACH,MAAOgP,CAAA,CAEX,CAGA,MAAO,CAAE,MAAO,EAAC,CACnB,CAKQ,yBAAyBnwB,EAAgB,CAC/C,GAAI,CAACA,GAAQ,CAACA,EAAK,YACjB,OAAOA,EAGT,MAAM8gB,EAAc9gB,EAAK,YACnBowB,EAAkBtP,EAAY,KAMpC,GAJA,QAAQ,MAAM,2CAA2C9gB,EAAK,KAAK,qBAAqBowB,CAAe,EAAE,EACzG,QAAQ,MAAM,uBAAwB,OAAO,KAAKtP,CAAW,CAAC,EAG1DsP,IAAoB,SAAWA,IAAoB,oBACrD,eAAQ,KAAK,2BAA2BA,CAAe,OAAO,EACvDpwB,EAGT,GAAI,CAEF,MAAMugB,EAAe,CACnB,KAAM6P,EACN,GAAGtP,CAAA,EAGL,QAAQ,MAAM,wBAAyB,OAAO,KAAKP,CAAY,CAAC,EAC5D6P,IAAoB,SAAW7P,EAAa,SAC9C,QAAQ,MAAM,mBAAoBA,EAAa,OAAO,MAAM,EACxDA,EAAa,OAAO,OAAS,GAC/B,QAAQ,MAAM,kBAAmBA,EAAa,OAAO,CAAC,CAAC,GAK3D,QAAQ,MAAM,uEAAwE,KAAK,iBAAiB,oBAAoB,EAChI,QAAQ,MAAM,2DAA4D,KAAK,iBAAiB,qBAAuB,OAAO,KAAK,KAAK,iBAAiB,oBAAoB,EAAI,CAAA,CAAE,EAGnL,MAAM8P,EAAmB,KAAK,oBAAoB,UAChD9P,EACA,KAAK,iBACL,CACE,0BAA2B,KAAK,OAAO,0BACvC,WAAY,KAAK,OAAO,UAAA,CAC1B,EAGF,QAAQ,MAAM,4BAA6B,OAAO,KAAK8P,CAAgB,CAAC,EACpED,IAAoB,SAAWC,EAAiB,QAClD,QAAQ,MAAM,+BAAgCA,EAAiB,OAAO,MAAM,EAI9E,IAAIC,EAEJ,GAAIF,IAAoB,qBAAuBC,EAAiB,UAAYA,EAAiB,SAAS,OAGpGC,EAAyBD,EACzB,QAAQ,MAAM,0DAA0D,CAAC,CAACC,EAAuB,UAAU,MAAM,EAAE,EACnH,QAAQ,MAAM,8CAA8CtwB,EAAK,KAAK,EAAE,EACxE,QAAQ,MAAM,+CAAgD,OAAO,KAAKswB,EAAuB,UAAU,QAAU,CAAA,CAAE,CAAC,EACxH,QAAQ,MAAM,0CAA2CA,EAAuB,UAAU,MAAM,UACvFF,IAAoB,SAAWC,EAAiB,YAAa,CAGtE,KAAM,CAAE,YAAA55B,EAAa,GAAG85B,CAAA,EAASF,EACjCC,EAAyB,CACvB,GAAGC,EAEH,GAAG95B,CAAA,EAEL,QAAQ,MAAM,mCAAmC65B,EAAuB,WAAW,EAAE,CACvF,MACEA,EAAyB,CAAE,GAAGD,CAAA,EAIhC,MAAO,CACL,GAAGrwB,EACH,YAAaswB,CAAA,CAEjB,OAASziD,EAAO,CAGd,GAFA,QAAQ,MAAM,6BAA8BA,CAAK,EAE7C,KAAK,OAAO,WACd,MAAMA,EAER,OAAOmyB,CACT,CACF,CAKQ,gBAAgBysB,EAAsB,CAC5C,MAAI,CAACA,GAAc,OAAOA,GAAe,SAChC,CACL,MAAO,EACP,KAAM,GACN,YAAa,EAAA,EAIV,CACL,MAAOA,EAAW,OAAS,EAC3B,KAAMA,EAAW,MAAQ,GACzB,YAAaA,EAAW,kBAAoB,EAAA,CAEhD,CAKQ,oBAAoBA,EAAsB,CAChD,GAAI,GAACA,GAAc,OAAOA,GAAe,UAIzC,MAAO,CACL,GAAGA,EACH,iBAAkBA,EAAW,kBAAoB,EAAA,CAErD,CAKQ,kBAAkB7+C,EAAgB,CAExC,MAAM4iD,EAAU,KAAK,iBAAiB,eAAe5iD,CAAI,EACzD,YAAK,mBAAmB,kBAAkB4iD,EAAQ,MAAM,EAGlC,KAAK,iBAAiB,aAAaA,EAAS,KAAK,gBAAgB,EAGhF9C,GAAe,kBAAkB9/C,EAAM,KAAK,iBAAkB,CACnE,WAAY,KAAK,OAAO,WACxB,UAAYyiC,IACV,QAAQ,KAAK,UAAUA,CAAG,EAAE,EACrBA,EACT,CACD,CACH,CAKQ,gBAAgBziC,EAAgB,CACtC,MAAMkiD,EAAkB,CAAE,GAAGliD,CAAA,EAE7B,OAAIkiD,EAAgB,QAAU,OAAOA,EAAgB,QAAW,WAC9D,QAAQ,MAAM,mDAAmD,EACjE,QAAQ,MAAM,6CAA8C,OAAO,KAAK,KAAK,iBAAiB,iBAAmB,CAAA,CAAE,CAAC,EACpH,QAAQ,MAAM,iCAAkC,KAAK,OAAO,yBAAyB,EAErFA,EAAgB,OAAS,KAAK,oBAAoB,gBAChDA,EAAgB,OAChB,KAAK,iBACL,CACE,0BAA2B,KAAK,OAAO,0BACvC,WAAY,KAAK,OAAO,UAAA,CAC1B,EAGF,QAAQ,MAAM,mDAAmD,GAG5DA,CACT,CAKQ,eAAeW,EAA6E,CAClG,OAAOxD,GAAkB,eAAewD,EAAY,CAClD,WAAY,KAAK,OAAO,YAAc,KAAK,OAAO,kBAAoB,QAAA,CACvE,CACH,CAKQ,YACN7iD,EACA8iD,EAMAhB,EACe,CACf,MAAMiB,EAAmB,KAAK,mBAAmB,SAAA,EAC3CC,EAAmB,KAAK,mBAAmB,iBAAA,EAG3Cr5B,EAA6B,CACjC,GAAGm5B,EAAK,gBAAgB,SAAS,IAAInqC,IAAQ,CAC3C,KAAM27B,EAAiB,cACvB,QAAS,WAAW37B,CAAG,GACvB,WAAY,UAAA,EACZ,EACF,GAAGmqC,EAAK,iBAAiB,SAAS,IAAInqC,IAAQ,CAC5C,KAAM27B,EAAiB,yBACvB,QAAS,WAAW37B,CAAG,GACvB,WAAY,UAAA,EACZ,EACF,GAAGqqC,EAAiB,SAAS,IAAIrqC,IAAQ,CACvC,KAAM27B,EAAiB,sBACvB,QAAS,SAAS37B,CAAG,GACrB,WAAY,UAAA,EACZ,CAAA,EAKEsqC,EAAYnB,GAAa9hD,EACzB4iD,EAAU,KAAK,OAAO,0BACxB,KAAK,iBAAiB,eAAeK,CAAS,EAC9C,CAAA,EACEC,EAAiBpD,GAAe,wBAAwB8C,EAAS,KAAK,gBAAgB,EAE5F,MAAO,CACL,KAAA5iD,EACA,SAAA2pB,EACA,YAAao5B,EACb,eAAgB,CACd,MAAOG,EAAe,MACtB,SAAUA,EAAe,SACzB,OAAQA,EAAe,OACvB,OAAQA,EAAe,MAAA,CACzB,CAEJ,CAKQ,qBAAqBpB,EAAgB7hD,EAA2B,CACtE,MAAMkjD,EAAe,CACnB,GAAGxO,GACH,GAAImN,GAAW,cAAgBnN,GAAsB,GACrD,MAAOmN,GAAW,OAASnN,GAAsB,KAAA,EAG7CkL,EAA0B,CAC9B,KAAMvL,EAAiB,sBACvB,QAAS,gBAAgBr0C,EAAM,OAAO,GACtC,WAAY,gBAAA,EAGd,MAAO,CACL,KAAMkjD,EACN,SAAU,CAACtD,CAAO,EAClB,YAAa,KAAK,mBAAmB,SAAA,EACrC,eAAgB,CACd,MAAO,EACP,SAAU,EACV,OAAQ,EACR,OAAQ,CAAA,CAAC,CACX,CAEJ,CAKA,qBAAsB,CACpB,OAAO,KAAK,mBAAmB,SAAA,CACjC,CAKA,OAAQ,CACN,KAAK,mBAAmB,MAAA,CAC1B,CACF,CC55BO,MAAMuD,EAAoB,CACvB,OACA,iBACA,iBACA,oBACA,mBACA,YAER,YAAYhqD,EAA4B,GAAI,CAC1C,KAAK,OAAS,CAAE,GAAGm7C,GAA6B,GAAGn7C,CAAA,EACnD,KAAK,iBAAmBs8C,GAAA,EACxB,KAAK,iBAAmBsE,GAAA,EACxB,KAAK,oBAAsBsE,GAAA,EAC3B,KAAK,mBAAqB,IAAIgC,GAE9B,KAAK,YAAc,IAAIuB,GAAgBzoD,CAAM,CAC/C,CAMA,MAAM0oD,EAAiD,CACjD,KAAK,OAAO,eACd,QAAQ,IAAI,kFAAmF,CAC7F,aAAcA,GAAW,aACzB,eAAgBA,GAAW,eAC3B,MAAOA,GAAW,YAAY,MAC9B,kBAAmB,CAAC,CAACA,GAAW,gBAChC,kBAAmBA,GAAW,gBAAkB,OAAO,KAAKA,EAAU,eAAe,EAAI,CAAA,EACzF,UAAW,CAAC,CAACA,GAAW,OACxB,UAAWA,GAAW,OAAS,OAAO,KAAKA,EAAU,MAAM,EAAI,CAAA,CAAC,CACjE,EAGH,KAAK,mBAAmB,UAAU,OAAO,EAEzC,GAAI,CAEF,MAAMuB,EAAUvB,EAGVh+C,EAAS,KAAK,YAAY,MAAMu/C,CAAO,EAE7C,YAAK,mBAAmB,QAAQ,OAAO,EAEnC,KAAK,OAAO,eACd,QAAQ,IAAI,kDAAmD,CAC7D,GAAIv/C,EAAO,KAAK,GAChB,aAAc,CAAC,CAACA,EAAO,KAAK,UAC5B,aAAcA,EAAO,SAAS,OAC9B,eAAgBA,EAAO,cAAA,CACxB,EAGIA,CAET,OAAS7D,EAAO,CAKd,GAJA,KAAK,mBAAmB,QAAQ,OAAO,EAInC,KAAK,OAAO,WACd,MAAMA,EAIR,GAAI,KAAK,OAAO,gBACd,eAAQ,KAAK,eAAgBA,CAAK,EAC3B,KAAK,qBAAqB6hD,EAAW7hD,CAAK,EAGnD,MAAMA,CACR,CACF,CAKQ,eAAe6hD,EAA4E,CACjG,OAAOzC,GAAkB,cAAcyC,EAAW,CAChD,WAAY,KAAK,OAAO,YAAc,KAAK,OAAO,kBAAoB,QAAA,CACvE,CACH,CAKQ,oCAAoCA,EAAwC,CAElF,GAAI,CAACA,EAAW,CACV,KAAK,OAAO,eACd,QAAQ,MAAM,wEAAwE,EAExF,MACF,CAGK,KAAK,iBAAiB,kBACzB,KAAK,iBAAiB,gBAAkB,CAAA,GAErC,KAAK,iBAAiB,uBACzB,KAAK,iBAAiB,qBAAuB,CAAA,GAI3CA,EAAU,iBAAmB,OAAOA,EAAU,iBAAoB,UAChE,KAAK,OAAO,eACd,QAAQ,IAAI,iCAAkC,OAAO,KAAKA,EAAU,eAAe,CAAC,EAGtF,OAAO,QAAQA,EAAU,eAAe,EAAE,QAAQ,CAAC,CAACxoD,EAAK4uB,CAAK,IAAM,CAClE,GAAIA,GAAS,OAAOA,GAAU,SAAU,CAEtC,MAAM8yB,EAAiB,KAAK,gCAAgC9yB,CAAgC,EAC5F,KAAK,iBAAiB,gBAAgB5uB,CAAG,EAAI0hD,CAC/C,CACF,CAAC,EACG,KAAK,OAAO,eACd,QAAQ,IAAI,sCAAuC,OAAO,KAAK,KAAK,iBAAiB,eAAe,CAAC,GAE9F,KAAK,OAAO,eACrB,QAAQ,IAAI,2CAA2C,EAIrD8G,EAAU,uBAAyB,OAAOA,EAAU,uBAA0B,WAE3E,KAAK,iBAAiB,uBACzB,KAAK,iBAAiB,qBAAuB,CAAA,GAE/C,OAAO,QAAQA,EAAU,qBAAqB,EAAE,QAAQ,CAAC,CAACxoD,EAAK2tB,CAAS,IAAM,CAC5E,GAAIA,GAAa,OAAOA,GAAc,SAAU,CAE9C,MAAMm7B,EAAqB,KAAK,sCAAsCn7B,CAAgC,EACtG,KAAK,iBAAiB,qBAAsB3tB,CAAG,EAAI8oD,CACrD,CACF,CAAC,EAKL,CAKQ,gBAAgBvD,EAAiG,CACvH,MAAI,CAACA,GAAc,OAAOA,GAAe,SAChC,CACL,MAAO,EACP,KAAM,GACN,YAAa,EAAA,EAIV,CACL,MAAOA,EAAW,OAAS,EAC3B,KAAMA,EAAW,MAAQ,GACzB,YAAaA,EAAW,kBAAoB,EAAA,CAEhD,CAKQ,oBAAoBA,EAAmE,CAC7F,GAAI,GAACA,GAAc,OAAOA,GAAe,UAIzC,MAAO,CACL,GAAGA,EACH,iBAAkBA,EAAW,kBAAoB,EAAA,CAErD,CAKQ,qBAAqBtL,EAAsF,CAUjH,GATI,KAAK,OAAO,eACd,QAAQ,IAAI,kCAAmC,CAC7C,eAAgB,CAAC,CAACA,EAClB,QAAS,MAAM,QAAQA,CAAW,EAClC,SAAUA,GAAe,CAAC,MAAM,QAAQA,CAAW,GAAKA,EAAY,OAAS,MAAM,QAAQA,EAAY,KAAK,EAC5G,WAAYA,EAAe,MAAM,QAAQA,CAAW,EAAIA,EAAY,OAAUA,EAAY,MAAQA,EAAY,MAAM,OAAS,EAAM,CAAA,CACpI,EAGC,CAACA,EACH,MAAO,CAAE,MAAO,EAAC,EAInB,GAAI,MAAM,QAAQA,CAAW,EAC3B,MAAO,CAAE,MAAOA,CAAA,EAIlB,GAAIA,EAAY,OAAS,MAAM,QAAQA,EAAY,KAAK,EAAG,CACrD,KAAK,OAAO,eACd,QAAQ,IAAI,uCAAuCA,EAAY,MAAM,MAAM,QAAQ,EAGrF,MAAMgP,EAAmBhP,EAAY,MAAM,IAAI,CAACnhB,EAAuBpmB,KACjE,KAAK,OAAO,eACd,QAAQ,IAAI,UAAUA,CAAK,oBAAoB,CAAC,CAAComB,EAAK,WAAW,EAAE,EAE9D,KAAK,yBAAyBA,CAAI,EAC1C,EACD,MAAO,CACL,GAAGmhB,EACH,MAAOgP,CAAA,CAEX,CAGA,MAAO,CAAE,MAAO,EAAC,CACnB,CAKQ,yBAAyBnwB,EAAwC,CACvE,GAAI,CAACA,GAAQ,CAACA,EAAK,YACjB,OAAOA,EAGT,MAAM8gB,EAAc9gB,EAAK,YACnBowB,EAAkBtP,EAAY,KAQpC,GANI,KAAK,OAAO,gBACd,QAAQ,IAAI,2CAA2C9gB,EAAK,KAAK,qBAAqBowB,CAAe,EAAE,EACvG,QAAQ,IAAI,uBAAwB,OAAO,KAAKtP,CAAW,CAAC,GAI1DsP,IAAoB,SAAWA,IAAoB,oBACrD,OAAI,KAAK,OAAO,eACd,QAAQ,KAAK,2BAA2BA,CAAe,OAAO,EAEzDpwB,EAGT,GAAI,CAEF,MAAMugB,EAAe,CACnB,GAAGO,EACH,KAAMsP,CAAA,EAGJ,KAAK,OAAO,gBACd,QAAQ,IAAI,wBAAyB,OAAO,KAAK7P,CAAY,CAAC,EAC1D6P,IAAoB,SAAW7P,EAAa,SAC9C,QAAQ,IAAI,mBAAoBA,EAAa,OAAO,MAAM,EACtDA,EAAa,OAAO,OAAS,GAC/B,QAAQ,IAAI,kBAAmBA,EAAa,OAAO,CAAC,CAAC,IAMvD,KAAK,OAAO,gBACd,QAAQ,IAAI,uEAAwE,KAAK,iBAAiB,oBAAoB,EAC9H,QAAQ,IAAI,2DAA4D,KAAK,iBAAiB,qBAAuB,OAAO,KAAK,KAAK,iBAAiB,oBAAoB,EAAI,CAAA,CAAE,GAInL,MAAM8P,EAAmB,KAAK,oBAAoB,UAChD9P,EACA,KAAK,iBACL,CACE,0BAA2B,KAAK,OAAO,0BACvC,WAAY,KAAK,OAAO,UAAA,CAC1B,EAGE,KAAK,OAAO,gBACd,QAAQ,IAAI,4BAA6B,OAAO,KAAK8P,CAAgB,CAAC,EAClED,IAAoB,SAAWC,EAAiB,QAClD,QAAQ,IAAI,+BAAgCA,EAAiB,OAAO,MAAM,GAK9E,IAAIC,EAEJ,GAAIF,IAAoB,qBAAuBC,EAAiB,UAAYA,EAAiB,SAAS,OAGpGC,EAAyBD,EACrB,KAAK,OAAO,gBACd,QAAQ,IAAI,0DAA0D,CAAC,CAACC,EAAuB,UAAU,MAAM,EAAE,EACjH,QAAQ,IAAI,8CAA8CtwB,EAAK,KAAK,EAAE,EACtE,QAAQ,IAAI,+CAAgD,OAAO,KAAKswB,EAAuB,UAAU,QAAU,CAAA,CAAE,CAAC,EACtH,QAAQ,IAAI,0CAA2CA,EAAuB,UAAU,MAAM,WAEvFF,IAAoB,SAAWC,EAAiB,YAAa,CAGtE,KAAM,CAAE,YAAA55B,EAAa,GAAG85B,CAAA,EAASF,EACjCC,EAAyB,CACvB,GAAGC,EAEH,GAAG95B,CAAA,EAED,KAAK,OAAO,eACd,QAAQ,IAAI,mCAAmC65B,EAAuB,WAAW,EAAE,CAEvF,MACEA,EAAyB,CAAE,GAAGD,CAAA,EAIhC,MAAO,CACL,GAAGrwB,EACH,YAAaswB,CAAA,CAEjB,OAASziD,EAAO,CAKd,GAJI,KAAK,OAAO,eACd,QAAQ,MAAM,6BAA8BA,CAAK,EAG/C,KAAK,OAAO,WACd,MAAMA,EAER,OAAOmyB,CACT,CACF,CAKQ,gCAAgClK,EAAyD,CAC/F,GAAI,CAACA,GAAS,OAAOA,GAAU,SAC7B,OAAOA,EAGL,KAAK,OAAO,eACd,QAAQ,IAAI,uDAAwD,CAClE,GAAIA,EAAM,GACV,KAAMA,EAAM,KACZ,aAAc,cAAeA,EAC7B,UAAWA,EAAM,UACjB,iBAAkB,MAAM,QAAQA,EAAM,SAAS,EAC/C,gBAAiBA,EAAM,UAAYA,EAAM,UAAU,OAAS,CAAA,CAC7D,EAGH,MAAM8yB,EAAiB,CAAE,GAAG9yB,CAAA,EAGxB8yB,EAAe,OAAS,YACtB,KAAK,OAAO,eACd,QAAQ,IAAI,2CAA2CA,EAAe,IAAM,SAAS,EAAE,EAEzFA,EAAe,KAAO,QAIpB,MAAM,QAAQA,EAAe,QAAQ,GAAKA,EAAe,SAAS,QAAU,IAC9EA,EAAe,SAAW,CACxB,EAAGA,EAAe,SAAS,CAAC,EAC5B,EAAGA,EAAe,SAAS,CAAC,CAAA,GAK5B,MAAM,QAAQA,EAAe,QAAQ,IACvCA,EAAe,SAAWA,EAAe,SAAS,IAAK3yB,GACjD,MAAM,QAAQA,CAAM,GAAKA,EAAO,QAAU,EACrC,CACL,EAAGA,EAAO,CAAC,EACX,EAAGA,EAAO,CAAC,CAAA,EAIRA,CACR,GAIC,MAAM,QAAQ2yB,EAAe,SAAS,GACpC,KAAK,OAAO,eACd,QAAQ,IAAI,qCAAqCA,EAAe,IAAM,SAAS,IAAK,CAClF,gBAAiBA,EAAe,UAAU,OAC1C,cAAeA,EAAe,UAAU,CAAC,EACzC,kBAAmB,OAAOA,EAAe,UAAU,CAAC,EACpD,qBAAsB,MAAM,QAAQA,EAAe,UAAU,CAAC,CAAC,CAAA,CAChE,EAEHA,EAAe,UAAYA,EAAe,UAAU,IAAI,CAAC73B,EAAenX,IAClE,MAAM,QAAQmX,CAAQ,GAAKA,EAAS,QAAU,EACzC,CACL,EAAGA,EAAS,CAAC,EACb,EAAGA,EAAS,CAAC,CAAA,GAGb,KAAK,OAAO,eACd,QAAQ,IAAI,cAAcnX,CAAK,iBAAkBmX,CAAQ,EAEpDA,EACR,EAGG63B,EAAe,OAAS,QAAU,MAAM,QAAQA,EAAe,SAAS,GAAKA,EAAe,UAAU,SAAW,IAC/G,KAAK,OAAO,eACd,QAAQ,IAAI,2CAA2CA,EAAe,IAAM,SAAS,EAAE,EAEzFA,EAAe,KAAO,OACtBA,EAAe,MAAQA,EAAe,UAAU,CAAC,EACjDA,EAAe,IAAMA,EAAe,UAAU,CAAC,EAE/C,OAAOA,EAAe,YAEf,cAAeA,GACpB,KAAK,OAAO,eACd,QAAQ,IAAI,YAAYA,EAAe,IAAM,SAAS,gCAAiC,CACrF,UAAWA,EAAe,UAC1B,cAAe,OAAOA,EAAe,SAAA,CACtC,EAKL,SAAW,CAAC1hD,EAAKkB,CAAK,IAAK,OAAO,QAAQwgD,CAAc,EAClD,MAAM,QAAQxgD,CAAK,EACrBwgD,EAAe1hD,CAAG,EAAIkB,EAAM,IAAK8D,GAE3BA,GAAQ,OAAOA,GAAS,UAAY,SAAUA,EACzCA,EAEF,OAAOA,GAAS,SAAW,KAAK,gCAAgCA,CAAI,EAAIA,CAChF,EACQ9D,GAAS,OAAOA,GAAU,WAE/B,SAAUA,EACZwgD,EAAe1hD,CAAG,EAAIkB,EAEtBwgD,EAAe1hD,CAAG,EAAI,KAAK,gCAAgCkB,CAAK,GAKtE,OAAI,KAAK,OAAO,eACd,QAAQ,IAAI,gDAAgD0tB,EAAM,EAAE,IAAK,CACvE,KAAM8yB,EAAe,KACrB,aAAc,cAAeA,EAC7B,UAAWA,EAAe,UAC1B,iBAAkB,MAAM,QAAQA,EAAe,SAAS,EACxD,gBAAiBA,EAAe,UAAYA,EAAe,UAAU,OAAS,EAC9E,KAAM,OAAO,KAAKA,CAAc,CAAA,CACjC,EAGIA,CACT,CAKQ,sCAAsC/zB,EAAqD,CACjG,GAAI,CAACA,GAAa,OAAOA,GAAc,SACrC,OAAOA,EAGT,MAAMm7B,EAA0C,CAAE,GAAGn7B,CAAA,EAGrD,GAAIm7B,EAAmB,QAAUA,EAAmB,OAAO,OAAQ,CACjE,MAAMj4B,EAASi4B,EAAmB,OAAO,OAGrCj4B,GAAU,OAAOA,GAAW,UAAY,MAAOA,GAAU,MAAOA,IAClEi4B,EAAmB,OAAO,OAAS,CAACj4B,EAAO,EAAGA,EAAO,CAAC,EAI1D,CAGA,SAAW,CAAC7wB,EAAKkB,CAAK,IAAK,OAAO,QAAQ4nD,CAAkB,EACtD,MAAM,QAAQ5nD,CAAK,EACrB4nD,EAAmB9oD,CAAG,EAAIkB,EAAM,IAAK8D,GAC/B,OAAOA,GAAS,UAAYA,IAAS,KAEnC,OAAQA,GAAQ,SAAUA,GAAQ,WAAYA,EACzC,KAAK,sCAAsCA,CAA2B,EAGtE,KAAK,UAAUA,CAAI,EAGvBA,CACR,EACQ9D,GAAS,OAAOA,GAAU,WAE/B,OAAQA,GAAS,SAAUA,GAAS,WAAYA,EAClD4nD,EAAmB9oD,CAAG,EAAI,KAAK,sCAAsCkB,CAA4B,EAGjG4nD,EAAmB9oD,CAAG,EAAI,KAAK,UAAUkB,CAAK,GAKpD,OAAO4nD,CACT,CAKQ,UAAUh9C,EAAe,CAC/B,GAAIA,IAAQ,MAAQ,OAAOA,GAAQ,SACjC,OAAOA,EAGT,GAAI,MAAM,QAAQA,CAAG,EACnB,OAAOA,EAAI,IAAI9G,GAAQ,KAAK,UAAUA,CAAI,CAAC,EAG7C,MAAMglD,EAA8B,CAAA,EACpC,UAAWhqD,KAAO8L,EACZA,EAAI,eAAe9L,CAAG,IACxBgqD,EAAOhqD,CAAG,EAAI,KAAK,UAAU8L,EAAI9L,CAAG,CAAC,GAIzC,OAAOgqD,CACT,CAKQ,mBAAmBxB,EAAuC,CAEhE,KAAK,oCAAoCA,CAAS,EAGlD,MAAM9wB,EAAc,CAElB,GAAI8wB,EAAU,aACd,MAAOA,EAAU,MACjB,MAAO,SAASA,EAAU,SAAS,QAAQ,IAAK,EAAE,CAAC,GAAK,EACxD,KAAMA,EAAU,UAChB,OAAQA,EAAU,YAClB,iBAAkBA,EAAU,kBAC5B,UAAWA,EAAU,UACrB,gBAAiBA,EAAU,iBAC3B,WAAYA,EAAU,WACtB,YAAaA,EAAU,YACvB,SAAUA,EAAU,SAGpB,UAAW,CACT,SAAUA,EAAU,WAAW,SAC/B,WAAYA,EAAU,WAAW,YAAcA,EAAU,WAAW,SACpE,MAAOA,EAAU,WAAW,MAE5B,KAAMA,EAAU,WAAW,KAC3B,OAAQA,EAAU,WAAW,OAC7B,SAAUA,EAAU,WAAW,SAC/B,WAAYA,EAAU,WAAW,WAEjC,QAASA,EAAU,WAAW,QAC9B,YAAaA,EAAU,WAAW,YAElC,OAAQA,EAAU,WAAW,OAC7B,MAAOA,EAAU,WAAW,MAC5B,WAAYA,EAAU,WAAW,WACjC,UAAWA,EAAU,WAAW,UAEhC,KAAMA,EAAU,WAAW,KAC3B,SAAUA,EAAU,WAAW,SAC/B,UAAWA,EAAU,WAAW,UAChC,MAAOA,EAAU,WAAW,MAC5B,QAASA,EAAU,WAAW,OAAA,EAIhC,kBAAmBA,EAAU,gBAC7B,wBAAyBA,EAAU,sBACnC,4BAA6BA,EAAU,2BACvC,oBAAqBA,EAAU,kBAC/B,UAAWA,EAAU,OACrB,eAAgBA,EAAU,YAC1B,cAAeA,EAAU,YAGzB,OAAQ,KAAK,gBAAgBA,EAAU,WAAW,EAClD,YAAa,KAAK,oBAAoBA,EAAU,WAAW,EAC3D,YAAa,KAAK,qBAAqBA,EAAU,WAAW,EAG5D,OAAQA,EAAU,QAClB,SAAUA,EAAU,UACpB,SAAUA,EAAU,UACpB,YAAaA,EAAU,cACvB,QAASA,EAAU,SACnB,UAAWA,EAAU,WACrB,UAAWA,EAAU,WACrB,OAAQA,EAAU,MAAA,EAIpB,YAAK,iBAAiB,UAAY9wB,EAAY,UAG1C8wB,EAAU,6BACZ,KAAK,iBAAiB,yBAA2BA,EAAU,4BAIzDA,EAAU,oBACZ,KAAK,iBAAiB,iBAAmBA,EAAU,mBAG9C9wB,CACT,CAKQ,mBAAmBhxB,EAAgB,CAEzC,MAAM4iD,EAAU,KAAK,iBAAiB,eAAe5iD,CAAI,EACzD,YAAK,mBAAmB,kBAAkB4iD,EAAQ,MAAM,EAGlC,KAAK,iBAAiB,aAAaA,EAAS,KAAK,gBAAgB,EAGhF9C,GAAe,kBAAkB9/C,EAAM,KAAK,iBAAkB,CACnE,WAAY,KAAK,OAAO,WACxB,UAAYyiC,IACN,KAAK,OAAO,eACd,QAAQ,KAAK,UAAUA,CAAG,EAAE,EAEvBA,EACT,CACD,CACH,CAKQ,iBAAiBziC,EAAgB,CACvC,MAAMkiD,EAAkB,CAAE,GAAGliD,CAAA,EAE7B,OAAIkiD,EAAgB,QAAU,OAAOA,EAAgB,QAAW,WAC1D,KAAK,OAAO,eACd,QAAQ,IAAI,mDAAmD,EAGjEA,EAAgB,OAAS,KAAK,oBAAoB,gBAChDA,EAAgB,OAChB,KAAK,iBACL,CACE,0BAA2B,KAAK,OAAO,0BACvC,WAAY,KAAK,OAAO,UAAA,CAC1B,EAGE,KAAK,OAAO,eACd,QAAQ,IAAI,mDAAmD,GAI5DA,CACT,CAKQ,gBAAgBliD,EAAuE,CAC7F,OAAOq/C,GAAkB,eAAer/C,EAAM,CAC5C,WAAY,KAAK,OAAO,YAAc,KAAK,OAAO,kBAAoB,QAAA,CACvE,CACH,CAKQ,YACNA,EACAujD,EACAzB,EACe,CACf,MAAMiB,EAAmB,KAAK,mBAAmB,SAAA,EAC3CG,EAAiB,KAAK,iBAAiB,WAAA,GAAgB,CAC3D,MAAO,EACP,SAAU,EACV,OAAQ,EACR,OAAQ,CAAA,CAAC,EAILv5B,EAA6B,CACjC,IAAI45B,EAAkB,eAAiB,CAAA,GAAI,IAAK5qC,IAAiB,CAC/D,KAAM27B,GAAiB,uBACvB,QAAS37B,EACT,KAAM,OAAA,EACN,EACF,IAAI4qC,EAAkB,gBAAkB,CAAA,GAAI,IAAK5qC,IAAiB,CAChE,KAAM27B,GAAiB,yBACvB,QAAS37B,EACT,KAAM,QAAA,EACN,CAAA,EAGJ,MAAO,CACL,KAAA3Y,EACA,SAAA2pB,EACA,YAAa,KAAK,OAAO,4BAA8Bo5B,EAAmB,OAC1E,eAAAG,CAAA,CAEJ,CAKQ,qBAAqBpB,EAAkC7hD,EAA2B,CAiBxF,MAAO,CACL,KAhBmB,CACnB,GAAG00C,GACH,GAAImN,GAAW,cAAgB,oBAC/B,MAAOA,GAAW,OAAS,WAC3B,UAAW,CACT,SAAUA,GAAW,YAAY,UAAY,eAC7C,WAAYA,GAAW,YAAY,YAAc,MACjD,MAAOA,GAAW,YAAY,OAAS,WACvC,KAAMA,GAAW,YAAY,MAAQ,EACrC,OAAQA,GAAW,YAAY,QAAU,EACzC,SAAUA,GAAW,YAAY,UAAY,KAC7C,WAAYA,GAAW,YAAY,YAAc,IAAA,CACnD,EAKA,SAAU,CAAC,CACT,KAAMxN,GAAiB,sBACvB,QAAS,gBAAgBr0C,aAAiB,MAAQA,EAAM,QAAUA,CAAK,GACvE,WAAY,kBAAA,CACb,EACD,eAAgB,CACd,MAAO,EACP,SAAU,EACV,OAAQ,EACR,OAAQ,CAAA,CAAC,CACX,CAEJ,CAKA,OAAO,OAAO7G,EAAiD,CAC7D,OAAO,IAAIgqD,GAAoBhqD,CAAM,CACvC,CACF,CCzwBO,SAASoqD,GACd1B,EACA1oD,EACe,CAEf,OADgB,IAAIgqD,GAAoBhqD,CAAM,EAC/B,MAAM0oD,CAAS,CAChC,CASA,eAAsB2B,GACpB3B,EACA1oD,EACwB,CAExB,OAAO,QAAQ,QAAQoqD,GAAsB1B,EAAW1oD,CAAM,CAAC,CACjE,CAaO,SAASsqD,GACd/W,EACAvzC,EACe,CACf,MAAM0oD,EAAY,OAAOnV,GAAe,WAAaA,IAAeA,EACpE,OAAO6W,GAAsB1B,EAAW1oD,CAAM,CAChD,CAKA,eAAsBuqD,GACpBhX,EACAvzC,EACwB,CACxB,MAAM0oD,EAAY,OAAOnV,GAAe,WACpC,MAAMA,IACNA,aAAsB,QACtB,MAAMA,EACNA,EAEJ,OAAO6W,GAAsB1B,EAAW1oD,CAAM,CAChD,CAaO,SAASwqD,GAAkBxqD,EAAiD,CACjF,OAAO,IAAIgqD,GAAoBhqD,CAAM,CACvC,CAKO,SAASyqD,GAAmBzqD,EAAgG,CACjI,MAAM0qD,EAAc,IAAIV,GAAoBhqD,CAAM,EAClD,MAAO,CACL,MAAQ4G,GAAgC,QAAQ,QAAQ8jD,EAAY,MAAM9jD,CAAI,CAAC,CAAA,CAEnF,CAeO,SAAS+jD,GAAqB/jD,EAAW7G,EAA2B,QAAqE,CAE9I,OAAIA,IAAS,QACJkmD,GAAkB,cAAcr/C,CAAI,EAEpCq/C,GAAkB,eAAer/C,CAAI,CAEhD,CAKO,SAASgkD,GACdvmC,EACAwmC,EACAC,EAAqB,IAC2D,CAChF,MAAMC,EAAkB,CAAA,EAExB,QAAS7+C,EAAI,EAAGA,EAAI4+C,EAAY5+C,IAAK,CACnC,MAAM8+C,EAAQ,YAAY,IAAA,EAC1B3mC,EAAQ,MAAMwmC,CAAQ,EACtB,MAAMnqC,EAAM,YAAY,IAAA,EACxBqqC,EAAM,KAAKrqC,EAAMsqC,CAAK,CACxB,CAEA,MAAMC,EAAcF,EAAM,OAAO,CAAC9lD,EAAKimD,IAASjmD,EAAMimD,EAAM,CAAC,EAAIJ,EAC3DK,EAAU,KAAK,IAAI,GAAGJ,CAAK,EAC3BK,EAAU,KAAK,IAAI,GAAGL,CAAK,EAG3BM,EAAc,QAAQ,cAAA,EAAgB,UAAY,EAExD,MAAO,CAAE,YAAAJ,EAAa,QAAAE,EAAS,QAAAC,EAAS,YAAAC,CAAA,CAC1C,CASA,MAAMC,GAAoB,CACxB,MAAO,CAAC1kD,EAA6B5G,IACnCoqD,GAAsBxjD,EAAM5G,CAAM,EACpC,WAAY,CAAC4G,EAA6B5G,IACxCqqD,GAAuBzjD,EAAM5G,CAAM,EACrC,OAASA,GAA+BwqD,GAAkBxqD,CAAM,CAClE,EAQa+kB,GAAU,QACVwmC,GAAiB,QAKvB,SAASC,GAAmBC,EAA0B,QAAkB,CAC7E,OAAOF,IAAkBE,CAC3B,CAKO,SAASC,GAAW9kD,EAAoB,CAC7C,OAAOA,GAAM,iBAAmB,SACzBA,GAAM,gBAAgB,WAAW,IAAI,CAC9C,CAKO,SAAS+kD,GAAkB/kD,EAAoB,CACpD,OAAO8kD,GAAW9kD,CAAI,IACdA,EAAK,iBACLA,EAAK,uBACJA,EAAK,YAAY,OACjB,CAAC,WAAY,iBAAkB,iBAAkB,kBAChD,YAAa,gBAAiB,YAAa,SAAU,SAAA,EAAW,SAASA,EAAK,WAAW,KAAK,EAC1G,CCvBO,MAAMglD,WAA8B,KAAM,CAC/C,YACEr6C,EACgBs6C,EACA15C,EACA25C,EAChB,CACA,MAAM,iCAAiCD,CAAS,KAAKt6C,CAAO,EAAE,EAJ9C,KAAA,UAAAs6C,EACA,KAAA,QAAA15C,EACA,KAAA,WAAA25C,EAGhB,KAAK,KAAO,uBACd,CACF,CC5KO,SAASC,GAAgC/rD,EAAqC,CACnF,MAAMswB,EAAkC,CAAA,EAClC07B,EAA+B,CAAA,EA+BrC,GA5BKhsD,EAAO,QACVswB,EAAO,KAAK27B,EACV,iBACA,SACA,WACA,MAAA,CACD,EAGEjsD,EAAO,WACVswB,EAAO,KAAK27B,EACV,oBACA,SACA,cACA,MAAA,CACD,EAGEjsD,EAAO,UACVswB,EAAO,KAAK27B,EACV,oBACA,SACA,aACA,MAAA,CACD,EAIC37B,EAAO,OAAS,EAClB,MAAO,CACL,QAAS,GACT,OAAAA,EACA,MAAO47B,GAAuB57B,CAAM,EACpC,UAAW,IAAI,KAAA,EAAO,YAAA,CAAY,EAKlCtwB,EAAO,QACTswB,EAAO,KAAK,GAAG67B,GAAensD,EAAO,MAAM,CAAC,EAK9C,IAAIosD,EAA4B,GAChC,GAAIpsD,EAAO,QAAQ,UACjB,UAAW8uB,KAAS9uB,EAAO,OAAO,SAChC,GAAI8uB,EAAM,UAAW,CACnBs9B,EAA4B,GAC5B,KACF,EAKJ,OAAIpsD,EAAO,UACTswB,EAAO,KAAK,GAAG+7B,GAAkBrsD,EAAO,SAAS,CAAC,EACxCosD,GAEV97B,EAAO,KAAK27B,EACV,oBACA,qCACA,cACA,OACA,CAAE,KAAM,UAAA,CAAW,CACpB,EAIH37B,EAAO,KAAK,GAAGg8B,GAAsBtsD,CAAM,CAAC,EAG5CswB,EAAO,KAAK,GAAGi8B,GAAwBvsD,CAAM,CAAC,EAG9CswB,EAAO,KAAK,GAAGk8B,GAA4BxsD,CAAM,CAAC,EAG9CswB,EAAO,OAAS,GAClB07B,EAAM,KAAK,GAAGE,GAAuB57B,CAAM,CAAC,EAGvC,CACL,QAASA,EAAO,SAAW,EAC3B,OAAAA,EACA,MAAA07B,EACA,UAAW,IAAI,KAAA,EAAO,YAAA,CAAY,CAEtC,CAmBO,SAASS,GAAuB5+B,EAAyB,CAW9D,GAVI,CAACA,GAAa,OAAOA,GAAc,UAKnC,CAACA,EAAU,MAAQ,OAAOA,EAAU,MAAS,UAK7C,CADwB,CAAC,WAAY,cAAe,QAAS,WAAW,EACnD,SAASA,EAAU,IAAI,EAC9C,MAAO,GAIT,OAAQA,EAAU,KAAA,CAChB,IAAK,WACH,GAAI,CAACA,EAAU,QAAU,OAAOA,EAAU,QAAW,SACnD,MAAO,GAGT,MAAMkD,EAASlD,EAAU,OAAO,OAUhC,GATIkD,IAAW,SAAW,CAAC,MAAM,QAAQA,CAAM,GAAKA,EAAO,SAAW,IAIlE,OAAOlD,EAAU,OAAO,YAAe,UACvC,OAAOA,EAAU,OAAO,UAAa,UAIrCA,EAAU,OAAO,YAAc,aAC/BA,EAAU,OAAO,YAAc,oBAC/BA,EAAU,OAAO,YAAc,cAC/BA,EAAU,OAAO,YAAc,WACjC,MAAO,GAET,MAEF,IAAK,cACH,GAAI,CAACA,EAAU,QAAU,OAAOA,EAAU,QAAW,SACnD,MAAO,GAGT,MAAMsD,EAAYtD,EAAU,OAAO,UACnC,GAAI,MAAM,QAAQsD,CAAS,GAKzB,GAHIA,EAAU,SAAW,GAGrB,OAAOA,EAAU,CAAC,GAAM,UAAY,OAAOA,EAAU,CAAC,GAAM,SAC9D,MAAO,WAEA,OAAOA,GAAc,UAE9B,GAAIA,IAAc,cAAgBA,IAAc,WAC9C,MAAO,OAIT,OAAO,GAGT,GAAI,OAAOtD,EAAU,OAAO,UAAa,UACrCA,EAAU,OAAO,UAAY,EAC/B,MAAO,GAET,MAEF,IAAK,QACH,GAAI,CAACA,EAAU,QAAU,OAAOA,EAAU,QAAW,SACnD,MAAO,GAGT,MAAM6+B,EAAc7+B,EAAU,OAAO,OAUrC,GATI6+B,IAAgB,aAAe,CAAC,MAAM,QAAQA,CAAW,GAAKA,EAAY,SAAW,IAIrF,OAAO7+B,EAAU,OAAO,YAAe,UACvC,OAAOA,EAAU,OAAO,UAAa,UAIrC,OAAOA,EAAU,OAAO,SAAY,UACtC,MAAO,GAET,MAEF,IAAK,YAEH,GAAI,CAACA,EAAU,YAAc,CAAC,MAAM,QAAQA,EAAU,UAAU,EAC9D,MAAO,GAGT,UAAW8+B,KAAgB9+B,EAAU,WACnC,GAAI,CAAC4+B,GAAuBE,CAAY,EACtC,MAAO,GAIX,GAAI9+B,EAAU,gBAAkB,QAC1BA,EAAU,gBAAkB,cAAgBA,EAAU,gBAAkB,WAC1E,MAAO,GAGX,KAAA,CAGJ,MAAO,EACT,CAQA,SAASS,GAA8BT,EAAgBhc,EAAuC,CAC5F,MAAMye,EAAkC,CAAA,EAExC,GAAI,CAACzC,GAAa,OAAOA,GAAc,SACrC,OAAAyC,EAAO,KAAK27B,EACV,2BACA,YACAp6C,EACAgc,EACA,CAAE,KAAM,UAAA,CAAW,CACpB,EACMyC,GAIL,CAACzC,EAAU,MAAQ,OAAOA,EAAU,MAAS,WAC/CyC,EAAO,KAAK27B,EACV,2BACA,YACA,GAAGp6C,CAAI,QACPgc,EAAU,KACV,UAAA,CACD,EAGH,MAAM++B,EAAsB,CAAC,WAAY,cAAe,QAAS,WAAW,EAY5E,OAXI/+B,EAAU,MAAQ,CAAC++B,EAAoB,SAAS/+B,EAAU,IAAI,GAChEyC,EAAO,KAAK27B,EACV,2BACA,YAAYp+B,EAAU,IAAI,GAC1B,GAAGhc,CAAI,QACPgc,EAAU,KACV,UAAA,CACD,EAIKA,EAAU,KAAA,CAChB,IAAK,WACH,GAAI,CAACA,EAAU,QAAU,OAAOA,EAAU,QAAW,SACnDyC,EAAO,KAAK27B,EACV,2BACA,WACA,GAAGp6C,CAAI,UACPgc,EAAU,OACV,CAAE,OAAQ,CAAC,EAAG,CAAC,EAAG,WAAY,EAAG,SAAU,KAAK,GAAI,UAAW,WAAA,CAAY,CAC5E,MACI,CAEL,MAAMkD,EAASlD,EAAU,OAAO,OAC5BkD,IAAW,SAAW,CAAC,MAAM,QAAQA,CAAM,GAAKA,EAAO,SAAW,IACpET,EAAO,KAAK27B,EACV,2BACA,8BACA,GAAGp6C,CAAI,iBACPgc,EAAU,OAAO,OACjB,CAAC,EAAG,CAAC,CAAA,CACN,GAGC,OAAOA,EAAU,OAAO,YAAe,UACvC,OAAOA,EAAU,OAAO,UAAa,WACvCyC,EAAO,KAAK27B,EACV,2BACA,mBACA,GAAGp6C,CAAI,qBACPgc,EAAU,OACV,CAAE,WAAY,EAAG,SAAU,KAAK,EAAA,CAAG,CACpC,EAGCA,EAAU,OAAO,YAAc,aAC/BA,EAAU,OAAO,YAAc,oBAC/BA,EAAU,OAAO,YAAc,cAC/BA,EAAU,OAAO,YAAc,YACjCyC,EAAO,KAAK27B,EACV,2BACA,2DACA,GAAGp6C,CAAI,oBACPgc,EAAU,OAAO,UACjB,WAAA,CACD,CAEL,CACA,MAEF,IAAK,cACH,GAAI,CAACA,EAAU,QAAU,OAAOA,EAAU,QAAW,SACnDyC,EAAO,KAAK27B,EACV,2BACA,WACA,GAAGp6C,CAAI,UACPgc,EAAU,OACV,CAAE,UAAW,aAAc,SAAU,CAAA,CAAE,CACxC,MACI,CAEL,MAAMsD,EAAYtD,EAAU,OAAO,UAC/B,MAAM,QAAQsD,CAAS,EAErBA,EAAU,SAAW,EACvBb,EAAO,KAAK27B,EACV,2BACA,iBACA,GAAGp6C,CAAI,oBACPsf,EACA,CAAC,EAAG,CAAC,CAAA,CACN,GACQ,OAAOA,EAAU,CAAC,GAAM,UAAY,OAAOA,EAAU,CAAC,GAAM,WACrEb,EAAO,KAAK27B,EACV,2BACA,eACA,GAAGp6C,CAAI,oBACPsf,EACA,CAAC,EAAG,CAAC,CAAA,CACN,EAEM,OAAOA,GAAc,SAE1BA,IAAc,cAAgBA,IAAc,YAC9Cb,EAAO,KAAK27B,EACV,2BACA,gCACA,GAAGp6C,CAAI,oBACPsf,EACA,YAAA,CACD,EAIHb,EAAO,KAAK27B,EACV,2BACA,sDACA,GAAGp6C,CAAI,oBACPsf,EACA,YAAA,CACD,GAGC,OAAOtD,EAAU,OAAO,UAAa,UACrCA,EAAU,OAAO,UAAY,IAC/ByC,EAAO,KAAK27B,EACV,2BACA,gBACA,GAAGp6C,CAAI,mBACPgc,EAAU,OAAO,SACjB,CAAA,CACD,CAEL,CACA,MAEF,IAAK,QACH,GAAI,CAACA,EAAU,QAAU,OAAOA,EAAU,QAAW,SACnDyC,EAAO,KAAK27B,EACV,2BACA,WACA,GAAGp6C,CAAI,UACPgc,EAAU,OACV,CAAE,OAAQ,WAAY,WAAY,EAAG,SAAU,EAAG,QAAS,EAAA,CAAK,CACjE,MACI,CAEL,MAAM6+B,EAAc7+B,EAAU,OAAO,OACjC6+B,IAAgB,aAAe,CAAC,MAAM,QAAQA,CAAW,GAAKA,EAAY,SAAW,IACvFp8B,EAAO,KAAK27B,EACV,2BACA,kCACA,GAAGp6C,CAAI,iBACPgc,EAAU,OAAO,OACjB,UAAA,CACD,GAGC,OAAOA,EAAU,OAAO,YAAe,UACvC,OAAOA,EAAU,OAAO,UAAa,WACvCyC,EAAO,KAAK27B,EACV,2BACA,mBACA,GAAGp6C,CAAI,qBACPgc,EAAU,OACV,CAAE,WAAY,EAAG,SAAU,CAAA,CAAE,CAC9B,EAGC,OAAOA,EAAU,OAAO,SAAY,WACtCyC,EAAO,KAAK27B,EACV,2BACA,oBACA,GAAGp6C,CAAI,kBACPgc,EAAU,OAAO,QACjB,EAAA,CACD,CAEL,CACA,MAEF,IAAK,YAEH,GAAI,CAACA,EAAU,YAAc,CAAC,MAAM,QAAQA,EAAU,UAAU,EAC9DyC,EAAO,KAAK27B,EACV,2BACA,wBACA,GAAGp6C,CAAI,cACPgc,EAAU,WACV,CAAA,CAAC,CACF,MAGD,SAAS3hB,EAAI,EAAGA,EAAI2hB,EAAU,WAAW,OAAQ3hB,IAAK,CACpD,MAAM2gD,EAAYv+B,GAChBT,EAAU,WAAW3hB,CAAC,EACtB,GAAG2F,CAAI,eAAe3F,CAAC,GAAA,EAEzBokB,EAAO,KAAK,GAAGu8B,CAAS,CAC1B,CAGEh/B,EAAU,gBAAkB,QAC1BA,EAAU,gBAAkB,cAAgBA,EAAU,gBAAkB,YAC1EyC,EAAO,KAAK27B,EACV,2BACA,oCACA,GAAGp6C,CAAI,iBACPgc,EAAU,cACV,YAAA,CACD,EAGL,KAAA,CAGJ,OAAOyC,CACT,CAmHO,SAAS27B,EACd/6C,EACAK,EACAM,EACAzQ,EACA0rD,EACuB,CAEvB,IAAIC,EAAsBD,EAC1B,GAAIA,IAAmB,OACrB,OAAQ57C,EAAA,CACN,IAAK,wBACH67C,EAAsB,iBACtB,MACF,IAAK,qBACL,IAAK,uBACHA,EAAsB,EACtB,MACF,IAAK,iBACHA,EAAsB,EACtB,MACF,IAAK,iBACHA,EAAsB,CAAE,OAAQ,GAAI,SAAU,CAAA,CAAC,EAC/C,MACF,IAAK,oBACHA,EAAsB,CAAE,KAAM,UAAA,EAC9B,MACF,IAAK,oBACHA,EAAsB,kBACtB,MACF,IAAK,gBACHA,EAAsB,KACtB,MACF,QACEA,EAAsB,MAAA,CAI5B,MAAO,CACL,KAAA77C,EACA,QAAAK,EACA,KAAAM,EACA,MAAAzQ,EACA,eAAgB2rD,CAAA,CAEpB,CAqHA,SAASZ,GAAev9B,EAAsC,CAC5D,MAAM0B,EAAkC,CAAA,EAExC,GAAI,CAAC1B,GAAU,OAAOA,GAAW,SAC/B,OAAA0B,EAAO,KAAK27B,EACV,iBACA,YACA,WACAr9B,CAAA,CACD,EACM0B,EAIT,GAAI,CAAC,MAAM,QAAQ1B,EAAO,MAAM,EAC9B0B,EAAO,KAAK27B,EACV,yBACA,YACA,kBACAr9B,EAAO,MAAA,CACR,MAGD,SAAS1iB,EAAI,EAAGA,EAAI0iB,EAAO,OAAO,OAAQ1iB,IAAK,CAC7C,MAAM4iB,EAAQF,EAAO,OAAO1iB,CAAC,EACvB8gD,EAAcC,GAAoBn+B,EAAO,mBAAmB5iB,CAAC,GAAG,EACtEokB,EAAO,KAAK,GAAG08B,CAAW,CAC5B,CAIF,GAAI,CAAC,MAAM,QAAQp+B,EAAO,QAAQ,EAChC0B,EAAO,KAAK27B,EACV,yBACA,YACA,oBACAr9B,EAAO,QAAA,CACR,MAGD,SAAS1iB,EAAI,EAAGA,EAAI0iB,EAAO,SAAS,OAAQ1iB,IAAK,CAC/C,MAAM4iB,EAAQF,EAAO,SAAS1iB,CAAC,EACzB8gD,EAAcC,GAAoBn+B,EAAO,qBAAqB5iB,CAAC,GAAG,EACxEokB,EAAO,KAAK,GAAG08B,CAAW,CAC5B,CAGF,OAAO18B,CACT,CAKA,SAAS28B,GAAoBn+B,EAAYjd,EAAuC,CAC9E,MAAMye,EAAkC,CAAA,EAExC,GAAI,CAACxB,GAAS,OAAOA,GAAU,SAC7B,OAAAwB,EAAO,KAAK27B,EACV,yBACA,YACAp6C,EACAid,CAAA,CACD,EACMwB,EAcT,IAVI,CAACxB,EAAM,MAAQ,OAAOA,EAAM,MAAS,WACvCwB,EAAO,KAAK27B,EACV,yBACA,YACA,GAAGp6C,CAAI,QACPid,EAAM,IAAA,CACP,EAIC,CAAC,MAAM,QAAQA,EAAM,QAAQ,EAC/BwB,EAAO,KAAK27B,EACV,yBACA,YACA,GAAGp6C,CAAI,YACPid,EAAM,QAAA,CACP,UACQA,EAAM,SAAS,SAAW,EACnCwB,EAAO,KAAK27B,EACV,yBACA,aACA,GAAGp6C,CAAI,YACPid,EAAM,QAAA,CACP,MAGD,SAAS5iB,EAAI,EAAGA,EAAI4iB,EAAM,SAAS,OAAQ5iB,IAAK,CAC9C,MAAM+iB,EAASH,EAAM,SAAS5iB,CAAC,EAC3B,CAAC,MAAM,QAAQ+iB,CAAM,GAAKA,EAAO,SAAW,EAC9CqB,EAAO,KAAK27B,EACV,yBACA,MAAM//C,CAAC,gBACP,GAAG2F,CAAI,aAAa3F,CAAC,IACrB+iB,CAAA,CACD,GACQ,OAAOA,EAAO,CAAC,GAAM,UAAY,OAAOA,EAAO,CAAC,GAAM,WAC/DqB,EAAO,KAAK27B,EACV,yBACA,MAAM//C,CAAC,UACP,GAAG2F,CAAI,aAAa3F,CAAC,IACrB+iB,CAAA,CACD,CAEL,CAIF,GAAIH,EAAM,YAAc,OAAW,CACjC,MAAMo+B,EAAkB5+B,GAA8BQ,EAAM,UAAW,GAAGjd,CAAI,YAAY,EAC1Fye,EAAO,KAAK,GAAG48B,CAAe,CAChC,CAEA,OAAO58B,CACT,CAQA,SAAS+7B,GAAkBx+B,EAAyC,CAClE,MAAMyC,EAAkC,CAAA,EAExC,GAAI,CAACzC,EACH,OAAAyC,EAAO,KAAK27B,EACV,oBACA,SACA,cACAp+B,CAAA,CACD,EACMyC,EAIT,MAAMnmB,EAAU,MAAM,QAAQ0jB,CAAS,EACjCgI,EAAa1rB,EAAU0jB,EAAY,CAACA,CAAS,EAC7Cs/B,EAAqB,cAE3B,QAASjhD,EAAI,EAAGA,EAAI2pB,EAAW,OAAQ3pB,IAAK,CAC1C,MAAMkhD,EAAmBv3B,EAAW3pB,CAAC,EAC/BmhD,EAAcljD,EAAU,GAAGgjD,CAAQ,IAAIjhD,CAAC,IAAMihD,EAE/CV,GAAuBW,CAAgB,GAC1C98B,EAAO,KAAK27B,EACV,2BACA,SACAoB,EACAD,CAAA,CACD,CAEL,CAEA,OAAO98B,CACT,CAQA,SAASg8B,GAAsBtsD,EAAiE,CAC9F,MAAMswB,EAAkC,CAAA,EAExC,GAAI,CAACtwB,EAAO,SACV,OAAOswB,EAGT,KAAM,CAAE,SAAAmG,GAAaz2B,EAGrB,IAAIstD,EAAiB,EAkBrB,GAfIttD,EAAO,YACL,MAAM,QAAQA,EAAO,SAAS,EAChCstD,GAAkBttD,EAAO,UAAU,OAC1B,OAAOA,EAAO,WAAc,WAEjCA,EAAO,WAAa,OAAOA,EAAO,WAAc,UAAY,eAAgBA,EAAO,UACrFstD,GAAmBttD,EAAO,UAAkB,WAAW,OAGvDstD,GAAkB,IAMpBttD,EAAO,QAAQ,SACjB,UAAW8uB,KAAS9uB,EAAO,OAAO,SAC5B8uB,EAAM,YACRw+B,GAAkB,GAMxB,OAAI72B,EAAS,SAAS,QAAQ,GAAK62B,IAAmB,GACpDh9B,EAAO,KAAK27B,EACV,oBACA,mBAAmBqB,CAAc,KACjC,aACA72B,EACA62B,IAAmB,EAAI,kBAAoB,iBAAA,CAC5C,EAGC72B,EAAS,SAAS,QAAQ,GAAK62B,IAAmB,GACpDh9B,EAAO,KAAK27B,EACV,oBACA,mBAAmBqB,CAAc,KACjC,aACA72B,EACA62B,IAAmB,EAAI,kBAAoB,iBAAA,CAC5C,EAIqB,CAAC,kBAAmB,kBAAmB,gBAAiB,iBAAkB,+BAAgC,gBAAgB,EAC7H,SAAS72B,CAAQ,GACpCnG,EAAO,KAAK27B,EACV,oBACA,YAAYx1B,CAAQ,GACpB,aACAA,EACA,iBAAA,CACD,EAGInG,CACT,CAQA,SAASi8B,GAAwBvsD,EAAiE,CAChG,MAAMswB,EAAkC,CAAA,EA4ExC,GAzEItwB,EAAO,MAAQ,OAAOA,EAAO,MAAS,UACxCswB,EAAO,KAAK27B,EACV,gBACA,WACA,SACAjsD,EAAO,KACP,IAAA,CACD,EAICA,EAAO,UAAY,OAAOA,EAAO,UAAa,UAChDswB,EAAO,KAAK27B,EACV,gBACA,aACA,aACAjsD,EAAO,SACPA,EAAO,MAAQ,IAAA,CAChB,EAGCA,EAAO,YAAc,OAAOA,EAAO,YAAe,UACpDswB,EAAO,KAAK27B,EACV,gBACA,aACA,eACAjsD,EAAO,WACPA,EAAO,MAAQ,IAAA,CAChB,EAICA,EAAO,MAAQA,EAAO,UAAYA,EAAO,WAAaA,EAAO,MAC/DswB,EAAO,KAAK27B,EACV,gBACA,SAASjsD,EAAO,QAAQ,WAAWA,EAAO,IAAI,QAC9C,aACAA,EAAO,SACPA,EAAO,IAAA,CACR,EAGCA,EAAO,MAAQA,EAAO,YAAcA,EAAO,aAAeA,EAAO,MACnEswB,EAAO,KAAK27B,EACV,gBACA,SAASjsD,EAAO,UAAU,WAAWA,EAAO,IAAI,QAChD,eACAA,EAAO,WACPA,EAAO,IAAA,CACR,EAwBCA,EAAO,MAAQA,EAAO,aAAeA,EAAO,YAAY,YAAa,CACvE,KAAM,CAACwyB,EAAMG,EAAMF,EAAMC,CAAI,EAAI1yB,EAAO,YAAY,YAC9Ck7B,EAAYzI,EAAOD,EACnB2I,EAAaxI,EAAOD,EAGpB66B,EAAiBvtD,EAAO,OAAS,KAAO,GAAK,IAC/Ck7B,EAAYqyB,EAAiB,GAAKpyB,EAAaoyB,EAAiB,IAClEj9B,EAAO,KAAK27B,EACV,gBACA,SAAS/wB,EAAU,QAAQ,CAAC,CAAC,IAAIC,EAAW,QAAQ,CAAC,CAAC,QAAQn7B,EAAO,IAAI,OACzE,4BACAA,EAAO,YAAY,YACnB,MAAA,CACD,CAEL,CAEA,OAAOswB,CACT,CAQA,SAASk8B,GAA4BxsD,EAAiE,CACpG,MAAMswB,EAAkC,CAAA,EAGxC,GAAItwB,EAAO,QAAUA,EAAO,aAAeA,EAAO,YAAY,YAAa,CACzE,MAAMi7B,EAAOj7B,EAAO,YAAY,YAC1B,CAACwyB,EAAMG,EAAMF,EAAMC,CAAI,EAAIuI,EAG3BuyB,EAAY,CAChB,GAAIxtD,EAAO,OAAO,QAAU,CAAA,EAC5B,GAAIA,EAAO,OAAO,UAAY,CAAA,CAAC,EAGjC,QAASkM,EAAI,EAAGA,EAAIshD,EAAU,OAAQthD,IAAK,CACzC,MAAM4iB,EAAQ0+B,EAAUthD,CAAC,EACzB,GAAI4iB,GAASA,EAAM,SACjB,QAAS2+B,EAAI,EAAGA,EAAI3+B,EAAM,SAAS,OAAQ2+B,IAAK,CAC9C,MAAMx+B,EAASH,EAAM,SAAS2+B,CAAC,EAC/B,GAAI,MAAM,QAAQx+B,CAAM,GAAKA,EAAO,SAAW,EAAG,CAChD,KAAM,CAACb,EAAGC,CAAC,EAAIY,GACXb,EAAIoE,GAAQpE,EAAIqE,GAAQpE,EAAIqE,GAAQrE,EAAIsE,IAC1CrC,EAAO,KAAK27B,EACV,yBACA,MAAM//C,CAAC,QAAQuhD,CAAC,KAAKr/B,CAAC,KAAKC,CAAC,WAC5B,YAAYniB,GAAKlM,EAAO,OAAO,QAAQ,QAAU,GAAK,SAAW,UAAU,IAAIkM,CAAC,cAAcuhD,CAAC,IAC/Fx+B,EACA,CAAC,KAAK,IAAIuD,EAAM,KAAK,IAAIpE,EAAGqE,CAAI,CAAC,EAAG,KAAK,IAAIC,EAAM,KAAK,IAAIrE,EAAGsE,CAAI,CAAC,CAAC,CAAA,CACtE,CAEL,CACF,CAEJ,CACF,CAGA,GAAI3yB,EAAO,UAAYA,EAAO,SAAS,MAAQA,EAAO,SAAS,OAAQ,CACrE,MAAM0tD,EAAe,GAAM1tD,EAAO,SAAS,KAAOA,EAAO,SAAS,OAGlE,GAAIA,EAAO,QAAQ,SAAS,CAAC,GAAG,SAAU,CACxC,MAAMiuB,EAAWjuB,EAAO,OAAO,OAAO,CAAC,EAAE,SACzC,GAAIiuB,EAAS,SAAW,EAAG,CAEzB,KAAM,CAAC0/B,EAAIC,CAAE,EAAI3/B,EAAS,CAAC,EACrB,CAACsiB,EAAIC,CAAE,EAAIviB,EAAS,CAAC,EACrB,CAAC4/B,EAAIC,CAAE,EAAI7/B,EAAS,CAAC,EACrB8/B,EAAiB,GAAM,KAAK,KAC/Bxd,EAAKod,IAAOG,EAAKF,IAAOC,EAAKF,IAAOnd,EAAKod,EAAA,EAKxC,KAAK,IAAIG,EAAiBL,CAAY,EADxB,KAEhBp9B,EAAO,KAAK27B,EACV,yBACA,SAAS8B,EAAe,QAAQ,CAAC,CAAC,YAAYL,EAAa,QAAQ,CAAC,CAAC,QACrE,aACA,CAAE,KAAM1tD,EAAO,SAAS,KAAM,OAAQA,EAAO,SAAS,OAAQ,eAAA+tD,EAAgB,aAAAL,CAAA,CAAa,CAC5F,CAEL,CACF,CACF,CAEA,OAAOp9B,CACT,CAQA,SAAS47B,GAAuB57B,EAAwD,CACtF,MAAM07B,EAA+B,CAAA,EAErC,UAAWnlD,KAASypB,EAClB,OAAQzpB,EAAM,KAAA,CACZ,IAAK,wBACHmlD,EAAM,KAAK,CACT,OAAQ,UACR,KAAMnlD,EAAM,KACZ,MAAOA,EAAM,gBAAkB,iBAC/B,YAAa,cAAcA,EAAM,gBAAkB,gBAAgB,GACnE,OAAQ,EAAA,CACT,EACD,MAEF,IAAK,qBACHmlD,EAAM,KAAK,CACT,OAAQ,UACR,KAAMnlD,EAAM,KACZ,MAAOA,EAAM,gBAAkB,EAC/B,YAAa,aAAaA,EAAM,gBAAkB,CAAC,GACnD,OAAQ,EAAA,CACT,EACD,MAEF,IAAK,uBACHmlD,EAAM,KAAK,CACT,OAAQ,UACR,KAAMnlD,EAAM,KACZ,MAAOA,EAAM,gBAAkB,EAC/B,YAAa,WAAWA,EAAM,gBAAkB,CAAC,GACjD,OAAQ,EAAA,CACT,EACD,MAEF,IAAK,iBACHmlD,EAAM,KAAK,CACT,OAAQ,UACR,KAAMnlD,EAAM,KACZ,MAAOA,EAAM,gBAAkB,EAC/B,YAAa,aAAaA,EAAM,gBAAkB,CAAC,GACnD,OAAQ,EAAA,CACT,EACD,MAEF,IAAK,oBACHmlD,EAAM,KAAK,CACT,OAAQ,MACR,KAAMnlD,EAAM,KACZ,MAAO,CAAE,KAAM,UAAA,EACf,YAAa,aACb,OAAQ,EAAA,CACT,EACD,MAEF,QAEMA,EAAM,iBAAmB,QAC3BmlD,EAAM,KAAK,CACT,OAAQ,UACR,KAAMnlD,EAAM,KACZ,MAAOA,EAAM,eACb,YAAa,MAAMA,EAAM,IAAI,MAC7B,OAAQ,EAAA,CACT,CACH,CAIN,OAAOmlD,CACT,CCpsCO,SAASgC,GAA4B77C,EAAqE,CAE/G,GAAI,CAAC87C,GAAkC97C,CAAO,EAC5C,MAAM,IAAIy5C,GACR,uCACA,gBACAz5C,CAAA,EAIJ,KAAM,CAAE,KAAAwc,EAAM,OAAAlD,EAAQ,KAAAplB,EAAO,KAAM,cAAAgzB,EAAgB,UAAW,MAAAE,EAAQ,OAAA,EAAYpnB,EAC5E+7C,EAAU/7C,EAAQ,SAAW,EAC7Bg8C,EAAUh8C,EAAQ,SAAW,EAC7Bi8C,EAAOj8C,EAAQ,MAAQwc,EAAO,EAEpC,GAAI,CAEF,MAAMC,EAASy/B,GAA4B1/B,EAAMlD,EAAQ2iC,EAAMF,EAASC,EAAS50B,CAAK,EAChF1L,EAAYygC,GAA6B3/B,CAAI,EAC7CW,EAAYi/B,GAAwBl1B,CAAa,EACjD5J,EAAc++B,GAAoB7/B,EAAMlD,EAAQ2iC,EAAMF,EAASC,CAAO,EAG5E,MAAO,CACL,GAAI,CACF,cAAA90B,CAAA,EAEF,KAAA1K,EACA,OAAAlD,EACA,KAAAplB,EACA,OAAAuoB,EACA,UAAAf,EACA,UAAAyB,EACA,YAAAG,EACA,SAAU,gBACV,MAAA8J,EACA,2BAA4B,GAC5B,yBAA0B,GAC1B,sBAAuB,IACvB,SAAU,CACR,aAAc,iBACd,KAAA5K,EACA,OAAAlD,EACA,KAAAplB,EACA,QAAA6nD,EACA,QAAAC,EACA,SAAU,gBACV,YAAa,IAAI,KAAA,EAAO,YAAA,CAAY,CACtC,CAEJ,OAAStnD,EAAO,CAEd,GAAIA,aAAiB+kD,GACnB,MAAM/kD,EAGR,MAAMsoB,EAAetoB,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EAC1E,MAAM,IAAI+kD,GACRz8B,EACA,gBACAhd,EACAtL,aAAiB,MAAQA,EAAQ,MAAA,CAErC,CACF,CAQO,SAASonD,GAAkC97C,EAAuB,CAEvE,GAAI,CAACA,GAAW,OAAOA,GAAY,SACjC,MAAO,GAIT,MAAMutC,EAAiB,CAAC,OAAQ,QAAQ,EACxC,UAAW5oB,KAAS4oB,EAClB,GAAI,EAAE5oB,KAAS3kB,GACb,MAAO,GAmBX,MAdI,SAAOA,EAAQ,MAAS,UAAYA,EAAQ,MAAQ,GACpD,OAAOA,EAAQ,QAAW,UAAYA,EAAQ,QAAU,GAKxDA,EAAQ,OAAS,SAAc,OAAOA,EAAQ,MAAS,UAAYA,EAAQ,KAAO,IAKlFA,EAAQ,UAAY,SAAc,OAAOA,EAAQ,SAAY,UAAY,CAAC,SAASA,EAAQ,OAAO,IAGlGA,EAAQ,UAAY,SAAc,OAAOA,EAAQ,SAAY,UAAY,CAAC,SAASA,EAAQ,OAAO,GAKxG,CAKA,SAASk8C,GACP1/B,EACAlD,EACA2iC,EACAF,EACAC,EACA50B,EACK,CAmBL,MAAMyS,EAhBAzS,IAAU,OACL,CACL,WAAY,UACZ,aAAc,UACd,aAAc,UACd,eAAgB,SAAA,EAGb,CACL,WAAY,UACZ,aAAc,UACd,aAAc,UACd,eAAgB,SAAA,EAQdk1B,EAAoB,CACxB,CAACP,EAAUE,EAAMD,CAAO,EACxB,CAACD,EAAUv/B,EAAMw/B,CAAO,EACxB,CAACD,EAAUv/B,EAAOy/B,EAAMD,EAAU1iC,CAAM,EACxC,CAACyiC,EAAUE,EAAMD,EAAU1iC,CAAM,CAAA,EAI7BijC,EAAmB,CACvB,CAACR,EAASC,CAAO,EACjB,CAACD,EAAUE,EAAMD,CAAO,EACxB,CAACD,EAAUE,EAAMD,EAAU1iC,CAAM,CAAA,EAGnC,MAAO,CACL,OAAQ,CACN,CACE,KAAM,YACN,SAAUgjC,EACV,MAAO,CACL,UAAWziB,EAAO,WAClB,YAAa,GACb,YAAaA,EAAO,aACpB,YAAa,CAAA,EAEf,SAAU,CACR,GAAI,mBACJ,MAAO,OACP,SAAU,EAAA,CACZ,CACF,EAEF,SAAU,CACR,CACE,KAAM,WACN,SAAU0iB,EACV,MAAO,CACL,UAAW1iB,EAAO,aAClB,YAAa,GACb,YAAaA,EAAO,eACpB,YAAa,CAAA,EAEf,SAAU,CACR,GAAI,oBACJ,MAAO,QACP,UAAW,EAAA,CACb,CACF,CACF,CAEJ,CAKA,SAASsiB,GAA6B3/B,EAAmB,CACvD,MAAO,CACL,KAAM,cACN,OAAQ,CACN,UAAW,CAAC,EAAG,CAAC,EAChB,SAAUA,CAAA,CACZ,CAEJ,CAKA,SAAS4/B,GAAwBl1B,EAA2C,CAI1E,MAAO,CACL,OAAQ,CACN,SAJmBA,IAAkB,UAAY,CAAC,EAAG,EAAE,EAAI,CAAC,EAAG,EAAE,EAKjE,OAAQ,GACR,YAAa,aACb,IAAK,EACL,IAAK,EACL,KAAM,GAAA,EAER,kBAAmB,CACjB,QAAS,EAAA,CACX,CAEJ,CAKA,SAASm1B,GACP7/B,EACAlD,EACA2iC,EACAF,EACAC,EACK,CAEL,MAAM37B,EAAO,KAAK,IAAI07B,EAASA,EAAUE,EAAMF,EAAUv/B,EAAMu/B,EAAUv/B,EAAOy/B,CAAI,EAC9E37B,EAAO,KAAK,IAAIy7B,EAASA,EAAUE,EAAMF,EAAUv/B,EAAMu/B,EAAUv/B,EAAOy/B,CAAI,EAC9E17B,EAAO,KAAK,IAAIy7B,EAASA,EAAU1iC,CAAM,EACzCkH,EAAO,KAAK,IAAIw7B,EAASA,EAAU1iC,CAAM,EAGzCge,EAAS,EAQf,MAAO,CACL,YARoD,CACpDjX,EAAOiX,EACP9W,EAAO8W,EACPhX,EAAOgX,EACP/W,EAAO+W,CAAA,EAKP,gBAAiB,GACjB,SAAU,GACV,SAAU,EAAA,CAEd,CC/PO,SAASklB,GAAqBC,EAAe,CAClD,MAAO,CAEL,GAAIA,EAAS,IAAMA,EAAS,aAC5B,MAAOA,EAAS,OAAS,GAGzB,MAAOA,EAAS,OAAS,EACzB,KAAMA,EAAS,MAAQA,EAAS,WAAa,GAC7C,OAAQA,EAAS,QAAUA,EAAS,aAAe,GACnD,MAAOA,EAAS,OAASA,EAAS,mBAAqB,GACvD,UAAWA,EAAS,WAAa,GAGjC,gBAAiB,MAAM,QAAQA,EAAS,gBAAgB,EACpDA,EAAS,iBACT,MAAM,QAAQA,EAAS,eAAe,EACtCA,EAAS,gBACT,CAAA,EAEJ,WAAYA,EAAS,YAAc,EACnC,YAAaA,EAAS,aAAe,GAGrC,SAAUA,EAAS,UAAY,CAC7B,MAAO,GACP,MAAO,GACP,KAAM,CAAA,CAAC,EAIT,aAAcA,EAAS,aACvB,SAAUA,EAAS,SACnB,QAASA,EAAS,QAClB,UAAWA,EAAS,UACpB,UAAWA,EAAS,UACpB,cAAeA,EAAS,cACxB,SAAUA,EAAS,SACnB,WAAYA,EAAS,WACrB,WAAYA,EAAS,WAGrB,OAAQA,EAAS,QAAU,CACzB,KAAM,OACN,QAAS,OACT,MAAO,OAAA,CACT,CAEJ,CAKO,SAASC,GAAmBrJ,EAAgB,CACjD,MAAMxhB,EAAOwhB,GAAa,CAAA,EAE1B,MAAO,CACL,SAAUxhB,EAAK,UAAY,GAC3B,WAAYA,EAAK,YAAc,GAC/B,SAAUA,EAAK,UAAY,GAC3B,MAAOA,EAAK,OAAS,GACrB,KAAMA,EAAK,MAAQA,EAAK,QAAU,EAClC,OAAQA,EAAK,QAAUA,EAAK,OAAS,EACrC,SAAUA,EAAK,UAAYA,EAAK,YAAc,GAC9C,WAAYA,EAAK,YAAcA,EAAK,WAAa,GAEjD,OAAQA,EAAK,MAAQA,EAAK,QAAU,EACpC,MAAOA,EAAK,QAAUA,EAAK,OAAS,EACpC,WAAYA,EAAK,UAAYA,EAAK,YAAc,GAChD,UAAWA,EAAK,YAAcA,EAAK,WAAa,GAChD,UAAWA,EAAK,WAAa,CAAA,EAC7B,QAASA,EAAK,SAAW,CAAA,CAAC,CAE9B,CA0BO,SAAS8qB,GAAwB1tD,EAAeiF,EAAc8zC,EAAqB,CACxF,MAAO,CACL,MAAA/4C,EACA,KAAAiF,EACA,KAAM,UACN,UAAW,IACX,OAAQ,CACN,eAAgB,EAChB,eAAgB,GAChB,eAAgB,EAAA,EAElB,iBAAkB,CAChB,SAAU,GACV,UAAW,EACX,UAAW,IACX,YAAa,EAAA,EAEf,iBAAkB8zC,CAAA,CAEtB,CAKO,SAAS4U,GAA2BtJ,EAAsB,CAC/D,OAAKA,EAEE,CACL,MAAOA,EAAW,MAClB,KAAMA,EAAW,KACjB,YAAaA,EAAW,kBAAoBA,EAAW,aAAe,MAAA,EALhD,IAO1B,CAKO,SAASuJ,GAAoBJ,EAAoB,CAEtD,OAAIA,EAAS,OAAeA,EAAS,OAGjCA,EAAS,YACJG,GAA2BH,EAAS,WAAW,EAIjD,IACT,CC/LO,SAASK,IAAgC,CAC9C,MAAO,CACL,SAAU,CACR,QAAS,CACP,CACE,KAAM,OACN,QAAS,yCACT,MAAO,CACL,SAAU,SACV,MAAO,UACP,WAAY,OACZ,UAAW,SACX,aAAc,MAAA,CAChB,CACF,EAEF,OAAQ,CACN,KAAM,WACN,QAAS,OACT,UAAW,QAAA,CACb,EAEF,MAAO,CACL,QAAS,CACP,CACE,KAAM,OACN,QAAS,QACT,MAAO,CACL,SAAU,UACV,WAAY,OACZ,MAAO,UACP,aAAc,MAAA,CAChB,EAEF,CACE,KAAM,oBACN,QAAS,YACT,QAAS,GACT,SAAU,CACR,cAAe,oBAAA,CAEjB,CACF,EAEF,OAAQ,CACN,KAAM,WACN,QAAS,OACT,UAAW,SACX,UAAW,CACT,gBAAiB,UACjB,YAAa,UACb,YAAa,KAAA,CACf,CACF,EAEF,OAAQ,CACN,QAAS,CACP,CACE,KAAM,OACN,QAAS,uBACT,MAAO,CACL,SAAU,UACV,WAAY,OACZ,MAAO,SAAA,CACT,EAEF,CACE,KAAM,OACN,QAAS,8EACT,MAAO,CACL,UAAW,KAAA,CACb,CACF,CACF,CACF,CAEJ,CAKO,SAASC,IAAkD,CAChE,MAAO,CACL,MAAO,CACL,CACE,GAAI,aACJ,KAAM,oBACN,MAAO,QACP,YAAa,gDAAA,EAEf,CACE,GAAI,aACJ,KAAM,oBACN,MAAO,QACP,YAAa,oCAAA,EAEf,CACE,GAAI,aACJ,KAAM,oBACN,MAAO,SACP,YAAa,0DAAA,CACf,EAEF,SAAU,wBACV,YAAa,EACb,eAAgB,GAAA,CAEpB,CAKO,SAASC,GAAkChV,EAAuC,CAOvF,OALI,MAAM,QAAQA,CAAW,GAKzBA,GAAeA,EAAY,MACtBA,EAIF,CACL,MAAO,CAAA,EACP,SAAU,wBACV,YAAa,EACb,eAAgB,CAAA,CAEpB,CCpHO,SAASiV,GAAuBR,EAAwC,CAE7E,MAAMS,EAAaV,GAAqBC,CAAQ,EAG1CU,EAAkBT,GAAmBD,EAAS,YAAcA,EAAS,SAAS,EAG9EW,EAAyB,CAC7B,iBACA,gBAAA,EA2FF,MAvF6C,CAE3C,GAAGF,EAGH,GAAIA,EAAW,IAAM,yBACrB,MAAOA,EAAW,OAAS,cAC3B,MAAOA,EAAW,OAAS,EAC3B,KAAMA,EAAW,MAAQ,SACzB,OAAQA,EAAW,QAAU,WAC7B,MAAOA,EAAW,OAAS,uBAC3B,UAAWA,EAAW,WAAa,mBAGnC,gBAAiBA,EAAW,iBAAiB,OACzCA,EAAW,gBACXE,EAGJ,WAAYF,EAAW,YAAc,EACrC,YAAaA,EAAW,aAAe,2BAGvC,SAAUA,EAAW,UAAY,CAC/B,MAAO,OACP,MAAO,eACP,KAAM,CAAC,QAAS,OAAQ,KAAM,OAAQ,MAAM,CAAA,EAI9C,UAAW,CACT,GAAGC,EAEH,SAAUA,EAAgB,UAAY,gBACtC,WAAYA,EAAgB,YAAc,OAC1C,MAAOA,EAAgB,OAAS,gBAChC,KAAMA,EAAgB,MAAQ,EAC9B,OAAQA,EAAgB,QAAU,EAClC,SAAUA,EAAgB,UAAY,KACtC,WAAYA,EAAgB,YAAc,KAC1C,UAAWA,EAAgB,WAAa,CAAE,EAAG,EAAG,EAAG,EAAG,KAAM,IAAA,EAC5D,QAASA,EAAgB,SAAW,CAClC,mBAAoB,gCACpB,oBAAqB,CAAC,iBAAkB,iBAAiB,EACzD,cAAe,GAAA,CACjB,EAIF,OAAQE,GACNZ,EAAS,QAAUK,GAAA,EACnB,gBACAK,CAAA,EAIF,YAAaH,GAAkCP,EAAS,aAAeM,IAAoC,EAG3G,OAAQF,GAAoBJ,CAAQ,GAAK,CACvC,MAAO,GACP,KAAM,gBACN,YAAa,qEAAA,EAIf,YAAaA,EAAS,aAAeE,GACnC,GACA,gBACA,qEAAA,EAIF,OAAQF,EAAS,QAAU,CACzB,KAAM,OACN,QAAS,OACT,MAAO,QACP,SAAU,CACR,iBAAkB,GAClB,sBAAuB,GACvB,gBAAiB,GACjB,cAAe,GACf,cAAe,EAAA,CACjB,CACF,CAIJ,CAKA,SAASa,GAAmBvqD,EAAoB,CAC9C,OAAOA,GAAM,QAAU,OAAOA,EAAK,QAAW,QAChD,CAOA,SAASwqD,GAA6CC,EAAsB,CAE1E,GAAIA,EAAW,QAAQ,QAAUA,EAAW,QAAQ,SAClD,eAAQ,IAAI,yCAAyC,EAC9CA,EAGT,QAAQ,IAAI,0DAA0D,EACtE,QAAQ,IAAI,kCAAmC,CAC7C,aAAc,CAAC,CAACA,EAAW,UAC3B,KAAMC,GAAiBD,EAAW,SAAS,EAC3C,SAAUE,GAAuBF,EAAW,SAAS,EACrD,UAAWG,GAAwBH,EAAW,SAAS,CAAA,CACxD,EAED,GAAI,CACF,MAAMI,EAAY,CAAE,GAAGJ,CAAA,EAGvB,GAAIA,EAAW,QAAU,OAAOA,EAAW,QAAW,SAAU,CAG9D,MAAMK,EAAsB,CAAA,EACtBC,EAAwB,CAAA,EAG9B,GAAIN,EAAW,OAAO,UAAW,CAC/B,MAAMO,EAAYP,EAAW,OAAO,UAChC,MAAM,QAAQO,CAAS,EACzBF,EAAa,KAAK,GAAGE,EAAU,IAAKphC,IAAgB,CAClD,GAAGA,EACH,SAAU,CACR,GAAGA,EAAM,SACT,SAAU,EAAA,CACZ,EACA,CAAC,EACM,OAAOohC,GAAc,UAC9BF,EAAa,KAAK,CAChB,GAAGE,EACH,SAAU,CACR,GAAGA,EAAU,SACb,SAAU,EAAA,CACZ,CACD,CAEL,CAGA,GAAIP,EAAW,OAAO,SAAU,CAC9B,MAAMQ,EAAWR,EAAW,OAAO,SAC/B,MAAM,QAAQQ,CAAQ,EACxBF,EAAe,KAAK,GAAGE,EAAS,IAAKrhC,IAAgB,CACnD,GAAGA,EACH,SAAU,CACR,GAAGA,EAAM,SACT,UAAW,EAAA,CACb,EACA,CAAC,EACM,OAAOqhC,GAAa,UAC7BF,EAAe,KAAK,CAClB,GAAGE,EACH,SAAU,CACR,GAAGA,EAAS,SACZ,UAAW,EAAA,CACb,CACD,CAEL,EAGIH,EAAa,SAAW,GAAKC,EAAe,SAAW,IAEzD,OAAO,QAAQN,EAAW,MAAM,EAAE,QAAQ,CAAC,CAACzvD,EAAK4uB,CAAK,IAAqB,CACzE,MAAMshC,EAAWlwD,EAAI,YAAA,EACjBkwD,EAAS,SAAS,QAAQ,GAAKA,EAAS,SAAS,UAAU,GAAKA,EAAS,SAAS,WAAW,EAC3F,MAAM,QAAQthC,CAAK,EACrBkhC,EAAa,KAAK,GAAGlhC,CAAK,EACjBA,GAAS,OAAOA,GAAU,UACnCkhC,EAAa,KAAKlhC,CAAK,GAEhBshC,EAAS,SAAS,UAAU,GAAKA,EAAS,SAAS,SAAS,GAAKA,EAAS,SAAS,UAAU,KAClG,MAAM,QAAQthC,CAAK,EACrBmhC,EAAe,KAAK,GAAGnhC,CAAK,EACnBA,GAAS,OAAOA,GAAU,UACnCmhC,EAAe,KAAKnhC,CAAK,EAG/B,CAAC,EAGHihC,EAAU,OAAS,CACjB,OAAQC,EACR,SAAUC,CAAA,CAEd,CAGI,CAACF,EAAU,MAAQJ,EAAW,OAChCI,EAAU,KAAOJ,EAAW,MAG1B,CAACI,EAAU,QAAUJ,EAAW,SAClCI,EAAU,OAASJ,EAAW,QAG5B,CAACI,EAAU,MAAQJ,EAAW,OAChCI,EAAU,KAAOJ,EAAW,MAI9B,MAAMU,EAAgBT,GAAiBD,EAAW,SAAS,EAC3D,OAAIA,EAAW,WAAaU,IAAkB,eAC5C,QAAQ,IAAI,+CAA+C,EAC3D,QAAQ,IAAI,6BAA8B,CACxC,KAAMA,EACN,YAAaV,EAAW,UAAU,YAClC,SAAUE,GAAuBF,EAAW,SAAS,EACrD,UAAWG,GAAwBH,EAAW,SAAS,CAAA,CACxD,EAGGA,EAAW,UAAU,cACvBI,EAAU,UAAY,CACpB,KAAM,cACN,YAAaJ,EAAW,UAAU,WAAA,EAEpC,QAAQ,IAAI,2CACVE,GAAuBF,EAAW,SAAS,CAAA,IAEtCA,EAAW,UACpB,QAAQ,IAAI,kDAAmDC,GAAiBD,EAAW,SAAS,CAAC,EAErG,QAAQ,IAAI,sCAAsC,EAI/CI,EAAU,WAgBRA,EAAU,UAAU,SACvBA,EAAU,UAAU,OAAS,CAC3B,SAAU,CAAC,EAAG,EAAE,EAChB,OAAQ,GACR,YAAa,aACb,IAAK,EACL,IAAK,EACL,KAAM,GAAA,GAILA,EAAU,UAAU,oBACvBA,EAAU,UAAU,kBAAoB,CACtC,QAAS,EAAA,IA5BbA,EAAU,UAAY,CACpB,OAAQ,CACN,SAAU,CAAC,EAAG,EAAE,EAChB,OAAQ,GACR,YAAa,aACb,IAAK,EACL,IAAK,EACL,KAAM,GAAA,EAER,kBAAmB,CACjB,QAAS,EAAA,CACX,EAuBA,CAACA,EAAU,aAAeJ,EAAW,cACvCI,EAAU,YAAcJ,EAAW,aAIhCI,EAAU,WACbA,EAAU,SAAW,iBAIlBA,EAAU,QACbA,EAAU,MAAQ,SAIfA,EAAU,gBACbA,EAAU,cAAgB,WAIvBA,EAAU,KACbA,EAAU,GAAK,CACb,cAAeA,EAAU,aAAA,GAKzB,CAACA,EAAU,UAAYA,EAAU,OACnCA,EAAU,SAAWA,EAAU,MAE7B,CAACA,EAAU,YAAcA,EAAU,OACrCA,EAAU,WAAaA,EAAU,MAI9BA,EAAU,WACbA,EAAU,SAAW,CACnB,UAAW,gBACX,KAAMA,EAAU,KAChB,OAAQA,EAAU,OAClB,KAAMA,EAAU,KAChB,SAAUA,EAAU,SACpB,YAAa,IAAI,KAAA,EAAO,YAAA,CAAY,GAIxC,QAAQ,IAAI,iDAAiD,EAC7D,QAAQ,IAAI,sBAAuB,CACjC,KAAMH,GAAiBG,EAAU,SAAS,EAC1C,SAAUF,GAAuBE,EAAU,SAAS,EACpD,UAAWD,GAAwBC,EAAU,SAAS,CAAA,CACvD,EACD,QAAQ,IAAI,iBAAkBA,EAAU,KAAM,UAAWA,EAAU,MAAM,EACzE,QAAQ,IAAI,sBAAuBA,EAAU,SAAU,SAAUA,EAAU,KAAK,EAEzEA,CACT,OAASlpD,EAAO,CACd,eAAQ,KAAK,sDAAuDA,CAAK,EAElE8oD,CACT,CACF,CAMA,SAASE,GAAuBhiC,EAAwB,CACtD,GAAI,CAACA,EAAW,MAAO,MAGvB,MAAM7tB,EAAS,MAAM,QAAQ6tB,CAAS,EAAIA,EAAU,CAAC,EAAIA,EAGzD,OAAI7tB,GAAQ,aAAa,WAAa,OAC7B,OAAOA,EAAO,YAAY,QAAQ,EAIvCA,GAAQ,QAAQ,WAAa,OACxB,OAAOA,EAAO,OAAO,QAAQ,EAG/B,KACT,CAMA,SAAS8vD,GAAwBjiC,EAAqB,CACpD,GAAI,CAACA,EAAW,OAGhB,MAAM7tB,EAAS,MAAM,QAAQ6tB,CAAS,EAAIA,EAAU,CAAC,EAAIA,EAGzD,GAAI7tB,GAAQ,aAAa,YAAc,OACrC,OAAOA,EAAO,YAAY,UAI5B,GAAIA,GAAQ,QAAQ,YAAc,OAChC,OAAOA,EAAO,OAAO,SAIzB,CAMA,SAAS4vD,GAAiB/hC,EAAwB,CAChD,OAAKA,IAGU,MAAM,QAAQA,CAAS,EAAIA,EAAU,CAAC,EAAIA,IAG1C,MAAQ,KACzB,CAKA,SAAS2hC,GAAkC9Q,EAAa4R,EAAqB9K,EAAsB,CAIjG,GAAI9G,GAAQ,OAAO,QAAS,CAC1B,MAAM6R,EAAkB7R,EAAO,MAAM,QAAQ,IAAKx5C,GAAc,CAC9D,GAAIA,EAAK,OAAS,oBAAqB,CAErC,GAAIuqD,GAAmBvqD,CAAI,EACzB,GAAI,CAEF,MAAMyqD,EAAaD,GAA6CxqD,EAAK,MAAM,EAGrE0wB,EAAmBm2B,GAAgC4D,CAAU,EAEnE,GAAI/5B,EAAiB,QACnB,eAAQ,IAAI,sEAAsE,EAClF,QAAQ,IAAI,8BACVi6B,GAAuBF,EAAW,SAAS,CAAA,EAC7C,QAAQ,IAAI,gBAAiBA,EAAW,KAAM,UAAWA,EAAW,MAAM,EACnE,CACL,GAAGzqD,EACH,SAAU,CACR,GAAGA,EAAK,SACR,OAAQyqD,EACR,OAAQ,OACR,iBAAA/5B,CAAA,CACF,EAGF,QAAQ,KAAK,0DAA2DA,EAAiB,MAAM,EAC/F,QAAQ,IAAI,4BAA6B,CACvC,UAAW,CAAC,CAAC+5B,EAAW,OACxB,aAAc,CAAC,CAACA,EAAW,UAC3B,cAAeC,GAAiBD,EAAW,SAAS,EACpD,SAAUE,GAAuBF,EAAW,SAAS,EACrD,SAAUA,EAAW,SACrB,MAAOA,EAAW,KAAA,CACnB,CAGL,OAAS9oD,EAAO,CACd,QAAQ,KAAK,wDAAyDA,CAAK,CAE7E,CAIF,IAAI2pD,EACJ,GAAI,CAEF,MAAMC,EAAcjL,GAAW,MAAQ,EACjCkL,EAAgBlL,GAAW,QAAU,EAC3C,QAAQ,IAAI,wDAAyDiL,EAAa,UAAWC,CAAa,EAE1GF,EAAgBxC,GAA4B,CAC1C,KAAMyC,EACN,OAAQC,EACR,KAAMlL,GAAW,UAAYA,GAAW,MAAQ,KAChD,QAASA,GAAW,QACpB,QAASA,GAAW,QACpB,cAAe,SAAA,CAChB,EAED,QAAQ,IAAI,iCACVqK,GAAuBW,EAAc,SAAS,CAAA,CAClD,OAAS3pD,EAAO,CACd,QAAQ,KAAK,mDAAoDA,CAAK,EAEtE,QAAQ,IAAI,0DAA0D,EACtE2pD,EAAgBxC,GAA4B,CAC1C,KAAM,EACN,OAAQ,EACR,KAAM,KACN,cAAe,SAAA,CAChB,EACD,QAAQ,IAAI,kCACV6B,GAAuBW,EAAc,SAAS,CAAA,CAClD,CAEA,eAAQ,IAAI,mCAAmC,EAC/C,QAAQ,IAAI,8BAA+B,CACzC,KAAMZ,GAAiBY,EAAc,SAAS,EAC9C,UAAWV,GAAwBU,EAAc,SAAS,EAC1D,SAAUX,GAAuBW,EAAc,SAAS,CAAA,CACzD,EAEM,CACL,GAAGtrD,EACH,SAAU,CACR,GAAGA,EAAK,SACR,OAAQsrD,EACR,OAAQ,WAAA,CACV,CAEJ,CACA,OAAOtrD,CACT,CAAC,EAED,MAAO,CACL,GAAGw5C,EACH,MAAO,CACL,GAAGA,EAAO,MACV,QAAS6R,CAAA,CACX,CAEJ,CAGA,OAAO7R,CACT,0kdC/eMiS,GAA4C,CAChD,0BAA2B,GAC3B,WAAY,GACZ,gBAAiB,GACjB,gBAAiB,QACjB,cAAe,EACjB,EAiCA,eAAsBC,IAA4D,CAEhF,QAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUb,IAAI,MAAA,EAAQ,OAAO,MAAM;AAAA,CAAI,EAAE,MAAM,EAAG,CAAC,EAAE,KAAK;AAAA,CAAI,GAAK,SAAS;AAAA,CACnE,EAGC,MAAMlmD,EAAS0/C,GAAsByG,GAAsDF,EAAsB,EACjH,eAAQ,IAAI,mCAAoCjmD,EAAO,KAAK,EAAE,EACvDA,EAAO,IAChB,CAsCA,eAAsBomD,IAA4D,CAEhF,eAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUb,IAAI,MAAA,EAAQ,OAAO,MAAM;AAAA,CAAI,EAAE,MAAM,EAAG,CAAC,EAAE,KAAK;AAAA,CAAI,GAAK,SAAS;AAAA,CACnE,EAGQF,GAAA,CACT,CAOA,eAAsBG,IAAiE,CAErF,QAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUb,IAAI,MAAA,EAAQ,OAAO,MAAM;AAAA,CAAI,EAAE,MAAM,EAAG,CAAC,EAAE,KAAK;AAAA,CAAI,GAAK,SAAS;AAAA,CACnE,EAEC,GAAI,CACF,MAAM5jB,EAAciiB,GAAuB4B,EAAqB,EAChE,eAAQ,IAAI,uBAAwB7jB,EAAY,EAAE,EAC3CA,CACT,OAAStmC,EAAO,CACd,eAAQ,MAAM,WAAYA,CAAK,EAExBoqD,GAAA,CACT,CACF,CAgGA,SAASA,IAA8D,CACrE,OAAO7B,GAAuB,CAC5B,GAAI,8BACJ,MAAO,kBACP,MAAO,EACP,KAAM,SACN,WAAY,CACV,SAAU,gBACV,WAAY,OACZ,KAAM,EACN,OAAQ,CAAA,CACV,CACD,CACH,CCxRO,MAAM8B,GAAkF,CAAC,CAC9F,UAAA1sD,EAAY,GACZ,YAAa2sD,CACf,IAAM,CAEJ,MAAMC,EAAe/Z,GAAA,EACfV,EAAaW,GAAA,EACbqB,EAAiBnB,GAAA,EACjBva,EAAkBwa,GAAA,EAClB,CAAE,iBAAA4Z,EAAkB,aAAAC,EAAc,aAAAC,EAAc,eAAAC,CAAA,EAAmB7Z,GAAA,EAGnE,CAAClzC,EAASklB,CAAU,EAAIsQ,EAAAA,SAAS,EAAI,EACrC,CAACpzB,EAAOqzB,CAAQ,EAAID,EAAAA,SAAwB,IAAI,EAChD,CAACw3B,EAAqBC,CAAsB,EAAIz3B,EAAAA,SAAyC,IAAI,EAG7F03B,EAA0BzkC,EAAAA,QAAQ,IAAMikC,EAAqB,CAACA,CAAmB,CAAC,EAGxFpkC,EAAAA,UAAU,IAAM,CACd,GAAI4kC,EAAyB,CAE3BhoC,EAAW,EAAK,EAChBuQ,EAAS,IAAI,EACbw3B,EAAuB,IAAI,EAC3B,MACF,EAEyB,SAAY,CACnC,GAAI,CACF/nC,EAAW,EAAI,EACfuQ,EAAS,IAAI,EACb,MAAMtzB,EAAO,MAAMmqD,GAAA,EACnBW,EAAuB9qD,CAAI,CAC7B,OAAS0Y,EAAK,CACZ,MAAM6P,EAAe7P,aAAe,MAAQA,EAAI,QAAU,SAC1D4a,EAAS/K,CAAY,EACrB,QAAQ,MAAM,YAAa7P,CAAG,CAChC,QAAA,CACEqK,EAAW,EAAK,CAClB,CACF,GAEA,CACF,EAAG,CAACgoC,CAAuB,CAAC,EAG5B,MAAM1a,EAAc/pB,EAAAA,QAAQ,IACnBykC,GAA2BF,EACjC,CAACE,EAAyBF,CAAmB,CAAC,EAUjD,OAPA1kC,EAAAA,UAAU,IAAM,CACVkqB,GACFua,EAAeva,CAAW,CAE9B,EAAG,CAACA,EAAaua,CAAc,CAAC,EAG5B/sD,EAEAc,EAAAA,KAAC,MAAA,CAAI,UAAU,kFACb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,kEAAkE,SAAA,SAEjF,EACAA,EAAAA,IAAC,MAAA,CAAI,UAAU,yBAAyB,SAAA,kBAAA,CAAgB,CAAA,EAC1D,EAKAiC,EAEAtB,EAAAA,KAAC,MAAA,CAAI,UAAU,kFACb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,kEAAkE,SAAA,SAEjF,EACAA,EAAAA,IAAC,MAAA,CAAI,UAAU,4BAA6B,SAAAiC,EAAM,EAClDjC,EAAAA,IAAC,MAAA,CAAI,UAAU,iBAAiB,SAAA,eAAA,CAAa,CAAA,EAC/C,EAKCqyC,EAYH1xC,EAAAA,KAAC,MAAA,CAAI,UAAU,kFAEb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,kEACZ,SAAA,CAAA0xC,EAAY,MAAM,QAAWA,EAAY,IAAA,EAC5C,EAGA1xC,EAAAA,KAAC,OAAA,CAAK,UAAU,wDAEb,SAAA,CAAA6rD,IAAiB,YAChBxsD,EAAAA,IAAC8zC,GAAA,CACC,YAAAzB,EACA,WAAAN,EACA,eAAAgC,EACA,eAAgB2Y,EAChB,eAAgBD,EAChB,gBAAAp0B,CAAA,CAAA,EAKHm0B,IAAiB,eAChBxsD,EAAAA,IAACm2C,GAAA,CACC,YAAA9D,EACA,WAAAN,EACA,eAAgB4a,CAAA,CAAA,EAKnBH,IAAiB,WAChBxsD,EAAAA,IAACq2C,GAAA,CACC,YAAAhE,EACA,eAAgBsa,CAAA,CAAA,CAClB,CAAA,CAEJ,CAAA,EACF,EA/CEhsD,EAAAA,KAAC,MAAA,CAAI,UAAU,kFACb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,kEAAkE,SAAA,QAEjF,EACAA,EAAAA,IAAC,MAAA,CAAI,UAAU,yBAAyB,SAAA,gBAAA,CAAc,CAAA,EACxD,CA4CN,EClHagtD,GAA6E,CAAC,CACzF,UAAAptD,EAAY,GACZ,YAAa2sD,CACf,IAAM,CAEJ,MAAMC,EAAe/Z,GAAA,EACfV,EAAaW,GAAA,EACbqB,EAAiBnB,GAAA,EACjBva,EAAkBwa,GAAA,EAClB,CAAE,iBAAA4Z,EAAkB,aAAAC,EAAc,aAAAC,EAAc,eAAAC,CAAA,EAAmB7Z,GAAA,EAGnE,CAAClzC,EAASklB,CAAU,EAAIsQ,EAAAA,SAAS,EAAI,EACrC,CAACpzB,EAAOqzB,CAAQ,EAAID,EAAAA,SAAwB,IAAI,EAChD,CAACw3B,EAAqBC,CAAsB,EAAIz3B,EAAAA,SAAyC,IAAI,EAG7F03B,EAA0BzkC,EAAAA,QAAQ,IAAMikC,EAAqB,CAACA,CAAmB,CAAC,EAGxFpkC,EAAAA,UAAU,IAAM,CACd,GAAI4kC,EAAyB,CAE3BhoC,EAAW,EAAK,EAChBuQ,EAAS,IAAI,EACbw3B,EAAuB,IAAI,EAC3B,MACF,EAEyB,SAAY,CACnC,GAAI,CACF/nC,EAAW,EAAI,EACfuQ,EAAS,IAAI,EACb,MAAMtzB,EAAO,MAAMkqD,GAAA,EACnBY,EAAuB9qD,CAAI,CAC7B,OAAS0Y,EAAK,CACZ,MAAM6P,EAAe7P,aAAe,MAAQA,EAAI,QAAU,SAC1D4a,EAAS/K,CAAY,EACrB,QAAQ,MAAM,YAAa7P,CAAG,CAChC,QAAA,CACEqK,EAAW,EAAK,CAClB,CACF,GAEA,CACF,EAAG,CAACgoC,CAAuB,CAAC,EAG5B,MAAM1a,EAAc/pB,EAAAA,QAAQ,IACnBykC,GAA2BF,EACjC,CAACE,EAAyBF,CAAmB,CAAC,EAUjD,OAPA1kC,EAAAA,UAAU,IAAM,CACVkqB,GACFua,EAAeva,CAAW,CAE9B,EAAG,CAACA,EAAaua,CAAc,CAAC,EAG5B/sD,EAEAc,EAAAA,KAAC,MAAA,CAAI,UAAU,kFACb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,kEAAkE,SAAA,SAEjF,EACAA,EAAAA,IAAC,MAAA,CAAI,UAAU,yBAAyB,SAAA,gBAAA,CAAc,CAAA,EACxD,EAKAiC,EAEAtB,EAAAA,KAAC,MAAA,CAAI,UAAU,kFACb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,kEAAkE,SAAA,SAEjF,EACAA,EAAAA,IAAC,MAAA,CAAI,UAAU,4BAA6B,SAAAiC,EAAM,EAClDjC,EAAAA,IAAC,MAAA,CAAI,UAAU,iBAAiB,SAAA,eAAA,CAAa,CAAA,EAC/C,EAKCqyC,EAYH1xC,EAAAA,KAAC,MAAA,CAAI,UAAU,kFAEb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,kEACZ,SAAA,CAAA0xC,EAAY,MAAM,QAAWA,EAAY,IAAA,EAC5C,EAGA1xC,EAAAA,KAAC,OAAA,CAAK,UAAU,wDAEb,SAAA,CAAA6rD,IAAiB,YAChBxsD,EAAAA,IAAC8zC,GAAA,CACC,YAAAzB,EACA,WAAAN,EACA,eAAAgC,EACA,eAAgB2Y,EAChB,eAAgBD,EAChB,gBAAAp0B,CAAA,CAAA,EAKHm0B,IAAiB,eAChBxsD,EAAAA,IAACm2C,GAAA,CACC,YAAA9D,EACA,WAAAN,EACA,eAAgB4a,CAAA,CAAA,EAKnBH,IAAiB,WAChBxsD,EAAAA,IAACq2C,GAAA,CACC,YAAAhE,EACA,eAAgBsa,CAAA,CAAA,CAClB,CAAA,CAEJ,CAAA,EACF,EA/CEhsD,EAAAA,KAAC,MAAA,CAAI,UAAU,kFACb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,kEAAkE,SAAA,QAEjF,EACAA,EAAAA,IAAC,MAAA,CAAI,UAAU,yBAAyB,SAAA,cAAA,CAAY,CAAA,EACtD,CA4CN,ECnKaitD,GAAkBpuD,EAAM,cAA+C,MAAS,EAEhFquD,GAAqB,IAAM,CACtC,MAAMrlD,EAAUhJ,EAAM,WAAWouD,EAAe,EAChD,GAAI,CAACplD,EACH,MAAM,IAAI,MAAM,6DAA6D,EAE/E,OAAOA,CACT,ECbaslD,GAAgB,CAC3BC,EACApb,EACAD,IAEOqb,EACJ,QAAQ,mBAAoBpb,EAAc,KAAK,IAAI,CAAC,EACpD,QAAQ,gBAAiBD,EAAW,KAAK,IAAI,CAAC,EAQtCtK,GAAsBC,GAC7BA,EAAM,OAAS,UAEV7oC,EAAM,cAAckpB,GAAgB,CACzC,IAAK2f,EAAM,QACX,MAAO,CAACA,EAAM,OAAO,EACrB,SAAU,KACV,YAAa,GACb,SAAU,MACV,MAAO,SAAA,CACR,EAGCA,EAAM,OAAS,QACV7oC,EAAM,cAAc,MAAO,CAChC,IAAK6oC,EAAM,QACX,IAAK,UACL,UAAW,QACX,IAAKA,EAAM,OAAA,CACZ,EAGI7oC,EAAM,cAAc,OAAQ,CAAE,IAAK6oC,EAAM,OAAA,EAAWA,EAAM,OAAO,EAQ7D2lB,GAAuBjS,GAC3BA,EAAO,IAAI,CAAC1T,EAAO15B,IACxBnP,EAAM,cAAc,MAAO,CACzB,UAAW,gBACX,IAAKmP,CAAA,EACJy5B,GAAmBC,CAAK,CAAC,CAAA,EAoFnB4lB,GAA6BF,GAAqC,CAC7E,MAAMhS,EAAyB,CAAA,EAC/B,IAAIphB,EAAe,EAGnB,MAAMuzB,EAAe,mBACrB,IAAIl/C,EAEJ,MAAQA,EAAQk/C,EAAa,KAAKH,CAAQ,KAAO,MAAM,CACrD,MAAMI,EAAan/C,EAAM,MACnBo/C,EAAWp/C,EAAM,MAAQA,EAAM,CAAC,EAAE,OAGxC,GAAIm/C,EAAaxzB,EAAc,CAC7B,MAAM0zB,EAAcN,EAAS,UAAUpzB,EAAcwzB,CAAU,EAC3DE,EAAY,QACdtS,EAAO,KAAK,CACV,KAAM,OACN,QAASsS,CAAA,CACV,CAEL,CAKA,MAAMC,EAFiBt/C,EAAM,CAAC,EAG3B,QAAQ,SAAU,EAAE,EACpB,QAAQ,SAAU,EAAE,EAEvB+sC,EAAO,KAAK,CACV,KAAM,UACN,QAASuS,CAAA,CACV,EAED3zB,EAAeyzB,CACjB,CAGA,GAAIzzB,EAAeozB,EAAS,OAAQ,CAClC,MAAMQ,EAAgBR,EAAS,UAAUpzB,CAAY,EACjD4zB,EAAc,QAChBxS,EAAO,KAAK,CACV,KAAM,OACN,QAASwS,CAAA,CACV,CAEL,CAEA,OAAOxS,CACT,EASayS,GAA6B,CACxCT,EACApb,EACAD,IACsB,CAEtB,MAAM+b,EAAiBX,GAAcC,EAAUpb,EAAeD,CAAU,EAGlEgM,EAAgBuP,GAA0BQ,CAAc,EAG9D,OAAOT,GAAoBtP,CAAa,CAC1C,EC/MagQ,GAAyB35B,GAA2C,CAC/E,KAAM,CAAE,KAAAj5B,EAAM,QAAAoN,EAAS,MAAA/F,EAAQ,CAAA,GAAO4xB,EAEhCyC,EAAiC,CACrC,aAAc,MACd,WAAY,MACZ,GAAGr0B,CAAA,EAGL,OAAQrH,EAAA,CACN,IAAK,cACH,OAAO0D,EAAM,cAAc,MAAO,CAChC,IAAKu1B,EAAK,GACV,MAAO,CACL,GAAGyC,EACH,WAAY,OACZ,MAAO,SAAA,CACT,EACCtuB,CAAO,EAEZ,IAAK,UAEH,MAAMylD,EAAmBzlD,EAAQ,SAAS,MAAM,GAAKA,EAAQ,SAAS,aAAa,GAAKA,EAAQ,SAAS,QAAQ,EACjH,OAAO1J,EAAM,cAAckpB,GAAgB,CACzC,IAAKqM,EAAK,GACV,MAAO,CAAC7rB,CAAO,EACf,SAAU,KACV,YAAaylD,EACb,SAAU,QACV,MAAO,SAAA,CACR,EAEH,IAAK,aACH,OAAOnvD,EAAM,cAAc,MAAO,CAChC,IAAKu1B,EAAK,GACV,MAAO,CACL,GAAGyC,EACH,WAAY,OACZ,MAAO,UACP,WAAY,oBACZ,YAAa,MAAA,CACf,EACCtuB,CAAO,EAEZ,IAAK,QACH,OAAO1J,EAAM,cAAc,MAAO,CAChC,IAAKu1B,EAAK,GACV,MAAOyC,CAAA,EACNh4B,EAAM,cAAc,MAAO,CAC5B,IAAK0J,EACL,IAAK,OACL,MAAO,CACL,SAAU,OACV,OAAQ,OACR,aAAc,KAAA,CAChB,CACD,CAAC,EAEJ,IAAK,QACH,OAAO1J,EAAM,cAAc,MAAO,CAChC,IAAKu1B,EAAK,GACV,MAAOyC,CAAA,EACNh4B,EAAM,cAAc,MAAO,CAC5B,MAAO,CACL,OAAQ,oBACR,aAAc,MACd,QAAS,MACT,gBAAiB,SAAA,CACnB,EACC0J,CAAO,CAAC,EAEb,QACE,OAAO1J,EAAM,cAAc,MAAO,CAChC,IAAKu1B,EAAK,GACV,MAAOyC,CAAA,EACNtuB,CAAO,CAAA,CAEhB,EASa0lD,GAAmB,CAC9B75B,EACA2d,EACAC,IACoB,CACpB,KAAM,CAAE,KAAA72C,EAAM,QAAAoN,EAAS,MAAA/F,EAAQ,CAAA,GAAO4xB,EAEhCyC,EAAiC,CACrC,aAAc,MACd,WAAY,MACZ,GAAGr0B,CAAA,EAGL,OAAQrH,EAAA,CACN,IAAK,cACH,OAAO0D,EAAM,cAAc,MAAO,CAChC,IAAKu1B,EAAK,GACV,MAAO,CACL,GAAGyC,EACH,WAAY,OACZ,MAAO,SAAA,CACT,EACCtuB,CAAO,EAEZ,IAAK,UAEH,MAAMylD,EAAmBzlD,EAAQ,SAAS,MAAM,GAAKA,EAAQ,SAAS,aAAa,GAAKA,EAAQ,SAAS,QAAQ,EACjH,OAAO1J,EAAM,cAAckpB,GAAgB,CACzC,IAAKqM,EAAK,GACV,MAAO,CAAC7rB,CAAO,EACf,SAAU,KACV,YAAaylD,EACb,SAAU,QACV,MAAO,SAAA,CACR,EAEH,IAAK,aAEH,MAAME,EAAgBf,GAAc5kD,EAASypC,EAAeD,CAAU,EACtE,OAAOlzC,EAAM,cAAc,MAAO,CAChC,IAAKu1B,EAAK,GACV,MAAO,CACL,GAAGyC,EACH,WAAY,OACZ,MAAO,UACP,WAAY,oBACZ,YAAa,MAAA,CACf,EACCq3B,CAAa,EAElB,QACE,OAAOrvD,EAAM,cAAc,MAAO,CAChC,IAAKu1B,EAAK,GACV,MAAOyC,CAAA,EACNtuB,CAAO,CAAA,CAEhB,EAOa4lD,GAA0BzY,GAC9BA,EAAM,IAAIqY,EAAqB,EAU3BK,GAAoB,CAC/B1Y,EACA3D,EACAC,IAEO0D,EAAM,IAAIthB,GAAQ65B,GAAiB75B,EAAM2d,EAAYC,CAAa,CAAC,EC1JtEqc,GAAgC,CAAC,CACrC,MAAAvwB,EACA,SAAAz6B,EAAW,SACX,KAAA3D,EAAO,SACP,MAAAinB,EACA,QAAA2nC,EACA,OAAAC,EAAS,EACX,IAAM,CACJ,GAAIA,EAAQ,OAAO,KAEnB,MAAMC,EAAa,CACjB,SAAU,OACV,MAAO,OACP,OAAQ,MAAA,EAGJC,EAAiB,IAA2B,CAChD,MAAM53B,EAAiC,CACrC,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,WAAY,IACZ,cAAe,YACf,cAAe,OAAA,EAIX63B,EAAc,CAClB,SAAU,UACV,MAAO,UACP,OAAQ,SAAA,EAGV,OAAA73B,EAAU,WAAay3B,GAAWI,EAAY5wB,CAAK,EACnDjH,EAAU,MAAQlQ,GAAS,UAGvBtjB,IAAa,SACfwzB,EAAU,aAAe,oBAChBxzB,IAAa,YACtBwzB,EAAU,YAAc,oBACxBA,EAAU,YAAc,cACxBA,EAAU,gBAAkB,SAU9B,OAAO,OAAOA,EANK,CACjB,MAAO,CAAE,SAAU,OAAQ,QAAS,UAAA,EACpC,OAAQ,CAAE,SAAU,OAAQ,QAAS,WAAA,EACrC,MAAO,CAAE,SAAU,OAAQ,QAAS,WAAA,CAAY,EAGdn3B,CAAI,CAAC,EAElCm3B,CACT,EAEA,aACG,MAAA,CAAI,MAAO43B,IACT,SAAAD,EAAW1wB,CAAK,EACnB,CAEJ,EAGM6wB,GAAoC,CAAC,CAAE,SAAAC,KAAe,CAC1D,MAAMC,EAAqC,CACzC,QAAS,OACT,WAAY,MACZ,SAAU,MAAA,EAGZ,aACG,MAAA,CAAI,MAAOA,EACT,SAAAxB,GAAoBuB,CAAQ,EAC/B,CAEJ,EAGME,GAA0C,CAAC,CAC/C,YAAApD,EACA,QAAAn+C,EACA,MAAA/Q,EAAQ,CAAA,EACR,SAAAs/B,EACA,YAAAizB,EAAc,OAChB,IAAM,CACJ,MAAMxoB,EAAsC,CAC1C,QAAS,OACT,UAAW,mBAAA,EAGPyoB,EAAkC,CACtC,MAAO,OACP,QAAS,YACT,OAAQ,oBACR,aAAc,MACd,SAAU,MAAA,EAGNC,EAAoC,CACxC,QAAS,OACT,IAAK,MAAA,EAGDC,EAAkBC,IAA8C,CACpE,QAAS,YACT,OAAQ,oBACR,aAAc,MACd,OAAQ,UACR,WAAY,gBACZ,WAAYA,EAAa,UAAY,cACrC,MAAOA,EAAa,UAAY,UAChC,YAAaA,EAAa,UAAY,SAAA,GAGlCC,EAAqBC,GAAqB,CAC9C,GAAKvzB,EAEL,GAAI4vB,IAAgB,kBAAmB,CACrC,MAAMzuB,EAAWzgC,EAAM,SAAS6yD,CAAQ,EACpC7yD,EAAM,OAAO2S,GAAMA,IAAOkgD,CAAQ,EAClC,CAAC,GAAG7yD,EAAO6yD,CAAQ,EACvBvzB,EAASmB,CAAQ,CACnB,MACEnB,EAAS,CAACuzB,CAAQ,CAAC,CAEvB,EAEMC,EAAqBvsD,GAA2C,CAChE+4B,GACFA,EAAS,CAAC/4B,EAAE,OAAO,KAAK,CAAC,CAE7B,EAEA,OAAI2oD,IAAgB,mBAAqBn+C,EAErCvN,EAAAA,IAAC,MAAA,CAAI,MAAOumC,EACV,SAAAvmC,MAAC,OAAI,MAAOivD,EACT,SAAA1hD,EAAQ,IAAIC,GACXxN,EAAAA,IAAC,MAAA,CAEC,MAAOkvD,EAAe1yD,EAAM,SAASgR,EAAO,EAAE,CAAC,EAC/C,QAAS,IAAM4hD,EAAkB5hD,EAAO,EAAE,EAEzC,SAAA6/C,GAAoB7/C,EAAO,OAAO,CAAA,EAJ9BA,EAAO,EAAA,CAMf,EACH,CAAA,CACF,EAKFxN,EAAAA,IAAC,MAAA,CAAI,MAAOumC,EACV,SAAAvmC,EAAAA,IAAC,QAAA,CACC,KAAK,OACL,MAAOgvD,EACP,YAAAD,EACA,MAAOvyD,EAAM,CAAC,GAAK,GACnB,SAAU8yD,CAAA,CAAA,EAEd,CAEJ,EAGMC,GAA4C,CAAC,CACjD,QAAAC,EACA,SAAAnxD,EACA,SAAAoxD,EAAW,GACX,QAAA5vD,EAAU,EACZ,IAAM,CACJ,MAAM6vD,EAAmC,CACvC,QAAS,YACT,WAAY,UACZ,MAAO,QACP,OAAQ,OACR,aAAc,MACd,SAAU,OACV,WAAY,IACZ,OAAQD,EAAW,cAAgB,UACnC,QAASA,EAAW,GAAM,CAAA,EAG5B,OACEzvD,EAAAA,IAAC,SAAA,CACC,MAAO0vD,EACP,QAAAF,EACA,SAAUC,GAAY5vD,EAErB,WAAU,SAAWxB,CAAA,CAAA,CAG5B,EAGMsxD,GAA0C,CAAC,CAAE,MAAAja,EAAO,MAAAV,EAAQ,UAAa,CAC7E,MAAMzO,EAAsC,CAC1C,QAAS,OACT,UAAW,mBAAA,EAGPqpB,EAAkC,CACtC,SAAU,OACV,WAAY,IACZ,aAAc,OACd,MAAO,SAAA,EAGHC,EAAkC,CACtC,QAAS,OACT,cAAe,SACf,IAAK,MAAA,EAGDC,EAAiC,CACrC,QAAS,OACT,WAAY,oBACZ,WAAY,UACZ,aAAc,cACd,WAAY,KAAA,EAGd,OACEnvD,EAAAA,KAAC,MAAA,CAAI,MAAO4lC,EACV,SAAA,CAAAvmC,EAAAA,IAAC,MAAA,CAAI,MAAO4vD,EAAa,SAAA5a,EAAM,EAC/Bh1C,EAAAA,IAAC,OAAI,MAAO6vD,EACT,YAAuBna,CAAK,EAAE,IAAI,CAACqa,EAAa/hD,IAC/ChO,EAAAA,IAAC,MAAA,CAA0B,MAAO8vD,EAC/B,SAAAC,CAAA,EADOra,EAAM1nC,CAAK,EAAE,EAEvB,CACD,CAAA,CACH,CAAA,EACF,CAEJ,EAGMgiD,GAA8C,CAAC,CACnD,cAAA3b,EACA,WAAAtC,EACA,cAAAC,CACF,IAAM,CACJ,MAAMzL,EAAsC,CAC1C,QAAS,OACT,UAAW,mBAAA,EAGPqpB,EAAkC,CACtC,SAAU,OACV,WAAY,IACZ,aAAc,OACd,MAAO,SAAA,EAGHtmB,EAAoC,CACxC,WAAY,KAAA,EAGR2mB,EAAqC,CACzC,QAAS,OACT,WAAY,UACZ,OAAQ,oBACR,aAAc,MACd,aAAc,MAAA,EAGVJ,EAAkC,CACtC,QAAS,OACT,cAAe,SACf,IAAK,MAAA,EAGDC,EAAiC,CACrC,QAAS,OACT,WAAY,oBACZ,WAAY,UACZ,aAAc,cACd,WAAY,KAAA,EAGd,OACEnvD,EAAAA,KAAC,MAAA,CAAI,MAAO4lC,EACV,SAAA,CAAAvmC,EAAAA,IAAC,MAAA,CAAI,MAAO4vD,EAAY,SAAA,OAAI,EAC5BjvD,EAAAA,KAAC,MAAA,CAAI,MAAO2oC,EACT,SAAA,CAAA+K,EAAc,gBACbr0C,MAAC,MAAA,CAAI,MAAOiwD,EACT,SAAApC,GACCxZ,EAAc,eACdrC,EACAD,CAAA,EAEJ,EAEDsC,EAAc,mBACbr0C,EAAAA,IAAC,MAAA,CAAI,MAAO6vD,EACT,SAAAzB,GAAkB/Z,EAAc,kBAAmBtC,EAAYC,CAAa,EAAE,IAAI,CAAC+d,EAAa/hD,IAC/FhO,EAAAA,IAAC,MAAA,CAAqD,MAAO8vD,EAC1D,SAAAC,CAAA,EADO1b,EAAc,kBAAmBrmC,CAAK,EAAE,EAElD,CACD,CAAA,CACH,CAAA,CAAA,CAEJ,CAAA,EACF,CAEJ,EAGMkiD,GAA4C,CAAC,CAAE,KAAA/0D,EAAO,cAAiB,CAC3E,MAAMg1D,EAAqC,CACzC,QAAS,MAAA,EAGLC,EAAyC,CAC7C,OAAQ,OACR,WAAY,gEACZ,eAAgB,YAChB,UAAW,wBACX,aAAc,MACd,aAAc,MAAA,EAGVC,EAAoC,CACxC,QAAS,OACT,eAAgB,SAChB,WAAY,SACZ,QAAS,MAAA,EAGLC,EAA2C,CAC/C,MAAO,OACP,OAAQ,OACR,OAAQ,oBACR,UAAW,oBACX,aAAc,MACd,UAAW,yBAAA,EAGb,OAAIn1D,IAAS,UAET6E,MAAC,OAAI,MAAOqwD,EACV,eAAC,MAAA,CAAI,MAAOC,EAAqB,CAAA,CACnC,EAKF3vD,EAAAA,KAAC,MAAA,CAAI,MAAOwvD,EAAe,cAAY,mBACrC,SAAA,CAAAnwD,MAAC,OAAI,MAAO,CAAE,GAAGowD,EAAmB,MAAO,OAAS,EACpDpwD,MAAC,OAAI,MAAO,CAAE,GAAGowD,EAAmB,MAAO,OAAS,EACpDpwD,EAAAA,IAAC,OAAI,MAAO,CAAE,GAAGowD,EAAmB,MAAO,MAAM,CAAG,CAAA,EACtD,CAEJ,EAGMG,GAAwC,CAAC,CAAE,MAAAtuD,EAAO,QAAAuuD,KAAc,CACpE,MAAMC,EAAkC,CACtC,QAAS,OACT,UAAW,SACX,MAAO,SAAA,EAGHC,EAAyC,CAC7C,aAAc,OACd,SAAU,MAAA,EAGNC,EAAwC,CAC5C,QAAS,YACT,WAAY,UACZ,MAAO,QACP,OAAQ,OACR,aAAc,MACd,OAAQ,UACR,SAAU,MAAA,EAGNpmC,EAAe,OAAOtoB,GAAU,SAAWA,EAAQA,EAAM,QAE/D,OACEtB,EAAAA,KAAC,MAAA,CAAI,MAAO8vD,EACV,SAAA,CAAAzwD,EAAAA,IAAC,MAAA,CAAI,MAAO0wD,EAAoB,SAAAnmC,EAAa,EAC5CimC,GACCxwD,EAAAA,IAAC,SAAA,CACC,MAAO2wD,EACP,QAAS,IAAMH,EAAQvuD,CAAK,EAC7B,SAAA,IAAA,CAAA,CAED,EAEJ,CAEJ,EAGM2uD,GAAkC,CAAC,CACvC,YAAAC,EAAc,aACd,KAAAnxD,EAAO,QACT,IAAM,CACJ,MAAMoxD,EAAoC,CACxC,WAAY,SAAA,EAIRC,EAAU,CACd,MAAO,OACP,OAAQ,OACR,MAAO,MAAA,EAGT,OAAIF,IAAgB,cAClBC,EAAa,OAAS,MACtBA,EAAa,MAAQ,OACrBA,EAAa,OAAS,GAAGC,EAAQrxD,CAAI,CAAC,OAEtCoxD,EAAa,MAAQ,MACrBA,EAAa,OAAS,OACtBA,EAAa,OAAS,KAAKC,EAAQrxD,CAAI,CAAC,IAGnCM,EAAAA,IAAC,MAAA,CAAI,MAAO8wD,CAAA,CAAc,CACnC,EAaME,GAA8C,CAAC,CACnD,SAAAC,EACA,OAAAC,EACA,QAAAV,EACA,eAAAvc,EAEA,MAAAz3C,CACF,IAAM,CACJ,KAAM,CAAE,YAAA61C,EAAa,MAAAvU,EAAO,iBAAAqzB,EAAkB,OAAA/1D,CAAA,EAAW8xD,GAAA,EAEzD,GAAI,CAAC7a,EACH,OAAOryC,EAAAA,IAACuwD,GAAA,CAAW,MAAM,0BAAA,CAA2B,EAGtD,MAAMrc,EAAe,IAAM,CACrB+c,GACFA,EAAA,CAEJ,EAEMG,EAAa,IAAM,CACnBF,GACFA,EAAO7e,EAAY,SAAS,CAEhC,EAEM/Y,EAAc,IAAM,CACpBk3B,GACFA,EAAQne,EAAY,SAAS,CAEjC,EAEM8B,EAAsB7B,GAAqB,CAC3C2B,GACFA,EAAe3B,EAAQD,EAAY,WAAW,CAElD,EAEMgf,EAAiC,CACrC,WAAYj2D,GAAQ,QAAU,OAAS,UAAY,UACnD,aAAc,MACd,UAAW,4BACX,WAAY,sBACZ,SAAU,OACV,SAAU,SACV,MAAOA,GAAQ,QAAU,OAAS,UAAY,UAC9C,MAAO,OACP,SAAU,OAAA,EAGNk2D,EAA4C,CAChD,QAAS,OACT,UAAW,oBACX,QAAS,OACT,IAAK,MAAA,EAGP,OACE3wD,EAAAA,KAAC,MAAA,CACC,MAAO0wD,EACP,cAAY,YACZ,aAAYj2D,GAAQ,MAGnB,SAAA,CAAAA,GAAQ,aAAe,IACtB4E,EAAAA,IAACquD,GAAA,CACC,MAAAvwB,EACA,SAAU1iC,GAAQ,eAClB,KAAMA,GAAQ,WACd,MAAOA,GAAQ,mBAAmB,MAClC,QAASA,GAAQ,mBAAmB,OAAA,CAAA,EAKxC4E,EAAAA,IAAC2uD,GAAA,CACC,SAAUtc,EAAY,SACtB,YAAaA,EAAY,WAAA,CAAA,EAI1BvU,IAAU,YACTn9B,EAAAA,KAAAsC,EAAAA,SAAA,CAEE,SAAA,CAAAjD,EAAAA,IAAC8uD,GAAA,CACC,YAAazc,EAAY,YACzB,QAASA,EAAY,OAAO,QAC5B,MAAA71C,EACA,SAAU23C,EACV,YAAa/4C,GAAQ,gBAAA,CAAA,EAIvB4E,EAAAA,IAAC,MAAA,CAAI,MAAOsxD,EACV,SAAAtxD,EAAAA,IAACuvD,GAAA,CACC,QAASrb,EACT,SAAU,CAAC+c,EAEV,YAAQ,kBAAoB,MAAA,CAAA,CAC/B,CACF,CAAA,EACF,EAGDnzB,IAAU,SAAWuU,EAAY,aAChCryC,EAAAA,IAAC2vD,GAAA,CACC,MAAOtd,EAAY,YACnB,MAAM,MAAA,CAAA,EAITvU,IAAU,UAAYqzB,GAAoB9e,EAAY,eACrDryC,EAAAA,IAACgwD,GAAA,CACC,cAAe3d,EAAY,cAC3B,WAAY8e,EAAiB,WAC7B,cAAe9e,EAAY,OAAO,aAAA,CAAA,GAKpCvU,IAAU,SAAWA,IAAU,WAC/Bn9B,OAAC,MAAA,CAAI,MAAO2wD,EACT,SAAA,CAAAJ,SACE3B,GAAA,CAAa,QAAS6B,EACpB,SAAAh2D,GAAQ,gBAAkB,MAC7B,EAEDo1D,GACCxwD,EAAAA,IAACuvD,GAAA,CAAa,QAASj2B,EACpB,SAAAl+B,GAAQ,iBAAmB,MAAA,CAC9B,CAAA,CAAA,CAEJ,CAAA,CAAA,CAAA,CAIR,EAIam2D,GAUT,CAAC,CACH,YAAAlf,EACA,MAAAvU,EACA,iBAAAqzB,EACA,QAAAtxD,EACA,MAAAoC,EACA,OAAA7G,EACA,SAAAiD,EACA,SAAA4yD,EACA,OAAAC,EACA,QAAAV,EACA,aAAAgB,EACA,eAAAvd,EACA,aAAAwd,EACA,MAAAj1D,CACF,IAAM,CAEJ,GAAIqD,EACF,OAAOG,EAAAA,IAACkwD,GAAA,CAAa,KAAK,UAAA,CAAW,EAGvC,GAAIjuD,EACF,OACEjC,EAAAA,IAACuwD,GAAA,CACC,MAAAtuD,EACA,QAASuvD,CAAA,CAAA,EAKf,GAAI,CAACnf,EACH,OAAOryC,EAAAA,IAACuwD,GAAA,CAAW,MAAM,0BAAA,CAA2B,EAItD,MAAM/nB,EAAoC,CACxC,YAAA6J,EACA,MAAAvU,EACA,iBAAAqzB,EACA,OAAA/1D,EACA,MAAAoB,CAAA,EAGF,aACGywD,GAAgB,SAAhB,CAAyB,MAAOzkB,EAC9B,SAAAnqC,GACC2B,EAAAA,IAACgxD,GAAA,CACC,SAAAC,EACA,OAAAC,EACA,QAAAV,EACA,eAAAvc,EACA,aAAAwd,EACA,MAAAj1D,CAAA,CAAA,EAGN,CAEJ,EAGA+0D,GAAS,OAASlD,GAClBkD,GAAS,SAAW5C,GACpB4C,GAAS,YAAczC,GACvByC,GAAS,aAAehC,GACxBgC,GAAS,YAAc5B,GACvB4B,GAAS,cAAgBvB,GACzBuB,GAAS,aAAerB,GACxBqB,GAAS,WAAahB,GACtBgB,GAAS,QAAUX,GC3oBnB,SAASc,GAAYC,EAAK,CACxB,GAAIA,EAAI,MACN,OAAOA,EAAI,MAMb,QAASrqD,EAAI,EAAGA,EAAI,SAAS,YAAY,OAAQA,IAC/C,GAAI,SAAS,YAAYA,CAAC,EAAE,YAAcqqD,EACxC,OAAO,SAAS,YAAYrqD,CAAC,CAOnC,CAEA,SAASsqD,GAAmBrkD,EAAS,CACnC,IAAIokD,EAAM,SAAS,cAAc,OAAO,EACxC,OAAAA,EAAI,aAAa,eAAgBpkD,EAAQ,GAAG,EAExCA,EAAQ,QAAU,QACpBokD,EAAI,aAAa,QAASpkD,EAAQ,KAAK,EAGzCokD,EAAI,YAAY,SAAS,eAAe,EAAE,CAAC,EAC3CA,EAAI,aAAa,SAAU,EAAE,EACtBA,CACT,CAEA,IAAIE,IAA0B,UAAY,CAExC,SAASA,EAAWtkD,EAAS,CAC3B,IAAIukD,EAAQ,KAEZ,KAAK,WAAa,SAAUH,EAAK,CAC/B,IAAII,EAEAD,EAAM,KAAK,SAAW,EACpBA,EAAM,eACRC,EAASD,EAAM,eAAe,YACrBA,EAAM,QACfC,EAASD,EAAM,UAAU,WAEzBC,EAASD,EAAM,OAGjBC,EAASD,EAAM,KAAKA,EAAM,KAAK,OAAS,CAAC,EAAE,YAG7CA,EAAM,UAAU,aAAaH,EAAKI,CAAM,EAExCD,EAAM,KAAK,KAAKH,CAAG,CACrB,EAEA,KAAK,SAAWpkD,EAAQ,SAAW,OAAY,GAAiBA,EAAQ,OACxE,KAAK,KAAO,CAAA,EACZ,KAAK,IAAM,EACX,KAAK,MAAQA,EAAQ,MAErB,KAAK,IAAMA,EAAQ,IACnB,KAAK,UAAYA,EAAQ,UACzB,KAAK,QAAUA,EAAQ,QACvB,KAAK,eAAiBA,EAAQ,eAC9B,KAAK,OAAS,IAChB,CAEA,IAAIykD,EAASH,EAAW,UAExB,OAAAG,EAAO,QAAU,SAAiBC,EAAO,CACvCA,EAAM,QAAQ,KAAK,UAAU,CAC/B,EAEAD,EAAO,OAAS,SAAgBE,EAAM,CAIhC,KAAK,KAAO,KAAK,SAAW,KAAQ,KAAO,GAC7C,KAAK,WAAWN,GAAmB,IAAI,CAAC,EAG1C,IAAID,EAAM,KAAK,KAAK,KAAK,KAAK,OAAS,CAAC,EAExC,GAAI,KAAK,SAAU,CACjB,IAAIvpC,EAAQspC,GAAYC,CAAG,EAE3B,GAAI,CAGFvpC,EAAM,WAAW8pC,EAAM9pC,EAAM,SAAS,MAAM,CAC9C,MAAY,CACZ,CACF,MACEupC,EAAI,YAAY,SAAS,eAAeO,CAAI,CAAC,EAG/C,KAAK,KACP,EAEAF,EAAO,MAAQ,UAAiB,CAC9B,KAAK,KAAK,QAAQ,SAAUL,EAAK,CAC/B,IAAIQ,EAEJ,OAAQA,EAAkBR,EAAI,aAAe,KAAO,OAASQ,EAAgB,YAAYR,CAAG,CAC9F,CAAC,EACD,KAAK,KAAO,CAAA,EACZ,KAAK,IAAM,CACb,EAEOE,CACT,GAAC,ECzIUO,GAAK,OACLC,GAAM,QACNC,EAAS,WAETC,GAAU,OACVC,GAAU,OACVC,GAAc,OAIdC,GAAS,UAMTC,GAAY,aAIZC,GAAQ,SChBRC,GAAM,KAAK,IAMX/iC,GAAO,OAAO,aAMdgjC,GAAS,OAAO,OAOpB,SAASC,GAAMv2D,EAAO2e,EAAQ,CACpC,OAAO63C,GAAOx2D,EAAO,CAAC,EAAI,MAAY2e,GAAU,EAAK63C,GAAOx2D,EAAO,CAAC,IAAM,EAAKw2D,GAAOx2D,EAAO,CAAC,IAAM,EAAKw2D,GAAOx2D,EAAO,CAAC,IAAM,EAAKw2D,GAAOx2D,EAAO,CAAC,EAAI,CACvJ,CAMO,SAAS0K,GAAM1K,EAAO,CAC5B,OAAOA,EAAM,KAAI,CAClB,CAOO,SAAS6R,GAAO7R,EAAOo1B,EAAS,CACtC,OAAQp1B,EAAQo1B,EAAQ,KAAKp1B,CAAK,GAAKA,EAAM,CAAC,EAAIA,CACnD,CAQO,SAAS07C,EAAS17C,EAAOo1B,EAASqhC,EAAa,CACrD,OAAOz2D,EAAM,QAAQo1B,EAASqhC,CAAW,CAC1C,CAOO,SAASC,GAAS12D,EAAO22D,EAAQ,CACvC,OAAO32D,EAAM,QAAQ22D,CAAM,CAC5B,CAOO,SAASH,GAAQx2D,EAAOwR,EAAO,CACrC,OAAOxR,EAAM,WAAWwR,CAAK,EAAI,CAClC,CAQO,SAASolD,GAAQ52D,EAAO62D,EAAOv3C,EAAK,CAC1C,OAAOtf,EAAM,MAAM62D,EAAOv3C,CAAG,CAC9B,CAMO,SAASw3C,GAAQ92D,EAAO,CAC9B,OAAOA,EAAM,MACd,CAMO,SAAS+2D,GAAQ/2D,EAAO,CAC9B,OAAOA,EAAM,MACd,CAOO,SAASg3D,GAAQh3D,EAAO02B,EAAO,CACrC,OAAOA,EAAM,KAAK12B,CAAK,EAAGA,CAC3B,CAOO,SAASi3D,GAASvgC,EAAOvQ,EAAU,CACzC,OAAOuQ,EAAM,IAAIvQ,CAAQ,EAAE,KAAK,EAAE,CACnC,CChHO,IAAI9Q,GAAO,EACP6hD,GAAS,EACTv4C,GAAS,EACT9X,GAAW,EACXswD,GAAY,EACZC,GAAa,GAWjB,SAASl1D,GAAMlC,EAAOq3D,EAAMC,EAAQ34D,EAAMoC,EAAOc,EAAU8c,EAAQ,CACzE,MAAO,CAAC,MAAO3e,EAAO,KAAMq3D,EAAM,OAAQC,EAAQ,KAAM34D,EAAM,MAAOoC,EAAO,SAAUc,EAAU,KAAMwT,GAAM,OAAQ6hD,GAAQ,OAAQv4C,EAAQ,OAAQ,EAAE,CACvJ,CAOO,SAAS44C,GAAMF,EAAMt2D,EAAO,CAClC,OAAOu1D,GAAOp0D,GAAK,GAAI,KAAM,KAAM,GAAI,KAAM,KAAM,CAAC,EAAGm1D,EAAM,CAAC,OAAQ,CAACA,EAAK,MAAM,EAAGt2D,CAAK,CAC3F,CAKO,SAASmV,IAAQ,CACvB,OAAOihD,EACR,CAKO,SAAS3iB,IAAQ,CACvB,OAAA2iB,GAAYtwD,GAAW,EAAI2vD,GAAOY,GAAY,EAAEvwD,EAAQ,EAAI,EAExDqwD,KAAUC,KAAc,KAC3BD,GAAS,EAAG7hD,MAEN8hD,EACR,CAKO,SAASK,IAAQ,CACvB,OAAAL,GAAYtwD,GAAW8X,GAAS63C,GAAOY,GAAYvwD,IAAU,EAAI,EAE7DqwD,KAAUC,KAAc,KAC3BD,GAAS,EAAG7hD,MAEN8hD,EACR,CAKO,SAASM,IAAQ,CACvB,OAAOjB,GAAOY,GAAYvwD,EAAQ,CACnC,CAKO,SAAS6wD,IAAS,CACxB,OAAO7wD,EACR,CAOO,SAAS8wD,GAAOd,EAAOv3C,EAAK,CAClC,OAAOs3C,GAAOQ,GAAYP,EAAOv3C,CAAG,CACrC,CAMO,SAAS/P,GAAO5Q,EAAM,CAC5B,OAAQA,EAAI,CAEX,IAAK,GAAG,IAAK,GAAG,IAAK,IAAI,IAAK,IAAI,IAAK,IACtC,MAAO,GAER,IAAK,IAAI,IAAK,IAAI,IAAK,IAAI,IAAK,IAAI,IAAK,IAAI,IAAK,IAAI,IAAK,KAE3D,IAAK,IAAI,IAAK,KAAK,IAAK,KACvB,MAAO,GAER,IAAK,IACJ,MAAO,GAER,IAAK,IAAI,IAAK,IAAI,IAAK,IAAI,IAAK,IAC/B,MAAO,GAER,IAAK,IAAI,IAAK,IACb,MAAO,EACV,CAEC,MAAO,EACR,CAMO,SAASi5D,GAAO53D,EAAO,CAC7B,OAAOqV,GAAO6hD,GAAS,EAAGv4C,GAASm4C,GAAOM,GAAap3D,CAAK,EAAG6G,GAAW,EAAG,CAAA,CAC9E,CAMO,SAASgxD,GAAS73D,EAAO,CAC/B,OAAOo3D,GAAa,GAAIp3D,CACzB,CAMO,SAAS83D,GAASn5D,EAAM,CAC9B,OAAO+L,GAAKitD,GAAM9wD,GAAW,EAAGyH,GAAU3P,IAAS,GAAKA,EAAO,EAAIA,IAAS,GAAKA,EAAO,EAAIA,CAAI,CAAC,CAAC,CACnG,CAcO,SAASo5D,GAAYp5D,EAAM,CACjC,MAAOw4D,GAAYM,GAAI,IAClBN,GAAY,IACfK,GAAI,EAIN,OAAOjoD,GAAM5Q,CAAI,EAAI,GAAK4Q,GAAM4nD,EAAS,EAAI,EAAI,GAAK,GACvD,CAwBO,SAASa,GAAUxmD,EAAO20C,EAAO,CACvC,KAAO,EAAEA,GAASqR,GAAI,GAEjB,EAAAL,GAAY,IAAMA,GAAY,KAAQA,GAAY,IAAMA,GAAY,IAAQA,GAAY,IAAMA,GAAY,KAA9G,CAGD,OAAOQ,GAAMnmD,EAAOkmD,GAAK,GAAMvR,EAAQ,GAAKsR,MAAU,IAAMD,GAAI,GAAM,GAAG,CAC1E,CAMO,SAASlpD,GAAW3P,EAAM,CAChC,KAAO64D,GAAI,GACV,OAAQL,GAAS,CAEhB,KAAKx4D,EACJ,OAAOkI,GAER,IAAK,IAAI,IAAK,IACTlI,IAAS,IAAMA,IAAS,IAC3B2P,GAAU6oD,EAAS,EACpB,MAED,IAAK,IACAx4D,IAAS,IACZ2P,GAAU3P,CAAI,EACf,MAED,IAAK,IACJ64D,GAAI,EACJ,KACJ,CAEC,OAAO3wD,EACR,CAOO,SAASoxD,GAAWt5D,EAAM6S,EAAO,CACvC,KAAOgmD,GAAI,GAEN74D,EAAOw4D,KAAc,IAGpB,GAAIx4D,EAAOw4D,KAAc,IAAWM,GAAI,IAAO,GACnD,MAEF,MAAO,KAAOE,GAAMnmD,EAAO3K,GAAW,CAAC,EAAI,IAAMysB,GAAK30B,IAAS,GAAKA,EAAO64D,GAAI,CAAE,CAClF,CAMO,SAASU,GAAY1mD,EAAO,CAClC,KAAO,CAACjC,GAAMkoD,IAAM,GACnBD,GAAI,EAEL,OAAOG,GAAMnmD,EAAO3K,EAAQ,CAC7B,CC7OO,SAASsxD,GAASn4D,EAAO,CAC/B,OAAO63D,GAAQO,GAAM,GAAI,KAAM,KAAM,KAAM,CAAC,EAAE,EAAGp4D,EAAQ43D,GAAM53D,CAAK,EAAG,EAAG,CAAC,CAAC,EAAGA,CAAK,CAAC,CACtF,CAcO,SAASo4D,GAAOp4D,EAAOq3D,EAAMC,EAAQ5B,EAAM2C,EAAOC,EAAUC,EAAQC,EAAQC,EAAc,CAiBhG,QAhBIjnD,EAAQ,EACRknD,EAAS,EACT/5C,EAAS45C,EACTI,EAAS,EACTC,EAAW,EACXC,EAAW,EACXC,EAAW,EACXC,EAAW,EACXC,EAAY,EACZ7B,EAAY,EACZx4D,EAAO,GACPoC,EAAQs3D,EACRx2D,EAAWy2D,EACXW,EAAYvD,EACZ0B,EAAaz4D,EAEVo6D,GACN,OAAQF,EAAW1B,EAAWA,EAAYK,GAAI,EAAE,CAE/C,IAAK,IACJ,GAAIqB,GAAY,KAAOrC,GAAOY,EAAYz4C,EAAS,CAAC,GAAK,GAAI,CACxD+3C,GAAQU,GAAc1b,EAAQoc,GAAQX,CAAS,EAAG,IAAK,KAAK,EAAG,KAAK,GAAK,KAC5E6B,EAAY,IACb,KACD,CAED,IAAK,IAAI,IAAK,IAAI,IAAK,IACtB5B,GAAcU,GAAQX,CAAS,EAC/B,MAED,IAAK,GAAG,IAAK,IAAI,IAAK,IAAI,IAAK,IAC9BC,GAAcW,GAAWc,CAAQ,EACjC,MAED,IAAK,IACJzB,GAAcY,GAASN,GAAK,EAAK,EAAG,CAAC,EACrC,SAED,IAAK,IACJ,OAAQD,GAAI,EAAE,CACb,IAAK,IAAI,IAAK,IACbT,GAAOkC,GAAQjB,GAAUT,GAAI,EAAIE,GAAK,CAAE,EAAGL,EAAMC,CAAM,EAAGmB,CAAY,EACtE,MACD,QACCrB,GAAc,GACpB,CACI,MAED,IAAK,KAAM0B,EACVN,EAAOhnD,GAAO,EAAIslD,GAAOM,CAAU,EAAI4B,EAExC,IAAK,KAAMF,EAAU,IAAK,IAAI,IAAK,GAClC,OAAQ3B,EAAS,CAEhB,IAAK,GAAG,IAAK,KAAK4B,EAAW,EAE7B,IAAK,IAAKL,EAAYM,GAAa,KAAI5B,EAAa1b,EAAQ0b,EAAY,MAAO,EAAE,GAC5EwB,EAAW,GAAM9B,GAAOM,CAAU,EAAIz4C,GACzCq4C,GAAO4B,EAAW,GAAKO,GAAY/B,EAAa,IAAK1B,EAAM4B,EAAQ34C,EAAS,CAAC,EAAIw6C,GAAYzd,EAAQ0b,EAAY,IAAK,EAAE,EAAI,IAAK1B,EAAM4B,EAAQ34C,EAAS,CAAC,EAAG85C,CAAY,EACzK,MAED,IAAK,IAAIrB,GAAc,IAEvB,QAGC,GAFAJ,GAAOiC,EAAYG,GAAQhC,EAAYC,EAAMC,EAAQ9lD,EAAOknD,EAAQL,EAAOG,EAAQ75D,EAAMoC,EAAQ,CAAA,EAAIc,EAAW,CAAA,EAAI8c,CAAM,EAAG25C,CAAQ,EAEjInB,IAAc,IACjB,GAAIuB,IAAW,EACdN,GAAMhB,EAAYC,EAAM4B,EAAWA,EAAWl4D,EAAOu3D,EAAU35C,EAAQ65C,EAAQ32D,CAAQ,MAEvF,QAAQ82D,IAAW,IAAMnC,GAAOY,EAAY,CAAC,IAAM,IAAM,IAAMuB,EAAM,CAEpE,IAAK,KAAK,IAAK,KAAK,IAAK,KAAK,IAAK,KAClCP,GAAMp4D,EAAOi5D,EAAWA,EAAWvD,GAAQsB,GAAOoC,GAAQp5D,EAAOi5D,EAAWA,EAAW,EAAG,EAAGZ,EAAOG,EAAQ75D,EAAM05D,EAAOt3D,EAAQ,GAAI4d,CAAM,EAAG9c,CAAQ,EAAGw2D,EAAOx2D,EAAU8c,EAAQ65C,EAAQ9C,EAAO30D,EAAQc,CAAQ,EACjN,MACD,QACCu2D,GAAMhB,EAAY6B,EAAWA,EAAWA,EAAW,CAAC,EAAE,EAAGp3D,EAAU,EAAG22D,EAAQ32D,CAAQ,CAChG,CACA,CAEI2P,EAAQknD,EAASE,EAAW,EAAGE,EAAWE,EAAY,EAAGr6D,EAAOy4D,EAAa,GAAIz4C,EAAS45C,EAC1F,MAED,IAAK,IACJ55C,EAAS,EAAIm4C,GAAOM,CAAU,EAAGwB,EAAWC,EAC7C,QACC,GAAIC,EAAW,GACd,GAAI3B,GAAa,IAChB,EAAE2B,UACM3B,GAAa,KAAO2B,KAAc,GAAKtkB,GAAI,GAAM,IACzD,SAEF,OAAQ4iB,GAAc9jC,GAAK6jC,CAAS,EAAGA,EAAY2B,EAAQ,CAE1D,IAAK,IACJE,EAAYN,EAAS,EAAI,GAAKtB,GAAc,KAAM,IAClD,MAED,IAAK,IACJoB,EAAOhnD,GAAO,GAAKslD,GAAOM,CAAU,EAAI,GAAK4B,EAAWA,EAAY,EACpE,MAED,IAAK,IAEAvB,GAAI,IAAO,KACdL,GAAcU,GAAQN,GAAI,CAAE,GAE7BmB,EAASlB,GAAI,EAAIiB,EAAS/5C,EAASm4C,GAAOn4D,EAAOy4D,GAAcc,GAAWR,GAAK,CAAE,CAAC,EAAGP,IACrF,MAED,IAAK,IACA0B,IAAa,IAAM/B,GAAOM,CAAU,GAAK,IAC5C0B,EAAW,EAClB,CACA,CAEC,OAAOR,CACR,CAgBO,SAASc,GAASp5D,EAAOq3D,EAAMC,EAAQ9lD,EAAOknD,EAAQL,EAAOG,EAAQ75D,EAAMoC,EAAOc,EAAU8c,EAAQ,CAK1G,QAJI06C,EAAOX,EAAS,EAChBhD,EAAOgD,IAAW,EAAIL,EAAQ,CAAC,EAAE,EACjCn1D,EAAO6zD,GAAOrB,CAAI,EAEb5qD,EAAI,EAAGuhD,EAAI,EAAG3lB,EAAI,EAAG57B,EAAI0G,EAAO,EAAE1G,EAC1C,QAAS,EAAI,EAAGmiB,EAAI2pC,GAAO52D,EAAOq5D,EAAO,EAAGA,EAAOhD,GAAIhK,EAAImM,EAAO1tD,CAAC,CAAC,CAAC,EAAGwuD,EAAIt5D,EAAO,EAAIkD,EAAM,EAAE,GAC1Fo2D,EAAI5uD,GAAK2hD,EAAI,EAAIqJ,EAAK,CAAC,EAAI,IAAMzoC,EAAIyuB,EAAQzuB,EAAG,OAAQyoC,EAAK,CAAC,CAAC,CAAC,KACnE30D,EAAM2lC,GAAG,EAAI4yB,GAEhB,OAAOp3D,GAAKlC,EAAOq3D,EAAMC,EAAQoB,IAAW,EAAI1C,GAAUr3D,EAAMoC,EAAOc,EAAU8c,CAAM,CACxF,CAQO,SAASu6C,GAASl5D,EAAOq3D,EAAMC,EAAQ,CAC7C,OAAOp1D,GAAKlC,EAAOq3D,EAAMC,EAAQvB,GAASziC,GAAKpd,GAAI,CAAE,EAAG0gD,GAAO52D,EAAO,EAAG,EAAE,EAAG,CAAC,CAChF,CASO,SAASm5D,GAAan5D,EAAOq3D,EAAMC,EAAQ34C,EAAQ,CACzD,OAAOzc,GAAKlC,EAAOq3D,EAAMC,EAAQrB,GAAaW,GAAO52D,EAAO,EAAG2e,CAAM,EAAGi4C,GAAO52D,EAAO2e,EAAS,EAAG,EAAE,EAAGA,CAAM,CAC9G,CCtLO,SAAS46C,GAAW13D,EAAUskB,EAAU,CAI9C,QAHIu+B,EAAS,GACT/lC,EAASo4C,GAAOl1D,CAAQ,EAEnBiJ,EAAI,EAAGA,EAAI6T,EAAQ7T,IAC3B45C,GAAUv+B,EAAStkB,EAASiJ,CAAC,EAAGA,EAAGjJ,EAAUskB,CAAQ,GAAK,GAE3D,OAAOu+B,CACR,CASO,SAAS8U,GAAW/9B,EAASjqB,EAAO3P,EAAUskB,EAAU,CAC9D,OAAQsV,EAAQ,KAAI,CACnB,KAAK26B,GAAO,GAAI36B,EAAQ,SAAS,OAAQ,MACzC,KAAKy6B,GAAQ,KAAKD,GAAa,OAAOx6B,EAAQ,OAASA,EAAQ,QAAUA,EAAQ,MACjF,KAAKs6B,GAAS,MAAO,GACrB,KAAKI,GAAW,OAAO16B,EAAQ,OAASA,EAAQ,MAAQ,IAAM89B,GAAU99B,EAAQ,SAAUtV,CAAQ,EAAI,IACtG,KAAK6vC,GAASv6B,EAAQ,MAAQA,EAAQ,MAAM,KAAK,GAAG,CACtD,CAEC,OAAOq7B,GAAOj1D,EAAW03D,GAAU99B,EAAQ,SAAUtV,CAAQ,CAAC,EAAIsV,EAAQ,OAASA,EAAQ,MAAQ,IAAM55B,EAAW,IAAM,EAC3H,CCzBO,SAAS43D,GAAYC,EAAY,CACvC,IAAI/6C,EAASo4C,GAAO2C,CAAU,EAE9B,OAAO,SAAUj+B,EAASjqB,EAAO3P,EAAUskB,EAAU,CAGpD,QAFIu+B,EAAS,GAEJ55C,EAAI,EAAGA,EAAI6T,EAAQ7T,IAC3B45C,GAAUgV,EAAW5uD,CAAC,EAAE2wB,EAASjqB,EAAO3P,EAAUskB,CAAQ,GAAK,GAEhE,OAAOu+B,CACR,CACD,CAMO,SAASiV,GAAWxzC,EAAU,CACpC,OAAO,SAAUsV,EAAS,CACpBA,EAAQ,OACRA,EAAUA,EAAQ,SACrBtV,EAASsV,CAAO,CACnB,CACD,CCjCA,SAASm+B,GAAQzxD,EAAI,CACnB,IAAIO,EAAQ,OAAO,OAAO,IAAI,EAC9B,OAAO,SAAUmxD,EAAK,CACpB,OAAInxD,EAAMmxD,CAAG,IAAM,SAAWnxD,EAAMmxD,CAAG,EAAI1xD,EAAG0xD,CAAG,GAC1CnxD,EAAMmxD,CAAG,CAClB,CACF,CCDA,IAAIC,GAA8B,SAAqCjD,EAAO2B,EAAQhnD,EAAO,CAI3F,QAHIqnD,EAAW,EACX1B,EAAY,EAGd0B,EAAW1B,EACXA,EAAYM,GAAI,EAEZoB,IAAa,IAAM1B,IAAc,KACnCqB,EAAOhnD,CAAK,EAAI,GAGd,CAAAjC,GAAM4nD,CAAS,GAInBK,GAAI,EAGN,OAAOG,GAAMd,EAAOhwD,EAAQ,CAC9B,EAEIkzD,GAAU,SAAiB3kD,EAAQojD,EAAQ,CAE7C,IAAIhnD,EAAQ,GACR2lD,EAAY,GAEhB,EACE,QAAQ5nD,GAAM4nD,CAAS,EAAC,CACtB,IAAK,GAECA,IAAc,IAAMM,GAAI,IAAO,KAKjCe,EAAOhnD,CAAK,EAAI,GAGlB4D,EAAO5D,CAAK,GAAKsoD,GAA4BjzD,GAAW,EAAG2xD,EAAQhnD,CAAK,EACxE,MAEF,IAAK,GACH4D,EAAO5D,CAAK,GAAKsmD,GAAQX,CAAS,EAClC,MAEF,IAAK,GAEH,GAAIA,IAAc,GAAI,CAEpB/hD,EAAO,EAAE5D,CAAK,EAAIimD,GAAI,IAAO,GAAK,MAAQ,GAC1Ce,EAAOhnD,CAAK,EAAI4D,EAAO5D,CAAK,EAAE,OAC9B,KACF,CAIF,QACE4D,EAAO5D,CAAK,GAAK8hB,GAAK6jC,CAAS,CACvC,OACWA,EAAYK,GAAI,GAEzB,OAAOpiD,CACT,EAEI4kD,GAAW,SAAkBh6D,EAAOw4D,EAAQ,CAC9C,OAAOX,GAAQkC,GAAQnC,GAAM53D,CAAK,EAAGw4D,CAAM,CAAC,CAC9C,EAGIyB,GAA+B,IAAI,QACnCC,GAAS,SAAgBz+B,EAAS,CACpC,GAAI,EAAAA,EAAQ,OAAS,QAAU,CAACA,EAAQ,QAExCA,EAAQ,OAAS,GAQjB,SAJIz7B,EAAQy7B,EAAQ,MAChB67B,EAAS77B,EAAQ,OACjB0+B,EAAiB1+B,EAAQ,SAAW67B,EAAO,QAAU77B,EAAQ,OAAS67B,EAAO,KAE1EA,EAAO,OAAS,QAErB,GADAA,EAASA,EAAO,OACZ,CAACA,EAAQ,OAIf,GAAI,EAAA77B,EAAQ,MAAM,SAAW,GAAKz7B,EAAM,WAAW,CAAC,IAAM,IAEvD,CAACi6D,GAAc,IAAI3C,CAAM,IAMxB,CAAA6C,EAIJ,CAAAF,GAAc,IAAIx+B,EAAS,EAAI,EAK/B,QAJI+8B,EAAS,CAAA,EACTH,EAAQ2B,GAASh6D,EAAOw4D,CAAM,EAC9B4B,EAAc9C,EAAO,MAEhBxsD,EAAI,EAAG47B,EAAI,EAAG57B,EAAIutD,EAAM,OAAQvtD,IACvC,QAASuhD,EAAI,EAAGA,EAAI+N,EAAY,OAAQ/N,IAAK3lB,IAC3CjL,EAAQ,MAAMiL,CAAC,EAAI8xB,EAAO1tD,CAAC,EAAIutD,EAAMvtD,CAAC,EAAE,QAAQ,OAAQsvD,EAAY/N,CAAC,CAAC,EAAI+N,EAAY/N,CAAC,EAAI,IAAMgM,EAAMvtD,CAAC,GAG9G,EACIuvD,GAAc,SAAqB5+B,EAAS,CAC9C,GAAIA,EAAQ,OAAS,OAAQ,CAC3B,IAAIz7B,EAAQy7B,EAAQ,MAGpBz7B,EAAM,WAAW,CAAC,IAAM,KACxBA,EAAM,WAAW,CAAC,IAAM,KAEtBy7B,EAAQ,OAAY,GACpBA,EAAQ,MAAQ,GAEpB,CACF,EAIA,SAASmrB,GAAO5mD,EAAO2e,EAAQ,CAC7B,OAAQ43C,GAAKv2D,EAAO2e,CAAM,EAAC,CAEzB,IAAK,MACH,OAAOm3C,EAAS,SAAW91D,EAAQA,EAGrC,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MAEL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MAEL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MAEL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACH,OAAO81D,EAAS91D,EAAQA,EAG1B,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACH,OAAO81D,EAAS91D,EAAQ61D,GAAM71D,EAAQ41D,GAAK51D,EAAQA,EAGrD,IAAK,MACL,IAAK,MACH,OAAO81D,EAAS91D,EAAQ41D,GAAK51D,EAAQA,EAGvC,IAAK,MACH,OAAO81D,EAAS91D,EAAQ41D,GAAK,QAAU51D,EAAQA,EAGjD,IAAK,MACH,OAAO81D,EAAS91D,EAAQ07C,EAAQ17C,EAAO,iBAAkB81D,EAAS,WAAaF,GAAK,WAAW,EAAI51D,EAGrG,IAAK,MACH,OAAO81D,EAAS91D,EAAQ41D,GAAK,aAAela,EAAQ17C,EAAO,cAAe,EAAE,EAAIA,EAGlF,IAAK,MACH,OAAO81D,EAAS91D,EAAQ41D,GAAK,iBAAmBla,EAAQ17C,EAAO,4BAA6B,EAAE,EAAIA,EAGpG,IAAK,MACH,OAAO81D,EAAS91D,EAAQ41D,GAAKla,EAAQ17C,EAAO,SAAU,UAAU,EAAIA,EAGtE,IAAK,MACH,OAAO81D,EAAS91D,EAAQ41D,GAAKla,EAAQ17C,EAAO,QAAS,gBAAgB,EAAIA,EAG3E,IAAK,MACH,OAAO81D,EAAS,OAASpa,EAAQ17C,EAAO,QAAS,EAAE,EAAI81D,EAAS91D,EAAQ41D,GAAKla,EAAQ17C,EAAO,OAAQ,UAAU,EAAIA,EAGpH,IAAK,MACH,OAAO81D,EAASpa,EAAQ17C,EAAO,qBAAsB,KAAO81D,EAAS,IAAI,EAAI91D,EAG/E,IAAK,MACH,OAAO07C,EAAQA,EAAQA,EAAQ17C,EAAO,eAAgB81D,EAAS,IAAI,EAAG,cAAeA,EAAS,IAAI,EAAG91D,EAAO,EAAE,EAAIA,EAGpH,IAAK,MACL,IAAK,MACH,OAAO07C,EAAQ17C,EAAO,oBAAqB81D,EAAS,QAAa,EAGnE,IAAK,MACH,OAAOpa,EAAQA,EAAQ17C,EAAO,oBAAqB81D,EAAS,cAAgBF,GAAK,cAAc,EAAG,aAAc,SAAS,EAAIE,EAAS91D,EAAQA,EAGhJ,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACH,OAAO07C,EAAQ17C,EAAO,kBAAmB81D,EAAS,MAAM,EAAI91D,EAG9D,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,MAEH,GAAI82D,GAAO92D,CAAK,EAAI,EAAI2e,EAAS,EAAG,OAAQ63C,GAAOx2D,EAAO2e,EAAS,CAAC,EAAC,CAEnE,IAAK,KAEH,GAAI63C,GAAOx2D,EAAO2e,EAAS,CAAC,IAAM,GAAI,MAGxC,IAAK,KACH,OAAO+8B,EAAQ17C,EAAO,mBAAoB,KAAO81D,EAAS,UAAiBD,IAAOW,GAAOx2D,EAAO2e,EAAS,CAAC,GAAK,IAAM,KAAO,QAAQ,EAAI3e,EAG1I,IAAK,KACH,MAAO,CAAC02D,GAAQ12D,EAAO,SAAS,EAAI4mD,GAAOlL,EAAQ17C,EAAO,UAAW,gBAAgB,EAAG2e,CAAM,EAAI3e,EAAQA,CACpH,CACM,MAGF,IAAK,MAEH,GAAIw2D,GAAOx2D,EAAO2e,EAAS,CAAC,IAAM,IAAK,MAGzC,IAAK,MACH,OAAQ63C,GAAOx2D,EAAO82D,GAAO92D,CAAK,EAAI,GAAK,CAAC02D,GAAQ12D,EAAO,YAAY,GAAK,GAAG,EAAC,CAE9E,IAAK,KACH,OAAO07C,EAAQ17C,EAAO,IAAK,IAAM81D,CAAM,EAAI91D,EAG7C,IAAK,KACH,OAAO07C,EAAQ17C,EAAO,wBAAyB,KAAO81D,GAAUU,GAAOx2D,EAAO,EAAE,IAAM,GAAK,UAAY,IAAM,UAAiB81D,EAAS,SAAgBF,GAAK,SAAS,EAAI51D,CACnL,CAEM,MAGF,IAAK,MACH,OAAQw2D,GAAOx2D,EAAO2e,EAAS,EAAE,EAAC,CAEhC,IAAK,KACH,OAAOm3C,EAAS91D,EAAQ41D,GAAKla,EAAQ17C,EAAO,qBAAsB,IAAI,EAAIA,EAG5E,IAAK,KACH,OAAO81D,EAAS91D,EAAQ41D,GAAKla,EAAQ17C,EAAO,qBAAsB,OAAO,EAAIA,EAG/E,IAAK,IACH,OAAO81D,EAAS91D,EAAQ41D,GAAKla,EAAQ17C,EAAO,qBAAsB,IAAI,EAAIA,CACpF,CAEM,OAAO81D,EAAS91D,EAAQ41D,GAAK51D,EAAQA,CAC3C,CAEE,OAAOA,CACT,CAEA,IAAIs6D,GAAW,SAAkB7+B,EAASjqB,EAAO3P,EAAUskB,EAAU,CACnE,GAAIsV,EAAQ,OAAS,IAAQ,CAACA,EAAQ,OAAW,OAAQA,EAAQ,KAAI,CACnE,KAAKw6B,GACHx6B,EAAQ,OAAYmrB,GAAOnrB,EAAQ,MAAOA,EAAQ,MAAM,EACxD,MAEF,KAAK06B,GACH,OAAOoD,GAAU,CAAChC,GAAK97B,EAAS,CAC9B,MAAOigB,EAAQjgB,EAAQ,MAAO,IAAK,IAAMq6B,CAAM,CACvD,CAAO,CAAC,EAAG3vC,CAAQ,EAEf,KAAK6vC,GACH,GAAIv6B,EAAQ,OAAQ,OAAOw7B,GAAQx7B,EAAQ,MAAO,SAAUz7B,EAAO,CACjE,OAAQ6R,GAAM7R,EAAO,uBAAuB,EAAC,CAE3C,IAAK,aACL,IAAK,cACH,OAAOu5D,GAAU,CAAChC,GAAK97B,EAAS,CAC9B,MAAO,CAACigB,EAAQ17C,EAAO,cAAe,IAAM61D,GAAM,IAAI,CAAC,CACrE,CAAa,CAAC,EAAG1vC,CAAQ,EAGf,IAAK,gBACH,OAAOozC,GAAU,CAAChC,GAAK97B,EAAS,CAC9B,MAAO,CAACigB,EAAQ17C,EAAO,aAAc,IAAM81D,EAAS,UAAU,CAAC,CAC7E,CAAa,EAAGyB,GAAK97B,EAAS,CAChB,MAAO,CAACigB,EAAQ17C,EAAO,aAAc,IAAM61D,GAAM,IAAI,CAAC,CACpE,CAAa,EAAG0B,GAAK97B,EAAS,CAChB,MAAO,CAACigB,EAAQ17C,EAAO,aAAc41D,GAAK,UAAU,CAAC,CACnE,CAAa,CAAC,EAAGzvC,CAAQ,CACzB,CAEQ,MAAO,EACT,CAAC,CACP,CACA,EAEIo0C,GAAuB,CAACD,EAAQ,EAEhCE,GAAc,SAAqBzpD,EAAS,CAC9C,IAAIjS,EAAMiS,EAAQ,IAElB,GAAIjS,IAAQ,MAAO,CACjB,IAAI27D,EAAY,SAAS,iBAAiB,mCAAmC,EAK7E,MAAM,UAAU,QAAQ,KAAKA,EAAW,SAAUv4D,EAAM,CAOtD,IAAIw4D,EAAuBx4D,EAAK,aAAa,cAAc,EAEvDw4D,EAAqB,QAAQ,GAAG,IAAM,KAI1C,SAAS,KAAK,YAAYx4D,CAAI,EAC9BA,EAAK,aAAa,SAAU,EAAE,EAChC,CAAC,CACH,CAEA,IAAIy4D,EAAgB5pD,EAAQ,eAAiBwpD,GAEzCK,EAAW,CAAA,EACXC,EACAC,EAAiB,CAAA,EAGnBD,EAAY9pD,EAAQ,WAAa,SAAS,KAC1C,MAAM,UAAU,QAAQ,KAExB,SAAS,iBAAiB,wBAA2BjS,EAAM,KAAM,EAAG,SAAUoD,EAAM,CAGlF,QAFI64D,EAAS74D,EAAK,aAAa,cAAc,EAAE,MAAM,GAAG,EAE/C4I,EAAI,EAAGA,EAAIiwD,EAAO,OAAQjwD,IACjC8vD,EAASG,EAAOjwD,CAAC,CAAC,EAAI,GAGxBgwD,EAAe,KAAK54D,CAAI,CAC1B,CAAC,EAGH,IAAI84D,EAEAC,EAAqB,CAACf,GAAQG,EAAW,EAE7C,CACE,IAAIa,EACAC,EAAoB,CAAC3B,GAAWG,GAAU,SAAUjE,EAAM,CAC5DwF,EAAa,OAAOxF,CAAI,CAC1B,CAAC,CAAC,EACE0F,EAAa3B,GAAWwB,EAAmB,OAAON,EAAeQ,CAAiB,CAAC,EAEnFE,EAAS,SAAgB7qB,EAAQ,CACnC,OAAO+oB,GAAUpB,GAAQ3nB,CAAM,EAAG4qB,CAAU,CAC9C,EAEAJ,EAAU,SAAgBpkB,EAAU0kB,EAAY1vC,EAAO2vC,EAAa,CAClEL,EAAetvC,EAEfyvC,EAAOzkB,EAAWA,EAAW,IAAM0kB,EAAW,OAAS,IAAMA,EAAW,MAAM,EAE1EC,IACF7yD,EAAM,SAAS4yD,EAAW,IAAI,EAAI,GAEtC,CACF,CAEA,IAAI5yD,EAAQ,CACV,IAAK5J,EACL,MAAO,IAAIu2D,GAAW,CACpB,IAAKv2D,EACL,UAAW+7D,EACX,MAAO9pD,EAAQ,MACf,OAAQA,EAAQ,OAChB,QAASA,EAAQ,QACjB,eAAgBA,EAAQ,cAC9B,CAAK,EACD,MAAOA,EAAQ,MACf,SAAU6pD,EACV,WAAY,CAAA,EACZ,OAAQI,CACZ,EACE,OAAAtyD,EAAM,MAAM,QAAQoyD,CAAc,EAC3BpyD,CACT,gEC1aa,IAAImD,EAAe,OAAO,QAApB,YAA4B,OAAO,IAAIoa,EAAEpa,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM2vD,EAAE3vD,EAAE,OAAO,IAAI,cAAc,EAAE,MAAMtF,EAAEsF,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM4vD,EAAE5vD,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM4mB,EAAE5mB,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM+G,EAAE/G,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM66B,EAAE76B,EAAE,OAAO,IAAI,eAAe,EAAE,MAAMd,EAAEc,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM6B,EAAE7B,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM6vD,EAAE7vD,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM2pB,EAAE3pB,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM8vD,EAAE9vD,EACpf,OAAO,IAAI,qBAAqB,EAAE,MAAM2mB,EAAE3mB,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM+pB,EAAE/pB,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM87B,EAAE97B,EAAE,OAAO,IAAI,aAAa,EAAE,MAAMoK,EAAEpK,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,EAAEA,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAMohB,EAAEphB,EAAE,OAAO,IAAI,aAAa,EAAE,MAClQ,SAASytD,EAAE1tD,EAAE,CAAC,GAAc,OAAOA,GAAlB,UAA4BA,IAAP,KAAS,CAAC,IAAIgwD,EAAEhwD,EAAE,SAAS,OAAOgwD,EAAC,CAAE,KAAK31C,EAAE,OAAOra,EAAEA,EAAE,KAAKA,EAAC,CAAE,KAAKb,EAAE,KAAK2C,EAAE,KAAKnH,EAAE,KAAKksB,EAAE,KAAKgpC,EAAE,KAAKjmC,EAAE,OAAO5pB,EAAE,QAAQ,OAAOA,EAAEA,GAAGA,EAAE,SAASA,EAAC,CAAE,KAAK86B,EAAE,KAAKg1B,EAAE,KAAK9lC,EAAE,KAAKpD,EAAE,KAAK5f,EAAE,OAAOhH,EAAE,QAAQ,OAAOgwD,CAAC,CAAC,CAAC,KAAKJ,EAAE,OAAOI,CAAC,CAAC,CAAC,CAAC,SAASC,EAAEjwD,EAAE,CAAC,OAAO0tD,EAAE1tD,CAAC,IAAI8B,CAAC,CAAC,OAAAouD,EAAA,UAAkB/wD,EAAE+wD,EAAA,eAAuBpuD,EAAEouD,EAAA,gBAAwBp1B,EAAEo1B,kBAAwBlpD,EAAEkpD,EAAA,QAAgB71C,EAAE61C,EAAA,WAAmBJ,EAAEI,EAAA,SAAiBv1D,EAAEu1D,EAAA,KAAalmC,EAAEkmC,OAAatpC,EAAEspC,EAAA,OAAeN,EAChfM,EAAA,SAAiBrpC,EAAEqpC,EAAA,WAAmBL,EAAEK,EAAA,SAAiBtmC,EAAEsmC,EAAA,YAAoB,SAASlwD,EAAE,CAAC,OAAOiwD,EAAEjwD,CAAC,GAAG0tD,EAAE1tD,CAAC,IAAIb,CAAC,EAAE+wD,EAAA,iBAAyBD,EAAEC,EAAA,kBAA0B,SAASlwD,EAAE,CAAC,OAAO0tD,EAAE1tD,CAAC,IAAI86B,CAAC,EAAEo1B,EAAA,kBAA0B,SAASlwD,EAAE,CAAC,OAAO0tD,EAAE1tD,CAAC,IAAIgH,CAAC,EAAEkpD,EAAA,UAAkB,SAASlwD,EAAE,CAAC,OAAiB,OAAOA,GAAlB,UAA4BA,IAAP,MAAUA,EAAE,WAAWqa,CAAC,EAAE61C,EAAA,aAAqB,SAASlwD,EAAE,CAAC,OAAO0tD,EAAE1tD,CAAC,IAAI8vD,CAAC,EAAEI,EAAA,WAAmB,SAASlwD,EAAE,CAAC,OAAO0tD,EAAE1tD,CAAC,IAAIrF,CAAC,EAAEu1D,EAAA,OAAe,SAASlwD,EAAE,CAAC,OAAO0tD,EAAE1tD,CAAC,IAAIgqB,CAAC,EAC1dkmC,EAAA,OAAe,SAASlwD,EAAE,CAAC,OAAO0tD,EAAE1tD,CAAC,IAAI4mB,CAAC,EAAEspC,WAAiB,SAASlwD,EAAE,CAAC,OAAO0tD,EAAE1tD,CAAC,IAAI4vD,CAAC,EAAEM,EAAA,WAAmB,SAASlwD,EAAE,CAAC,OAAO0tD,EAAE1tD,CAAC,IAAI6mB,CAAC,EAAEqpC,EAAA,aAAqB,SAASlwD,EAAE,CAAC,OAAO0tD,EAAE1tD,CAAC,IAAI6vD,CAAC,EAAEK,EAAA,WAAmB,SAASlwD,EAAE,CAAC,OAAO0tD,EAAE1tD,CAAC,IAAI4pB,CAAC,EAC1OsmC,EAAA,mBAA2B,SAASlwD,EAAE,CAAC,OAAiB,OAAOA,GAAlB,UAAkC,OAAOA,GAApB,YAAuBA,IAAIrF,GAAGqF,IAAI8B,GAAG9B,IAAI6mB,GAAG7mB,IAAI6vD,GAAG7vD,IAAI4pB,GAAG5pB,IAAI+vD,GAAc,OAAO/vD,GAAlB,UAA4BA,IAAP,OAAWA,EAAE,WAAWgqB,GAAGhqB,EAAE,WAAW4mB,GAAG5mB,EAAE,WAAWgH,GAAGhH,EAAE,WAAW86B,GAAG96B,EAAE,WAAW8vD,GAAG9vD,EAAE,WAAWqK,GAAGrK,EAAE,WAAW,GAAGA,EAAE,WAAWqhB,GAAGrhB,EAAE,WAAW+7B,EAAE,EAAEm0B,EAAA,OAAexC,mDCD/T,QAAQ,IAAI,WAAa,eAC1B,UAAW,CAKd,IAAIyC,EAAY,OAAO,QAAW,YAAc,OAAO,IACnDv9D,EAAqBu9D,EAAY,OAAO,IAAI,eAAe,EAAI,MAC/Dv8D,EAAoBu8D,EAAY,OAAO,IAAI,cAAc,EAAI,MAC7Dt9D,EAAsBs9D,EAAY,OAAO,IAAI,gBAAgB,EAAI,MACjE38D,EAAyB28D,EAAY,OAAO,IAAI,mBAAmB,EAAI,MACvE58D,EAAsB48D,EAAY,OAAO,IAAI,gBAAgB,EAAI,MACjEC,EAAsBD,EAAY,OAAO,IAAI,gBAAgB,EAAI,MACjEt8D,EAAqBs8D,EAAY,OAAO,IAAI,eAAe,EAAI,MAG/DE,EAAwBF,EAAY,OAAO,IAAI,kBAAkB,EAAI,MACrEG,EAA6BH,EAAY,OAAO,IAAI,uBAAuB,EAAI,MAC/Ep8D,EAAyBo8D,EAAY,OAAO,IAAI,mBAAmB,EAAI,MACvE18D,EAAsB08D,EAAY,OAAO,IAAI,gBAAgB,EAAI,MACjEz8D,EAA2By8D,EAAY,OAAO,IAAI,qBAAqB,EAAI,MAC3El8D,EAAkBk8D,EAAY,OAAO,IAAI,YAAY,EAAI,MACzDj8D,EAAkBi8D,EAAY,OAAO,IAAI,YAAY,EAAI,MACzDI,EAAmBJ,EAAY,OAAO,IAAI,aAAa,EAAI,MAC3DK,EAAyBL,EAAY,OAAO,IAAI,mBAAmB,EAAI,MACvEM,EAAuBN,EAAY,OAAO,IAAI,iBAAiB,EAAI,MACnEO,EAAmBP,EAAY,OAAO,IAAI,aAAa,EAAI,MAE/D,SAASQ,EAAmB59D,EAAM,CAChC,OAAO,OAAOA,GAAS,UAAY,OAAOA,GAAS,YACnDA,IAASF,GAAuBE,IAASu9D,GAA8Bv9D,IAASQ,GAAuBR,IAASS,GAA0BT,IAASU,GAAuBV,IAASW,GAA4B,OAAOX,GAAS,UAAYA,IAAS,OAASA,EAAK,WAAamB,GAAmBnB,EAAK,WAAakB,GAAmBlB,EAAK,WAAaq9D,GAAuBr9D,EAAK,WAAac,GAAsBd,EAAK,WAAagB,GAA0BhB,EAAK,WAAay9D,GAA0Bz9D,EAAK,WAAa09D,GAAwB19D,EAAK,WAAa29D,GAAoB39D,EAAK,WAAaw9D,EACplB,CAEA,SAASK,EAAOp6D,EAAQ,CACtB,GAAI,OAAOA,GAAW,UAAYA,IAAW,KAAM,CACjD,IAAIq6D,EAAWr6D,EAAO,SAEtB,OAAQq6D,EAAQ,CACd,KAAKj+D,EACH,IAAIG,GAAOyD,EAAO,KAElB,OAAQzD,GAAI,CACV,KAAKs9D,EACL,KAAKC,EACL,KAAKz9D,EACL,KAAKU,EACL,KAAKC,EACL,KAAKC,EACH,OAAOV,GAET,QACE,IAAI+9D,EAAe/9D,IAAQA,GAAK,SAEhC,OAAQ+9D,EAAY,CAClB,KAAKj9D,EACL,KAAKE,EACL,KAAKG,EACL,KAAKD,EACL,KAAKm8D,EACH,OAAOU,EAET,QACE,OAAOD,CACvB,CAEA,CAEM,KAAKj9D,EACH,OAAOi9D,CACf,CACA,CAGA,CAEA,IAAIE,EAAYV,EACZW,EAAiBV,EACjBW,EAAkBp9D,EAClBq9D,EAAkBd,EAClBe,EAAUv+D,EACVw+D,EAAar9D,EACb8G,EAAWhI,EACXw+D,EAAOn9D,EACPo9D,EAAOr9D,EACPs9D,EAAS39D,EACT49D,EAAWj+D,EACXk+D,EAAaj+D,EACbk+D,GAAWj+D,EACXk+D,GAAsC,GAE1C,SAASC,EAAYp7D,EAAQ,CAEzB,OAAKm7D,KACHA,GAAsC,GAEtC,QAAQ,KAAQ,+KAAyL,GAItME,GAAiBr7D,CAAM,GAAKo6D,EAAOp6D,CAAM,IAAM65D,CACxD,CACA,SAASwB,GAAiBr7D,EAAQ,CAChC,OAAOo6D,EAAOp6D,CAAM,IAAM85D,CAC5B,CACA,SAASwB,EAAkBt7D,EAAQ,CACjC,OAAOo6D,EAAOp6D,CAAM,IAAM3C,CAC5B,CACA,SAASk+D,EAAkBv7D,EAAQ,CACjC,OAAOo6D,EAAOp6D,CAAM,IAAM45D,CAC5B,CACA,SAAS4B,EAAUx7D,EAAQ,CACzB,OAAO,OAAOA,GAAW,UAAYA,IAAW,MAAQA,EAAO,WAAa5D,CAC9E,CACA,SAASq/D,GAAaz7D,EAAQ,CAC5B,OAAOo6D,EAAOp6D,CAAM,IAAMzC,CAC5B,CACA,SAASm+D,GAAW17D,EAAQ,CAC1B,OAAOo6D,EAAOp6D,CAAM,IAAM3D,CAC5B,CACA,SAASs/D,GAAO37D,EAAQ,CACtB,OAAOo6D,EAAOp6D,CAAM,IAAMtC,CAC5B,CACA,SAASk+D,GAAO57D,EAAQ,CACtB,OAAOo6D,EAAOp6D,CAAM,IAAMvC,CAC5B,CACA,SAASo+D,GAAS77D,EAAQ,CACxB,OAAOo6D,EAAOp6D,CAAM,IAAM5C,CAC5B,CACA,SAAS0+D,GAAW97D,EAAQ,CAC1B,OAAOo6D,EAAOp6D,CAAM,IAAMjD,CAC5B,CACA,SAASg/D,EAAa/7D,EAAQ,CAC5B,OAAOo6D,EAAOp6D,CAAM,IAAMhD,CAC5B,CACA,SAASg/D,EAAWh8D,EAAQ,CAC1B,OAAOo6D,EAAOp6D,CAAM,IAAM/C,CAC5B,CAEAg/D,EAAA,UAAoB1B,EACpB0B,EAAA,eAAyBzB,EACzByB,EAAA,gBAA0BxB,EAC1BwB,EAAA,gBAA0BvB,EAC1BuB,EAAA,QAAkBtB,EAClBsB,EAAA,WAAqBrB,EACrBqB,EAAA,SAAmB53D,EACnB43D,EAAA,KAAepB,EACfoB,EAAA,KAAenB,EACfmB,EAAA,OAAiBlB,EACjBkB,EAAA,SAAmBjB,EACnBiB,EAAA,WAAqBhB,EACrBgB,EAAA,SAAmBf,GACnBe,EAAA,YAAsBb,EACtBa,EAAA,iBAA2BZ,GAC3BY,EAAA,kBAA4BX,EAC5BW,EAAA,kBAA4BV,EAC5BU,EAAA,UAAoBT,EACpBS,EAAA,aAAuBR,GACvBQ,EAAA,WAAqBP,GACrBO,EAAA,OAAiBN,GACjBM,EAAA,OAAiBL,GACjBK,EAAA,SAAmBJ,GACnBI,EAAA,WAAqBH,GACrBG,EAAA,aAAuBF,EACvBE,EAAA,WAAqBD,EACrBC,EAAA,mBAA6B9B,EAC7B8B,EAAA,OAAiB7B,CACjB,GAAG,2CCjLC,QAAQ,IAAI,WAAa,aAC3B8B,GAAA,QAAiBh8D,GAAA,EAEjBg8D,GAAA,QAAiBx7D,GAAA,2DCHnB,IAAIy7D,EAAUj8D,GAAA,EAMVk8D,EAAgB,CAClB,kBAAmB,GACnB,YAAa,GACb,aAAc,GACd,aAAc,GACd,YAAa,GACb,gBAAiB,GACjB,yBAA0B,GAC1B,yBAA0B,GAC1B,OAAQ,GACR,UAAW,GACX,KAAM,IAEJC,EAAgB,CAClB,KAAM,GACN,OAAQ,GACR,UAAW,GACX,OAAQ,GACR,OAAQ,GACR,UAAW,GACX,MAAO,IAELC,EAAsB,CACxB,SAAY,GACZ,OAAQ,GACR,aAAc,GACd,YAAa,GACb,UAAW,IAETC,EAAe,CACjB,SAAY,GACZ,QAAS,GACT,aAAc,GACd,YAAa,GACb,UAAW,GACX,KAAM,IAEJC,EAAe,CAAA,EACnBA,EAAaL,EAAQ,UAAU,EAAIG,EACnCE,EAAaL,EAAQ,IAAI,EAAII,EAE7B,SAASE,EAAWC,EAAW,CAE7B,OAAIP,EAAQ,OAAOO,CAAS,EACnBH,EAIFC,EAAaE,EAAU,QAAW,GAAKN,CAChD,CAEA,IAAIO,EAAiB,OAAO,eACxBC,EAAsB,OAAO,oBAC7BC,EAAwB,OAAO,sBAC/BC,EAA2B,OAAO,yBAClC52D,EAAiB,OAAO,eACxB62D,EAAkB,OAAO,UAC7B,SAASC,EAAqBC,EAAiBC,EAAiBC,EAAW,CACzE,GAAI,OAAOD,GAAoB,SAAU,CAEvC,GAAIH,EAAiB,CACnB,IAAIK,EAAqBl3D,EAAeg3D,CAAe,EAEnDE,GAAsBA,IAAuBL,GAC/CC,EAAqBC,EAAiBG,EAAoBD,CAAS,CAE3E,CAEI,IAAIv9D,EAAOg9D,EAAoBM,CAAe,EAE1CL,IACFj9D,EAAOA,EAAK,OAAOi9D,EAAsBK,CAAe,CAAC,GAM3D,QAHIG,EAAgBZ,EAAWQ,CAAe,EAC1CK,EAAgBb,EAAWS,CAAe,EAErCx0D,EAAI,EAAGA,EAAI9I,EAAK,OAAQ,EAAE8I,EAAG,CACpC,IAAIhM,EAAMkD,EAAK8I,CAAC,EAEhB,GAAI,CAAC2zD,EAAc3/D,CAAG,GAAK,EAAEygE,GAAaA,EAAUzgE,CAAG,IAAM,EAAE4gE,GAAiBA,EAAc5gE,CAAG,IAAM,EAAE2gE,GAAiBA,EAAc3gE,CAAG,GAAI,CAC7I,IAAImP,EAAaixD,EAAyBI,EAAiBxgE,CAAG,EAE9D,GAAI,CAEFigE,EAAeM,EAAiBvgE,EAAKmP,CAAU,CACzD,MAAoB,CAAA,CACpB,CACA,CACA,CAEE,OAAOoxD,CACT,CAEA,OAAAM,GAAiBP,UCtGjB,IAAIhtB,GAAY,GAEhB,SAASwtB,GAAoBC,EAAYC,EAAkBC,EAAY,CACrE,IAAIC,EAAe,GACnB,OAAAD,EAAW,MAAM,GAAG,EAAE,QAAQ,SAAU38D,EAAW,CAC7Cy8D,EAAWz8D,CAAS,IAAM,OAC5B08D,EAAiB,KAAKD,EAAWz8D,CAAS,EAAI,GAAG,EACxCA,IACT48D,GAAgB58D,EAAY,IAEhC,CAAC,EACM48D,CACT,CACA,IAAIC,GAAiB,SAAwBv3D,EAAO4yD,EAAY4E,EAAa,CAC3E,IAAI98D,EAAYsF,EAAM,IAAM,IAAM4yD,EAAW,MAO5C4E,IAAgB,IAIjB9tB,KAAc,KAAW1pC,EAAM,WAAWtF,CAAS,IAAM,SACvDsF,EAAM,WAAWtF,CAAS,EAAIk4D,EAAW,OAE7C,EACI6E,GAAe,SAAsBz3D,EAAO4yD,EAAY4E,EAAa,CACvED,GAAev3D,EAAO4yD,EAAY4E,CAAW,EAC7C,IAAI98D,EAAYsF,EAAM,IAAM,IAAM4yD,EAAW,KAE7C,GAAI5yD,EAAM,SAAS4yD,EAAW,IAAI,IAAM,OAAW,CACjD,IAAIjgB,EAAUigB,EAEd,GACE5yD,EAAM,OAAO4yD,IAAejgB,EAAU,IAAMj4C,EAAY,GAAIi4C,EAAS3yC,EAAM,MAAO,EAAI,EAEtF2yC,EAAUA,EAAQ,WACXA,IAAY,OACvB,CACF,ECvCA,SAAS+kB,GAAQx3D,EAAK,CAYpB,QANIgK,EAAI,EAEJ8zB,EACA57B,EAAI,EACJE,EAAMpC,EAAI,OAEPoC,GAAO,EAAG,EAAEF,EAAGE,GAAO,EAC3B07B,EAAI99B,EAAI,WAAWkC,CAAC,EAAI,KAAQlC,EAAI,WAAW,EAAEkC,CAAC,EAAI,MAAS,GAAKlC,EAAI,WAAW,EAAEkC,CAAC,EAAI,MAAS,IAAMlC,EAAI,WAAW,EAAEkC,CAAC,EAAI,MAAS,GACxI47B,GAECA,EAAI,OAAU,aAAeA,IAAM,IAAM,OAAU,IACpDA,GAEAA,IAAM,GACN9zB,GAEC8zB,EAAI,OAAU,aAAeA,IAAM,IAAM,OAAU,KAEnD9zB,EAAI,OAAU,aAAeA,IAAM,IAAM,OAAU,IAItD,OAAQ5H,EAAG,CACT,IAAK,GACH4H,IAAMhK,EAAI,WAAWkC,EAAI,CAAC,EAAI,MAAS,GAEzC,IAAK,GACH8H,IAAMhK,EAAI,WAAWkC,EAAI,CAAC,EAAI,MAAS,EAEzC,IAAK,GACH8H,GAAKhK,EAAI,WAAWkC,CAAC,EAAI,IACzB8H,GAECA,EAAI,OAAU,aAAeA,IAAM,IAAM,OAAU,GAC1D,CAIE,OAAAA,GAAKA,IAAM,GACXA,GAECA,EAAI,OAAU,aAAeA,IAAM,IAAM,OAAU,MAC3CA,EAAIA,IAAM,MAAQ,GAAG,SAAS,EAAE,CAC3C,CCpDA,IAAIytD,GAAe,CACjB,wBAAyB,EACzB,YAAa,EACb,kBAAmB,EACnB,iBAAkB,EAClB,iBAAkB,EAClB,QAAS,EACT,aAAc,EACd,gBAAiB,EACjB,YAAa,EACb,QAAS,EACT,KAAM,EACN,SAAU,EACV,aAAc,EACd,WAAY,EACZ,aAAc,EACd,UAAW,EACX,QAAS,EACT,WAAY,EACZ,YAAa,EACb,aAAc,EACd,WAAY,EACZ,cAAe,EACf,eAAgB,EAChB,gBAAiB,EACjB,UAAW,EACX,cAAe,EACf,aAAc,EACd,iBAAkB,EAClB,WAAY,EACZ,WAAY,EACZ,QAAS,EACT,MAAO,EACP,QAAS,EACT,MAAO,EACP,QAAS,EACT,OAAQ,EACR,OAAQ,EACR,KAAM,EACN,gBAAiB,EAEjB,YAAa,EACb,aAAc,EACd,YAAa,EACb,gBAAiB,EACjB,iBAAkB,EAClB,iBAAkB,EAClB,cAAe,EACf,YAAa,CACf,EC3CIC,GAAiB,aACjBC,GAAiB,8BAEjBC,GAAmB,SAA0B5H,EAAU,CACzD,OAAOA,EAAS,WAAW,CAAC,IAAM,EACpC,EAEI6H,GAAqB,SAA4BzgE,EAAO,CAC1D,OAAOA,GAAS,MAAQ,OAAOA,GAAU,SAC3C,EAEI0gE,GAAkC9G,GAAQ,SAAUhd,EAAW,CACjE,OAAO4jB,GAAiB5jB,CAAS,EAAIA,EAAYA,EAAU,QAAQ0jB,GAAgB,KAAK,EAAE,YAAW,CACvG,CAAC,EAEGK,GAAoB,SAA2B7hE,EAAKkB,EAAO,CAC7D,OAAQlB,EAAG,CACT,IAAK,YACL,IAAK,gBAED,GAAI,OAAOkB,GAAU,SACnB,OAAOA,EAAM,QAAQugE,GAAgB,SAAU1uD,EAAOlE,EAAIC,EAAI,CAC5D,OAAAgzD,GAAS,CACP,KAAMjzD,EACN,OAAQC,EACR,KAAMgzD,EACpB,EACmBjzD,CACT,CAAC,CAGX,CAEE,OAAIkzD,GAAS/hE,CAAG,IAAM,GAAK,CAAC0hE,GAAiB1hE,CAAG,GAAK,OAAOkB,GAAU,UAAYA,IAAU,EACnFA,EAAQ,KAGVA,CACT,EAIA,SAAS8gE,GAAoBC,EAAalB,EAAYmB,EAAe,CACnE,GAAIA,GAAiB,KACnB,MAAO,GAGT,IAAIC,EAAoBD,EAExB,GAAIC,EAAkB,mBAAqB,OAEzC,OAAOA,EAGT,OAAQ,OAAOD,EAAa,CAC1B,IAAK,UAED,MAAO,GAGX,IAAK,SACH,CACE,IAAIE,EAAYF,EAEhB,GAAIE,EAAU,OAAS,EACrB,OAAAN,GAAS,CACP,KAAMM,EAAU,KAChB,OAAQA,EAAU,OAClB,KAAMN,EAClB,EACiBM,EAAU,KAGnB,IAAIC,EAAmBH,EAEvB,GAAIG,EAAiB,SAAW,OAAW,CACzC,IAAI3J,EAAO2J,EAAiB,KAE5B,GAAI3J,IAAS,OAGX,KAAOA,IAAS,QACdoJ,GAAS,CACP,KAAMpJ,EAAK,KACX,OAAQA,EAAK,OACb,KAAMoJ,EACtB,EACcpJ,EAAOA,EAAK,KAIhB,IAAIhnB,EAAS2wB,EAAiB,OAAS,IACvC,OAAO3wB,CACT,CAEA,OAAO4wB,GAAuBL,EAAalB,EAAYmB,CAAa,CACtE,CAEF,IAAK,WACH,CACE,GAAID,IAAgB,OAAW,CAC7B,IAAIM,EAAiBT,GACjBt3D,EAAS03D,EAAcD,CAAW,EACtC,OAAAH,GAASS,EACFP,GAAoBC,EAAalB,EAAYv2D,CAAM,CAC5D,CAEA,KACF,CACN,CAGE,IAAIg4D,EAAWN,EAGb,OAAOM,CAKX,CAEA,SAASF,GAAuBL,EAAalB,EAAYj1D,EAAK,CAC5D,IAAI22D,EAAS,GAEb,GAAI,MAAM,QAAQ32D,CAAG,EACnB,QAASE,EAAI,EAAGA,EAAIF,EAAI,OAAQE,IAC9By2D,GAAUT,GAAoBC,EAAalB,EAAYj1D,EAAIE,CAAC,CAAC,EAAI,QAGnE,SAAShM,KAAO8L,EAAK,CACnB,IAAI5K,EAAQ4K,EAAI9L,CAAG,EAEnB,GAAI,OAAOkB,GAAU,SAAU,CAC7B,IAAIshE,EAAWthE,EAIJygE,GAAmBa,CAAQ,IACpCC,GAAUb,GAAiB5hE,CAAG,EAAI,IAAM6hE,GAAkB7hE,EAAKwiE,CAAQ,EAAI,IAE/E,SAKM,MAAM,QAAQthE,CAAK,GAAK,OAAOA,EAAM,CAAC,GAAM,UAAa6/D,GAAc,KACzE,QAAS2B,EAAK,EAAGA,EAAKxhE,EAAM,OAAQwhE,IAC9Bf,GAAmBzgE,EAAMwhE,CAAE,CAAC,IAC9BD,GAAUb,GAAiB5hE,CAAG,EAAI,IAAM6hE,GAAkB7hE,EAAKkB,EAAMwhE,CAAE,CAAC,EAAI,SAG3E,CACL,IAAIC,EAAeX,GAAoBC,EAAalB,EAAY7/D,CAAK,EAErE,OAAQlB,EAAG,CACT,IAAK,YACL,IAAK,gBACH,CACEyiE,GAAUb,GAAiB5hE,CAAG,EAAI,IAAM2iE,EAAe,IACvD,KACF,CAEF,QAGIF,GAAUziE,EAAM,IAAM2iE,EAAe,GAErD,CACQ,CAEJ,CAGF,OAAOF,CACT,CAEA,IAAIG,GAAe,+BAGfd,GACJ,SAASe,GAAgB5nD,EAAM8lD,EAAYkB,EAAa,CACtD,GAAIhnD,EAAK,SAAW,GAAK,OAAOA,EAAK,CAAC,GAAM,UAAYA,EAAK,CAAC,IAAM,MAAQA,EAAK,CAAC,EAAE,SAAW,OAC7F,OAAOA,EAAK,CAAC,EAGf,IAAI6nD,EAAa,GACbpxB,EAAS,GACbowB,GAAS,OACT,IAAIiB,EAAU9nD,EAAK,CAAC,EAEpB,GAAI8nD,GAAW,MAAQA,EAAQ,MAAQ,OACrCD,EAAa,GACbpxB,GAAUswB,GAAoBC,EAAalB,EAAYgC,CAAO,MACzD,CACL,IAAIC,EAAuBD,EAE3BrxB,GAAUsxB,EAAqB,CAAC,CAClC,CAGA,QAASh3D,EAAI,EAAGA,EAAIiP,EAAK,OAAQjP,IAG/B,GAFA0lC,GAAUswB,GAAoBC,EAAalB,EAAY9lD,EAAKjP,CAAC,CAAC,EAE1D82D,EAAY,CACd,IAAIG,EAAqBF,EAEzBrxB,GAAUuxB,EAAmBj3D,CAAC,CAChC,CAIF42D,GAAa,UAAY,EAIzB,QAHIM,EAAiB,GACjBnwD,GAEIA,EAAQ6vD,GAAa,KAAKlxB,CAAM,KAAO,MAC7CwxB,GAAkB,IAAMnwD,EAAM,CAAC,EAGjC,IAAIvR,EAAO2hE,GAAWzxB,CAAM,EAAIwxB,EAEhC,MAAO,CACL,KAAM1hE,EACN,OAAQkwC,EACR,KAAMowB,EACV,CACA,CCvOA,IAAIsB,GAAe,SAAsB9kC,EAAQ,CAC/C,OAAOA,EAAM,CACf,EAEI+kC,GAAqB9/D,GAAM,mBAA6BA,GAAM,mBAA6B,GAC3F+/D,GAA2CD,IAAsBD,GCKjEG,GAAqChgE,GAAM,cAM/C,OAAO,YAAgB,IAA6Bm4D,GAAY,CAC9D,IAAK,KACP,CAAC,EAAI,IAAI,EAEW6H,GAAoB,SAKxC,IAAIC,GAAmB,SAA0Bt1B,EAAM,CACrD,OAAoBu1B,EAAAA,WAAW,SAAUxhE,EAAOknC,EAAK,CAEnD,IAAIv/B,EAAQ2qC,EAAAA,WAAWgvB,EAAmB,EAC1C,OAAOr1B,EAAKjsC,EAAO2H,EAAOu/B,CAAG,CAC/B,CAAC,CACH,EAEIu6B,GAA8BngE,GAAM,cAAc,EAAE,EA6CpDogE,GAAS,CAAA,EAAG,eAEZC,GAAe,qCACfC,GAAqB,SAA4BhkE,EAAMoC,EAAO,CAEhE,IAAI6hE,EAAW,CAAA,EAEf,QAAS13D,KAAQnK,EACX0hE,GAAO,KAAK1hE,EAAOmK,CAAI,IACzB03D,EAAS13D,CAAI,EAAInK,EAAMmK,CAAI,GAI/B,OAAA03D,EAASF,EAAY,EAAI/jE,EAElBikE,CACT,EAEIC,GAAY,SAAmBC,EAAM,CACvC,IAAIp6D,EAAQo6D,EAAK,MACbxH,EAAawH,EAAK,WAClB5C,EAAc4C,EAAK,YACvB,OAAA7C,GAAev3D,EAAO4yD,EAAY4E,CAAW,EAC7CkC,GAAyC,UAAY,CACnD,OAAOjC,GAAaz3D,EAAO4yD,EAAY4E,CAAW,CACpD,CAAC,EAEM,IACT,EAEI6C,GAAyBT,GAAiB,SAAUvhE,EAAO2H,EAAOu/B,EAAK,CACzE,IAAI+6B,EAAUjiE,EAAM,IAIhB,OAAOiiE,GAAY,UAAYt6D,EAAM,WAAWs6D,CAAO,IAAM,SAC/DA,EAAUt6D,EAAM,WAAWs6D,CAAO,GAGpC,IAAIC,EAAmBliE,EAAM2hE,EAAY,EACrC5C,EAAmB,CAACkD,CAAO,EAC3B5/D,EAAY,GAEZ,OAAOrC,EAAM,WAAc,SAC7BqC,EAAYw8D,GAAoBl3D,EAAM,WAAYo3D,EAAkB/+D,EAAM,SAAS,EAC1EA,EAAM,WAAa,OAC5BqC,EAAYrC,EAAM,UAAY,KAGhC,IAAIu6D,EAAaqG,GAAgB7B,EAAkB,OAAWz9D,GAAM,WAAWmgE,EAAY,CAAC,EAE5Fp/D,GAAasF,EAAM,IAAM,IAAM4yD,EAAW,KAC1C,IAAIsH,EAAW,CAAA,EAEf,QAASM,KAASniE,EACZ0hE,GAAO,KAAK1hE,EAAOmiE,CAAK,GAAKA,IAAU,OAASA,IAAUR,KAC5DE,EAASM,CAAK,EAAIniE,EAAMmiE,CAAK,GAIjC,OAAAN,EAAS,UAAYx/D,EAEjB6kC,IACF26B,EAAS,IAAM36B,GAGG5lC,GAAM,cAAcA,GAAM,SAAU,KAAmBA,GAAM,cAAcwgE,GAAW,CACxG,MAAOn6D,EACP,WAAY4yD,EACZ,YAAa,OAAO2H,GAAqB,QAC7C,CAAG,EAAgB5gE,GAAM,cAAc4gE,EAAkBL,CAAQ,CAAC,CAClE,CAAC,EAEGO,GAAYJ,GC7IZv/D,GAAM,SAAa7E,EAAMoC,EAAO,CAElC,IAAIgZ,EAAO,UAEX,GAAIhZ,GAAS,MAAQ,CAAC0hE,GAAO,KAAK1hE,EAAO,KAAK,EAC5C,OAAOsB,GAAM,cAAc,MAAM,OAAW0X,CAAI,EAGlD,IAAIqpD,EAAarpD,EAAK,OAClBspD,EAAwB,IAAI,MAAMD,CAAU,EAChDC,EAAsB,CAAC,EAAIN,GAC3BM,EAAsB,CAAC,EAAIV,GAAmBhkE,EAAMoC,CAAK,EAEzD,QAAS,EAAI,EAAG,EAAIqiE,EAAY,IAC9BC,EAAsB,CAAC,EAAItpD,EAAK,CAAC,EAGnC,OAAO1X,GAAM,cAAc,MAAM,KAAMghE,CAAqB,CAC9D,GAEC,SAAUC,EAAM,CACf,IAAIC,EAEiBA,IAAQA,EAAMD,EAAK,MAAQA,EAAK,IAAM,CAAA,GAC7D,GAAG9/D,KAAQA,GAAM,CAAA,EAAG,EAsEpB,SAASggE,IAAM,CACb,QAASC,EAAO,UAAU,OAAQ1pD,EAAO,IAAI,MAAM0pD,CAAI,EAAGv4D,EAAO,EAAGA,EAAOu4D,EAAMv4D,IAC/E6O,EAAK7O,CAAI,EAAI,UAAUA,CAAI,EAG7B,OAAOy2D,GAAgB5nD,CAAI,CAC7B,CC7GO,MAAMpE,EAAS,CACpB,OAAQ,CACN,KAAM,CAA4C,MAAO,SAAA,EACzD,WAAY,CAAE,KAAM,UAAW,gBAAiB,UAAW,kBAAmB,SAAA,EAC9E,OAAQ,CAAE,QAAS,SAAA,EACnB,MAAO,CAAE,MAAO,UAAW,OAAQ,UAAW,SAAU,SAAA,CAAU,EAEpE,WAAY,CACV,WAAY,sBACZ,aAAc,OACd,cAAe,OACf,cAAe,MAAA,EAEjB,QAAS,CAAE,GAAI,OAAQ,GAAI,OAAQ,GAAI,OAAQ,GAAI,MAAA,EACnD,aAAc,CAAE,KAAM,MAAO,OAAQ,MAAO,MAAO,KAAA,EACnD,QAAS,CAAE,KAAM,2BAAkE,CACrF,EAG0B6tD;AAAA,gBACV7tD,EAAO,OAAO,WAAW,IAAI;AAAA,mBAC1BA,EAAO,aAAa,IAAI;AAAA,gBAC3BA,EAAO,QAAQ,IAAI;AAAA,iBAClBA,EAAO,WAAW,UAAU;AAAA,eAC9BA,EAAO,WAAW,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWrC6tD;AAAA;AAAA;AAAA;AAAA,eAIO7tD,EAAO,QAAQ,EAAE,IAAIA,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA;AAAA,IAM1C6tD;AAAA,mBACQ7tD,EAAO,WAAW,aAAa;AAAA,qBAC7BA,EAAO,QAAQ,EAAE;AAAA,MAE1B6tD;AAAA,mBACO7tD,EAAO,WAAW,YAAY;AAAA,iBAChCA,EAAO,QAAQ,EAAE,IAAIA,EAAO,QAAQ,EAAE;AAAA,MAE5C6tD;AAAA,mBACQ7tD,EAAO,WAAW,aAAa;AAAA,iBACjCA,EAAO,QAAQ,EAAE,IAAIA,EAAO,QAAQ,EAAE;AAAA,MAI3C6tD;AAAA,iCACqB7tD,EAAO,OAAO,OAAO,OAAO;AAAA,MAEhD6tD;AAAA,gCACmB7tD,EAAO,OAAO,OAAO,OAAO;AAAA;AAAA;AAAA,MAM9C6tD;AAAA,oBACM7tD,EAAO,OAAO,MAAM,QAAQ;AAAA,eACjCA,EAAO,OAAO,KAAK,KAAK;AAAA,MAE5B6tD;AAAA,oBACS7tD,EAAO,OAAO,MAAM,KAAK;AAAA,eAC9BA,EAAO,OAAO,KAAK,KAAK;AAAA,MAE3B6tD;AAAA,oBACQ7tD,EAAO,OAAO,MAAM,MAAM;AAAA,eAC/BA,EAAO,OAAO,KAAK,KAAK;AAAA,MAMT6tD;AAAA,aACjB7tD,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA;AAAA,qBAITA,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAgBjBA,EAAO,aAAa,KAAK;AAAA;AAAA,EAMjC6tD;AAAA,eACE7tD,EAAO,QAAQ,EAAE;AAAA,4BACJA,EAAO,OAAO,OAAO,OAAO;AAAA,IAE/C6tD;AAAA;AAAA,eAEM7tD,EAAO,QAAQ,EAAE,IAAIA,EAAO,QAAQ,EAAE;AAAA,wBAC7BA,EAAO,OAAO,OAAO,OAAO;AAAA,qBAC/BA,EAAO,aAAa,KAAK;AAAA,iBAC7BA,EAAO,WAAW,YAAY;AAAA;AAAA;AAAA;AAAA,sBAIzBA,EAAO,OAAO,MAAM,QAAQ;AAAA;AAAA,IAGvC6tD;AAAA;AAAA,WAEA7tD,EAAO,QAAQ,EAAE;AAAA,IAElB6tD;AAAA,eACK7tD,EAAO,QAAQ,EAAE,IAAIA,EAAO,QAAQ,EAAE;AAAA,wBAC7BA,EAAO,OAAO,OAAO,OAAO;AAAA,qBAC/BA,EAAO,aAAa,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,sBAKxBA,EAAO,OAAO,MAAM,QAAQ;AAAA;AAAA;AAAA;AAAA,oBAI9BA,EAAO,OAAO,MAAM,QAAQ;AAAA,eACjCA,EAAO,OAAO,KAAK,KAAK;AAAA,sBACjBA,EAAO,OAAO,MAAM,QAAQ;AAAA;AAAA,IAOrC6tD;AAAA,eACE7tD,EAAO,QAAQ,EAAE;AAAA,qBACXA,EAAO,aAAa,IAAI;AAAA,cAC/BA,EAAO,QAAQ,EAAE;AAAA,IAEpB6tD;AAAA,kBACO7tD,EAAO,OAAO,WAAW,eAAe;AAAA;AAAA,IAG7C6tD;AAAA,kBACK7tD,EAAO,OAAO,WAAW,iBAAiB;AAAA;AAAA,IAOhD6tD;AAAA,eACG7tD,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAQTA,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAY7B6tD;AAAA;AAAA;AAAA;AAAA,eAII7tD,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAMFA,EAAO,OAAO,MAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAa/B6tD;AAAA,aACd7tD,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,qBAKTA,EAAO,QAAQ,EAAE;AAAA,iBACrBA,EAAO,WAAW,aAAa;AAAA;AAAA;AAAA;AAAA,eAIjCA,EAAO,QAAQ,EAAE,IAAIA,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA;AAAA,qBAIhCA,EAAO,aAAa,MAAM;AAAA;AAAA,iBAE9BA,EAAO,WAAW,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUjC6tD;AAAA;AAAA,kBAEI7tD,EAAO,OAAO,OAAO,OAAO;AAAA,cAChCA,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA,gBAGfA,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA;AAAA,gBAIjBA,EAAO,QAAQ,EAAE;AAAA;AAAA,IAGrB6tD;AAAA;AAAA,kBAEM7tD,EAAO,OAAO,OAAO,OAAO;AAAA,gBAC9BA,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA,kBAGfA,EAAO,QAAQ,EAAE;AAAA;AAAA;AAAA;AAAA,kBAIjBA,EAAO,QAAQ,EAAE;AAAA;AAAA,ICnQnC,MAAM+tD,GAAe,kBACf5yB,GAAiB,0SAGjB6yB,GAAyB,GACzBC,GAA+B,WA6FxBC,GAAkBzmC,GAAAA,OAAA,EAC7B0mC,GAAAA,SACE,CAACzmC,EAAKC,KAAS,CAEb,UAAW,KACX,SAAU,CAAA,EACV,cAAe,EACf,oBAAqB,EACrB,aAAc,WACd,YAAa,CAAA,EACb,kBAAmB,CAAA,EACnB,eAAgB,CAAA,EAChB,gBAAiB,KACjB,aAAc,OACd,QAAS,GACT,MAAO,KACP,UAAW,EACX,UAAW,KACX,gBAAiB,GAGjB,cAAe,MAAOymC,EAAWhzD,IAAY,CAC3CssB,EAAI,CAAE,QAAS,GAAM,UAAA0mC,CAAA,CAAW,EAEhC,GAAI,CACF,KAAM,CAAE,WAAAC,EAAY,OAAA79D,EAAQ,SAAAirC,EAAU,MAAA+U,EAAQwd,IAA2B5yD,EAGnEoB,EAAM,GAAGuxD,EAAY,WAAWM,CAAU,UAAU79D,CAAM,YAAYirC,CAAQ,aAAa2yB,CAAS,aAEpG/zD,EAAW,MAAM,MAAMmC,EAAK,CAChC,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,cAAiB,UAAU2+B,EAAc,EAAA,EAE3C,KAAM,KAAK,UAAU,CAAE,MAAAqV,EAAO,CAAA,CAC/B,EAED,GAAI,CAACn2C,EAAS,GACZ,MAAM,IAAI,MAAM,6BAA6BA,EAAS,MAAM,IAAIA,EAAS,UAAU,EAAE,EAIvF,MAAMi0D,GADO,MAAMj0D,EAAS,KAAA,GACL,WAAa,CAAA,EAG9Bk0D,EAA0C,CAAA,EAChDD,EAAU,QAAS7R,GAAkB,CAC/BA,EAAS,gBAAkB,MAAM,QAAQA,EAAS,cAAc,IAClE8R,EAAe9R,EAAS,SAAS,EAAIA,EAAS,eAElD,CAAC,EAED/0B,EAAI,CACF,SAAU4mC,EACV,cAAeA,EAAU,OACzB,oBAAqB,EACrB,aAAcL,GACd,eAAAM,EACA,QAAS,GACT,MAAO,KACP,UAAW,KAAK,IAAA,CAAI,CACrB,CACH,OAASz+D,EAAO,CACd,MAAMsoB,EAAetoB,aAAiB,MAAQA,EAAM,QAAU,yBAC9D,MAAA43B,EAAI,CACF,MAAOtP,EACP,QAAS,EAAA,CACV,EAEKtoB,CACR,CACF,EAGA,gBAAiB,IAAM,CACrB,KAAM,CAAE,oBAAA0+D,EAAqB,SAAAC,EAAU,aAAApU,CAAA,EAAiB1yB,EAAA,EAGxD,GAAI0yB,IAAiB4T,GAAe,CAClC,QAAQ,KAAK,2CAA2C,EACxD,MACF,CAEIO,EAAsBC,EAAS,OAAS,EAC1C/mC,EAAI,CACF,oBAAqB8mC,EAAsB,EAC3C,aAAcP,EAAA,CACf,EAGDvmC,EAAI,CAAE,gBAAiB,GAAM,CAEjC,EAEA,oBAAqB,IAAM,CACzB,KAAM,CAAE,oBAAA8mC,EAAqB,aAAAnU,CAAA,EAAiB1yB,EAAA,EAE1C0yB,IAAiB4T,IAEjBO,EAAsB,GACxB9mC,EAAI,CACF,oBAAqB8mC,EAAsB,EAC3C,aAAcP,EAAA,CACf,CAEL,EAEA,YAAcpyD,GAAU,CACtB,KAAM,CAAE,SAAA4yD,EAAU,aAAApU,CAAA,EAAiB1yB,EAAA,EAE/B0yB,IAAiB4T,KACjBpyD,EAAQ,GAAKA,GAAS4yD,EAAS,QAEnC/mC,EAAI,CACF,oBAAqB7rB,EACrB,aAAcoyD,EAAA,CACf,EACH,EAGA,YAActiC,GAAU,CACtBjE,EAAI,CAAE,aAAciE,EAAO,CAC7B,EAGA,aAAc,MAAO+iC,EAAWvuB,IAAW,CACzC,KAAM,CAAE,SAAAsuB,EAAU,oBAAAD,CAAA,EAAwB7mC,EAAA,EACpCgnC,EAAiBF,EAASD,CAAmB,EAEnD9mC,EAAI,CAAE,QAAS,GAAM,EAErB,GAAI,CAEF,MAAMmY,EAAgB8uB,GAAgB,OAAO,eAAiB,CAAA,EACxD3uB,EAAYG,EAAO,OAAS,GAAKA,EAAO,CAAC,IAAMN,EAAc,CAAC,EAE9DlsC,EAA2B,CAC/B,WAAYwsC,EACZ,UAAAH,EACA,SAAUA,EACN,wCACA,8BAAA,EAGNtY,EAAI9Z,IAAU,CACZ,YAAa,CAAE,GAAGA,EAAM,YAAa,CAAC8gD,CAAS,EAAGvuB,CAAA,EAClD,kBAAmB,CAAE,GAAGvyB,EAAM,kBAAmB,CAAC8gD,CAAS,EAAG/6D,CAAA,EAC9D,QAAS,GACT,aAAcqsC,EAAY,SAAW,OAAA,EACrC,CACJ,OAASlwC,EAAO,CACd43B,EAAI,CACF,MAAO53B,aAAiB,MAAQA,EAAM,QAAU,mBAChD,QAAS,EAAA,CACV,CACH,CACF,EAEA,iBAAkB,CAAC4+D,EAAWvuB,IAAW,CACvCzY,EAAI9Z,IAAU,CACZ,YAAa,CAAE,GAAGA,EAAM,YAAa,CAAC8gD,CAAS,EAAGvuB,CAAA,CAAO,EACzD,CACJ,EAGA,YAAa,CAACuuB,EAAWx+B,EAAS0+B,IAAgB,CAChDlnC,EAAI9Z,GAAS,CAEX,MAAMihD,GADgBjhD,EAAM,eAAe8gD,CAAS,GAAK,CAAA,GACrB,IAAI32C,GAClCA,EAAM,KAAOmY,GAAWnY,EAAM,OAAS,QAClC,CACL,GAAGA,EACH,SAAU62C,CAAA,EAGP72C,CACR,EAED,MAAO,CACL,eAAgB,CACd,GAAGnK,EAAM,eACT,CAAC8gD,CAAS,EAAGG,CAAA,CACf,CAEJ,CAAC,CACH,EAEA,YAAa,CAACC,EAAY5+B,IAAY,CACpCxI,EAAI,CACF,gBAAiBwI,CAAA,CAClB,CACH,EAEA,gBAAiB,CAAC4+B,EAAYplC,IAAS,CACrChC,EAAI,CACF,aAAcgC,CAAA,CACf,CACH,EAGA,WAAY,IAAM,CAChBhC,EAAI,CAAE,UAAW,KAAK,IAAA,EAAO,CAC/B,EAEA,UAAW,IAAM,CACf,KAAM,CAAE,UAAAqnC,CAAA,EAAcpnC,EAAA,EACtB,GAAIonC,EAAW,CACb,MAAMC,EAAU,KAAK,OAAO,KAAK,IAAA,EAAQD,GAAa,GAAI,EAC1DrnC,EAAI9Z,IAAU,CACZ,UAAWA,EAAM,UAAYohD,EAC7B,UAAW,IAAA,EACX,CACJ,CACF,EAGA,MAAO,IAAM,CACXtnC,EAAI,CACF,UAAW,KACX,SAAU,CAAA,EACV,cAAe,EACf,oBAAqB,EACrB,aAAcumC,GACd,YAAa,CAAA,EACb,kBAAmB,CAAA,EACnB,eAAgB,CAAA,EAChB,gBAAiB,KACjB,aAAc,OACd,QAAS,GACT,MAAO,KACP,UAAW,EACX,UAAW,KACX,gBAAiB,EAAA,CAClB,CACH,EAGA,kBAAmB,IAAM,CACvB,KAAM,CAAE,SAAAQ,EAAU,oBAAAD,CAAA,EAAwB7mC,EAAA,EAC1C,OAAO8mC,EAASD,CAAmB,GAAK,IAC1C,EAEA,YAAa,IAAM,CACjB,KAAM,CAAE,oBAAAA,EAAqB,cAAAS,CAAA,EAAkBtnC,EAAA,EAC/C,MAAO,CACL,QAAS6mC,EAAsB,EAC/B,MAAOS,EACP,WAAYA,EAAgB,GACtBT,EAAsB,GAAKS,EAAiB,IAC9C,CAAA,CAER,EAEA,kBAAmB,IAAM,CACvB,KAAM,CAAE,UAAAb,EAAW,SAAAK,EAAU,kBAAAS,EAAmB,UAAAC,CAAA,EAAcxnC,EAAA,EACxDynC,EAAUX,EAAS,IAAI5uC,IAAM,CACjC,UAAWA,EAAE,UACb,WAAYqvC,EAAkBrvC,EAAE,SAAS,GAAG,YAAc,CAAA,EAC1D,UAAWqvC,EAAkBrvC,EAAE,SAAS,GAAG,WAAa,GACxD,UAAW,CAAA,EACX,EAEIwvC,EAAiBD,EAAQ,OAAOn5D,GAAKA,EAAE,SAAS,EAAE,OAExD,MAAO,CACL,UAAWm4D,GAAa,GACxB,cAAeK,EAAS,OACxB,eAAAY,EACA,SAAUZ,EAAS,OAAS,EAAIY,EAAiBZ,EAAS,OAAS,EACnE,UAAAU,EACA,YAAaV,EAAS,OAAS,EAAIU,EAAYV,EAAS,OAAS,EACjE,QAAAW,CAAA,CAEJ,CAAA,GAEF,CAAE,KAAM,kBAAA,CAAmB,CAE/B,ECrXaE,GAAyB,CAClCznC,EACA4mC,EACApU,EACAsU,EACAY,EACAhB,EACAtlE,IACC,CAED,MAAMumE,EAAcr5C,EAAAA,QAChB,IAAMkkC,IAAiB,WACvB,CAACA,CAAY,CAAA,EAGXoV,EAAYt5C,EAAAA,QACd,IAAM0R,EAAe4mC,EAAS,OAAS,EACvC,CAAC5mC,EAAc4mC,EAAS,MAAM,CAAA,EAG5BiB,EAAgBv5C,EAAAA,QAClB,IAAM0R,EAAe,EACrB,CAACA,CAAY,CAAA,EAIX8nC,EAAwBx5C,EAAAA,QAAQ,IAC9B,CAACw4C,GAAkB,CAACY,EAAyB,GAG7CZ,EAAe,aAAa,SAAS,UAAU,GAGzBJ,GACtBA,EAAegB,CAAgB,GAC/BhB,EAAegB,CAAgB,EAAE,OAAS,EAChB,GAG1BtmE,GAAQ,kBAAoB,OAAkBA,EAAO,gBAElD,GACR,CAAC0lE,EAAgBY,EAAkBhB,EAAgBtlE,GAAQ,eAAe,CAAC,EAE9E,MAAO,CACH,YAAAumE,EACA,UAAAC,EACA,cAAAC,EACA,sBAAAC,CAAA,CAER,ECjDaC,GAAwB,CACjCvV,EACAkV,EACAI,EACApB,EACAsB,IACC,CACD,MAAMC,EAAc5B,GAAgBrgD,GAAKA,EAAE,WAAW,EAChDkiD,EAAkB7B,GAAgBrgD,GAAKA,EAAE,eAAe,EAGxDmiD,EAAwB75C,EAAAA,QAAQ,IAC9B,CAACo5C,GAAoB,CAAChB,EAAuB,CAAA,EAC1CA,EAAegB,CAAgB,GAAK,CAAA,EAC5C,CAAChB,EAAgBgB,CAAgB,CAAC,EAGrCv5C,EAAAA,UAAU,IAAM,CACZ,GAAI,CAACu5C,GAAoB,CAACI,EAAuB,OAGjD,IAAIM,EAA2B,OAE/B,OAAQ5V,EAAA,CACJ,IAAK,WACD4V,EAAU,OACV,MACJ,IAAK,QACL,IAAK,SACDA,EAAU,OACV,MACJ,QACIA,EAAU,MAAA,CAGdJ,IAAiBI,GACjBF,EAAgBR,EAAkBU,CAAO,CAEjD,EAAG,CAAC5V,EAAckV,EAAkBM,EAAcE,EAAiBJ,CAAqB,CAAC,EAGzF,MAAM7/B,EAAoBtO,cAAaqtC,GAAyB,CACxDU,GAGArB,GAAgB,SAAStgD,IAAU,CAC/B,eAAgB,CACZ,GAAGA,EAAM,eACT,CAAC2hD,CAAgB,EAAGV,CAAA,CACxB,EACF,CAEV,EAAG,CAACU,CAAgB,CAAC,EAGft/B,EAAwBzO,cAAa0uC,GAA0B,CACjE,GAAIX,EAAkB,CAGlB,MAAMY,EAAaD,EAAY,OAAS,EAAIA,EAAY,CAAC,EAAI,KAC7DJ,EAAYP,EAAkBY,CAAU,CAC5C,CACJ,EAAG,CAACZ,EAAkBO,CAAW,CAAC,EAElC,MAAO,CACH,sBAAAE,EACA,aAAAH,EACA,kBAAA//B,EACA,sBAAAG,CAAA,CAER,ECvEamgC,GAA0B,CACnCb,EACA1nC,EACAwoC,IACC,CACD,MAAM/V,EAAmB4T,GAAgBrgD,GAAKA,EAAE,gBAAgB,EAC1D0sC,EAAe2T,GAAgBrgD,GAAKA,EAAE,YAAY,EAClDyiD,EAAkBpC,GAAgBrgD,GAAKA,EAAE,eAAe,EACxD0iD,EAAsBrC,GAAgBrgD,GAAKA,EAAE,mBAAmB,EAChE2iD,EAActC,GAAgBrgD,GAAKA,EAAE,WAAW,EAGhDm0B,EAAqBxgB,EAAAA,YACtB2e,GAAqB,CACdovB,GACAjV,EAAiBiV,EAAkBpvB,CAAM,CAEjD,EACA,CAACovB,EAAkBjV,CAAgB,CAAA,EAIjCvY,EAAevgB,EAAAA,YAAY,IAAM,CAC/B+tC,GAAoBc,EAAYd,CAAgB,GAChDhV,EAAagV,EAAkBc,EAAYd,CAAgB,CAAC,CAEpE,EAAG,CAACA,EAAkBc,EAAa9V,CAAY,CAAC,EAG1C0E,EAAaz9B,EAAAA,YACdivC,GAAiE,CAC9DH,EAAA,EACAG,IAAkBlB,EAAkB1nC,EAAe,CAAC,CACxD,EACA,CAACyoC,EAAiBf,EAAkB1nC,CAAY,CAAA,EAI9C6oC,EAAiBlvC,EAAAA,YAClBivC,GAAiE,CAC9DF,EAAA,EACAE,IAAkBlB,EAAkB1nC,EAAe,CAAC,CACxD,EACA,CAAC0oC,EAAqBhB,EAAkB1nC,CAAY,CAAA,EAIlD8oC,EAAmBnvC,EAAAA,YACrB,CAACovC,EAAcH,IAAiE,CAC5ED,EAAYI,EAAO,CAAC,EACpBH,IAAkBlB,EAAkBqB,EAAO,CAAC,CAChD,EACA,CAACJ,EAAajB,CAAgB,CAAA,EAGlC,MAAO,CACH,mBAAAvtB,EACA,aAAAD,EACA,WAAAkd,EACA,eAAAyR,EACA,iBAAAC,CAAA,CAER,ECnDME,GAA4D,CAAC,CACjE,OAAA5nE,EAAS,CAAA,EACT,kBAAA6nE,EACA,cAAAC,EACA,gBAAAN,EACA,UAAAhjE,EAAY,GACZ,MAAA4C,CACF,IAAM,CAEJ,MAAMo+D,EAAWP,GAAgBrgD,GAAKA,EAAE,QAAQ,EAC1Cga,EAAeqmC,GAAgBrgD,GAAKA,EAAE,mBAAmB,EACzDwsC,EAAe6T,GAAgBrgD,GAAKA,EAAE,YAAY,EAClDngB,EAAUwgE,GAAgBrgD,GAAKA,EAAE,OAAO,EACxC/d,EAAQo+D,GAAgBrgD,GAAKA,EAAE,KAAK,EACpCmjD,EAAkB9C,GAAgBrgD,GAAKA,EAAE,eAAe,EACxDqhD,EAAoBhB,GAAgBrgD,GAAKA,EAAE,iBAAiB,EAC5DwiD,EAAcnC,GAAgBrgD,GAAKA,EAAE,WAAW,EAChD0gD,EAAiBL,GAAgBrgD,GAAKA,EAAE,cAAc,EACtDgiD,EAAe3B,GAAgBrgD,GAAKA,EAAE,YAAY,EAClDojD,EAAoB/C,GAAgBrgD,GAAKA,EAAE,iBAAiB,EAG5D8gD,EAAiBx4C,UAAQ,IAAMs4C,EAAS5mC,CAAY,GAAK,KAAM,CAAC4mC,EAAU5mC,CAAY,CAAC,EACvF0nC,EAAmBp5C,EAAAA,QAAQ,IAAMw4C,GAAgB,WAAa,GAAI,CAACA,CAAc,CAAC,EAGlF,CAAE,YAAAa,EAAa,UAAAC,EAAW,cAAAC,EAAe,sBAAAC,CAAA,EAC7CL,GAAuBznC,EAAc4mC,EAAUpU,EAAcsU,EAAgBY,EAAkBhB,EAAgBtlE,CAAM,EAEjH,CAAE,sBAAA+mE,EAAuB,kBAAAlgC,EAAmB,sBAAAG,GAChD2/B,GAAsBvV,EAAckV,EAAkBI,EAAuBpB,EAAgBsB,CAAY,EAErG,CAAE,mBAAA7tB,EAAoB,aAAAD,EAAc,WAAAkd,EAAY,eAAAyR,EAAgB,iBAAAC,GACpEP,GAAwBb,EAAkB1nC,EAAcwoC,CAAW,EAGrEr6C,EAAAA,UAAU,IAAM,CACd,GAAIg7C,GAAmB,OAAOC,GAAsB,WAAY,CAC9D,MAAMrrB,EAAUqrB,EAAA,EAChBH,IAAoBlrB,CAAO,CAC7B,CACF,EAAG,CAACorB,EAAiBC,EAAmBH,CAAiB,CAAC,EAG1D,MAAMI,EAAsBphE,GACtB,OAAOA,GAAU,SAAiBA,EAClCA,aAAiB,MAAcA,EAAM,QAClC,OAAOA,CAAK,EAIrB,OAAIpC,GAAW+gE,EAAS,SAAW,EAE/B5gE,EAAAA,IAAC,OAAI,UAAU,wCAAwC,cAAY,uBACjE,SAAAW,EAAAA,KAAC,MAAA,CAAI,UAAU,cACb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,6EAAA,CAA8E,EAC7FA,EAAAA,IAAC,IAAA,CAAE,UAAU,gBAAgB,SAAA,sBAAA,CAAoB,CAAA,CAAA,CACnD,CAAA,CACF,EAKAiC,GAASA,IAAU,KAEnBjC,EAAAA,IAAC,OAAI,UAAU,wCAAwC,cAAY,qBACjE,SAAAW,EAAAA,KAAC,MAAA,CAAI,UAAU,2BACb,SAAA,CAAAX,EAAAA,IAAC,IAAA,CAAE,UAAU,6BAA6B,SAAA,QAAK,EAC/CA,EAAAA,IAAC,IAAA,CAAG,SAAAqjE,EAAmBphE,CAAK,CAAA,CAAE,CAAA,CAAA,CAChC,CAAA,CACF,EAKC6+D,EAUHngE,EAAAA,KAAC,MAAA,CACC,UAAW,uCAAuCf,CAAS,GAC3D,MAAA4C,EACA,cAAY,yBACZ,KAAK,SACL,aAAW,SAGX,SAAA,CAAAxC,EAAAA,IAAC,MAAA,CAAI,UAAU,OACb,SAAAA,EAAAA,IAACsjE,GAAAA,WAAA,CACC,MAAO1C,EAAS,OAChB,KAAM5mC,EAAe,EACrB,SAAW+oC,GAASD,EAAiBC,EAAMH,CAAe,EAC1D,WAAY,CAACjB,EACb,aAAc,GACd,MAAM,UACN,KAAK,KACL,UAAU,gBAAA,CAAA,EAEd,EAGA3hE,EAAAA,IAACuxD,GAAA,CACC,YAAauP,EACb,MAAOtU,EACP,iBAAkB6U,EAAkBK,CAAgB,EACpD,QAAA7hE,EACA,MAAOoC,EAAQohE,EAAmBphE,CAAK,EAAI,OAC3C,MAAOugE,EAAYd,CAAgB,EACnC,eAAgBvtB,EAChB,SAAUD,EACV,OAAQ,IAAMkd,EAAWwR,CAAe,EACxC,OAAQ,CACN,MAAOxnE,EAAO,OAAS,QACvB,iBAAkB,OAClB,eAAgBoxD,IAAiB,QAAU,UAAY,MACvD,UAAWpxD,EAAO,WAAA,CACpB,CAAA,EAID0mE,GACC9hE,EAAAA,IAAC,MAAA,CAAI,UAAU,gCAAgC,cAAY,sBACzD,SAAAA,EAAAA,IAAC8lC,GAAA,CACC,OAAQq8B,EACR,KAAMH,EACN,cAAe//B,EACf,kBAAmBG,EAEnB,SAAU,GACV,SAAU,GACV,MAAO,IACP,OAAQ,IACR,mBAAoB,CAClB,QAAS,GACT,OAAQ,EACR,QAAS,CAAA,CACX,CAAA,EAEJ,EAIDhnC,EAAO,cACNuF,OAAC,MAAA,CAAI,UAAU,yCACb,SAAA,CAAAX,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM6iE,EAAeD,CAAe,EAC7C,SAAU,CAACf,EACX,UAAU,yIACX,SAAA,KAAA,CAAA,EAIDlhE,EAAAA,KAAC,MAAA,CAAI,UAAU,wBACZ,SAAA,CAAAq5B,EAAe,EAAE,MAAI4mC,EAAS,MAAA,EACjC,EAEA5gE,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMoxD,EAAWwR,CAAe,EACzC,SAAU,CAAChB,GAAa,CAACD,EACzB,UAAU,0IACX,SAAA,KAAA,CAAA,CAED,EACF,EAIDuB,GACCljE,EAAAA,IAAC,MAAA,CAAI,UAAU,2BACb,SAAAA,EAAAA,IAAC,SAAA,CACC,QAASkjE,EACT,UAAU,wEACX,SAAA,MAAA,CAAA,CAED,CACF,CAAA,CAAA,CAAA,EAxGFljE,EAAAA,IAAC,MAAA,CAAI,UAAU,wCAAwC,cAAY,qBACjE,SAAAA,EAAAA,IAAC,IAAA,CAAE,UAAU,gBAAgB,SAAA,uBAAA,CAAqB,EACpD,CA0GN,EC5LMujE,GAAkD,CAAC,CACvD,UAAAhD,EACA,QAAA7yB,EACA,OAAA/qC,EACA,SAAAirC,EACA,OAAA/pB,EACA,OAAAzoB,EAAS,CAAA,EACT,UAAAwE,EAAY,GACZ,kBAAAqjE,EACA,cAAAC,CACF,IAAM,CAEJ,KAAM,CAACM,EAAWC,CAAY,EAAIpuC,WAA+B,CAC/D,QAAS,GACT,MAAO,KACP,YAAa,EAAA,CACd,EACK,CAACquC,EAAYC,CAAa,EAAItuC,EAAAA,SAAS,CAAC,EAGxC,CAACuuC,EAAcC,CAAe,EAAIxuC,EAAAA,SAAiB,EAAE,EACrDyuC,EAAiBrwC,EAAAA,OAAoB,IAAI,EACzCswC,EAAatwC,EAAAA,OAAuB,IAAI,EACxCuwC,EAAWvwC,EAAAA,OAAuB,IAAI,EAGtCwwC,EAAgB5D,GAAgBrgD,GAAKA,EAAE,aAAa,EACpDkkD,EAAQ7D,GAAgBrgD,GAAKA,EAAE,KAAK,EAG1CmI,EAAAA,UAAU,IAAM,CACd,MAAMg8C,EAAoB,SAAY,CACpC,GAAI,CACFV,EAAazyB,IAAS,CAAE,GAAGA,EAAM,QAAS,GAAM,MAAO,MAAO,EAE9D,QAAQ,IAAI,8BAA+B,CACzC,UAAAuvB,EACA,QAAA7yB,EACA,OAAA/qC,EACA,SAAAirC,EACA,OAAA/pB,CAAA,CACD,EAGD,MAAMogD,EAAc1D,EAAW,CAC7B,WAAY,SAAS7yB,EAAQ,QAAQ,IAAK,EAAE,CAAC,GAAK,EAClD,OAAA/qC,EACA,SAAAirC,EACA,MAAOxyC,EAAO,eAAiB,EAAA,CAChC,EAEDqoE,EAAazyB,IAAS,CAAE,GAAGA,EAAM,QAAS,GAAO,YAAa,IAAO,EACrE,QAAQ,IAAI,4BAA4B,CAE1C,OAASt2B,EAAK,CACZ,MAAM6P,EAAe7P,aAAe,MAAQA,EAAI,QAAU,+BAC1D+oD,EAAazyB,IAAS,CACpB,GAAGA,EACH,QAAS,GACT,MAAOzmB,EACP,YAAa,EAAA,EACb,EACF,QAAQ,MAAM,6BAA8B7P,CAAG,CACjD,CACF,EAGI6lD,GAAa7yB,GAAW/qC,GAAUirC,GAAY,CAAC41B,EAAU,aAC3DW,EAAA,CAEJ,EAAG,CAAC5D,EAAW7yB,EAAS/qC,EAAQirC,EAAUq2B,EAAe7oE,EAAO,cAAeooE,EAAU,YAAaE,CAAU,CAAC,EAGjHv7C,EAAAA,UAAU,IAAM,CAEVq7C,EAAU,SAAW,CAACA,EAAU,YAClCK,EAAgB,mBAAmB,EAC1BL,EAAU,MACnBK,EAAgB,QAAQL,EAAU,KAAK,cAAc,EAC5CA,EAAU,aACnBK,EAAgB,oBAAoB,CAExC,EAAG,CAACL,EAAU,QAASA,EAAU,MAAOA,EAAU,WAAW,CAAC,EAE9Dr7C,EAAAA,UAAU,IAAM,CAEVq7C,EAAU,aAAeM,EAAe,SAC1CA,EAAe,QAAQ,MAAA,CAE3B,EAAG,CAACN,EAAU,WAAW,CAAC,EAE1Br7C,EAAAA,UAAU,IAAM,CAEVq7C,EAAU,OAASQ,EAAS,SAC9BA,EAAS,QAAQ,MAAA,CAErB,EAAG,CAACR,EAAU,KAAK,CAAC,EAEpBr7C,EAAAA,UAAU,IAAM,CAEVq7C,EAAU,SAAWO,EAAW,SAClCA,EAAW,QAAQ,MAAA,CAEvB,EAAG,CAACP,EAAU,OAAO,CAAC,EAGtBr7C,EAAAA,UAAU,IACD,IAAM,CACX,QAAQ,IAAI,4BAA4B,EACxC+7C,EAAA,CACF,EACC,CAACA,CAAK,CAAC,EAGV,MAAME,EAAwBzwC,cAAaokB,GAAiB,CAC1D,QAAQ,IAAI,2BAA4BA,CAAO,EAC/CkrB,IAAoBlrB,CAAO,CAC7B,EAAG,CAACkrB,CAAiB,CAAC,EAEhBoB,EAAoB1wC,EAAAA,YAAY,IAAM,CAC1C,QAAQ,IAAI,0BAA0B,EACtCuvC,IAAA,CACF,EAAG,CAACA,CAAa,CAAC,EAEZoB,EAAsB3wC,EAAAA,YAAY,CAACktC,EAAmB7yD,IAAkB,CAC5E,QAAQ,IAAI,6BAA6BA,EAAQ,CAAC,GAAI6yD,CAAS,CACjE,EAAG,CAAA,CAAE,EAGC1sC,EAAgBR,cAAa/wB,GAA+B,CAE5DA,EAAM,MAAQ,WAChBA,EAAM,eAAA,EACNyhE,EAAA,GAGEzhE,EAAM,MAAQ,SAAW4gE,EAAU,OAAS5gE,EAAM,SAAWohE,EAAS,UACxEphE,EAAM,eAAA,EACN6gE,EAAa,CAAE,QAAS,GAAO,MAAO,KAAM,YAAa,GAAO,EAChEE,EAAc3yB,GAAQA,EAAO,CAAC,EAElC,EAAG,CAACqzB,EAAmBb,EAAU,KAAK,CAAC,EAKvC,OAAIA,EAAU,SAAW,CAACA,EAAU,YAEhC7iE,EAAAA,KAAC,MAAA,CACC,UAAW,6BAA6Bf,CAAS,GACjD,cAAY,oBACZ,KAAK,OACL,aAAW,SACX,UAAWu0B,EACX,SAAU,GACV,IAAK4vC,EAGL,SAAA,CAAA/jE,EAAAA,IAAC,MAAA,CACC,YAAU,YACV,cAAY,OACZ,UAAU,UAET,SAAA4jE,CAAA,CAAA,EAGH5jE,EAAAA,IAAC,MAAA,CAAI,UAAU,yBACb,SAAAW,EAAAA,KAAC,MAAA,CACC,UAAU,kBACV,cAAY,uBACZ,KAAK,SACL,aAAW,WAEX,SAAA,CAAAX,EAAAA,IAAC,MAAA,CACC,UAAU,UACV,cAAY,MAAA,CAAA,EAEdA,EAAAA,IAAC,IAAA,CAAE,UAAU,eAAe,SAAA,aAAA,CAAW,CAAA,CAAA,CAAA,CACzC,CACF,CAAA,CAAA,CAAA,EAMFwjE,EAAU,MAEV7iE,EAAAA,KAAC,MAAA,CACC,UAAW,2BAA2Bf,CAAS,GAC/C,cAAY,oBACZ,KAAK,OACL,aAAW,gBACX,UAAWu0B,EACX,SAAU,GACV,IAAK6vC,EAGL,SAAA,CAAAhkE,EAAAA,IAAC,MAAA,CACC,YAAU,YACV,cAAY,OACZ,UAAU,UAET,SAAA4jE,CAAA,CAAA,EAGHjjE,EAAAA,KAAC,MAAA,CAAI,UAAU,kBACb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CACC,UAAU,aACV,KAAK,MACL,aAAW,OACZ,SAAA,IAAA,CAAA,EAGDA,EAAAA,IAAC,KAAA,CAAG,UAAU,cAAc,SAAA,OAAI,EAChCA,EAAAA,IAAC,IAAA,CAAE,UAAU,gBAAiB,WAAU,MAAM,EAC9CA,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM,CACbyjE,EAAa,CAAE,QAAS,GAAO,MAAO,KAAM,YAAa,GAAO,EAChEE,EAAc3yB,GAAQA,EAAO,CAAC,CAChC,EACA,UAAU,eACV,cAAY,eACZ,aAAW,WACZ,SAAA,IAAA,CAAA,CAED,CAAA,CACF,CAAA,CAAA,CAAA,EAOJrwC,EAAAA,KAAC,MAAA,CACC,UAAW,qBAAqBf,CAAS,GACzC,cAAY,oBACZ,KAAK,OACL,aAAW,SACX,UAAWu0B,EAGX,SAAA,CAAAn0B,EAAAA,IAAC,MAAA,CACC,YAAU,SACV,cAAY,OACZ,UAAU,UAET,SAAA4jE,CAAA,CAAA,EAIFxoE,EAAO,QAAQ,YACd4E,EAAAA,IAAC,SAAA,CAAO,UAAU,cAAc,KAAK,SACnC,SAAAW,OAAC,MAAA,CAAI,UAAU,iBACb,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,aAAa,SAAA,OAAI,EAC/BW,EAAAA,KAAC,MAAA,CAAI,UAAU,eAAe,aAAW,OACvC,SAAA,CAAAA,EAAAA,KAAC,OAAA,CAAK,UAAU,aAAa,SAAA,CAAA,OAAK4/D,CAAA,EAAU,EAC5C5/D,EAAAA,KAAC,OAAA,CAAK,UAAU,aAAa,SAAA,CAAA,OAAK+sC,CAAA,CAAA,CAAQ,CAAA,CAAA,CAC5C,CAAA,CAAA,CACF,CAAA,CACF,EAIF1tC,EAAAA,IAAC,OAAA,CACC,UAAU,YACV,IAAK8jE,EACL,SAAU,GACV,aAAW,aAEX,SAAA9jE,EAAAA,IAACgjE,GAAA,CACC,OAAQ,CACN,aAAc5nE,EAAO,cAAgB,GACrC,YAAaA,EAAO,aAAe,GACnC,YAAaA,EAAO,aAAe,GACnC,MAAOA,EAAO,OAAS,OAAA,EAEzB,kBAAmBgpE,EACnB,cAAeC,EACf,gBAAiBC,CAAA,CAAA,CACnB,CAAA,EAIDlpE,EAAO,QAAQ,kBACb,SAAA,CAAO,UAAU,cAAc,KAAK,cACnC,eAAC,MAAA,CAAI,UAAU,iBACb,SAAA4E,EAAAA,IAAC,IAAA,CAAE,UAAU,cAAc,SAAA,6BAAA,CAE3B,EACF,CAAA,CACF,CAAA,CAAA,CAAA,CAIR,EAGAukE,GAAe1lE,EAAM,KAAK0kE,EAAe,ECpT5BiB,GAAiE,CAAC,CAC7E,YAAAnyB,EACA,WAAAN,EACA,eAAAqE,CACF,WAEK,MAAA,CAEC,SAAA,CAAAz1C,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,sBAAsB,SAAA,cAAW,EAC/CW,EAAAA,KAAC,IAAA,CAAE,UAAU,4BAA4B,SAAA,CAAA,UAChCX,EAAAA,IAAC,SAAA,CACL,SAAAqyC,EAAY,OAAO,KAAA,CACtB,CAAA,CAAA,CACF,CAAA,EACF,EACAryC,EAAAA,IAAC,SAAA,CACC,QAASo2C,EACT,UAAU,4BACX,SAAA,KAAA,CAAA,CAED,EACF,EAGAz1C,EAAAA,KAAC,MAAA,CAAI,UAAU,uBAEb,SAAA,CAAAX,EAAAA,IAAC40C,GAAA,CACC,YAAAvC,EACA,WAAAN,CAAA,CAAA,EAIF/xC,EAAAA,IAAC21C,GAAA,CACC,YAAAtD,CAAA,CAAA,CACF,EACF,EAGAryC,EAAAA,IAAC,MAAA,CAAI,UAAU,sBACb,SAAAA,EAAAA,IAAC,SAAA,CACC,QAASo2C,EACT,UAAU,wBACX,SAAA,KAAA,CAAA,CAED,CACF,CAAA,EACF,yjLCtCSquB,GAAkE,CAAC,CAC9E,UAAA7kE,EAAY,EACd,IAAM,CAEJ,MAAM4sD,EAAe/Z,GAAA,EACfV,EAAaW,GAAA,EACbqB,EAAiBnB,GAAA,EACjB,CAAE,iBAAA6Z,EAAkB,aAAAC,EAAc,aAAAC,CAAA,EAAiB5Z,GAAA,EAGnD2xB,EAAwB1iE,GAAuC,CACnE,GAAI,CAACA,EAAM,OAAOA,EAGlB,MAAMiS,EAAa,KAAK,MAAM,KAAK,UAAUjS,CAAI,CAAC,EAGlD,OAAKiS,EAAW,SAAQA,EAAW,OAAS,QACvCA,EAAW,QAAOA,EAAW,MAAQ,UACrCA,EAAW,YAAWA,EAAW,UAAY,aAC9C,CAACA,EAAW,iBAAmB,CAAC,MAAM,QAAQA,EAAW,eAAe,KAC1EA,EAAW,gBAAkB,CAAC,OAAQ,MAAM,GAEzCA,EAAW,aAAYA,EAAW,WAAa,GAC/CA,EAAW,WACdA,EAAW,SAAW,CACpB,MAAO,KACP,MAAO,OACP,KAAM,CAAC,KAAM,IAAI,CAAA,GAKF,CAAC,WAAY,QAAS,SAAU,UAAU,EAClD,QAAQ0wD,GAAa,CAC9B,GAAI1wD,EAAW,SAAS0wD,CAAS,EAAG,CAClC,MAAM7mC,EAAQ7pB,EAAW,OAAO0wD,CAAS,EAErC,CAAC7mC,EAAM,OAASA,EAAM,UACxBA,EAAM,MAAQA,EAAM,SAGjB,MAAM,QAAQA,EAAM,KAAK,IAC5BA,EAAM,MAAQ,CAAA,EAElB,CACF,CAAC,EAEM7pB,CACT,EAGM2wD,EAAoBt8C,EAAAA,QAAQ,IACzBo8C,EAAqBG,EAAe,EAC1C,CAAA,CAAE,EAEL,OACElkE,EAAAA,KAAC,MAAA,CAAI,UAAW,yDAAyDf,CAAS,GAEhF,SAAA,CAAAe,EAAAA,KAAC,SAAA,CAAO,UAAU,OAChB,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,oCAAoC,SAAA,OAAI,EACtDW,EAAAA,KAAC,IAAA,CAAE,UAAU,sBACV,SAAA,CAAAikE,EAAkB,MAAM,QAAMA,EAAkB,IAAA,CAAA,CACnD,CAAA,EACF,EAGAjkE,EAAAA,KAAC,OAAA,CAAK,UAAU,wDAEb,SAAA,CAAA6rD,IAAiB,YAChBxsD,EAAAA,IAAC8zC,GAAA,CACC,YAAa8wB,EACb,WAAA7yB,EACA,eAAAgC,EACA,eAAgB2Y,EAChB,eAAgBD,CAAA,CAAA,EAKnBD,IAAiB,eAChBxsD,EAAAA,IAACm2C,GAAA,CACC,YAAayuB,EACb,WAAA7yB,EACA,eAAgB4a,CAAA,CAAA,EAKnBH,IAAiB,WAChBxsD,EAAAA,IAACq2C,GAAA,CACC,YAAauuB,EACb,eAAgBjY,CAAA,CAAA,CAClB,CAAA,CAEJ,CAAA,EACF,CAEJ,EC7GamY,GAA0ClrC,GAAAA,OAAkCC,IAAS,CAEhG,aAAc,WACd,WAAY,GACZ,UAAW,KACX,eAAgB,GAChB,YAAa,KACb,gBAAiB,KAGjB,eAAiBwY,GAAgB,CAC/BxY,EAAI,CACF,YAAAwY,EACA,aAAc,WACd,WAAY,GACZ,UAAW,KACX,eAAgB,GAChB,gBAAiB,IAAA,CAClB,CACH,EAGA,iBAAmBC,GAAmB,CACpCzY,EAAI,CACF,WAAYyY,EACZ,gBAAiB,IAAA,CAClB,CACH,EAGA,aAAeA,GAAmB,CAChC,MAAMvyB,EAAQ+kD,GAAwC,SAAA,EAGtD,GAAI,CAAC/kD,EAAM,YAAa,CACtB8Z,EAAI,CACF,gBAAiB,iBAAA,CAClB,EACD,MACF,CAGA,MAAMmY,EAAgBjyB,EAAM,YAAY,OAAO,MAAM,SAAA,EAG/CglD,EAAmBzyB,EAAO,KAAA,EAC1B0yB,EAAoBhzB,EAAc,KAAA,EAGxC,IAAIG,EAAY,IACZ4yB,IAAqBC,GAEdD,IAAqB,OAASC,IAAsB,QAEpDD,IAAqB,QAAUC,IAAsB,UAC9D7yB,EAAY,IAGdtY,EAAI,CACF,WAAYyY,EACZ,UAAAH,EACA,eAAgB,GAChB,gBAAiB,KACjB,aAAcA,EAAY,UAAY,aAAA,CACvC,CACH,EAGA,aAAc,IAAM,CAClBtY,EAAI,CACF,aAAc,WACd,WAAY,GACZ,UAAW,KACX,eAAgB,GAChB,gBAAiB,IAAA,CAClB,CACH,EAGA,aAAc,IAAM,CAClBA,EAAI,CACF,aAAc,WACd,WAAY,GACZ,UAAW,KACX,eAAgB,GAChB,gBAAiB,IAAA,CAClB,CACH,CACF,EAAE,EAKWorC,GAAyB,IAC7BH,GAAyC/kD,GAAUA,EAAM,YAAY,EAMjEmlD,GAAuB,IAC3BJ,GAAyC/kD,GAAUA,EAAM,UAAU,EAa/DolD,GAAiC,IACrCL,GAAyC/kD,GAAUA,EAAM,cAAc,EAMnEqlD,GAA4B,IAChCN,GAAyC/kD,GAAUA,EAAM,eAAe,EAcpEslD,GAA2B,IACtCP,GACEvqC,GAAAA,WAGIxa,IAAW,CACb,iBAAkBA,EAAM,iBACxB,aAAcA,EAAM,aACpB,aAAcA,EAAM,aACpB,aAAcA,EAAM,aACpB,eAAgBA,EAAM,cAAA,EACtB,CACJ,ECrJWulD,GAAwD,CACnE,GAAI,2BACJ,MAAO,UACP,MAAO,EACP,KAAM,QACN,OAAQ,OACR,MAAO,UACP,UAAW,cACX,gBAAiB,CACf,OACA,QACA,OAAA,EAEF,WAAY,EACZ,SAAU,CACR,MAAO,KACP,MAAO,OACP,KAAM,CAAC,MAAO,MAAO,MAAM,CAAA,EAE7B,YAAa,sBACb,UAAW,CACT,SAAU,gDACV,WAAY,EAAA,EAEd,OAAQ,CACN,SAAU,CACR,QAAS,CACP,CACE,KAAM,OACN,QAAS,gDACT,MAAO,CACL,SAAU,SACV,MAAO,UACP,WAAY,MAAA,CACd,EAEF,CACE,KAAM,OACN,QAAS,uCACT,MAAO,CACL,SAAU,OACV,MAAO,UACP,UAAW,KAAA,CACb,EAEF,CACE,KAAM,cACN,QAAS,GACT,MAAO,CACL,MAAO,IACP,KAAM,WACN,KAAM,GACN,KAAM,GACN,SAAU,GACV,UAAW,UACX,UAAW,UACX,YAAa,UACb,iBAAkB,MAClB,UAAW,EAAA,CACb,CACF,EAEF,MAAO,CACL,CACE,KAAM,OACN,QAAS,gDACT,MAAO,CACL,SAAU,SACV,MAAO,UACP,WAAY,MAAA,CACd,EAEF,CACE,KAAM,OACN,QAAS,uCACT,MAAO,CACL,SAAU,OACV,MAAO,UACP,UAAW,KAAA,CACb,EAEF,CACE,KAAM,cACN,QAAS,GACT,MAAO,CACL,MAAO,IACP,KAAM,WACN,KAAM,GACN,KAAM,GACN,SAAU,GACV,UAAW,UACX,UAAW,UACX,YAAa,UACb,iBAAkB,MAClB,UAAW,EAAA,CACb,CACF,CACF,EAEF,MAAO,CACL,QAAS,CACP,CACE,KAAM,OACN,QAAS,QACT,MAAO,CACL,SAAU,UACV,WAAY,OACZ,MAAO,SAAA,CACT,EAEF,CACE,KAAM,OACN,QAAS,iDAAA,EAEX,CACE,KAAM,OACN,QAAS,2BAAA,EAEX,CACE,KAAM,kBACN,QAAS,GACT,MAAO,CACL,QAAS,CAAC,YAAa,eAAgB,kBAAkB,EACzD,OAAQ,CAAC,IAAK,IAAK,GAAG,EACtB,OAAQ,CACN,SAAU,UACV,QAAS,UACT,YAAa,SAAA,CACf,CACF,EAEF,CACE,KAAM,OACN,QAAS,wCACT,MAAO,CACL,UAAW,MAAA,CACb,CACF,EAEF,MAAO,CACL,CACE,KAAM,OACN,QAAS,QACT,MAAO,CACL,SAAU,UACV,WAAY,OACZ,MAAO,SAAA,CACT,EAEF,CACE,KAAM,OACN,QAAS,iDAAA,EAEX,CACE,KAAM,OACN,QAAS,2BAAA,EAEX,CACE,KAAM,kBACN,QAAS,GACT,MAAO,CACL,QAAS,CAAC,YAAa,eAAgB,kBAAkB,EACzD,OAAQ,CAAC,IAAK,IAAK,GAAG,EACtB,OAAQ,CACN,SAAU,UACV,QAAS,UACT,YAAa,SAAA,CACf,CACF,EAEF,CACE,KAAM,OACN,QAAS,wCACT,MAAO,CACL,UAAW,MAAA,CACb,CACF,CACF,EAEF,OAAQ,CACN,QAAS,CACP,CACE,KAAM,OACN,QAAS,QACT,MAAO,CACL,SAAU,UACV,WAAY,OACZ,MAAO,SAAA,CACT,EAEF,CACE,KAAM,OACN,QAAS;AAAA,qCAAA,EAEX,CACE,KAAM,cACN,QAAS,GACT,MAAO,CACL,MAAO,IACP,KAAM,WACN,KAAM,GACN,KAAM,GACN,SAAU,GACV,UAAW,UACX,UAAW,UACX,YAAa,UACb,iBAAkB,MAClB,UAAW,EAAA,CACb,CACF,EAEF,MAAO,CACL,CACE,KAAM,OACN,QAAS,QACT,MAAO,CACL,SAAU,UACV,WAAY,OACZ,MAAO,SAAA,CACT,EAEF,CACE,KAAM,OACN,QAAS;AAAA,qCAAA,EAEX,CACE,KAAM,cACN,QAAS,GACT,MAAO,CACL,MAAO,IACP,KAAM,WACN,KAAM,GACN,KAAM,GACN,SAAU,GACV,UAAW,UACX,UAAW,UACX,YAAa,UACb,iBAAkB,MAClB,UAAW,EAAA,CACb,CACF,CACF,CACF,EAEF,YAAa,CAAA,EACb,OAAQ,CACN,MAAO,IACP,KAAM,GACN,YAAa,kCAAA,CAEjB,EC5OaC,GAA8E,CAAC,CAC1F,UAAA3lE,EAAY,GACZ,YAAa2sD,CACf,IAAM,CAEJ,MAAMC,EAAeyY,GAAA,EACflzB,EAAamzB,GAAA,EACbnxB,EAAiBoxB,GAAA,EACjB9sC,EAAkB+sC,GAAA,EAClB,CAAE,iBAAA3Y,EAAkB,aAAAC,EAAc,aAAAC,EAAc,eAAAC,CAAA,EAAmByY,GAAA,EAGnET,EAAoBt8C,EAAAA,QAAQ,IACzBikC,GAAuB+Y,GAC7B,CAAC/Y,CAAmB,CAAC,EAGxBpkC,OAAAA,EAAAA,UAAU,IAAM,CACdykC,EAAegY,CAAiB,CAClC,EAAG,CAACA,EAAmBhY,CAAc,CAAC,EAGpCjsD,EAAAA,KAAC,MAAA,CAAI,UAAW,yDAAyDf,CAAS,GAEhF,SAAA,CAAAe,EAAAA,KAAC,SAAA,CAAO,UAAU,OAChB,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAU,oCAAoC,SAAA,SAAM,EACxDW,EAAAA,KAAC,IAAA,CAAE,UAAU,sBACV,SAAA,CAAAikE,EAAkB,MAAM,QAAMA,EAAkB,IAAA,EACnD,EACA5kE,EAAAA,IAAC,IAAA,CAAE,UAAU,8BAA8B,SAAA,oBAAA,CAE3C,CAAA,EACF,EAGAW,EAAAA,KAAC,OAAA,CAAK,UAAU,wDAEb,SAAA,CAAA6rD,IAAiB,YAChBxsD,EAAAA,IAAC8zC,GAAA,CACC,YAAa8wB,EACb,WAAA7yB,EACA,eAAAgC,EACA,eAAgB2Y,EAChB,eAAgBD,EAChB,gBAAAp0B,CAAA,CAAA,EAKHm0B,IAAiB,eAChBxsD,EAAAA,IAACwkE,GAAA,CACC,YAAaI,EACb,WAAA7yB,EACA,eAAgB4a,CAAA,CAAA,EAKnBH,IAAiB,WAChBxsD,EAAAA,IAACq2C,GAAA,CACC,YAAauuB,EACb,eAAgBjY,CAAA,CAAA,CAClB,EAEJ,EAGAhsD,EAAAA,KAAC,MAAA,CAAI,UAAU,0CACZ,SAAA,CAAA6rD,IAAiB,YAAc,cAC/BA,IAAiB,eAAiB,SAClCA,IAAiB,WAAa,SAAA,CAAA,CACjC,CAAA,EACF,CAEJ,ECjFagZ,GAAc,CAACr7D,EAAIC,EAAIq7D,KAAW,CAC3C,EAAGt7D,EAAG,GAAKC,EAAG,EAAID,EAAG,GAAKs7D,EAC1B,EAAGt7D,EAAG,GAAKC,EAAG,EAAID,EAAG,GAAKs7D,CAC9B,GAmBaC,GAAsB,IAAM,CAGrC,MAAMrN,EAAI,CAAE,EAAG,GAAK,EAAG,GAAK,KAAM,KAC5BsN,EAAI,CAAE,EAAG,GAAK,EAAG,IAAM,KAAM,KAC7BC,EAAI,CAAE,EAAG,GAAK,EAAG,IAAM,KAAM,KAG7BC,EAAI,CAAE,GAAGL,GAAYnN,EAAGsN,EAAG,EAAI,CAAC,EAAG,KAAM,KACzCG,EAAI,CAAE,GAAGN,GAAYnN,EAAGuN,EAAG,EAAI,CAAC,EAAG,KAAM,KAGzCG,EAAI,CAAE,GAAGP,GAAYnN,EAAGsN,EAAG,EAAI,CAAC,EAAG,KAAM,KACzCK,EAAI,CAAE,GAAGR,GAAYnN,EAAGuN,EAAG,EAAI,CAAC,EAAG,KAAM,KAGzCK,EAAI,CAAE,GAAGT,GAAYG,EAAGC,EAAG,EAAI,CAAC,EAAG,KAAM,KACzCM,EAAI,CAAE,GAAGV,GAAYG,EAAGC,EAAG,EAAI,CAAC,EAAG,KAAM,KAGzCO,EAAI,CAAE,GAAGX,GAAYK,EAAGC,EAAG,EAAI,CAAC,EAAG,KAAM,KACzCM,EAAI,CAAE,GAAGZ,GAAYK,EAAGC,EAAG,EAAI,CAAC,EAAG,KAAM,KAGzCO,EAAI,CAAE,GAAGb,GAAYO,EAAGC,EAAG,EAAI,CAAC,EAAG,KAAM,KACzCM,EAAI,CAAE,GAAGd,GAAYO,EAAGC,EAAG,EAAI,CAAC,EAAG,KAAM,KAE/C,MAAO,CAAE,EAAA3N,EAAG,EAAAsN,EAAG,EAAAC,EAAG,EAAAC,EAAG,EAAAC,EAAG,EAAAC,EAAG,EAAAC,EAAG,EAAAC,EAAG,EAAAC,EAAG,EAAAC,EAAG,EAAAC,EAAG,EAAAC,EAAG,EAAAC,CAAC,CAClD,EASaC,GAAqB,CAACC,EAAkBnhC,EAAOxe,IAAW,CACnE,MAAM4/C,EAAc,CAAA,EAEpB,SAAW,CAAC3pE,EAAM4mC,CAAK,IAAK,OAAO,QAAQ8iC,CAAgB,EACvDC,EAAY3pE,CAAI,EAAI,CAChB,GAAG4mC,EACH,EAAGA,EAAM,EAAI2B,EACb,EAAG3B,EAAM,EAAI7c,CACzB,EAGI,OAAO4/C,CACX,EAUaC,GAAoB,CAAChjC,EAAO6nB,IAAa,CAClD,KAAM,CAACphD,EAAIC,EAAIu8D,CAAE,EAAIpb,EACf,CAAE,EAAA/hC,EAAG,EAAAC,CAAC,EAAKia,EAGXkjC,GAAgBx8D,EAAG,EAAIu8D,EAAG,IAAMx8D,EAAG,EAAIw8D,EAAG,IAAMA,EAAG,EAAIv8D,EAAG,IAAMD,EAAG,EAAIw8D,EAAG,GAEhF,GAAI,KAAK,IAAIC,CAAW,EAAI,KAAQ,MAAO,GAE3C,MAAMx+D,IAAMgC,EAAG,EAAIu8D,EAAG,IAAMn9C,EAAIm9C,EAAG,IAAMA,EAAG,EAAIv8D,EAAG,IAAMqf,EAAIk9C,EAAG,IAAMC,EAChEv+D,IAAMs+D,EAAG,EAAIx8D,EAAG,IAAMqf,EAAIm9C,EAAG,IAAMx8D,EAAG,EAAIw8D,EAAG,IAAMl9C,EAAIk9C,EAAG,IAAMC,EAChE,EAAI,EAAIx+D,EAAIC,EAGlB,OAAOD,GAAK,OAAUC,GAAK,OAAU,GAAK,KAC9C,EAQaw+D,GAAiB,CAACC,EAAWC,IAAc,CAEpD,GADI,CAACD,GAAa,CAACC,GACfD,EAAU,SAAW,GAAKC,EAAU,SAAW,EAAG,MAAO,GAE7D,MAAMC,EAASF,EAAU,IAAI90C,GAAKA,EAAE,IAAI,EAAE,OACpCi1C,EAASF,EAAU,IAAI/0C,GAAKA,EAAE,IAAI,EAAE,OAE1C,OAAOg1C,EAAO,MAAM,CAAClqE,EAAMkR,IAAUlR,IAASmqE,EAAOj5D,CAAK,CAAC,CAC/D,EAQak5D,GAAqB,CAACC,EAASC,IAAY,CACpD,GAAI,CAACD,GAAW,CAACC,GAAWD,EAAQ,SAAWC,EAAQ,OACnD,MAAO,GAGX,MAAMJ,EAASG,EAAQ,IAAIn1C,GAAKA,EAAE,IAAI,EAAE,OAClCi1C,EAASG,EAAQ,IAAIp1C,GAAKA,EAAE,IAAI,EAAE,OAExC,OAAOg1C,EAAO,KAAK,EAAE,IAAMC,EAAO,KAAK,EAAE,CAC7C,EAQaI,GAA0B,IAAM,CAEzC,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EAGpB,CAAE,KAAM,IAAK,GAAI,GAAG,EAGpB,CAAE,KAAM,IAAK,GAAI,GAAG,EAGpB,CAAE,KAAM,IAAK,GAAI,GAAG,EAGpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EAGpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EAGpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,EACpB,CAAE,KAAM,IAAK,GAAI,GAAG,CACxB,EAMaC,GAAyB,IAAM,CAExC,CAAE,GAAI,QAAS,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,OAAO,EACvE,CAAE,GAAI,QAAS,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,OAAO,EACvE,CAAE,GAAI,QAAS,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,OAAO,EAGvE,CAAE,GAAI,QAAS,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,QAAQ,EACxE,CAAE,GAAI,QAAS,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,QAAQ,EACxE,CAAE,GAAI,QAAS,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,OAAO,EAGvE,CAAE,GAAI,QAAS,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,WAAW,EAC3E,CAAE,GAAI,QAAS,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,WAAW,EAC3E,CAAE,GAAI,QAAS,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,WAAW,EAC3E,CAAE,GAAI,SAAU,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,YAAY,EAC7E,CAAE,GAAI,SAAU,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,YAAY,EAC7E,CAAE,GAAI,SAAU,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,WAAW,EAG5E,CAAE,GAAI,SAAU,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,WAAW,EAC5E,CAAE,GAAI,SAAU,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,WAAW,EAC5E,CAAE,GAAI,SAAU,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,WAAW,EAC5E,CAAE,GAAI,SAAU,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,YAAY,EAC7E,CAAE,GAAI,SAAU,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,YAAY,EAC7E,CAAE,GAAI,SAAU,SAAU,CAAC,IAAK,IAAK,GAAG,EAAG,OAAQ,GAAI,SAAU,WAAW,CAChF,EAOaC,GAAkB,CAC3B,WAAY,GACZ,aAAc,EAAI,EAClB,gBAAiB,CAAE,MAAO,IAAK,OAAQ,GAAG,EAC1C,aAAc,CAAE,QAAS,EAAG,SAAU,CAAC,EACvC,UAAW,KAGX,kBAAmB,KACnB,qBAAsB,KACtB,sBAAuB,KAC3B,ECxMaC,GAAiC,CAAC3jD,EAAiBupB,GAAe,KAA2B,CACxG,MAAMq6B,EAAoCl6B,GAAW,MAAM,IAAI,CAAC9rC,EAAMuM,IAAU,CAE9E,MAAM05D,EAAe,KAAK,IAAI,IAAK,KAAK,IAAI,EAAG15D,EAAQ,GAAK,KAAK,OAAA,EAAW,EAAE,CAAC,EACzE25D,EAAmB,KAAK,MAAOlmE,EAAK,QAAQ,OAASimE,EAAgB,GAAG,EAExEE,EAAwCnmE,EAAK,QAAQ,IAAI,CAACR,EAAQ4mE,IAAgB,CACtF,MAAMxmE,EAAiB,KAAK,IAAI,IAAK,KAAK,IAAI,EAAGqmE,EAAgBG,EAAc,GAAM,KAAK,OAAA,EAAW,EAAE,CAAC,EAExG,MAAO,CACL,SAAU5mE,EAAO,GACjB,OAAQI,GAAkB,IAAM,YAAcA,EAAiB,EAAI,cAAgB,cACnF,mBAAoB,KAAK,MAAMA,CAAc,EAC7C,aAAcA,EAAiB,EAAI,IAAI,KAAK,KAAK,MAAQ,KAAK,OAAA,EAAW,EAAI,GAAK,GAAK,GAAK,GAAI,EAAE,cAAgB,OAClH,UAAWA,EAAiB,EAAI,KAAK,MAAM,KAAK,SAAW,IAAM,EAAE,EAAI,OACvE,MAAOA,GAAkB,IAAM,KAAK,MAAM,KAAK,SAAW,GAAK,EAAE,EAAI,OACrE,SAAUA,EAAiB,EAAI,KAAK,MAAM,KAAK,OAAA,EAAW,EAAI,CAAC,EAAI,MAAA,CAEvE,CAAC,EAED,MAAO,CACL,OAAQI,EAAK,GACb,OAAAoiB,EACA,aAAcpiB,EAAK,QAAQ,OAC3B,iBAAAkmE,EACA,mBAAoB,KAAK,MAAMD,CAAY,EAC3C,OAAQA,GAAgB,IAAM,YAAcA,EAAe,EAAI,cAAgB,cAC/E,aAAcA,EAAe,EAAI,IAAI,KAAK,KAAK,MAAQ,KAAK,OAAA,EAAW,GAAK,GAAK,GAAK,GAAK,GAAI,EAAE,cAAgB,OACjH,QAASE,CAAA,CAEb,CAAC,EAEKxnE,EAAgBqnE,EAAc,OAAO,CAACpnE,EAAKoB,IAASpB,EAAMoB,EAAK,mBAAoB,CAAC,EAAIgmE,EAAc,OACtGK,EAAiBL,EAAc,UAAehmE,EAAK,SAAW,WAAW,EAAE,OAEjF,MAAO,CACL,SAAU8rC,GAAW,GACrB,OAAA1pB,EACA,WAAY4jD,EAAc,OAC1B,eAAAK,EACA,mBAAoB,KAAK,MAAM1nE,CAAa,EAC5C,OAAQA,GAAiB,IAAM,YAAcA,EAAgB,EAAI,cAAgB,cACjF,aAAc,IAAI,KAAK,KAAK,MAAQ,KAAK,OAAA,EAAW,EAAI,GAAK,GAAK,GAAK,GAAI,EAAE,YAAA,EAC7E,MAAOqnE,CAAA,CAEX,EAGaM,GAAgDP,GAAA,EAGhDQ,GAAwB,CAACnkD,EAAgB4pB,IAChD5pB,IAAWupB,GAAe,IAAMK,IAAaF,GAAW,GACnDw6B,GAEF,KAIIE,GAAsB,CAACpkD,EAAgB4pB,EAAkB9qC,IAA4C,CAChH,MAAMulE,EAAiBF,GAAsBnkD,EAAQ4pB,CAAQ,EAC7D,OAAKy6B,GAEEA,EAAe,MAAM,QAAazmE,EAAK,SAAWkB,CAAM,GAAK,IACtE,EAGawlE,GAAwB,CAACtkD,EAAgB4pB,EAAkB9qC,EAAgBirC,IAAgD,CACtI,MAAMw6B,EAAeH,GAAoBpkD,EAAQ4pB,EAAU9qC,CAAM,EACjE,OAAKylE,GAEEA,EAAa,QAAQ,QAAennE,EAAO,WAAa2sC,CAAQ,GAAK,IAC9E,EAGay6B,GAA2B,CACtCxkD,EACA4pB,EACA9qC,EACAirC,EACApuC,KAIA,QAAQ,IAAI,4BAA6B,CAAE,OAAAqkB,EAAQ,SAAA4pB,EAAU,OAAA9qC,EAAQ,SAAAirC,EAAU,SAAApuC,EAAU,EAClF,ICtFI8oE,GAAuB,CAACzkD,EAAgB4pB,IAA+C,CAClG,MAAM86B,EAAeP,GAAsBnkD,EAAQ4pB,CAAQ,EAC3D,GAAI,CAAC86B,EAAc,OAAO,KAE1B,MAAMC,EAAmCj7B,GAAW,MAAM,IAAI,CAAC9rC,EAAMuM,IAAU,CAC7E,MAAMo6D,EAAeG,EAAa,MAAM,QAAWE,EAAG,SAAWhnE,EAAK,EAAE,EAExE,MAAO,CACL,OAAQA,EAAK,GACb,MAAOA,EAAK,MACZ,YAAaA,EAAK,YAClB,eAAgBA,EAAK,eACrB,kBAAmBA,EAAK,kBACxB,aAAcA,EAAK,QAAQ,OAC3B,iBAAkB2mE,GAAc,kBAAoB,EACpD,mBAAoBA,GAAc,oBAAsB,EACxD,OAAQA,GAAc,QAAU,cAChC,aAAcA,GAAc,aAC5B,SAAUp6D,IAAU,EACpB,MAAO,eAAeu/B,GAAW,KAAK,SAAS9rC,EAAK,EAAE,EAAA,CAE1D,CAAC,EAED,MAAO,CACL,OAAAoiB,EACA,SAAU0pB,GAAW,GACrB,YAAaA,GAAW,MACxB,YAAaA,GAAW,MACxB,WAAYi7B,EAAS,OACrB,eAAgBA,EAAS,UAAe/mE,EAAK,SAAW,WAAW,EAAE,OACrE,gBAAiB8mE,EAAa,mBAC9B,OAAQA,EAAa,OACrB,aAAcA,EAAa,aAC3B,MAAOC,CAAA,CAEX,EAGaE,GAAiB,CAAC7kD,EAAgB4pB,EAAkB9qC,IAAgD,CAC/G,MAAMgmE,EAAUL,GAAqBzkD,EAAQ4pB,CAAQ,EACrD,OAAKk7B,GAEEA,EAAQ,MAAM,QAAalnE,EAAK,SAAWkB,CAAM,GAAK,IAC/D,EAGaimE,GAAyB,CAAC/kD,EAAgB4pB,EAAkB9qC,EAAgBg7B,KAGvF,QAAQ,IAAI,+BAAgC,CAAE,OAAA9Z,EAAQ,SAAA4pB,EAAU,OAAA9qC,EAAQ,SAAAg7B,EAAU,EAC3E,IAIIkrC,GAA+CP,GAAqBl7B,GAAe,GAAIG,GAAW,EAAE,ECrDpGu7B,GAA6D,CACxE,OAAQ17B,GAAe,GACvB,SAAUG,GAAW,GACrB,YAAaA,GAAW,MACxB,YAAaA,GAAW,MACxB,WAAYA,GAAW,MAAM,OAC7B,eAAgB,EAChB,gBAAiB,GACjB,OAAQ,cACR,aAAc,uBACd,MAAO,CACL,CACE,OAAQ,SACR,MAAO,OACP,YAAa,iBACb,eAAgB,yBAChB,kBAAmB,KACnB,aAAc,GACd,iBAAkB,EAClB,mBAAoB,GACpB,OAAQ,YACR,aAAc,uBACd,SAAU,GACV,MAAO,4BACP,KAAM,IAAA,EAER,CACE,OAAQ,SACR,MAAO,OACP,YAAa,iBACb,eAAgB,yBAChB,kBAAmB,KACnB,aAAc,GACd,iBAAkB,EAClB,mBAAoB,GACpB,OAAQ,cACR,aAAc,uBACd,SAAU,GACV,MAAO,4BACP,KAAM,GAAA,EAER,CACE,OAAQ,SACR,MAAO,OACP,YAAa,iBACb,eAAgB,yBAChB,kBAAmB,KACnB,aAAc,GACd,iBAAkB,EAClB,mBAAoB,GACpB,OAAQ,cACR,aAAc,uBACd,SAAU,GACV,MAAO,4BACP,KAAM,IAAA,EAER,CACE,OAAQ,SACR,MAAO,SACP,YAAa,2BACb,eAAgB,wBAChB,kBAAmB,KACnB,aAAc,GACd,iBAAkB,EAClB,mBAAoB,EACpB,OAAQ,cACR,SAAU,GACV,MAAO,4BACP,KAAM,IAAA,EAER,CACE,OAAQ,SACR,MAAO,QACP,YAAa,mBACb,eAAgB,yBAChB,kBAAmB,KACnB,aAAc,GACd,iBAAkB,EAClB,mBAAoB,EACpB,OAAQ,cACR,SAAU,GACV,MAAO,4BACP,KAAM,IAAA,EAER,CACE,OAAQ,SACR,MAAO,UACP,YAAa,wBACb,eAAgB,wBAChB,kBAAmB,KACnB,aAAc,GACd,iBAAkB,EAClB,mBAAoB,EACpB,OAAQ,cACR,SAAU,GACV,MAAO,4BACP,KAAM,IAAA,EAER,CACE,OAAQ,SACR,MAAO,WACP,YAAa,sBACb,eAAgB,yBAChB,kBAAmB,KACnB,aAAc,GACd,iBAAkB,EAClB,mBAAoB,EACpB,OAAQ,cACR,SAAU,GACV,MAAO,4BACP,KAAM,GAAA,EAER,CACE,OAAQ,SACR,MAAO,WACP,YAAa,sBACb,eAAgB,yBAChB,kBAAmB,KACnB,aAAc,GACd,iBAAkB,EAClB,mBAAoB,EACpB,OAAQ,cACR,SAAU,GACV,MAAO,4BACP,KAAM,GAAA,EAER,CACE,OAAQ,SACR,MAAO,QACP,YAAa,0BACb,eAAgB,6BAChB,kBAAmB,KACnB,aAAc,EACd,iBAAkB,EAClB,mBAAoB,EACpB,OAAQ,cACR,SAAU,GACV,MAAO,4BACP,KAAM,IAAA,CACR,CAEJ,EC5Iaw7B,GAAkE,CAAC,CAC9E,UAAAnpE,EAAY,GACZ,YAAAyyC,EACA,SAAAh0C,CACF,IAAM,CAEJ,MAAMmuD,EAAe/Z,GAAA,EACfV,EAAaW,GAAA,EACbqB,EAAiBnB,GAAA,EACjBva,EAAkBwa,GAAA,EAClB,CAAE,iBAAA4Z,EAAkB,aAAAC,EAAc,aAAAC,EAAc,eAAAC,CAAA,EAAmB7Z,GAAA,EAKzE5qB,EAAAA,UAAU,IAAM,CACVkqB,GACFua,EAAeva,CAAW,CAE9B,EAAG,CAACA,EAAaua,CAAc,CAAC,EAyBhC,MAAMoc,GApBe,IAAM,CAGzB,OADc32B,GAAa,WAAW,MAC9B,CACN,IAAK,WACH,MAAO,CAAE,WAAY,gBAAiB,MAAO,OAAA,EAC/C,IAAK,gBACH,MAAO,CAAE,WAAY,gBAAiB,MAAO,SAAA,EAC/C,IAAK,YACH,MAAO,CAAE,WAAY,iBAAkB,MAAO,MAAA,EAChD,QAIE,OAFqBA,GAAa,OAAO,SAAS,IAAI,GACpDA,GAAa,WAAW,UAAU,SAAS,IAAI,EAE7C,CAAE,WAAY,kBAAmB,MAAO,MAAA,EACxC,CAAE,WAAY,iBAAkB,MAAO,MAAA,CAAO,CAExD,GAEkB,EAElB,OACE1xC,EAAAA,KAAC,MAAA,CAAI,UAAU,kHAEb,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,wBAChB,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,+DACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAAX,EAAAA,IAAC,KAAA,CAAG,UAAW,kCAAkCgpE,EAAU,UAAU,GAClE,SAAA32B,GAAa,OAAS,QAAA,CACzB,EACA1xC,EAAAA,KAAC,IAAA,CAAE,UAAU,sBACV,SAAA,CAAA0xC,GAAa,OAAS,EAAE,QAAMA,GAAa,MAAQ,KACnDA,GAAa,QAAU,MAAMA,EAAY,MAAM,EAAA,CAAA,CAClD,CAAA,EACF,EAGAryC,EAAAA,IAAC,MAAA,CAAI,UAAU,eACb,SAAAA,EAAAA,IAAC,QAAK,UAAU,0GACb,SAAAgpE,EAAU,KAAA,CACb,CAAA,CACF,CAAA,EACF,EAEC32B,GAAa,aACZryC,EAAAA,IAAC,KAAE,UAAU,yEACV,WAAY,WAAA,CACf,CAAA,EAEJ,EAGAA,EAAAA,IAAC,QAAK,UAAU,yFACb,SAACqyC,EAOA1xC,EAAAA,KAAAsC,EAAAA,SAAA,CAEG,SAAA,CAAAupD,IAAiB,YAChBxsD,EAAAA,IAAC8zC,GAAA,CACC,YAAAzB,EACA,WAAAN,EACA,eAAAgC,EACA,eAAgB2Y,EAChB,eAAgBD,EAChB,gBAAAp0B,CAAA,CAAA,EAIHm0B,IAAiB,eAChBxsD,EAAAA,IAACm2C,GAAA,CACC,YAAA9D,EACA,WAAAN,EACA,eAAgB4a,CAAA,CAAA,EAInBH,IAAiB,WAChBxsD,EAAAA,IAACq2C,GAAA,CACC,YAAAhE,EACA,eAAgBsa,CAAA,CAAA,CAClB,CAAA,CAEJ,EAjCAhsD,EAAAA,KAAC,MAAA,CAAI,UAAU,kBACb,SAAA,CAAAX,EAAAA,IAAC,MAAA,CAAI,UAAU,6BAA6B,SAAA,KAAE,EAC9CA,EAAAA,IAAC,KAAA,CAAG,UAAU,4CAA4C,SAAA,SAAM,EAChEA,EAAAA,IAAC,IAAA,CAAE,UAAU,iBAAiB,SAAA,wBAAA,CAAsB,CAAA,CAAA,CACtD,CA6BA,CAEJ,QAGC,SAAA,CAAO,UAAU,2DAChB,SAAAW,EAAAA,KAAC,MAAA,CAAI,UAAU,4DACb,SAAA,CAAAX,EAAAA,IAAC,OAAI,UAAU,eACb,SAAAA,MAAC,IAAA,CAAE,sCAA0B,CAAA,CAC/B,EACAA,EAAAA,IAAC,MAAA,CACC,SAAAW,EAAAA,KAAC,IAAA,CAAE,SAAA,CAAA,QAAM0xC,GAAa,IAAM,IAAA,CAAA,CAAK,CAAA,CACnC,CAAA,CAAA,CACF,CAAA,CACF,EAGCh0C,GACC2B,EAAAA,IAAC,MAAA,CAAI,UAAU,wBACZ,SAAA3B,CAAA,CACH,CAAA,EAEJ,CAEJ,ECvDakzD,GAAW,IAAI,MAAM,GAAI,CACpC,KAAM,CACJ,MAAM,IAAI,MAAM;AAAA,wHAAiK,CACnL,CACF,CAAC","x_google_ignoreList":[0,1,2,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196]}