{"version":3,"file":"segmenter.cjs","names":[],"sources":["../../../src/vision/tasks/segmenter.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Instance-segmentation task using YOLO seg ONNX models (v8-seg / v11-seg / ...).\n */\n\nimport type * as ort from \"onnxruntime-web\";\n\nimport { type ModelSource, type OrtSessionOptions, OrtSession } from \"../core/session\";\nimport { SpeedTimer } from \"../core/timing\";\n\nimport { type ImageInput, loadImage } from \"../io/image\";\nimport { detectionNumClasses, resolveInputSize } from \"../core/graph\";\nimport { modelNames } from \"../core/metadata\";\nimport { type LabelSpec, defaultLabels, resolveLabels } from \"../labels\";\nimport { decodeYoloSeg } from \"../postprocess/segmentation\";\nimport { toFloat32Tensor } from \"../preprocess/image\";\nimport { LetterboxPipeline, zeroTensorData } from \"../preprocess/pipeline\";\nimport { Boxes, Masks, SegmentationResults } from \"../results\";\nimport { VisionTask, requireDetections } from \"./base\";\nimport { type BoundingBox, type SegmentationResult, Mask, RGBImage } from \"../types\";\n\n/**\n * Decoder family for the segmentation head.\n *\n * - `\"yolo-seg\"`: YOLO instance-segmentation head with two outputs —\n *   `[1, 4 + nc + nm, N]` per-anchor predictions plus `[1, nm, mh, mw]`\n *   prototype masks. Covers YOLOv8-seg, v11-seg, v26-seg.\n *\n * The SDK does **not** auto-detect this — the caller is responsible for\n * picking a head that matches their export.\n */\nexport type SegmenterHead = \"yolo-seg\";\n\nexport interface SegmenterOptions extends OrtSessionOptions {\n    /**\n     * Decoder family for the segmentation head. Default `\"yolo-seg\"` covers\n     * YOLOv8-seg/v11-seg/v26-seg.\n     */\n    readonly head?: SegmenterHead;\n    /** Class label spec — see {@link resolveLabels}. Defaults to the COCO 80-class preset. */\n    readonly labels?: LabelSpec;\n    /** Number of classes — used to validate the supplied labels. */\n    readonly numClasses?: number;\n    /**\n     * Model input `[width, height]` in pixels for letterboxing.\n     *\n     * Only used when the model's graph leaves its spatial axes dynamic: a graph\n     * that declares a static size always wins, since that is the only shape ONNX\n     * Runtime will accept. Defaults to `[640, 640]`.\n     */\n    readonly inputSize?: readonly [number, number];\n    /** Default minimum class score to keep a candidate. */\n    readonly confThreshold?: number;\n    /** Default IoU threshold for non-maximum suppression. */\n    readonly iouThreshold?: number;\n    /** Maximum number of instances per image. */\n    readonly maxDetections?: number;\n    /**\n     * If `true`, a run that finds nothing throws {@link NoDetectionsError}\n     * instead of returning an empty envelope. Default `false`, because looking\n     * and finding nothing is a successful inference. Turn it on when an empty\n     * result means the surrounding pipeline should stop rather than carry on with\n     * zero rows. Can be overridden per `predict` call.\n     */\n    readonly raiseOnEmpty?: boolean;\n    /** Probability cutoff applied to soft masks. Defaults to `0.5`. */\n    readonly maskThreshold?: number;\n}\n\nexport interface SegmenterPredictOptions {\n    readonly confThreshold?: number;\n    readonly iouThreshold?: number;\n    /**\n     * If set, keep only instances whose `classId` is in this list.\n     * Mirrors Ultralytics' `model.predict(img, classes=[0, 16])`.\n     */\n    readonly classes?: readonly number[];\n    /** Override the constructor's `raiseOnEmpty` setting for this call. */\n    readonly raiseOnEmpty?: boolean;\n}\n\n/**\n * Instance segmenter for YOLO seg ONNX models (v8-seg / v11-seg / ...).\n *\n * The model is expected to expose two outputs:\n *\n * 1. `output0`: `(1, 4 + numClasses + numMaskCoefs, numAnchors)` — per-anchor\n *    predictions (boxes, class scores, mask coefficients).\n * 2. `output1`: `(1, numMaskCoefs, maskH, maskW)` — prototype masks.\n *\n * `predict()` returns `Promise<SegmentationResults[]>` (length 1 for a\n * single image), mirroring Ultralytics' API. The envelope exposes:\n *\n * - `boxes`: bulk numpy view (`xyxy`, `xywh`, `xyxyn`, `xywhn`, `cls`, `conf`).\n * - `masks`: per-instance binary masks cropped to each box.\n * - per-instance {@link SegmentationResult} via iteration.\n *\n * @example\n * ```typescript\n * const seg = await Segmenter.create(\"/models/yolov8n-seg.onnx\");\n * const r = (await seg.predict(\"/images/street.jpg\"))[0];\n * for (const inst of r) {\n *   console.log(inst.cls, inst.conf, inst.box.xyxy);\n * }\n * ```\n */\nexport class Segmenter extends VisionTask {\n    private constructor(\n        session: OrtSession,\n        private readonly _head: SegmenterHead,\n        private readonly _labels: readonly string[],\n        private readonly _names: Readonly<Record<number, string>>,\n        private readonly _inputSize: readonly [number, number],\n        private readonly _confThreshold: number,\n        private readonly _iouThreshold: number,\n        private readonly _maxDetections: number,\n        private readonly _maskThreshold: number,\n        private readonly _raiseOnEmpty: boolean,\n    ) {\n        super(session);\n    }\n\n    private _pipelineCache: LetterboxPipeline | null = null;\n\n    /**\n     * Run the model once on a zero-filled tensor, paying one-time costs up front.\n     *\n     * The first inference of a session is not representative: WebGPU compiles its\n     * shaders on it and the WASM backend faults in its arenas, which on a phone\n     * can turn the first frame into seconds while every later frame is tens of\n     * milliseconds. Calling this while a loading spinner is still up moves that\n     * cost somewhere the user is already waiting.\n     *\n     * @param runs How many warm-up inferences to run. One is enough for WASM;\n     *   WebGPU sometimes settles on the second.\n     */\n    async warmup(runs: number = 1): Promise<void> {\n        const [tw, th] = this._inputSize;\n        for (let i = 0; i < runs; i++) {\n            const tensor = toFloat32Tensor(zeroTensorData(tw, th), [1, 3, th, tw]);\n            await this._session.run({ [this._session.inputName]: tensor });\n        }\n    }\n\n    /**\n     * The fused preprocessing pipeline, built on first use.\n     *\n     * Lazily, because constructing it allocates canvases: a task built in an\n     * environment without a canvas implementation stays constructible, and only\n     * fails if it is actually asked to preprocess something.\n     */\n    private get _pipeline(): LetterboxPipeline {\n        if (this._pipelineCache === null) {\n            this._pipelineCache = new LetterboxPipeline(this._inputSize[0], this._inputSize[1]);\n        }\n        return this._pipelineCache;\n    }\n\n    /** Load the model and resolve labels. */\n    static async create(model: ModelSource, options: SegmenterOptions = {}): Promise<Segmenter> {\n        const head: SegmenterHead = options.head ?? \"yolo-seg\";\n        if (head !== \"yolo-seg\") {\n            throw new Error(`Unsupported segmenter head '${head}'. Supported: 'yolo-seg'.`);\n        }\n        const session = await OrtSession.create(model, options);\n        const numClasses =\n            options.numClasses ?? detectionNumClasses(session.outputShape) ?? undefined;\n        const labels = resolveLabels(\n            options.labels ?? modelNames(session.metadata) ?? defaultLabels(numClasses),\n            { numClasses },\n        );\n        const names: Record<number, string> = {};\n        for (let i = 0; i < labels.length; i++) {\n            names[i] = labels[i] as string;\n        }\n        return new Segmenter(\n            session,\n            head,\n            labels,\n            names,\n            resolveInputSize({\n                graphShape: session.inputShape,\n                requested: options.inputSize,\n                fallback: [640, 640],\n            }),\n            options.confThreshold ?? 0.25,\n            options.iouThreshold ?? 0.45,\n            options.maxDetections ?? 300,\n            options.maskThreshold ?? 0.5,\n            options.raiseOnEmpty ?? false,\n        );\n    }\n\n    /** The decoder family used to interpret the model's output. */\n    get head(): SegmenterHead {\n        return this._head;\n    }\n\n    /** Class labels indexed by class id. */\n    get labels(): readonly string[] {\n        return this._labels;\n    }\n\n    /** Class id → class name dict (matches Ultralytics' `model.names`). */\n    get names(): Readonly<Record<number, string>> {\n        return this._names;\n    }\n\n    /**\n     * The `[width, height]` this task preprocesses to.\n     *\n     * Resolved at creation time from the model's graph when it declares a static\n     * input, so reading it back tells you the resolution inference really runs at\n     * — not merely what was requested.\n     */\n    get inputSize(): readonly [number, number] {\n        return this._inputSize;\n    }\n\n    /** Number of classes the model predicts. */\n    get numClasses(): number {\n        return this._labels.length;\n    }\n\n    /** Alias for {@link predict} (parity with PyTorch `nn.Module.__call__`). */\n    async call(\n        image: ImageInput,\n        options: SegmenterPredictOptions = {},\n    ): Promise<SegmentationResults[]> {\n        return this.predict(image, options);\n    }\n\n    /** Run instance segmentation on a single image. */\n    async predict(\n        image: ImageInput,\n        options: SegmenterPredictOptions = {},\n    ): Promise<SegmentationResults[]> {\n        const timer = new SpeedTimer();\n        const path = typeof image === \"string\" ? image : null;\n        const original = await loadImage(image);\n        timer.stage(\"load\");\n        const { tensor, scale, padLeft, padTop } = this._preprocess(original);\n        timer.stage(\"preprocess\");\n        const outputs = await this._session.run({ [this._session.inputName]: tensor });\n        this._pipeline.release();\n        timer.stage(\"inference\");\n\n        const { perAnchor, prototypes } = this._splitOutputs(outputs);\n\n        const threshold = options.confThreshold ?? this._confThreshold;\n        const decodedAll = decodeYoloSeg(\n            perAnchor.data as Float32Array,\n            perAnchor.dims,\n            prototypes.data as Float32Array,\n            prototypes.dims,\n            {\n                numClasses: this._labels.length,\n                inputWidth: this._inputSize[0],\n                inputHeight: this._inputSize[1],\n                originalWidth: original.width,\n                originalHeight: original.height,\n                padLeft,\n                padTop,\n                scale,\n                confThreshold: threshold,\n                iouThreshold: options.iouThreshold ?? this._iouThreshold,\n                maxDetections: this._maxDetections,\n                maskThreshold: this._maskThreshold,\n            },\n        );\n\n        const decoded =\n            options.classes !== undefined\n                ? (() => {\n                      const allowed = new Set(options.classes);\n                      return decodedAll.filter((d) => allowed.has(d.classId));\n                  })()\n                : decodedAll;\n\n        requireDetections(decoded.length, {\n            raiseOnEmpty: options.raiseOnEmpty ?? this._raiseOnEmpty,\n            confThreshold: threshold,\n            classes: options.classes,\n            path,\n        });\n\n        const detections = decoded.map((d) =>\n            this._buildResult(original, d.bbox, d.classId, d.confidence, d.mask),\n        );\n\n        const orig: readonly [number, number] = [original.height, original.width];\n        const boxes = this._buildBoxes(detections, orig);\n        const masks = this._buildMasks(detections, orig);\n        timer.stage(\"postprocess\");\n        return [\n            new SegmentationResults(\n                boxes,\n                masks,\n                detections,\n                this._names,\n                original,\n                orig,\n                path,\n                timer.speed(),\n            ),\n        ];\n    }\n\n    private _preprocess(image: RGBImage): {\n        tensor: ort.Tensor;\n        scale: number;\n        padLeft: number;\n        padTop: number;\n    } {\n        const [tw, th] = this._inputSize;\n        const fused = this._pipeline.run(image);\n        return {\n            tensor: toFloat32Tensor(fused.data, [1, 3, th, tw]),\n            scale: fused.scale,\n            padLeft: fused.padLeft,\n            padTop: fused.padTop,\n        };\n    }\n\n    private _splitOutputs(outputs: Record<string, ort.Tensor>): {\n        perAnchor: ort.Tensor;\n        prototypes: ort.Tensor;\n    } {\n        let perAnchor: ort.Tensor | undefined;\n        let prototypes: ort.Tensor | undefined;\n        for (const name of this._session.outputNames) {\n            const t = outputs[name];\n            if (t === undefined) continue;\n            if (t.dims.length === 3 && perAnchor === undefined) {\n                perAnchor = t;\n            } else if (t.dims.length === 4 && prototypes === undefined) {\n                prototypes = t;\n            }\n        }\n        if (perAnchor === undefined || prototypes === undefined) {\n            const shapes = this._session.outputNames.map(\n                (n) => `${n}: ${JSON.stringify(outputs[n]?.dims ?? [])}`,\n            );\n            throw new Error(\n                `Segmenter expected one 3-D and one 4-D output, got [${shapes.join(\", \")}].`,\n            );\n        }\n        return { perAnchor, prototypes };\n    }\n\n    private _buildResult(\n        original: RGBImage,\n        bbox: BoundingBox,\n        classId: number,\n        confidence: number,\n        mask: Mask,\n    ): SegmentationResult {\n        const [x1, y1, x2, y2] = bbox.asIntXyxy();\n        const cx1 = Math.max(0, x1);\n        const cy1 = Math.max(0, y1);\n        const cx2 = Math.min(original.width, x2);\n        const cy2 = Math.min(original.height, y2);\n\n        let segmentedImage: RGBImage;\n        let finalMask = mask;\n        if (cx2 > cx1 && cy2 > cy1 && mask.data.length > 0) {\n            const cropW = cx2 - cx1;\n            const cropH = cy2 - cy1;\n            const mw = Math.min(mask.width, cropW);\n            const mh = Math.min(mask.height, cropH);\n            const segData = new Uint8Array(mw * mh * 3);\n            for (let row = 0; row < mh; row++) {\n                const srcRowOffset = ((cy1 + row) * original.width + cx1) * 3;\n                const dstRowOffset = row * mw * 3;\n                const maskRowOffset = row * mask.width;\n                for (let col = 0; col < mw; col++) {\n                    const m = mask.data[maskRowOffset + col];\n                    if (m !== 0) {\n                        const s = srcRowOffset + col * 3;\n                        const d = dstRowOffset + col * 3;\n                        segData[d] = original.data[s];\n                        segData[d + 1] = original.data[s + 1];\n                        segData[d + 2] = original.data[s + 2];\n                    }\n                }\n            }\n            segmentedImage = new RGBImage(segData, mw, mh);\n            if (mw !== mask.width || mh !== mask.height) {\n                const trimmed = new Uint8Array(mw * mh);\n                for (let row = 0; row < mh; row++) {\n                    trimmed.set(\n                        mask.data.subarray(row * mask.width, row * mask.width + mw),\n                        row * mw,\n                    );\n                }\n                finalMask = new Mask(trimmed, mw, mh);\n            }\n        } else {\n            finalMask = new Mask(new Uint8Array(0), 0, 0);\n            segmentedImage = new RGBImage(new Uint8Array(0), 0, 0);\n        }\n\n        const className = this._names[classId] ?? `class_${classId}`;\n\n        return {\n            classId,\n            className,\n            confidence,\n            bbox,\n            cls: classId,\n            name: className,\n            conf: confidence,\n            box: bbox,\n            mask: finalMask,\n            segmentedImage,\n        };\n    }\n\n    private _buildBoxes(\n        detections: readonly SegmentationResult[],\n        origShape: readonly [number, number],\n    ): Boxes {\n        const n = detections.length;\n        const xyxy = new Float32Array(n * 4);\n        const cls = new Int32Array(n);\n        const conf = new Float32Array(n);\n        for (let i = 0; i < n; i++) {\n            const d = detections[i] as SegmentationResult;\n            xyxy[i * 4] = d.bbox.x1;\n            xyxy[i * 4 + 1] = d.bbox.y1;\n            xyxy[i * 4 + 2] = d.bbox.x2;\n            xyxy[i * 4 + 3] = d.bbox.y2;\n            cls[i] = d.classId;\n            conf[i] = d.confidence;\n        }\n        return new Boxes(xyxy, cls, conf, origShape);\n    }\n\n    private _buildMasks(\n        detections: readonly SegmentationResult[],\n        origShape: readonly [number, number],\n    ): Masks {\n        const xyxy = new Float32Array(detections.length * 4);\n        for (let i = 0; i < detections.length; i++) {\n            const d = detections[i] as SegmentationResult;\n            xyxy[i * 4] = d.bbox.x1;\n            xyxy[i * 4 + 1] = d.bbox.y1;\n            xyxy[i * 4 + 2] = d.bbox.x2;\n            xyxy[i * 4 + 3] = d.bbox.y2;\n        }\n        return new Masks(\n            detections.map((d) => d.mask),\n            xyxy,\n            origShape,\n        );\n    }\n}\n"],"mappings":"wYA0GA,IAAa,EAAb,MAAa,UAAkB,EAAA,UAAW,CAGjB,MACA,QACA,OACA,WACA,eACA,cACA,eACA,eACA,cAVrB,YACI,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACF,CACE,MAAM,CAAO,EAVI,KAAA,MAAA,EACA,KAAA,QAAA,EACA,KAAA,OAAA,EACA,KAAA,WAAA,EACA,KAAA,eAAA,EACA,KAAA,cAAA,EACA,KAAA,eAAA,EACA,KAAA,eAAA,EACA,KAAA,cAAA,CAGrB,CAEA,eAAmD,KAcnD,MAAM,OAAO,EAAe,EAAkB,CAC1C,GAAM,CAAC,EAAI,GAAM,KAAK,WACtB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,IAAK,CAC3B,IAAM,EAAS,EAAA,gBAAgB,EAAA,eAAe,EAAI,CAAE,EAAG,CAAC,EAAG,EAAG,EAAI,CAAE,CAAC,EACrE,MAAM,KAAK,SAAS,IAAI,EAAG,KAAK,SAAS,WAAY,CAAO,CAAC,CACjE,CACJ,CASA,IAAY,WAA+B,CAIvC,OAHI,KAAK,iBAAmB,OACxB,KAAK,eAAiB,IAAI,EAAA,kBAAkB,KAAK,WAAW,GAAI,KAAK,WAAW,EAAE,GAE/E,KAAK,cAChB,CAGA,aAAa,OAAO,EAAoB,EAA4B,CAAC,EAAuB,CACxF,IAAM,EAAsB,EAAQ,MAAQ,WAC5C,GAAI,IAAS,WACT,MAAU,MAAM,+BAA+B,EAAK,0BAA0B,EAElF,IAAM,EAAU,MAAM,EAAA,WAAW,OAAO,EAAO,CAAO,EAChD,EACF,EAAQ,YAAc,EAAA,oBAAoB,EAAQ,WAAW,GAAK,IAAA,GAChE,EAAS,EAAA,cACX,EAAQ,QAAU,EAAA,WAAW,EAAQ,QAAQ,GAAK,EAAA,cAAc,CAAU,EAC1E,CAAE,YAAW,CACjB,EACM,EAAgC,CAAC,EACvC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IAC/B,EAAM,GAAK,EAAO,GAEtB,OAAO,IAAI,EACP,EACA,EACA,EACA,EACA,EAAA,iBAAiB,CACb,WAAY,EAAQ,WACpB,UAAW,EAAQ,UACnB,SAAU,CAAC,IAAK,GAAG,CACvB,CAAC,EACD,EAAQ,eAAiB,IACzB,EAAQ,cAAgB,IACxB,EAAQ,eAAiB,IACzB,EAAQ,eAAiB,GACzB,EAAQ,cAAgB,EAC5B,CACJ,CAGA,IAAI,MAAsB,CACtB,OAAO,KAAK,KAChB,CAGA,IAAI,QAA4B,CAC5B,OAAO,KAAK,OAChB,CAGA,IAAI,OAA0C,CAC1C,OAAO,KAAK,MAChB,CASA,IAAI,WAAuC,CACvC,OAAO,KAAK,UAChB,CAGA,IAAI,YAAqB,CACrB,OAAO,KAAK,QAAQ,MACxB,CAGA,MAAM,KACF,EACA,EAAmC,CAAC,EACN,CAC9B,OAAO,KAAK,QAAQ,EAAO,CAAO,CACtC,CAGA,MAAM,QACF,EACA,EAAmC,CAAC,EACN,CAC9B,IAAM,EAAQ,IAAI,EAAA,WACZ,EAAO,OAAO,GAAU,SAAW,EAAQ,KAC3C,EAAW,MAAM,EAAA,UAAU,CAAK,EACtC,EAAM,MAAM,MAAM,EAClB,GAAM,CAAE,SAAQ,QAAO,UAAS,UAAW,KAAK,YAAY,CAAQ,EACpE,EAAM,MAAM,YAAY,EACxB,IAAM,EAAU,MAAM,KAAK,SAAS,IAAI,EAAG,KAAK,SAAS,WAAY,CAAO,CAAC,EAC7E,KAAK,UAAU,QAAQ,EACvB,EAAM,MAAM,WAAW,EAEvB,GAAM,CAAE,YAAW,cAAe,KAAK,cAAc,CAAO,EAEtD,EAAY,EAAQ,eAAiB,KAAK,eAC1C,EAAa,EAAA,cACf,EAAU,KACV,EAAU,KACV,EAAW,KACX,EAAW,KACX,CACI,WAAY,KAAK,QAAQ,OACzB,WAAY,KAAK,WAAW,GAC5B,YAAa,KAAK,WAAW,GAC7B,cAAe,EAAS,MACxB,eAAgB,EAAS,OACzB,UACA,SACA,QACA,cAAe,EACf,aAAc,EAAQ,cAAgB,KAAK,cAC3C,cAAe,KAAK,eACpB,cAAe,KAAK,cACxB,CACJ,EAEM,EACF,EAAQ,UAAY,IAAA,GAKd,OAJO,CACH,IAAM,EAAU,IAAI,IAAI,EAAQ,OAAO,EACvC,OAAO,EAAW,OAAQ,GAAM,EAAQ,IAAI,EAAE,OAAO,CAAC,CAC1D,EAAA,CAAG,EAGb,EAAA,kBAAkB,EAAQ,OAAQ,CAC9B,aAAc,EAAQ,cAAgB,KAAK,cAC3C,cAAe,EACf,QAAS,EAAQ,QACjB,MACJ,CAAC,EAED,IAAM,EAAa,EAAQ,IAAK,GAC5B,KAAK,aAAa,EAAU,EAAE,KAAM,EAAE,QAAS,EAAE,WAAY,EAAE,IAAI,CACvE,EAEM,EAAkC,CAAC,EAAS,OAAQ,EAAS,KAAK,EAClE,EAAQ,KAAK,YAAY,EAAY,CAAI,EACzC,EAAQ,KAAK,YAAY,EAAY,CAAI,EAE/C,OADA,EAAM,MAAM,aAAa,EAClB,CACH,IAAI,EAAA,oBACA,EACA,EACA,EACA,KAAK,OACL,EACA,EACA,EACA,EAAM,MAAM,CAChB,CACJ,CACJ,CAEA,YAAoB,EAKlB,CACE,GAAM,CAAC,EAAI,GAAM,KAAK,WAChB,EAAQ,KAAK,UAAU,IAAI,CAAK,EACtC,MAAO,CACH,OAAQ,EAAA,gBAAgB,EAAM,KAAM,CAAC,EAAG,EAAG,EAAI,CAAE,CAAC,EAClD,MAAO,EAAM,MACb,QAAS,EAAM,QACf,OAAQ,EAAM,MAClB,CACJ,CAEA,cAAsB,EAGpB,CACE,IAAI,EACA,EACJ,IAAK,IAAM,KAAQ,KAAK,SAAS,YAAa,CAC1C,IAAM,EAAI,EAAQ,GACd,IAAM,IAAA,KACN,EAAE,KAAK,SAAW,GAAK,IAAc,IAAA,GACrC,EAAY,EACL,EAAE,KAAK,SAAW,GAAK,IAAe,IAAA,KAC7C,EAAa,GAErB,CACA,GAAI,IAAc,IAAA,IAAa,IAAe,IAAA,GAAW,CACrD,IAAM,EAAS,KAAK,SAAS,YAAY,IACpC,GAAM,GAAG,EAAE,IAAI,KAAK,UAAU,EAAQ,EAAE,EAAE,MAAQ,CAAC,CAAC,GACzD,EACA,MAAU,MACN,uDAAuD,EAAO,KAAK,IAAI,EAAE,GAC7E,CACJ,CACA,MAAO,CAAE,YAAW,YAAW,CACnC,CAEA,aACI,EACA,EACA,EACA,EACA,EACkB,CAClB,GAAM,CAAC,EAAI,EAAI,EAAI,GAAM,EAAK,UAAU,EAClC,EAAM,KAAK,IAAI,EAAG,CAAE,EACpB,EAAM,KAAK,IAAI,EAAG,CAAE,EACpB,EAAM,KAAK,IAAI,EAAS,MAAO,CAAE,EACjC,EAAM,KAAK,IAAI,EAAS,OAAQ,CAAE,EAEpC,EACA,EAAY,EAChB,GAAI,EAAM,GAAO,EAAM,GAAO,EAAK,KAAK,OAAS,EAAG,CAChD,IAAM,EAAQ,EAAM,EACd,EAAQ,EAAM,EACd,EAAK,KAAK,IAAI,EAAK,MAAO,CAAK,EAC/B,EAAK,KAAK,IAAI,EAAK,OAAQ,CAAK,EAChC,EAAU,IAAI,WAAW,EAAK,EAAK,CAAC,EAC1C,IAAK,IAAI,EAAM,EAAG,EAAM,EAAI,IAAO,CAC/B,IAAM,IAAiB,EAAM,GAAO,EAAS,MAAQ,GAAO,EACtD,EAAe,EAAM,EAAK,EAC1B,EAAgB,EAAM,EAAK,MACjC,IAAK,IAAI,EAAM,EAAG,EAAM,EAAI,IAExB,GADU,EAAK,KAAK,EAAgB,KAC1B,EAAG,CACT,IAAM,EAAI,EAAe,EAAM,EACzB,EAAI,EAAe,EAAM,EAC/B,EAAQ,GAAK,EAAS,KAAK,GAC3B,EAAQ,EAAI,GAAK,EAAS,KAAK,EAAI,GACnC,EAAQ,EAAI,GAAK,EAAS,KAAK,EAAI,EACvC,CAER,CAEA,GADA,EAAiB,IAAI,EAAA,SAAS,EAAS,EAAI,CAAE,EACzC,IAAO,EAAK,OAAS,IAAO,EAAK,OAAQ,CACzC,IAAM,EAAU,IAAI,WAAW,EAAK,CAAE,EACtC,IAAK,IAAI,EAAM,EAAG,EAAM,EAAI,IACxB,EAAQ,IACJ,EAAK,KAAK,SAAS,EAAM,EAAK,MAAO,EAAM,EAAK,MAAQ,CAAE,EAC1D,EAAM,CACV,EAEJ,EAAY,IAAI,EAAA,KAAK,EAAS,EAAI,CAAE,CACxC,CACJ,KACI,GAAY,IAAI,EAAA,KAAK,IAAI,WAAe,EAAG,CAAC,EAC5C,EAAiB,IAAI,EAAA,SAAS,IAAI,WAAe,EAAG,CAAC,EAGzD,IAAM,EAAY,KAAK,OAAO,IAAY,SAAS,IAEnD,MAAO,CACH,UACA,YACA,aACA,OACA,IAAK,EACL,KAAM,EACN,KAAM,EACN,IAAK,EACL,KAAM,EACN,gBACJ,CACJ,CAEA,YACI,EACA,EACK,CACL,IAAM,EAAI,EAAW,OACf,EAAO,IAAI,aAAa,EAAI,CAAC,EAC7B,EAAM,IAAI,WAAW,CAAC,EACtB,EAAO,IAAI,aAAa,CAAC,EAC/B,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,IAAK,CACxB,IAAM,EAAI,EAAW,GACrB,EAAK,EAAI,GAAK,EAAE,KAAK,GACrB,EAAK,EAAI,EAAI,GAAK,EAAE,KAAK,GACzB,EAAK,EAAI,EAAI,GAAK,EAAE,KAAK,GACzB,EAAK,EAAI,EAAI,GAAK,EAAE,KAAK,GACzB,EAAI,GAAK,EAAE,QACX,EAAK,GAAK,EAAE,UAChB,CACA,OAAO,IAAI,EAAA,MAAM,EAAM,EAAK,EAAM,CAAS,CAC/C,CAEA,YACI,EACA,EACK,CACL,IAAM,EAAO,IAAI,aAAa,EAAW,OAAS,CAAC,EACnD,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,OAAQ,IAAK,CACxC,IAAM,EAAI,EAAW,GACrB,EAAK,EAAI,GAAK,EAAE,KAAK,GACrB,EAAK,EAAI,EAAI,GAAK,EAAE,KAAK,GACzB,EAAK,EAAI,EAAI,GAAK,EAAE,KAAK,GACzB,EAAK,EAAI,EAAI,GAAK,EAAE,KAAK,EAC7B,CACA,OAAO,IAAI,EAAA,MACP,EAAW,IAAK,GAAM,EAAE,IAAI,EAC5B,EACA,CACJ,CACJ,CACJ"}