spice-html5-react 0.1.0

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.
Files changed (64) hide show
  1. package/README.md +262 -0
  2. package/dist/components/SpiceDisplay.d.ts +109 -0
  3. package/dist/components/SpiceDisplay.d.ts.map +1 -0
  4. package/dist/hooks/useSpice.d.ts +107 -0
  5. package/dist/hooks/useSpice.d.ts.map +1 -0
  6. package/dist/index.cjs +14 -0
  7. package/dist/index.cjs.map +1 -0
  8. package/dist/index.d.ts +8 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.mjs +6745 -0
  11. package/dist/index.mjs.map +1 -0
  12. package/dist/protocol/bitmap.d.ts +20 -0
  13. package/dist/protocol/bitmap.d.ts.map +1 -0
  14. package/dist/protocol/cursor.d.ts +16 -0
  15. package/dist/protocol/cursor.d.ts.map +1 -0
  16. package/dist/protocol/display.d.ts +311 -0
  17. package/dist/protocol/display.d.ts.map +1 -0
  18. package/dist/protocol/enums.d.ts +677 -0
  19. package/dist/protocol/enums.d.ts.map +1 -0
  20. package/dist/protocol/filexfer.d.ts +61 -0
  21. package/dist/protocol/filexfer.d.ts.map +1 -0
  22. package/dist/protocol/index.d.ts +34 -0
  23. package/dist/protocol/index.d.ts.map +1 -0
  24. package/dist/protocol/inputs.d.ts +95 -0
  25. package/dist/protocol/inputs.d.ts.map +1 -0
  26. package/dist/protocol/lz.d.ts +24 -0
  27. package/dist/protocol/lz.d.ts.map +1 -0
  28. package/dist/protocol/main.d.ts +205 -0
  29. package/dist/protocol/main.d.ts.map +1 -0
  30. package/dist/protocol/playback.d.ts +51 -0
  31. package/dist/protocol/playback.d.ts.map +1 -0
  32. package/dist/protocol/png.d.ts +14 -0
  33. package/dist/protocol/png.d.ts.map +1 -0
  34. package/dist/protocol/port.d.ts +46 -0
  35. package/dist/protocol/port.d.ts.map +1 -0
  36. package/dist/protocol/quic.d.ts +105 -0
  37. package/dist/protocol/quic.d.ts.map +1 -0
  38. package/dist/protocol/resize.d.ts +61 -0
  39. package/dist/protocol/resize.d.ts.map +1 -0
  40. package/dist/protocol/simulatecursor.d.ts +49 -0
  41. package/dist/protocol/simulatecursor.d.ts.map +1 -0
  42. package/dist/protocol/spicearraybuffer.d.ts +44 -0
  43. package/dist/protocol/spicearraybuffer.d.ts.map +1 -0
  44. package/dist/protocol/spiceconn.d.ts +118 -0
  45. package/dist/protocol/spiceconn.d.ts.map +1 -0
  46. package/dist/protocol/spicedataview.d.ts +144 -0
  47. package/dist/protocol/spicedataview.d.ts.map +1 -0
  48. package/dist/protocol/spicemsg.d.ts +435 -0
  49. package/dist/protocol/spicemsg.d.ts.map +1 -0
  50. package/dist/protocol/spicetype.d.ts +166 -0
  51. package/dist/protocol/spicetype.d.ts.map +1 -0
  52. package/dist/protocol/ticket.d.ts +14 -0
  53. package/dist/protocol/ticket.d.ts.map +1 -0
  54. package/dist/protocol/webm.d.ts +118 -0
  55. package/dist/protocol/webm.d.ts.map +1 -0
  56. package/dist/protocol/wire.d.ts +81 -0
  57. package/dist/protocol/wire.d.ts.map +1 -0
  58. package/dist/utils/atKeynames.d.ts +96 -0
  59. package/dist/utils/atKeynames.d.ts.map +1 -0
  60. package/dist/utils/codeToScancode.d.ts +2 -0
  61. package/dist/utils/codeToScancode.d.ts.map +1 -0
  62. package/dist/utils/debug.d.ts +84 -0
  63. package/dist/utils/debug.d.ts.map +1 -0
  64. package/package.json +60 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/protocol/enums.ts","../src/protocol/spicetype.ts","../src/protocol/spicemsg.ts","../src/utils/atKeynames.ts","../src/utils/codeToScancode.ts","../src/utils/debug.ts","../src/protocol/wire.ts","../src/protocol/webm.ts","../src/protocol/ticket.ts","../src/protocol/spiceconn.ts","../src/protocol/main.ts","../src/protocol/filexfer.ts","../src/protocol/resize.ts","../src/components/SpiceDisplay.tsx","../src/hooks/useSpice.ts","../src/protocol/quic.ts","../src/protocol/lz.ts","../src/protocol/bitmap.ts","../src/protocol/display.ts","../src/protocol/inputs.ts","../src/protocol/png.ts","../src/protocol/simulatecursor.ts","../src/protocol/cursor.ts","../src/protocol/playback.ts","../src/protocol/port.ts","../src/protocol/spicearraybuffer.ts","../src/protocol/spicedataview.ts","../src/index.ts"],"sourcesContent":["/*----------------------------------------------------------------------------\n** enums.ts\n** Constants for the SPICE protocol, organized by subsystem.\n** Faithfully converted from enums.js.\n**--------------------------------------------------------------------------*/\n\n// ---------------------------------------------------------------------------\n// Protocol version and connection\n// ---------------------------------------------------------------------------\n\nexport const SPICE_MAGIC = \"REDQ\" as const;\nexport const SPICE_VERSION_MAJOR = 2 as const;\nexport const SPICE_VERSION_MINOR = 2 as const;\nexport const SPICE_CONNECT_TIMEOUT = 30000;\n\n// ---------------------------------------------------------------------------\n// Common capabilities\n// ---------------------------------------------------------------------------\n\nexport const SpiceCommonCap = {\n PROTOCOL_AUTH_SELECTION: 0,\n AUTH_SPICE: 1,\n AUTH_SASL: 2,\n MINI_HEADER: 3,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Ticket / authentication\n// ---------------------------------------------------------------------------\n\nexport const SPICE_TICKET_KEY_PAIR_LENGTH = 1024 as const;\nexport const SPICE_TICKET_PUBKEY_BYTES = 162; // SPICE_TICKET_KEY_PAIR_LENGTH / 8 + 34\n\n// ---------------------------------------------------------------------------\n// Link errors\n// ---------------------------------------------------------------------------\n\nexport const SpiceLinkErr = {\n OK: 0,\n ERROR: 1,\n INVALID_MAGIC: 2,\n INVALID_DATA: 3,\n VERSION_MISMATCH: 4,\n NEED_SECURED: 5,\n NEED_UNSECURED: 6,\n PERMISSION_DENIED: 7,\n BAD_CONNECTION_ID: 8,\n CHANNEL_NOT_AVAILABLE: 9,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Server messages (common / base)\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsg = {\n MIGRATE: 1,\n MIGRATE_DATA: 2,\n SET_ACK: 3,\n PING: 4,\n WAIT_FOR_CHANNELS: 5,\n DISCONNECTING: 6,\n NOTIFY: 7,\n LIST: 8,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Server messages — Main channel\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsgMain = {\n MIGRATE_BEGIN: 101,\n MIGRATE_CANCEL: 102,\n INIT: 103,\n CHANNELS_LIST: 104,\n MOUSE_MODE: 105,\n MULTI_MEDIA_TIME: 106,\n AGENT_CONNECTED: 107,\n AGENT_DISCONNECTED: 108,\n AGENT_DATA: 109,\n AGENT_TOKEN: 110,\n MIGRATE_SWITCH_HOST: 111,\n MIGRATE_END: 112,\n NAME: 113,\n UUID: 114,\n AGENT_CONNECTED_TOKENS: 115,\n MIGRATE_BEGIN_SEAMLESS: 116,\n MIGRATE_DST_SEAMLESS_ACK: 117,\n MIGRATE_DST_SEAMLESS_NACK: 118,\n END: 119,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Client messages (common / base)\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsgc = {\n ACK_SYNC: 1,\n ACK: 2,\n PONG: 3,\n MIGRATE_FLUSH_MARK: 4,\n MIGRATE_DATA: 5,\n DISCONNECTING: 6,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Client messages — Main channel\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsgcMain = {\n CLIENT_INFO: 101,\n MIGRATE_CONNECTED: 102,\n MIGRATE_CONNECT_ERROR: 103,\n ATTACH_CHANNELS: 104,\n MOUSE_MODE_REQUEST: 105,\n AGENT_START: 106,\n AGENT_DATA: 107,\n AGENT_TOKEN: 108,\n MIGRATE_END: 109,\n END: 110,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Server messages — Display channel\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsgDisplay = {\n MODE: 101,\n MARK: 102,\n RESET: 103,\n COPY_BITS: 104,\n INVAL_LIST: 105,\n INVAL_ALL_PIXMAPS: 106,\n INVAL_PALETTE: 107,\n INVAL_ALL_PALETTES: 108,\n STREAM_CREATE: 122,\n STREAM_DATA: 123,\n STREAM_CLIP: 124,\n STREAM_DESTROY: 125,\n STREAM_DESTROY_ALL: 126,\n DRAW_FILL: 302,\n DRAW_OPAQUE: 303,\n DRAW_COPY: 304,\n DRAW_BLEND: 305,\n DRAW_BLACKNESS: 306,\n DRAW_WHITENESS: 307,\n DRAW_INVERS: 308,\n DRAW_ROP3: 309,\n DRAW_STROKE: 310,\n DRAW_TEXT: 311,\n DRAW_TRANSPARENT: 312,\n DRAW_ALPHA_BLEND: 313,\n SURFACE_CREATE: 314,\n SURFACE_DESTROY: 315,\n STREAM_DATA_SIZED: 316,\n MONITORS_CONFIG: 317,\n DRAW_COMPOSITE: 318,\n STREAM_ACTIVATE_REPORT: 319,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Client messages — Display channel\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsgcDisplay = {\n INIT: 101,\n STREAM_REPORT: 102,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Server messages — Inputs channel\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsgInputs = {\n INIT: 101,\n KEY_MODIFIERS: 102,\n MOUSE_MOTION_ACK: 111,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Client messages — Inputs channel\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsgcInputs = {\n KEY_DOWN: 101,\n KEY_UP: 102,\n KEY_MODIFIERS: 103,\n MOUSE_MOTION: 111,\n MOUSE_POSITION: 112,\n MOUSE_PRESS: 113,\n MOUSE_RELEASE: 114,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Server messages — Cursor channel\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsgCursor = {\n INIT: 101,\n RESET: 102,\n SET: 103,\n MOVE: 104,\n HIDE: 105,\n TRAIL: 106,\n INVAL_ONE: 107,\n INVAL_ALL: 108,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Server messages — Playback channel\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsgPlayback = {\n DATA: 101,\n MODE: 102,\n START: 103,\n STOP: 104,\n VOLUME: 105,\n MUTE: 106,\n LATENCY: 107,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Server messages — Port / SpiceVMC channel\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsgPort = {\n SPICEVMC_DATA: 101,\n INIT: 201,\n EVENT: 202,\n END: 203,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Client messages — Port / SpiceVMC channel\n// ---------------------------------------------------------------------------\n\nexport const SpiceMsgcPort = {\n SPICEVMC_DATA: 101,\n EVENT: 201,\n END: 202,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Playback capabilities\n// ---------------------------------------------------------------------------\n\nexport const SpicePlaybackCap = {\n CELT_0_5_1: 0,\n VOLUME: 1,\n LATENCY: 2,\n OPUS: 3,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Main channel capabilities\n// ---------------------------------------------------------------------------\n\nexport const SpiceMainCap = {\n SEMI_SEAMLESS_MIGRATE: 0,\n NAME_AND_UUID: 1,\n AGENT_CONNECTED_TOKENS: 2,\n SEAMLESS_MIGRATE: 3,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Display channel capabilities\n// ---------------------------------------------------------------------------\n\nexport const SpiceDisplayCap = {\n SIZED_STREAM: 0,\n MONITORS_CONFIG: 1,\n COMPOSITE: 2,\n A8_SURFACE: 3,\n STREAM_REPORT: 4,\n LZ4_COMPRESSION: 5,\n PREF_COMPRESSION: 6,\n GL_SCANOUT: 7,\n MULTI_CODEC: 8,\n CODEC_MJPEG: 9,\n CODEC_VP8: 10,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Audio data mode\n// ---------------------------------------------------------------------------\n\nexport const SpiceAudioDataMode = {\n INVALID: 0,\n RAW: 1,\n CELT_0_5_1: 2,\n OPUS: 3,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Audio format\n// ---------------------------------------------------------------------------\n\nexport const SpiceAudioFmt = {\n INVALID: 0,\n S16: 1,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Channel types\n// ---------------------------------------------------------------------------\n\nexport const SpiceChannel = {\n MAIN: 1,\n DISPLAY: 2,\n INPUTS: 3,\n CURSOR: 4,\n PLAYBACK: 5,\n RECORD: 6,\n TUNNEL: 7,\n SMARTCARD: 8,\n USBREDIR: 9,\n PORT: 10,\n WEBDAV: 11,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Surface flags\n// ---------------------------------------------------------------------------\n\nexport const SPICE_SURFACE_FLAGS_PRIMARY = 1;\n\n// ---------------------------------------------------------------------------\n// Notify severity\n// ---------------------------------------------------------------------------\n\nexport const SpiceNotifySeverity = {\n INFO: 0,\n WARN: 1,\n ERROR: 2,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Mouse mode\n// ---------------------------------------------------------------------------\n\nexport const SpiceMouseMode = {\n SERVER: (1 << 0),\n CLIENT: (1 << 1),\n MASK: 0x3,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Clip type\n// ---------------------------------------------------------------------------\n\nexport const SpiceClipType = {\n NONE: 0,\n RECTS: 1,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Image type\n// ---------------------------------------------------------------------------\n\nexport const SpiceImageType = {\n BITMAP: 0,\n QUIC: 1,\n RESERVED: 2,\n LZ_PLT: 100,\n LZ_RGB: 101,\n GLZ_RGB: 102,\n FROM_CACHE: 103,\n SURFACE: 104,\n JPEG: 105,\n FROM_CACHE_LOSSLESS: 106,\n ZLIB_GLZ_RGB: 107,\n JPEG_ALPHA: 108,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Image flags\n// ---------------------------------------------------------------------------\n\nexport const SpiceImageFlags = {\n CACHE_ME: (1 << 0),\n HIGH_BITS_SET: (1 << 1),\n CACHE_REPLACE_ME: (1 << 2),\n} as const;\n\n// ---------------------------------------------------------------------------\n// Bitmap flags\n// ---------------------------------------------------------------------------\n\nexport const SpiceBitmapFlags = {\n PAL_CACHE_ME: (1 << 0),\n PAL_FROM_CACHE: (1 << 1),\n TOP_DOWN: (1 << 2),\n MASK: 0x7,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Bitmap format\n// ---------------------------------------------------------------------------\n\nexport const SpiceBitmapFmt = {\n INVALID: 0,\n _1BIT_LE: 1,\n _1BIT_BE: 2,\n _4BIT_LE: 3,\n _4BIT_BE: 4,\n _8BIT: 5,\n _16BIT: 6,\n _24BIT: 7,\n _32BIT: 8,\n RGBA: 9,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Cursor flags\n// ---------------------------------------------------------------------------\n\nexport const SpiceCursorFlags = {\n NONE: (1 << 0),\n CACHE_ME: (1 << 1),\n FROM_CACHE: (1 << 2),\n MASK: 0x7,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Mouse button mask\n// ---------------------------------------------------------------------------\n\nexport const SpiceMouseButtonMask = {\n LEFT: (1 << 0),\n MIDDLE: (1 << 1),\n RIGHT: (1 << 2),\n MASK: 0x7,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Mouse button\n// ---------------------------------------------------------------------------\n\nexport const SpiceMouseButton = {\n INVALID: 0,\n LEFT: 1,\n MIDDLE: 2,\n RIGHT: 3,\n UP: 4,\n DOWN: 5,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Brush type\n// ---------------------------------------------------------------------------\n\nexport const SpiceBrushType = {\n NONE: 0,\n SOLID: 1,\n PATTERN: 2,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Surface format\n// ---------------------------------------------------------------------------\n\nexport const SpiceSurfaceFmt = {\n INVALID: 0,\n _1_A: 1,\n _8_A: 8,\n _16_555: 16,\n _32_xRGB: 32,\n _16_565: 80,\n _32_ARGB: 96,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Raster operation descriptor\n// ---------------------------------------------------------------------------\n\nexport const SpiceRopd = {\n INVERS_SRC: (1 << 0),\n INVERS_BRUSH: (1 << 1),\n INVERS_DEST: (1 << 2),\n OP_PUT: (1 << 3),\n OP_OR: (1 << 4),\n OP_AND: (1 << 5),\n OP_XOR: (1 << 6),\n OP_BLACKNESS: (1 << 7),\n OP_WHITENESS: (1 << 8),\n OP_INVERS: (1 << 9),\n INVERS_RES: (1 << 10),\n MASK: 0x7ff,\n} as const;\n\n// ---------------------------------------------------------------------------\n// LZ image type\n// ---------------------------------------------------------------------------\n\nexport const LzImageType = {\n INVALID: 0,\n PLT1_LE: 1,\n PLT1_BE: 2, // PLT stands for palette\n PLT4_LE: 3,\n PLT4_BE: 4,\n PLT8: 5,\n RGB16: 6,\n RGB24: 7,\n RGB32: 8,\n RGBA: 9,\n XXXA: 10,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Input motion ACK\n// ---------------------------------------------------------------------------\n\nexport const SPICE_INPUT_MOTION_ACK_BUNCH = 4 as const;\n\n// ---------------------------------------------------------------------------\n// Cursor type\n// ---------------------------------------------------------------------------\n\nexport const SpiceCursorType = {\n ALPHA: 0,\n MONO: 1,\n COLOR4: 2,\n COLOR8: 3,\n COLOR16: 4,\n COLOR24: 5,\n COLOR32: 6,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Video codec type\n// ---------------------------------------------------------------------------\n\nexport const SpiceVideoCodecType = {\n MJPEG: 1,\n VP8: 2,\n} as const;\n\n// ---------------------------------------------------------------------------\n// VD Agent — protocol and limits\n// ---------------------------------------------------------------------------\n\nexport const VD_AGENT_PROTOCOL = 1 as const;\nexport const VD_AGENT_MAX_DATA_SIZE = 2048 as const;\n\n// ---------------------------------------------------------------------------\n// VD Agent — message types\n// ---------------------------------------------------------------------------\n\nexport const VdAgentMsg = {\n MOUSE_STATE: 1,\n MONITORS_CONFIG: 2,\n REPLY: 3,\n CLIPBOARD: 4,\n DISPLAY_CONFIG: 5,\n ANNOUNCE_CAPABILITIES: 6,\n CLIPBOARD_GRAB: 7,\n CLIPBOARD_REQUEST: 8,\n CLIPBOARD_RELEASE: 9,\n FILE_XFER_START: 10,\n FILE_XFER_STATUS: 11,\n FILE_XFER_DATA: 12,\n CLIENT_DISCONNECTED: 13,\n MAX_CLIPBOARD: 14,\n} as const;\n\n// ---------------------------------------------------------------------------\n// VD Agent — capabilities\n// ---------------------------------------------------------------------------\n\nexport const VdAgentCap = {\n MOUSE_STATE: 0,\n MONITORS_CONFIG: 1,\n REPLY: 2,\n CLIPBOARD: 3,\n DISPLAY_CONFIG: 4,\n CLIPBOARD_BY_DEMAND: 5,\n CLIPBOARD_SELECTION: 6,\n SPARSE_MONITORS_CONFIG: 7,\n GUEST_LINEEND_LF: 8,\n GUEST_LINEEND_CRLF: 9,\n MAX_CLIPBOARD: 10,\n END: 11,\n} as const;\n\n// ---------------------------------------------------------------------------\n// VD Agent — file transfer status\n// ---------------------------------------------------------------------------\n\nexport const VdAgentFileXferStatus = {\n CAN_SEND_DATA: 0,\n CANCELLED: 1,\n ERROR: 2,\n SUCCESS: 3,\n} as const;\n\n// ---------------------------------------------------------------------------\n// VD Agent — clipboard type\n// ---------------------------------------------------------------------------\n\nexport const VdAgentClipboard = {\n NONE: 0,\n UTF8_TEXT: 1,\n IMAGE_PNG: 2,\n IMAGE_BMP: 3,\n IMAGE_TIFF: 4,\n IMAGE_JPG: 5,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Backward-compatible \"Constants\" object\n// ---------------------------------------------------------------------------\n// This aggregated object mirrors the original enums.js export shape so that\n// downstream modules being migrated incrementally can continue to use\n// `Constants.SPICE_*` references until they are fully converted.\n// ---------------------------------------------------------------------------\n\nexport const Constants = {\n SPICE_MAGIC,\n SPICE_VERSION_MAJOR,\n SPICE_VERSION_MINOR,\n SPICE_CONNECT_TIMEOUT,\n\n // Common capabilities\n SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION: SpiceCommonCap.PROTOCOL_AUTH_SELECTION,\n SPICE_COMMON_CAP_AUTH_SPICE: SpiceCommonCap.AUTH_SPICE,\n SPICE_COMMON_CAP_AUTH_SASL: SpiceCommonCap.AUTH_SASL,\n SPICE_COMMON_CAP_MINI_HEADER: SpiceCommonCap.MINI_HEADER,\n\n // Ticket\n SPICE_TICKET_KEY_PAIR_LENGTH,\n SPICE_TICKET_PUBKEY_BYTES,\n\n // Link errors\n SPICE_LINK_ERR_OK: SpiceLinkErr.OK,\n SPICE_LINK_ERR_ERROR: SpiceLinkErr.ERROR,\n SPICE_LINK_ERR_INVALID_MAGIC: SpiceLinkErr.INVALID_MAGIC,\n SPICE_LINK_ERR_INVALID_DATA: SpiceLinkErr.INVALID_DATA,\n SPICE_LINK_ERR_VERSION_MISMATCH: SpiceLinkErr.VERSION_MISMATCH,\n SPICE_LINK_ERR_NEED_SECURED: SpiceLinkErr.NEED_SECURED,\n SPICE_LINK_ERR_NEED_UNSECURED: SpiceLinkErr.NEED_UNSECURED,\n SPICE_LINK_ERR_PERMISSION_DENIED: SpiceLinkErr.PERMISSION_DENIED,\n SPICE_LINK_ERR_BAD_CONNECTION_ID: SpiceLinkErr.BAD_CONNECTION_ID,\n SPICE_LINK_ERR_CHANNEL_NOT_AVAILABLE: SpiceLinkErr.CHANNEL_NOT_AVAILABLE,\n\n // Server messages (common)\n SPICE_MSG_MIGRATE: SpiceMsg.MIGRATE,\n SPICE_MSG_MIGRATE_DATA: SpiceMsg.MIGRATE_DATA,\n SPICE_MSG_SET_ACK: SpiceMsg.SET_ACK,\n SPICE_MSG_PING: SpiceMsg.PING,\n SPICE_MSG_WAIT_FOR_CHANNELS: SpiceMsg.WAIT_FOR_CHANNELS,\n SPICE_MSG_DISCONNECTING: SpiceMsg.DISCONNECTING,\n SPICE_MSG_NOTIFY: SpiceMsg.NOTIFY,\n SPICE_MSG_LIST: SpiceMsg.LIST,\n\n // Server messages — Main\n SPICE_MSG_MAIN_MIGRATE_BEGIN: SpiceMsgMain.MIGRATE_BEGIN,\n SPICE_MSG_MAIN_MIGRATE_CANCEL: SpiceMsgMain.MIGRATE_CANCEL,\n SPICE_MSG_MAIN_INIT: SpiceMsgMain.INIT,\n SPICE_MSG_MAIN_CHANNELS_LIST: SpiceMsgMain.CHANNELS_LIST,\n SPICE_MSG_MAIN_MOUSE_MODE: SpiceMsgMain.MOUSE_MODE,\n SPICE_MSG_MAIN_MULTI_MEDIA_TIME: SpiceMsgMain.MULTI_MEDIA_TIME,\n SPICE_MSG_MAIN_AGENT_CONNECTED: SpiceMsgMain.AGENT_CONNECTED,\n SPICE_MSG_MAIN_AGENT_DISCONNECTED: SpiceMsgMain.AGENT_DISCONNECTED,\n SPICE_MSG_MAIN_AGENT_DATA: SpiceMsgMain.AGENT_DATA,\n SPICE_MSG_MAIN_AGENT_TOKEN: SpiceMsgMain.AGENT_TOKEN,\n SPICE_MSG_MAIN_MIGRATE_SWITCH_HOST: SpiceMsgMain.MIGRATE_SWITCH_HOST,\n SPICE_MSG_MAIN_MIGRATE_END: SpiceMsgMain.MIGRATE_END,\n SPICE_MSG_MAIN_NAME: SpiceMsgMain.NAME,\n SPICE_MSG_MAIN_UUID: SpiceMsgMain.UUID,\n SPICE_MSG_MAIN_AGENT_CONNECTED_TOKENS: SpiceMsgMain.AGENT_CONNECTED_TOKENS,\n SPICE_MSG_MAIN_MIGRATE_BEGIN_SEAMLESS: SpiceMsgMain.MIGRATE_BEGIN_SEAMLESS,\n SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_ACK: SpiceMsgMain.MIGRATE_DST_SEAMLESS_ACK,\n SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_NACK: SpiceMsgMain.MIGRATE_DST_SEAMLESS_NACK,\n SPICE_MSG_END_MAIN: SpiceMsgMain.END,\n\n // Client messages (common)\n SPICE_MSGC_ACK_SYNC: SpiceMsgc.ACK_SYNC,\n SPICE_MSGC_ACK: SpiceMsgc.ACK,\n SPICE_MSGC_PONG: SpiceMsgc.PONG,\n SPICE_MSGC_MIGRATE_FLUSH_MARK: SpiceMsgc.MIGRATE_FLUSH_MARK,\n SPICE_MSGC_MIGRATE_DATA: SpiceMsgc.MIGRATE_DATA,\n SPICE_MSGC_DISCONNECTING: SpiceMsgc.DISCONNECTING,\n\n // Client messages — Main\n SPICE_MSGC_MAIN_CLIENT_INFO: SpiceMsgcMain.CLIENT_INFO,\n SPICE_MSGC_MAIN_MIGRATE_CONNECTED: SpiceMsgcMain.MIGRATE_CONNECTED,\n SPICE_MSGC_MAIN_MIGRATE_CONNECT_ERROR: SpiceMsgcMain.MIGRATE_CONNECT_ERROR,\n SPICE_MSGC_MAIN_ATTACH_CHANNELS: SpiceMsgcMain.ATTACH_CHANNELS,\n SPICE_MSGC_MAIN_MOUSE_MODE_REQUEST: SpiceMsgcMain.MOUSE_MODE_REQUEST,\n SPICE_MSGC_MAIN_AGENT_START: SpiceMsgcMain.AGENT_START,\n SPICE_MSGC_MAIN_AGENT_DATA: SpiceMsgcMain.AGENT_DATA,\n SPICE_MSGC_MAIN_AGENT_TOKEN: SpiceMsgcMain.AGENT_TOKEN,\n SPICE_MSGC_MAIN_MIGRATE_END: SpiceMsgcMain.MIGRATE_END,\n SPICE_MSGC_END_MAIN: SpiceMsgcMain.END,\n\n // Server messages — Display\n SPICE_MSG_DISPLAY_MODE: SpiceMsgDisplay.MODE,\n SPICE_MSG_DISPLAY_MARK: SpiceMsgDisplay.MARK,\n SPICE_MSG_DISPLAY_RESET: SpiceMsgDisplay.RESET,\n SPICE_MSG_DISPLAY_COPY_BITS: SpiceMsgDisplay.COPY_BITS,\n SPICE_MSG_DISPLAY_INVAL_LIST: SpiceMsgDisplay.INVAL_LIST,\n SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS: SpiceMsgDisplay.INVAL_ALL_PIXMAPS,\n SPICE_MSG_DISPLAY_INVAL_PALETTE: SpiceMsgDisplay.INVAL_PALETTE,\n SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES: SpiceMsgDisplay.INVAL_ALL_PALETTES,\n SPICE_MSG_DISPLAY_STREAM_CREATE: SpiceMsgDisplay.STREAM_CREATE,\n SPICE_MSG_DISPLAY_STREAM_DATA: SpiceMsgDisplay.STREAM_DATA,\n SPICE_MSG_DISPLAY_STREAM_CLIP: SpiceMsgDisplay.STREAM_CLIP,\n SPICE_MSG_DISPLAY_STREAM_DESTROY: SpiceMsgDisplay.STREAM_DESTROY,\n SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL: SpiceMsgDisplay.STREAM_DESTROY_ALL,\n SPICE_MSG_DISPLAY_DRAW_FILL: SpiceMsgDisplay.DRAW_FILL,\n SPICE_MSG_DISPLAY_DRAW_OPAQUE: SpiceMsgDisplay.DRAW_OPAQUE,\n SPICE_MSG_DISPLAY_DRAW_COPY: SpiceMsgDisplay.DRAW_COPY,\n SPICE_MSG_DISPLAY_DRAW_BLEND: SpiceMsgDisplay.DRAW_BLEND,\n SPICE_MSG_DISPLAY_DRAW_BLACKNESS: SpiceMsgDisplay.DRAW_BLACKNESS,\n SPICE_MSG_DISPLAY_DRAW_WHITENESS: SpiceMsgDisplay.DRAW_WHITENESS,\n SPICE_MSG_DISPLAY_DRAW_INVERS: SpiceMsgDisplay.DRAW_INVERS,\n SPICE_MSG_DISPLAY_DRAW_ROP3: SpiceMsgDisplay.DRAW_ROP3,\n SPICE_MSG_DISPLAY_DRAW_STROKE: SpiceMsgDisplay.DRAW_STROKE,\n SPICE_MSG_DISPLAY_DRAW_TEXT: SpiceMsgDisplay.DRAW_TEXT,\n SPICE_MSG_DISPLAY_DRAW_TRANSPARENT: SpiceMsgDisplay.DRAW_TRANSPARENT,\n SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND: SpiceMsgDisplay.DRAW_ALPHA_BLEND,\n SPICE_MSG_DISPLAY_SURFACE_CREATE: SpiceMsgDisplay.SURFACE_CREATE,\n SPICE_MSG_DISPLAY_SURFACE_DESTROY: SpiceMsgDisplay.SURFACE_DESTROY,\n SPICE_MSG_DISPLAY_STREAM_DATA_SIZED: SpiceMsgDisplay.STREAM_DATA_SIZED,\n SPICE_MSG_DISPLAY_MONITORS_CONFIG: SpiceMsgDisplay.MONITORS_CONFIG,\n SPICE_MSG_DISPLAY_DRAW_COMPOSITE: SpiceMsgDisplay.DRAW_COMPOSITE,\n SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT: SpiceMsgDisplay.STREAM_ACTIVATE_REPORT,\n\n // Client messages — Display\n SPICE_MSGC_DISPLAY_INIT: SpiceMsgcDisplay.INIT,\n SPICE_MSGC_DISPLAY_STREAM_REPORT: SpiceMsgcDisplay.STREAM_REPORT,\n\n // Server messages — Inputs\n SPICE_MSG_INPUTS_INIT: SpiceMsgInputs.INIT,\n SPICE_MSG_INPUTS_KEY_MODIFIERS: SpiceMsgInputs.KEY_MODIFIERS,\n SPICE_MSG_INPUTS_MOUSE_MOTION_ACK: SpiceMsgInputs.MOUSE_MOTION_ACK,\n\n // Client messages — Inputs\n SPICE_MSGC_INPUTS_KEY_DOWN: SpiceMsgcInputs.KEY_DOWN,\n SPICE_MSGC_INPUTS_KEY_UP: SpiceMsgcInputs.KEY_UP,\n SPICE_MSGC_INPUTS_KEY_MODIFIERS: SpiceMsgcInputs.KEY_MODIFIERS,\n SPICE_MSGC_INPUTS_MOUSE_MOTION: SpiceMsgcInputs.MOUSE_MOTION,\n SPICE_MSGC_INPUTS_MOUSE_POSITION: SpiceMsgcInputs.MOUSE_POSITION,\n SPICE_MSGC_INPUTS_MOUSE_PRESS: SpiceMsgcInputs.MOUSE_PRESS,\n SPICE_MSGC_INPUTS_MOUSE_RELEASE: SpiceMsgcInputs.MOUSE_RELEASE,\n\n // Server messages — Cursor\n SPICE_MSG_CURSOR_INIT: SpiceMsgCursor.INIT,\n SPICE_MSG_CURSOR_RESET: SpiceMsgCursor.RESET,\n SPICE_MSG_CURSOR_SET: SpiceMsgCursor.SET,\n SPICE_MSG_CURSOR_MOVE: SpiceMsgCursor.MOVE,\n SPICE_MSG_CURSOR_HIDE: SpiceMsgCursor.HIDE,\n SPICE_MSG_CURSOR_TRAIL: SpiceMsgCursor.TRAIL,\n SPICE_MSG_CURSOR_INVAL_ONE: SpiceMsgCursor.INVAL_ONE,\n SPICE_MSG_CURSOR_INVAL_ALL: SpiceMsgCursor.INVAL_ALL,\n\n // Server messages — Playback\n SPICE_MSG_PLAYBACK_DATA: SpiceMsgPlayback.DATA,\n SPICE_MSG_PLAYBACK_MODE: SpiceMsgPlayback.MODE,\n SPICE_MSG_PLAYBACK_START: SpiceMsgPlayback.START,\n SPICE_MSG_PLAYBACK_STOP: SpiceMsgPlayback.STOP,\n SPICE_MSG_PLAYBACK_VOLUME: SpiceMsgPlayback.VOLUME,\n SPICE_MSG_PLAYBACK_MUTE: SpiceMsgPlayback.MUTE,\n SPICE_MSG_PLAYBACK_LATENCY: SpiceMsgPlayback.LATENCY,\n\n // Server messages — Port / SpiceVMC\n SPICE_MSG_SPICEVMC_DATA: SpiceMsgPort.SPICEVMC_DATA,\n SPICE_MSG_PORT_INIT: SpiceMsgPort.INIT,\n SPICE_MSG_PORT_EVENT: SpiceMsgPort.EVENT,\n SPICE_MSG_END_PORT: SpiceMsgPort.END,\n\n // Client messages — Port / SpiceVMC\n SPICE_MSGC_SPICEVMC_DATA: SpiceMsgcPort.SPICEVMC_DATA,\n SPICE_MSGC_PORT_EVENT: SpiceMsgcPort.EVENT,\n SPICE_MSGC_END_PORT: SpiceMsgcPort.END,\n\n // Playback capabilities\n SPICE_PLAYBACK_CAP_CELT_0_5_1: SpicePlaybackCap.CELT_0_5_1,\n SPICE_PLAYBACK_CAP_VOLUME: SpicePlaybackCap.VOLUME,\n SPICE_PLAYBACK_CAP_LATENCY: SpicePlaybackCap.LATENCY,\n SPICE_PLAYBACK_CAP_OPUS: SpicePlaybackCap.OPUS,\n\n // Main capabilities\n SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE: SpiceMainCap.SEMI_SEAMLESS_MIGRATE,\n SPICE_MAIN_CAP_NAME_AND_UUID: SpiceMainCap.NAME_AND_UUID,\n SPICE_MAIN_CAP_AGENT_CONNECTED_TOKENS: SpiceMainCap.AGENT_CONNECTED_TOKENS,\n SPICE_MAIN_CAP_SEAMLESS_MIGRATE: SpiceMainCap.SEAMLESS_MIGRATE,\n\n // Display capabilities\n SPICE_DISPLAY_CAP_SIZED_STREAM: SpiceDisplayCap.SIZED_STREAM,\n SPICE_DISPLAY_CAP_MONITORS_CONFIG: SpiceDisplayCap.MONITORS_CONFIG,\n SPICE_DISPLAY_CAP_COMPOSITE: SpiceDisplayCap.COMPOSITE,\n SPICE_DISPLAY_CAP_A8_SURFACE: SpiceDisplayCap.A8_SURFACE,\n SPICE_DISPLAY_CAP_STREAM_REPORT: SpiceDisplayCap.STREAM_REPORT,\n SPICE_DISPLAY_CAP_LZ4_COMPRESSION: SpiceDisplayCap.LZ4_COMPRESSION,\n SPICE_DISPLAY_CAP_PREF_COMPRESSION: SpiceDisplayCap.PREF_COMPRESSION,\n SPICE_DISPLAY_CAP_GL_SCANOUT: SpiceDisplayCap.GL_SCANOUT,\n SPICE_DISPLAY_CAP_MULTI_CODEC: SpiceDisplayCap.MULTI_CODEC,\n SPICE_DISPLAY_CAP_CODEC_MJPEG: SpiceDisplayCap.CODEC_MJPEG,\n SPICE_DISPLAY_CAP_CODEC_VP8: SpiceDisplayCap.CODEC_VP8,\n\n // Audio data mode\n SPICE_AUDIO_DATA_MODE_INVALID: SpiceAudioDataMode.INVALID,\n SPICE_AUDIO_DATA_MODE_RAW: SpiceAudioDataMode.RAW,\n SPICE_AUDIO_DATA_MODE_CELT_0_5_1: SpiceAudioDataMode.CELT_0_5_1,\n SPICE_AUDIO_DATA_MODE_OPUS: SpiceAudioDataMode.OPUS,\n\n // Audio format\n SPICE_AUDIO_FMT_INVALID: SpiceAudioFmt.INVALID,\n SPICE_AUDIO_FMT_S16: SpiceAudioFmt.S16,\n\n // Channel types\n SPICE_CHANNEL_MAIN: SpiceChannel.MAIN,\n SPICE_CHANNEL_DISPLAY: SpiceChannel.DISPLAY,\n SPICE_CHANNEL_INPUTS: SpiceChannel.INPUTS,\n SPICE_CHANNEL_CURSOR: SpiceChannel.CURSOR,\n SPICE_CHANNEL_PLAYBACK: SpiceChannel.PLAYBACK,\n SPICE_CHANNEL_RECORD: SpiceChannel.RECORD,\n SPICE_CHANNEL_TUNNEL: SpiceChannel.TUNNEL,\n SPICE_CHANNEL_SMARTCARD: SpiceChannel.SMARTCARD,\n SPICE_CHANNEL_USBREDIR: SpiceChannel.USBREDIR,\n SPICE_CHANNEL_PORT: SpiceChannel.PORT,\n SPICE_CHANNEL_WEBDAV: SpiceChannel.WEBDAV,\n\n // Surface flags\n SPICE_SURFACE_FLAGS_PRIMARY,\n\n // Notify severity\n SPICE_NOTIFY_SEVERITY_INFO: SpiceNotifySeverity.INFO,\n SPICE_NOTIFY_SEVERITY_WARN: SpiceNotifySeverity.WARN,\n SPICE_NOTIFY_SEVERITY_ERROR: SpiceNotifySeverity.ERROR,\n\n // Mouse mode\n SPICE_MOUSE_MODE_SERVER: SpiceMouseMode.SERVER,\n SPICE_MOUSE_MODE_CLIENT: SpiceMouseMode.CLIENT,\n SPICE_MOUSE_MODE_MASK: SpiceMouseMode.MASK,\n\n // Clip type\n SPICE_CLIP_TYPE_NONE: SpiceClipType.NONE,\n SPICE_CLIP_TYPE_RECTS: SpiceClipType.RECTS,\n\n // Image type\n SPICE_IMAGE_TYPE_BITMAP: SpiceImageType.BITMAP,\n SPICE_IMAGE_TYPE_QUIC: SpiceImageType.QUIC,\n SPICE_IMAGE_TYPE_RESERVED: SpiceImageType.RESERVED,\n SPICE_IMAGE_TYPE_LZ_PLT: SpiceImageType.LZ_PLT,\n SPICE_IMAGE_TYPE_LZ_RGB: SpiceImageType.LZ_RGB,\n SPICE_IMAGE_TYPE_GLZ_RGB: SpiceImageType.GLZ_RGB,\n SPICE_IMAGE_TYPE_FROM_CACHE: SpiceImageType.FROM_CACHE,\n SPICE_IMAGE_TYPE_SURFACE: SpiceImageType.SURFACE,\n SPICE_IMAGE_TYPE_JPEG: SpiceImageType.JPEG,\n SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS: SpiceImageType.FROM_CACHE_LOSSLESS,\n SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB: SpiceImageType.ZLIB_GLZ_RGB,\n SPICE_IMAGE_TYPE_JPEG_ALPHA: SpiceImageType.JPEG_ALPHA,\n\n // Image flags\n SPICE_IMAGE_FLAGS_CACHE_ME: SpiceImageFlags.CACHE_ME,\n SPICE_IMAGE_FLAGS_HIGH_BITS_SET: SpiceImageFlags.HIGH_BITS_SET,\n SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME: SpiceImageFlags.CACHE_REPLACE_ME,\n\n // Bitmap flags\n SPICE_BITMAP_FLAGS_PAL_CACHE_ME: SpiceBitmapFlags.PAL_CACHE_ME,\n SPICE_BITMAP_FLAGS_PAL_FROM_CACHE: SpiceBitmapFlags.PAL_FROM_CACHE,\n SPICE_BITMAP_FLAGS_TOP_DOWN: SpiceBitmapFlags.TOP_DOWN,\n SPICE_BITMAP_FLAGS_MASK: SpiceBitmapFlags.MASK,\n\n // Bitmap format\n SPICE_BITMAP_FMT_INVALID: SpiceBitmapFmt.INVALID,\n SPICE_BITMAP_FMT_1BIT_LE: SpiceBitmapFmt._1BIT_LE,\n SPICE_BITMAP_FMT_1BIT_BE: SpiceBitmapFmt._1BIT_BE,\n SPICE_BITMAP_FMT_4BIT_LE: SpiceBitmapFmt._4BIT_LE,\n SPICE_BITMAP_FMT_4BIT_BE: SpiceBitmapFmt._4BIT_BE,\n SPICE_BITMAP_FMT_8BIT: SpiceBitmapFmt._8BIT,\n SPICE_BITMAP_FMT_16BIT: SpiceBitmapFmt._16BIT,\n SPICE_BITMAP_FMT_24BIT: SpiceBitmapFmt._24BIT,\n SPICE_BITMAP_FMT_32BIT: SpiceBitmapFmt._32BIT,\n SPICE_BITMAP_FMT_RGBA: SpiceBitmapFmt.RGBA,\n\n // Cursor flags\n SPICE_CURSOR_FLAGS_NONE: SpiceCursorFlags.NONE,\n SPICE_CURSOR_FLAGS_CACHE_ME: SpiceCursorFlags.CACHE_ME,\n SPICE_CURSOR_FLAGS_FROM_CACHE: SpiceCursorFlags.FROM_CACHE,\n SPICE_CURSOR_FLAGS_MASK: SpiceCursorFlags.MASK,\n\n // Mouse button mask\n SPICE_MOUSE_BUTTON_MASK_LEFT: SpiceMouseButtonMask.LEFT,\n SPICE_MOUSE_BUTTON_MASK_MIDDLE: SpiceMouseButtonMask.MIDDLE,\n SPICE_MOUSE_BUTTON_MASK_RIGHT: SpiceMouseButtonMask.RIGHT,\n SPICE_MOUSE_BUTTON_MASK_MASK: SpiceMouseButtonMask.MASK,\n\n // Mouse button\n SPICE_MOUSE_BUTTON_INVALID: SpiceMouseButton.INVALID,\n SPICE_MOUSE_BUTTON_LEFT: SpiceMouseButton.LEFT,\n SPICE_MOUSE_BUTTON_MIDDLE: SpiceMouseButton.MIDDLE,\n SPICE_MOUSE_BUTTON_RIGHT: SpiceMouseButton.RIGHT,\n SPICE_MOUSE_BUTTON_UP: SpiceMouseButton.UP,\n SPICE_MOUSE_BUTTON_DOWN: SpiceMouseButton.DOWN,\n\n // Brush type\n SPICE_BRUSH_TYPE_NONE: SpiceBrushType.NONE,\n SPICE_BRUSH_TYPE_SOLID: SpiceBrushType.SOLID,\n SPICE_BRUSH_TYPE_PATTERN: SpiceBrushType.PATTERN,\n\n // Surface format\n SPICE_SURFACE_FMT_INVALID: SpiceSurfaceFmt.INVALID,\n SPICE_SURFACE_FMT_1_A: SpiceSurfaceFmt._1_A,\n SPICE_SURFACE_FMT_8_A: SpiceSurfaceFmt._8_A,\n SPICE_SURFACE_FMT_16_555: SpiceSurfaceFmt._16_555,\n SPICE_SURFACE_FMT_32_xRGB: SpiceSurfaceFmt._32_xRGB,\n SPICE_SURFACE_FMT_16_565: SpiceSurfaceFmt._16_565,\n SPICE_SURFACE_FMT_32_ARGB: SpiceSurfaceFmt._32_ARGB,\n\n // Raster operation descriptor\n SPICE_ROPD_INVERS_SRC: SpiceRopd.INVERS_SRC,\n SPICE_ROPD_INVERS_BRUSH: SpiceRopd.INVERS_BRUSH,\n SPICE_ROPD_INVERS_DEST: SpiceRopd.INVERS_DEST,\n SPICE_ROPD_OP_PUT: SpiceRopd.OP_PUT,\n SPICE_ROPD_OP_OR: SpiceRopd.OP_OR,\n SPICE_ROPD_OP_AND: SpiceRopd.OP_AND,\n SPICE_ROPD_OP_XOR: SpiceRopd.OP_XOR,\n SPICE_ROPD_OP_BLACKNESS: SpiceRopd.OP_BLACKNESS,\n SPICE_ROPD_OP_WHITENESS: SpiceRopd.OP_WHITENESS,\n SPICE_ROPD_OP_INVERS: SpiceRopd.OP_INVERS,\n SPICE_ROPD_INVERS_RES: SpiceRopd.INVERS_RES,\n SPICE_ROPD_MASK: SpiceRopd.MASK,\n\n // LZ image type\n LZ_IMAGE_TYPE_INVALID: LzImageType.INVALID,\n LZ_IMAGE_TYPE_PLT1_LE: LzImageType.PLT1_LE,\n LZ_IMAGE_TYPE_PLT1_BE: LzImageType.PLT1_BE,\n LZ_IMAGE_TYPE_PLT4_LE: LzImageType.PLT4_LE,\n LZ_IMAGE_TYPE_PLT4_BE: LzImageType.PLT4_BE,\n LZ_IMAGE_TYPE_PLT8: LzImageType.PLT8,\n LZ_IMAGE_TYPE_RGB16: LzImageType.RGB16,\n LZ_IMAGE_TYPE_RGB24: LzImageType.RGB24,\n LZ_IMAGE_TYPE_RGB32: LzImageType.RGB32,\n LZ_IMAGE_TYPE_RGBA: LzImageType.RGBA,\n LZ_IMAGE_TYPE_XXXA: LzImageType.XXXA,\n\n // Input\n SPICE_INPUT_MOTION_ACK_BUNCH,\n\n // Cursor type\n SPICE_CURSOR_TYPE_ALPHA: SpiceCursorType.ALPHA,\n SPICE_CURSOR_TYPE_MONO: SpiceCursorType.MONO,\n SPICE_CURSOR_TYPE_COLOR4: SpiceCursorType.COLOR4,\n SPICE_CURSOR_TYPE_COLOR8: SpiceCursorType.COLOR8,\n SPICE_CURSOR_TYPE_COLOR16: SpiceCursorType.COLOR16,\n SPICE_CURSOR_TYPE_COLOR24: SpiceCursorType.COLOR24,\n SPICE_CURSOR_TYPE_COLOR32: SpiceCursorType.COLOR32,\n\n // Video codec type\n SPICE_VIDEO_CODEC_TYPE_MJPEG: SpiceVideoCodecType.MJPEG,\n SPICE_VIDEO_CODEC_TYPE_VP8: SpiceVideoCodecType.VP8,\n\n // VD Agent — protocol\n VD_AGENT_PROTOCOL,\n VD_AGENT_MAX_DATA_SIZE,\n\n // VD Agent — messages\n VD_AGENT_MOUSE_STATE: VdAgentMsg.MOUSE_STATE,\n VD_AGENT_MONITORS_CONFIG: VdAgentMsg.MONITORS_CONFIG,\n VD_AGENT_REPLY: VdAgentMsg.REPLY,\n VD_AGENT_CLIPBOARD: VdAgentMsg.CLIPBOARD,\n VD_AGENT_DISPLAY_CONFIG: VdAgentMsg.DISPLAY_CONFIG,\n VD_AGENT_ANNOUNCE_CAPABILITIES: VdAgentMsg.ANNOUNCE_CAPABILITIES,\n VD_AGENT_CLIPBOARD_GRAB: VdAgentMsg.CLIPBOARD_GRAB,\n VD_AGENT_CLIPBOARD_REQUEST: VdAgentMsg.CLIPBOARD_REQUEST,\n VD_AGENT_CLIPBOARD_RELEASE: VdAgentMsg.CLIPBOARD_RELEASE,\n VD_AGENT_FILE_XFER_START: VdAgentMsg.FILE_XFER_START,\n VD_AGENT_FILE_XFER_STATUS: VdAgentMsg.FILE_XFER_STATUS,\n VD_AGENT_FILE_XFER_DATA: VdAgentMsg.FILE_XFER_DATA,\n VD_AGENT_CLIENT_DISCONNECTED: VdAgentMsg.CLIENT_DISCONNECTED,\n VD_AGENT_MAX_CLIPBOARD: VdAgentMsg.MAX_CLIPBOARD,\n\n // VD Agent — capabilities\n VD_AGENT_CAP_MOUSE_STATE: VdAgentCap.MOUSE_STATE,\n VD_AGENT_CAP_MONITORS_CONFIG: VdAgentCap.MONITORS_CONFIG,\n VD_AGENT_CAP_REPLY: VdAgentCap.REPLY,\n VD_AGENT_CAP_CLIPBOARD: VdAgentCap.CLIPBOARD,\n VD_AGENT_CAP_DISPLAY_CONFIG: VdAgentCap.DISPLAY_CONFIG,\n VD_AGENT_CAP_CLIPBOARD_BY_DEMAND: VdAgentCap.CLIPBOARD_BY_DEMAND,\n VD_AGENT_CAP_CLIPBOARD_SELECTION: VdAgentCap.CLIPBOARD_SELECTION,\n VD_AGENT_CAP_SPARSE_MONITORS_CONFIG: VdAgentCap.SPARSE_MONITORS_CONFIG,\n VD_AGENT_CAP_GUEST_LINEEND_LF: VdAgentCap.GUEST_LINEEND_LF,\n VD_AGENT_CAP_GUEST_LINEEND_CRLF: VdAgentCap.GUEST_LINEEND_CRLF,\n VD_AGENT_CAP_MAX_CLIPBOARD: VdAgentCap.MAX_CLIPBOARD,\n VD_AGENT_END_CAP: VdAgentCap.END,\n\n // VD Agent — file transfer status\n VD_AGENT_FILE_XFER_STATUS_CAN_SEND_DATA: VdAgentFileXferStatus.CAN_SEND_DATA,\n VD_AGENT_FILE_XFER_STATUS_CANCELLED: VdAgentFileXferStatus.CANCELLED,\n VD_AGENT_FILE_XFER_STATUS_ERROR: VdAgentFileXferStatus.ERROR,\n VD_AGENT_FILE_XFER_STATUS_SUCCESS: VdAgentFileXferStatus.SUCCESS,\n\n // VD Agent — clipboard type\n VD_AGENT_CLIPBOARD_NONE: VdAgentClipboard.NONE,\n VD_AGENT_CLIPBOARD_UTF8_TEXT: VdAgentClipboard.UTF8_TEXT,\n VD_AGENT_CLIPBOARD_IMAGE_PNG: VdAgentClipboard.IMAGE_PNG,\n VD_AGENT_CLIPBOARD_IMAGE_BMP: VdAgentClipboard.IMAGE_BMP,\n VD_AGENT_CLIPBOARD_IMAGE_TIFF: VdAgentClipboard.IMAGE_TIFF,\n VD_AGENT_CLIPBOARD_IMAGE_JPG: VdAgentClipboard.IMAGE_JPG,\n} as const;\n","/*----------------------------------------------------------------------------\n** spicetype.ts\n** TypeScript classes for common SPICE protocol data types.\n** Used as helpers in reading and writing messages to/from the server.\n** Faithfully converted from spicetype.js.\n**--------------------------------------------------------------------------*/\n\nimport {\n SpiceClipType,\n SpiceImageType,\n SpiceBitmapFlags,\n SpiceBrushType,\n SpiceCursorFlags,\n} from './enums';\n\n// ---------------------------------------------------------------------------\n// Forward-declared interface for SpiceQuic (implemented in quic.ts)\n// This avoids a circular dependency while providing type safety.\n// ---------------------------------------------------------------------------\n\nexport interface SpiceQuicData {\n data_size: number;\n outptr: Uint8Array | null;\n type: number;\n width: number;\n height: number;\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number;\n}\n\n/**\n * Factory function type for creating SpiceQuic instances.\n * Registered at runtime to avoid circular dependency with quic.ts.\n */\ntype SpiceQuicFactory = () => SpiceQuicData;\n\nlet spiceQuicFactory: SpiceQuicFactory | null = null;\n\n/**\n * Register the SpiceQuic factory so SpiceImage can create instances\n * without directly importing quic.ts.\n */\nexport function registerSpiceQuicFactory(factory: SpiceQuicFactory): void {\n spiceQuicFactory = factory;\n}\n\n// ---------------------------------------------------------------------------\n// LZ RGB header — used by SpiceImage for LZ_RGB and JPEG_ALPHA alpha channel\n// ---------------------------------------------------------------------------\n\nexport interface LzRgbHeader {\n length: number;\n magic: string;\n version: number;\n type: number;\n width: number;\n height: number;\n stride: number;\n top_down: number;\n data: ArrayBuffer;\n}\n\n// ---------------------------------------------------------------------------\n// JPEG data — used by SpiceImage for JPEG type\n// ---------------------------------------------------------------------------\n\nexport interface JpegData {\n data_size: number;\n data: ArrayBuffer;\n}\n\n// ---------------------------------------------------------------------------\n// JPEG Alpha data — used by SpiceImage for JPEG_ALPHA type\n// ---------------------------------------------------------------------------\n\nexport interface JpegAlphaData {\n flags: number;\n jpeg_size: number;\n data_size: number;\n data: ArrayBuffer;\n alpha: LzRgbHeader;\n}\n\n// ---------------------------------------------------------------------------\n// SpiceChannelId\n// ---------------------------------------------------------------------------\n\nexport class SpiceChannelId {\n type: number = 0;\n id: number = 0;\n\n fromDataView(dv: DataView, at: number, _mb: ArrayBuffer): number {\n this.type = dv.getUint8(at); at++;\n this.id = dv.getUint8(at); at++;\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceRect\n// ---------------------------------------------------------------------------\n\nexport class SpiceRect {\n top: number = 0;\n left: number = 0;\n bottom: number = 0;\n right: number = 0;\n\n fromDataView(dv: DataView, at: number, _mb: ArrayBuffer): number {\n this.top = dv.getUint32(at, true); at += 4;\n this.left = dv.getUint32(at, true); at += 4;\n this.bottom = dv.getUint32(at, true); at += 4;\n this.right = dv.getUint32(at, true); at += 4;\n return at;\n }\n\n isSameSize(r: SpiceRect): boolean {\n return (this.bottom - this.top) === (r.bottom - r.top) &&\n (this.right - this.left) === (r.right - r.left);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceClipRects\n// ---------------------------------------------------------------------------\n\nexport class SpiceClipRects {\n numRects: number = 0;\n rects: SpiceRect[] = [];\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n this.numRects = dv.getUint32(at, true); at += 4;\n this.rects = [];\n for (let i = 0; i < this.numRects; i++) {\n const rect = new SpiceRect();\n at = rect.fromDataView(dv, at, mb);\n this.rects.push(rect);\n }\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceClip\n// ---------------------------------------------------------------------------\n\nexport class SpiceClip {\n type: number = 0;\n rects: SpiceClipRects | null = null;\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n this.type = dv.getUint8(at); at++;\n if (this.type === SpiceClipType.RECTS) {\n this.rects = new SpiceClipRects();\n at = this.rects.fromDataView(dv, at, mb);\n }\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceImageDescriptor\n// ---------------------------------------------------------------------------\n\nexport class SpiceImageDescriptor {\n id: bigint = 0n;\n type: number = 0;\n flags: number = 0;\n width: number = 0;\n height: number = 0;\n\n fromDataView(dv: DataView, at: number, _mb: ArrayBuffer): number {\n this.id = dv.getBigUint64(at, true); at += 8;\n this.type = dv.getUint8(at); at++;\n this.flags = dv.getUint8(at); at++;\n this.width = dv.getUint32(at, true); at += 4;\n this.height = dv.getUint32(at, true); at += 4;\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpicePalette\n// ---------------------------------------------------------------------------\n\nexport class SpicePalette {\n unique: bigint = 0n;\n numEnts: number = 0;\n ents: number[] = [];\n\n fromDataView(dv: DataView, at: number, _mb: ArrayBuffer): number {\n this.unique = dv.getBigUint64(at, true); at += 8;\n this.numEnts = dv.getUint16(at, true); at += 2;\n this.ents = [];\n for (let i = 0; i < this.numEnts; i++) {\n this.ents[i] = dv.getUint32(at, true); at += 4;\n }\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceBitmap\n// ---------------------------------------------------------------------------\n\nexport class SpiceBitmap {\n format: number = 0;\n flags: number = 0;\n x: number = 0;\n y: number = 0;\n stride: number = 0;\n paletteId: bigint = 0n;\n palette: SpicePalette | null = null;\n data: ArrayBuffer = new ArrayBuffer(0);\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n this.format = dv.getUint8(at); at++;\n this.flags = dv.getUint8(at); at++;\n this.x = dv.getUint32(at, true); at += 4;\n this.y = dv.getUint32(at, true); at += 4;\n this.stride = dv.getUint32(at, true); at += 4;\n if (this.flags & SpiceBitmapFlags.PAL_FROM_CACHE) {\n this.paletteId = dv.getBigUint64(at, true); at += 8;\n } else {\n const offset = dv.getUint32(at, true); at += 4;\n if (offset === 0) {\n this.palette = null;\n } else {\n this.palette = new SpicePalette();\n this.palette.fromDataView(dv, offset, mb);\n }\n }\n // FIXME - should probably constrain this to the offset\n // of palette, if non zero\n this.data = mb.slice(at);\n at += this.data.byteLength;\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpicePoint\n// ---------------------------------------------------------------------------\n\nexport class SpicePoint {\n x: number = 0;\n y: number = 0;\n\n fromDataView(dv: DataView, at: number, _mb: ArrayBuffer): number {\n this.x = dv.getUint32(at, true); at += 4;\n this.y = dv.getUint32(at, true); at += 4;\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpicePoint16\n// ---------------------------------------------------------------------------\n\nexport class SpicePoint16 {\n x: number = 0;\n y: number = 0;\n\n fromDataView(dv: DataView, at: number, _mb: ArrayBuffer): number {\n this.x = dv.getUint16(at, true); at += 2;\n this.y = dv.getUint16(at, true); at += 2;\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceImage\n// ---------------------------------------------------------------------------\n\nexport class SpiceImage {\n descriptor: SpiceImageDescriptor = new SpiceImageDescriptor();\n lzRgb: LzRgbHeader | null = null;\n bitmap: SpiceBitmap | null = null;\n surfaceId: number | null = null;\n jpeg: JpegData | null = null;\n jpegAlpha: JpegAlphaData | null = null;\n quic: SpiceQuicData | null = null;\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n this.descriptor = new SpiceImageDescriptor();\n at = this.descriptor.fromDataView(dv, at, mb);\n\n if (this.descriptor.type === SpiceImageType.LZ_RGB) {\n at = this.parseLzRgb(dv, at, mb);\n }\n\n if (this.descriptor.type === SpiceImageType.BITMAP) {\n this.bitmap = new SpiceBitmap();\n at = this.bitmap.fromDataView(dv, at, mb);\n }\n\n if (this.descriptor.type === SpiceImageType.SURFACE) {\n this.surfaceId = dv.getUint32(at, true); at += 4;\n }\n\n if (this.descriptor.type === SpiceImageType.JPEG) {\n const jpegDataSize = dv.getUint32(at, true); at += 4;\n const jpegDataBuf = mb.slice(at);\n this.jpeg = {\n data_size: jpegDataSize,\n data: jpegDataBuf,\n };\n at += jpegDataBuf.byteLength;\n }\n\n if (this.descriptor.type === SpiceImageType.JPEG_ALPHA) {\n at = this.parseJpegAlpha(dv, at, mb);\n }\n\n if (this.descriptor.type === SpiceImageType.QUIC) {\n if (!spiceQuicFactory) {\n throw new Error('SpiceQuic factory not registered. Call registerSpiceQuicFactory() before decoding QUIC images.');\n }\n this.quic = spiceQuicFactory();\n at = this.quic.fromDataView(dv, at, mb);\n }\n\n return at;\n }\n\n private parseLzRgb(dv: DataView, at: number, mb: ArrayBuffer): number {\n const length = dv.getUint32(at, true); at += 4;\n const initialAt = at;\n\n let magic = '';\n for (let i = 3; i >= 0; i--) {\n magic += String.fromCharCode(dv.getUint8(at + i));\n }\n at += 4;\n\n // NOTE: The endian change is *correct* (big-endian reads)\n const version = dv.getUint32(at); at += 4;\n const type = dv.getUint32(at); at += 4;\n const width = dv.getUint32(at); at += 4;\n const height = dv.getUint32(at); at += 4;\n const stride = dv.getUint32(at); at += 4;\n const topDown = dv.getUint32(at); at += 4;\n\n const headerSize = at - initialAt;\n const data = mb.slice(at, length + at - headerSize);\n at += data.byteLength;\n\n this.lzRgb = {\n length,\n magic,\n version,\n type,\n width,\n height,\n stride,\n top_down: topDown,\n data,\n };\n\n return at;\n }\n\n private parseJpegAlpha(dv: DataView, at: number, mb: ArrayBuffer): number {\n const flags = dv.getUint8(at); at += 1;\n const jpegSize = dv.getUint32(at, true); at += 4;\n const dataSize = dv.getUint32(at, true); at += 4;\n const jpegData = mb.slice(at, jpegSize + at);\n at += jpegData.byteLength;\n\n // Alpha channel is an LZ image\n const alphaLength = dataSize - jpegSize;\n const alphaInitialAt = at;\n\n let alphaMagic = '';\n for (let i = 3; i >= 0; i--) {\n alphaMagic += String.fromCharCode(dv.getUint8(at + i));\n }\n at += 4;\n\n // NOTE: The endian change is *correct* (big-endian reads)\n const alphaVersion = dv.getUint32(at); at += 4;\n const alphaType = dv.getUint32(at); at += 4;\n const alphaWidth = dv.getUint32(at); at += 4;\n const alphaHeight = dv.getUint32(at); at += 4;\n const alphaStride = dv.getUint32(at); at += 4;\n const alphaTopDown = dv.getUint32(at); at += 4;\n\n const alphaHeaderSize = at - alphaInitialAt;\n const alphaData = mb.slice(at, alphaLength + at - alphaHeaderSize);\n at += alphaData.byteLength;\n\n this.jpegAlpha = {\n flags,\n jpeg_size: jpegSize,\n data_size: dataSize,\n data: jpegData,\n alpha: {\n length: alphaLength,\n magic: alphaMagic,\n version: alphaVersion,\n type: alphaType,\n width: alphaWidth,\n height: alphaHeight,\n stride: alphaStride,\n top_down: alphaTopDown,\n data: alphaData,\n },\n };\n\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceQMask\n// ---------------------------------------------------------------------------\n\nexport class SpiceQMask {\n flags: number = 0;\n pos: SpicePoint = new SpicePoint();\n bitmap: SpiceImage | null = null;\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n this.flags = dv.getUint8(at); at++;\n this.pos = new SpicePoint();\n at = this.pos.fromDataView(dv, at, mb);\n const offset = dv.getUint32(at, true); at += 4;\n if (offset === 0) {\n this.bitmap = null;\n return at;\n }\n\n this.bitmap = new SpiceImage();\n return this.bitmap.fromDataView(dv, offset, mb);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpicePattern\n// ---------------------------------------------------------------------------\n\nexport class SpicePattern {\n pat: SpiceImage | null = null;\n pos: SpicePoint = new SpicePoint();\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n const offset = dv.getUint32(at, true); at += 4;\n if (offset === 0) {\n this.pat = null;\n } else {\n this.pat = new SpiceImage();\n this.pat.fromDataView(dv, offset, mb);\n }\n\n this.pos = new SpicePoint();\n return this.pos.fromDataView(dv, at, mb);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceBrush\n// ---------------------------------------------------------------------------\n\nexport class SpiceBrush {\n type: number = 0;\n color: number = 0;\n pattern: SpicePattern | null = null;\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n this.type = dv.getUint8(at); at++;\n if (this.type === SpiceBrushType.SOLID) {\n this.color = dv.getUint32(at, true); at += 4;\n } else if (this.type === SpiceBrushType.PATTERN) {\n this.pattern = new SpicePattern();\n at = this.pattern.fromDataView(dv, at, mb);\n }\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceFill\n// ---------------------------------------------------------------------------\n\nexport class SpiceFill {\n brush: SpiceBrush = new SpiceBrush();\n ropDescriptor: number = 0;\n mask: SpiceQMask = new SpiceQMask();\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n this.brush = new SpiceBrush();\n at = this.brush.fromDataView(dv, at, mb);\n this.ropDescriptor = dv.getUint16(at, true); at += 2;\n this.mask = new SpiceQMask();\n return this.mask.fromDataView(dv, at, mb);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceCopy\n// ---------------------------------------------------------------------------\n\nexport class SpiceCopy {\n srcBitmap: SpiceImage | null = null;\n srcArea: SpiceRect = new SpiceRect();\n ropDescriptor: number = 0;\n scaleMode: number = 0;\n mask: SpiceQMask = new SpiceQMask();\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n const offset = dv.getUint32(at, true); at += 4;\n if (offset === 0) {\n this.srcBitmap = null;\n } else {\n this.srcBitmap = new SpiceImage();\n this.srcBitmap.fromDataView(dv, offset, mb);\n }\n this.srcArea = new SpiceRect();\n at = this.srcArea.fromDataView(dv, at, mb);\n this.ropDescriptor = dv.getUint16(at, true); at += 2;\n this.scaleMode = dv.getUint8(at); at++;\n this.mask = new SpiceQMask();\n return this.mask.fromDataView(dv, at, mb);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceCursorHeader\n// ---------------------------------------------------------------------------\n\nexport class SpiceCursorHeader {\n unique: bigint = 0n;\n type: number = 0;\n width: number = 0;\n height: number = 0;\n hotSpotX: number = 0;\n hotSpotY: number = 0;\n\n fromDataView(dv: DataView, at: number, _mb: ArrayBuffer): number {\n this.unique = dv.getBigUint64(at, true); at += 8;\n this.type = dv.getUint8(at); at++;\n this.width = dv.getUint16(at, true); at += 2;\n this.height = dv.getUint16(at, true); at += 2;\n this.hotSpotX = dv.getUint16(at, true); at += 2;\n this.hotSpotY = dv.getUint16(at, true); at += 2;\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceCursor\n// ---------------------------------------------------------------------------\n\nexport class SpiceCursor {\n flags: number = 0;\n header: SpiceCursorHeader | null = null;\n data: ArrayBuffer = new ArrayBuffer(0);\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n this.flags = dv.getUint16(at, true); at += 2;\n if (this.flags & SpiceCursorFlags.NONE) {\n this.header = null;\n } else {\n this.header = new SpiceCursorHeader();\n at = this.header.fromDataView(dv, at, mb);\n this.data = mb.slice(at);\n at += this.data.byteLength;\n }\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceSurface\n// ---------------------------------------------------------------------------\n\nexport class SpiceSurface {\n surfaceId: number = 0;\n width: number = 0;\n height: number = 0;\n format: number = 0;\n flags: number = 0;\n\n fromDataView(dv: DataView, at: number, _mb: ArrayBuffer): number {\n this.surfaceId = dv.getUint32(at, true); at += 4;\n this.width = dv.getUint32(at, true); at += 4;\n this.height = dv.getUint32(at, true); at += 4;\n this.format = dv.getUint32(at, true); at += 4;\n this.flags = dv.getUint32(at, true); at += 4;\n return at;\n }\n}\n\n/* FIXME - SpiceImage types lz_plt, jpeg, zlib_glz, and jpeg_alpha are\n completely unimplemented */\n","/*----------------------------------------------------------------------------\n** spicemsg.ts\n** TypeScript classes for SPICE protocol messages.\n** Faithfully converted from spicemsg.js using ES6 class syntax,\n** standard DataView (replacing the SpiceDataView polyfill), and\n** BigInt for 64-bit fields.\n**--------------------------------------------------------------------------*/\n\nimport {\n SPICE_MAGIC,\n SPICE_VERSION_MAJOR,\n SPICE_VERSION_MINOR,\n SPICE_TICKET_KEY_PAIR_LENGTH,\n SPICE_TICKET_PUBKEY_BYTES,\n VD_AGENT_PROTOCOL,\n VdAgentCap,\n SpiceMouseButton,\n SpiceMouseButtonMask,\n} from './enums';\n\nimport {\n SpiceChannelId,\n SpiceRect,\n SpiceClip,\n SpiceCopy,\n SpiceFill,\n SpicePoint,\n SpiceSurface,\n SpicePoint16,\n SpiceCursor,\n} from './spicetype';\n\n// ---------------------------------------------------------------------------\n// Interface for messages that can be serialized to a buffer\n// ---------------------------------------------------------------------------\n\nexport interface Serializable {\n toBuffer(a: ArrayBuffer, at?: number): void;\n bufferSize(): number;\n}\n\n// ---------------------------------------------------------------------------\n// No RSA factory needed — Web Crypto API accepts raw DER (SPKI) bytes\n// directly via crypto.subtle.importKey(\"spki\", ...). SpiceLinkReply now\n// stores the raw DER public key as an ArrayBuffer.\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// SpiceLinkHeader\n// ---------------------------------------------------------------------------\n\nexport class SpiceLinkHeader implements Serializable {\n magic: string = SPICE_MAGIC;\n majorVersion: number = SPICE_VERSION_MAJOR;\n minorVersion: number = SPICE_VERSION_MINOR;\n size: number = 0;\n\n constructor(a?: ArrayBuffer, at?: number) {\n if (a !== undefined) {\n this.fromBuffer(a, at);\n }\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.magic = '';\n for (let i = 0; i < 4; i++) {\n this.magic += String.fromCharCode(dv.getUint8(at + i));\n }\n at += 4;\n\n this.majorVersion = dv.getUint32(at, true); at += 4;\n this.minorVersion = dv.getUint32(at, true); at += 4;\n this.size = dv.getUint32(at, true); at += 4;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n for (let i = 0; i < 4; i++) {\n dv.setUint8(at + i, this.magic.charCodeAt(i));\n }\n at += 4;\n\n dv.setUint32(at, this.majorVersion, true); at += 4;\n dv.setUint32(at, this.minorVersion, true); at += 4;\n dv.setUint32(at, this.size, true); at += 4;\n }\n\n bufferSize(): number {\n return 16;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceLinkMess\n// ---------------------------------------------------------------------------\n\nexport class SpiceLinkMess implements Serializable {\n connectionId: number = 0;\n channelType: number = 0;\n channelId: number = 0;\n commonCaps: number[] = [];\n channelCaps: number[] = [];\n\n constructor(a?: ArrayBuffer, at?: number) {\n if (a !== undefined) {\n this.fromBuffer(a, at);\n }\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const origAt = at;\n const dv = new DataView(a);\n this.connectionId = dv.getUint32(at, true); at += 4;\n this.channelType = dv.getUint8(at); at++;\n this.channelId = dv.getUint8(at); at++;\n const numCommonCaps = dv.getUint32(at, true); at += 4;\n const numChannelCaps = dv.getUint32(at, true); at += 4;\n const capsOffset = dv.getUint32(at, true); at += 4;\n\n at = origAt + capsOffset;\n this.commonCaps = [];\n for (let i = 0; i < numCommonCaps; i++) {\n this.commonCaps.unshift(dv.getUint32(at, true)); at += 4;\n }\n\n this.channelCaps = [];\n for (let i = 0; i < numChannelCaps; i++) {\n this.channelCaps.unshift(dv.getUint32(at, true)); at += 4;\n }\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const origAt = at;\n const dv = new DataView(a);\n dv.setUint32(at, this.connectionId, true); at += 4;\n dv.setUint8(at, this.channelType); at++;\n dv.setUint8(at, this.channelId); at++;\n dv.setUint32(at, this.commonCaps.length, true); at += 4;\n dv.setUint32(at, this.channelCaps.length, true); at += 4;\n dv.setUint32(at, (at - origAt) + 4, true); at += 4;\n\n for (let i = 0; i < this.commonCaps.length; i++) {\n dv.setUint32(at, this.commonCaps[i] ?? 0, true); at += 4;\n }\n\n for (let i = 0; i < this.channelCaps.length; i++) {\n dv.setUint32(at, this.channelCaps[i] ?? 0, true); at += 4;\n }\n }\n\n bufferSize(): number {\n return 18 + (4 * this.commonCaps.length) + (4 * this.channelCaps.length);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceLinkReply\n// ---------------------------------------------------------------------------\n\nexport class SpiceLinkReply {\n error: number = 0;\n /** Raw DER-encoded SPKI public key bytes from the server. */\n pubKeyDer: ArrayBuffer | null = null;\n commonCaps: number[] = [];\n channelCaps: number[] = [];\n\n constructor(a?: ArrayBuffer, at?: number) {\n if (a !== undefined) {\n this.fromBuffer(a, at);\n }\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const origAt = at;\n const dv = new DataView(a);\n this.error = dv.getUint32(at, true); at += 4;\n\n // Store the raw DER (SPKI) public key bytes for use with\n // crypto.subtle.importKey(\"spki\", ...) during ticket encryption.\n this.pubKeyDer = a.slice(at, at + SPICE_TICKET_PUBKEY_BYTES);\n at += SPICE_TICKET_PUBKEY_BYTES;\n\n const numCommonCaps = dv.getUint32(at, true); at += 4;\n const numChannelCaps = dv.getUint32(at, true); at += 4;\n const capsOffset = dv.getUint32(at, true); at += 4;\n\n at = origAt + capsOffset;\n this.commonCaps = [];\n for (let i = 0; i < numCommonCaps; i++) {\n this.commonCaps.unshift(dv.getUint32(at, true)); at += 4;\n }\n\n this.channelCaps = [];\n for (let i = 0; i < numChannelCaps; i++) {\n this.channelCaps.unshift(dv.getUint32(at, true)); at += 4;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceLinkAuthTicket\n// ---------------------------------------------------------------------------\n\nexport class SpiceLinkAuthTicket implements Serializable {\n authMechanism: number = 0;\n encryptedData: number[] | null = null;\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.authMechanism, true); at += 4;\n const keyBytes = SPICE_TICKET_KEY_PAIR_LENGTH / 8;\n for (let i = 0; i < keyBytes; i++) {\n if (this.encryptedData && i < this.encryptedData.length) {\n dv.setUint8(at, this.encryptedData[i] ?? 0);\n } else {\n dv.setUint8(at, 0);\n }\n at++;\n }\n }\n\n bufferSize(): number {\n return 4 + (SPICE_TICKET_KEY_PAIR_LENGTH / 8);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceLinkAuthReply\n// ---------------------------------------------------------------------------\n\nexport class SpiceLinkAuthReply {\n authCode: number = 0;\n\n constructor(a?: ArrayBuffer, at?: number) {\n if (a !== undefined) {\n this.fromBuffer(a, at);\n }\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.authCode = dv.getUint32(at, true); at += 4;\n }\n\n bufferSize(): number {\n return 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMiniData\n// ---------------------------------------------------------------------------\n\nexport class SpiceMiniData implements Serializable {\n type: number = 0;\n size: number = 0;\n data: ArrayBuffer | undefined = undefined;\n\n constructor(a?: ArrayBuffer, at?: number) {\n if (a !== undefined) {\n this.fromBuffer(a, at);\n }\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.type = dv.getUint16(at, true); at += 2;\n this.size = dv.getUint32(at, true); at += 4;\n if (a.byteLength > at) {\n this.data = a.slice(at);\n }\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint16(at, this.type, true); at += 2;\n dv.setUint32(at, this.data ? this.data.byteLength : 0, true); at += 4;\n if (this.data && this.data.byteLength > 0) {\n const u8arr = new Uint8Array(this.data);\n const target = new Uint8Array(a);\n for (let i = 0; i < u8arr.length; i++, at++) {\n target[at] = u8arr[i] ?? 0;\n }\n }\n }\n\n buildMsg(inType: number, extra: Serializable): void {\n this.type = inType;\n this.size = extra.bufferSize();\n this.data = new ArrayBuffer(this.size);\n extra.toBuffer(this.data);\n }\n\n bufferSize(): number {\n if (this.data) {\n return 6 + this.data.byteLength;\n }\n return 6;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgChannels\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgChannels {\n numOfChannels: number = 0;\n channels: SpiceChannelId[] = [];\n\n constructor(a?: ArrayBuffer, at?: number) {\n if (a !== undefined) {\n this.fromBuffer(a, at);\n }\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.numOfChannels = dv.getUint32(at, true); at += 4;\n this.channels = [];\n for (let i = 0; i < this.numOfChannels; i++) {\n const chan = new SpiceChannelId();\n at = chan.fromDataView(dv, at, a);\n this.channels.push(chan);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Clipboard helpers\n// ---------------------------------------------------------------------------\n\nfunction hasClipboardSelection(caps: number[]): boolean {\n const cap0 = caps[0];\n if (cap0 === undefined) return false;\n return ((cap0 >> VdAgentCap.CLIPBOARD_SELECTION) & 1) !== 0;\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgClipboardGrab\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgClipboardGrab implements Serializable {\n hasClipboardSelection: boolean;\n type: number;\n\n constructor(type: number, caps: number[]) {\n this.hasClipboardSelection = hasClipboardSelection(caps);\n this.type = type;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n if (this.hasClipboardSelection) {\n dv.setUint32(at, 0, true); at += 4;\n }\n dv.setUint32(at, this.type, true); at += 4;\n }\n\n bufferSize(): number {\n return this.hasClipboardSelection ? 8 : 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgClipboardReceive\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgClipboardReceive {\n hasClipboardSelection: boolean;\n type: number;\n payload: ArrayBuffer;\n\n constructor(agentData: { data: ArrayBuffer }, caps: number[]) {\n this.hasClipboardSelection = hasClipboardSelection(caps);\n const dv = new DataView(agentData.data);\n let at = this.hasClipboardSelection ? 4 : 0;\n this.type = dv.getUint32(at, true); at += 4;\n this.payload = agentData.data.slice(at);\n }\n\n getText(): string {\n return new TextDecoder('utf-8').decode(this.payload);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgClipboardRequest\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgClipboardRequest implements Serializable {\n hasClipboardSelection: boolean;\n type: number;\n\n constructor(type: number, caps: number[]) {\n this.hasClipboardSelection = hasClipboardSelection(caps);\n this.type = type;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n if (this.hasClipboardSelection) {\n dv.setUint32(at, 0, true); at += 4;\n }\n dv.setUint32(at, this.type, true); at += 4;\n }\n\n bufferSize(): number {\n return this.hasClipboardSelection ? 8 : 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgClipboardSend\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgClipboardSend implements Serializable {\n hasClipboardSelection: boolean;\n type: number;\n text: string;\n\n constructor(type: number, text: string, caps: number[]) {\n this.hasClipboardSelection = hasClipboardSelection(caps);\n this.type = type;\n this.text = text;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n if (this.hasClipboardSelection) {\n dv.setUint32(at, 0, true); at += 4;\n }\n dv.setUint32(at, this.type, true); at += 4;\n const payload = new TextEncoder().encode(this.text);\n new Uint8Array(a, at, payload.byteLength).set(payload); at += payload.byteLength;\n }\n\n bufferSize(): number {\n const payloadLength = new TextEncoder().encode(this.text).byteLength;\n return (this.hasClipboardSelection ? 8 : 4) + payloadLength;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgMainInit\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgMainInit {\n sessionId: number = 0;\n displayChannelsHint: number = 0;\n supportedMouseModes: number = 0;\n currentMouseMode: number = 0;\n agentConnected: number = 0;\n agentTokens: number = 0;\n multiMediaTime: number = 0;\n ramHint: number = 0;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.sessionId = dv.getUint32(at, true); at += 4;\n this.displayChannelsHint = dv.getUint32(at, true); at += 4;\n this.supportedMouseModes = dv.getUint32(at, true); at += 4;\n this.currentMouseMode = dv.getUint32(at, true); at += 4;\n this.agentConnected = dv.getUint32(at, true); at += 4;\n this.agentTokens = dv.getUint32(at, true); at += 4;\n this.multiMediaTime = dv.getUint32(at, true); at += 4;\n this.ramHint = dv.getUint32(at, true); at += 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgMainMouseMode\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgMainMouseMode {\n supportedModes: number = 0;\n currentMode: number = 0;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.supportedModes = dv.getUint16(at, true); at += 2;\n this.currentMode = dv.getUint16(at, true); at += 2;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgMainAgentData\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgMainAgentData {\n protocol: number = 0;\n type: number = 0;\n opaque: bigint = 0n;\n size: number = 0;\n data: ArrayBuffer | undefined = undefined;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.protocol = dv.getUint32(at, true); at += 4;\n this.type = dv.getUint32(at, true); at += 4;\n this.opaque = dv.getBigUint64(at, true); at += 8;\n this.size = dv.getUint32(at, true); at += 4;\n if (a.byteLength > at) {\n this.data = a.slice(at);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgMainAgentTokens\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgMainAgentTokens {\n numTokens: number = 0;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.numTokens = dv.getUint32(at, true); at += 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgSetAck\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgSetAck {\n generation: number = 0;\n window: number = 0;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.generation = dv.getUint32(at, true); at += 4;\n this.window = dv.getUint32(at, true); at += 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcAckSync\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcAckSync implements Serializable {\n generation: number;\n\n constructor(ack: { generation: number }) {\n this.generation = ack.generation;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.generation, true); at += 4;\n }\n\n bufferSize(): number {\n return 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcMainMouseModeRequest\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcMainMouseModeRequest implements Serializable {\n mode: number;\n\n constructor(mode: number) {\n this.mode = mode;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint16(at, this.mode, true); at += 2;\n }\n\n bufferSize(): number {\n return 2;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcMainAgentStart\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcMainAgentStart implements Serializable {\n numTokens: number;\n\n constructor(numTokens: number) {\n this.numTokens = numTokens;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.numTokens, true); at += 4;\n }\n\n bufferSize(): number {\n return 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcMainAgentData\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcMainAgentData implements Serializable {\n protocol: number;\n type: number;\n opaque: bigint = 0n;\n size: number;\n data: Serializable;\n\n constructor(type: number, data: Serializable) {\n this.protocol = VD_AGENT_PROTOCOL;\n this.type = type;\n this.size = data.bufferSize();\n this.data = data;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.protocol, true); at += 4;\n dv.setUint32(at, this.type, true); at += 4;\n dv.setBigUint64(at, this.opaque, true); at += 8;\n dv.setUint32(at, this.size, true); at += 4;\n this.data.toBuffer(a, at);\n }\n\n bufferSize(): number {\n return 4 + 4 + 8 + 4 + this.data.bufferSize();\n }\n}\n\n// ---------------------------------------------------------------------------\n// VDAgentAnnounceCapabilities\n// ---------------------------------------------------------------------------\n\nexport class VDAgentAnnounceCapabilities implements Serializable {\n request: number = 0;\n caps: number = 0;\n\n constructor(requestOrBuffer: number | ArrayBuffer, caps?: number) {\n if (typeof requestOrBuffer === 'number' && caps !== undefined) {\n this.request = requestOrBuffer;\n this.caps = caps;\n } else if (requestOrBuffer instanceof ArrayBuffer) {\n this.fromBuffer(requestOrBuffer);\n }\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.request, true); at += 4;\n dv.setUint32(at, this.caps, true); at += 4;\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): number {\n const dv = new DataView(a);\n this.request = dv.getUint32(at, true); at += 4;\n this.caps = dv.getUint32(at, true); at += 4;\n return at;\n }\n\n bufferSize(): number {\n return 8;\n }\n}\n\n// ---------------------------------------------------------------------------\n// VDAgentMonitorsConfig\n// ---------------------------------------------------------------------------\n\nexport class VDAgentMonitorsConfig implements Serializable {\n numMon: number = 1;\n flags: number;\n width: number;\n height: number;\n depth: number;\n x: number;\n y: number;\n\n constructor(flags: number, width: number, height: number, depth: number, x: number, y: number) {\n this.flags = flags;\n this.width = width;\n this.height = height;\n this.depth = depth;\n this.x = x;\n this.y = y;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.numMon, true); at += 4;\n dv.setUint32(at, this.flags, true); at += 4;\n dv.setUint32(at, this.height, true); at += 4;\n dv.setUint32(at, this.width, true); at += 4;\n dv.setUint32(at, this.depth, true); at += 4;\n dv.setUint32(at, this.x, true); at += 4;\n dv.setUint32(at, this.y, true); at += 4;\n }\n\n bufferSize(): number {\n return 28;\n }\n}\n\n// ---------------------------------------------------------------------------\n// VDAgentFileXferStatusMessage\n// ---------------------------------------------------------------------------\n\nexport class VDAgentFileXferStatusMessage implements Serializable {\n id: number = 0;\n result: number = 0;\n\n constructor(idOrBuffer: number | ArrayBuffer, result?: number) {\n if (typeof idOrBuffer === 'number' && result !== undefined) {\n this.id = idOrBuffer;\n this.result = result;\n } else if (idOrBuffer instanceof ArrayBuffer) {\n this.fromBuffer(idOrBuffer);\n }\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.id, true); at += 4;\n dv.setUint32(at, this.result, true); at += 4;\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): number {\n const dv = new DataView(a);\n this.id = dv.getUint32(at, true); at += 4;\n this.result = dv.getUint32(at, true); at += 4;\n return at;\n }\n\n bufferSize(): number {\n return 8;\n }\n}\n\n// ---------------------------------------------------------------------------\n// VDAgentFileXferStartMessage\n// ---------------------------------------------------------------------------\n\nexport class VDAgentFileXferStartMessage implements Serializable {\n id: number;\n string: string;\n\n constructor(id: number, name: string, size: number) {\n this.id = id;\n this.string = '[vdagent-file-xfer]\\nname=' + name + '\\nsize=' + size + '\\n';\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.id, true); at += 4;\n for (let i = 0; i < this.string.length; i++, at++) {\n dv.setUint8(at, this.string.charCodeAt(i));\n }\n }\n\n bufferSize(): number {\n return 4 + this.string.length + 1;\n }\n}\n\n// ---------------------------------------------------------------------------\n// VDAgentFileXferDataMessage\n// ---------------------------------------------------------------------------\n\nexport class VDAgentFileXferDataMessage implements Serializable {\n id: number;\n size: number;\n data: ArrayBuffer;\n\n constructor(id: number, size: number, data: ArrayBuffer) {\n this.id = id;\n this.size = size;\n this.data = data;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.id, true); at += 4;\n dv.setBigUint64(at, BigInt(this.size), true); at += 8;\n if (this.data && this.data.byteLength > 0) {\n const u8arr = new Uint8Array(this.data);\n const target = new Uint8Array(a);\n for (let i = 0; i < u8arr.length; i++, at++) {\n target[at] = u8arr[i] ?? 0;\n }\n }\n }\n\n bufferSize(): number {\n return 12 + this.size;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgNotify\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgNotify {\n timeStamp: bigint = 0n;\n severity: number = 0;\n visibility: number = 0;\n what: number = 0;\n messageLen: number = 0;\n message: string = '';\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.timeStamp = dv.getBigUint64(at, true); at += 8;\n this.severity = dv.getUint32(at, true); at += 4;\n this.visibility = dv.getUint32(at, true); at += 4;\n this.what = dv.getUint32(at, true); at += 4;\n this.messageLen = dv.getUint32(at, true); at += 4;\n this.message = '';\n for (let i = 0; i < this.messageLen; i++) {\n const c = dv.getUint8(at); at++;\n this.message += String.fromCharCode(c);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcDisplayInit\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcDisplayInit implements Serializable {\n pixmapCacheId: number = 1;\n glzDictionaryId: number = 0;\n pixmapCacheSize: number = 10 * 1024 * 1024;\n glzDictionaryWindowSize: number = 0;\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint8(at, this.pixmapCacheId); at++;\n dv.setBigUint64(at, BigInt(this.pixmapCacheSize), true); at += 8;\n dv.setUint8(at, this.glzDictionaryId); at++;\n dv.setUint32(at, this.glzDictionaryWindowSize, true); at += 4;\n }\n\n bufferSize(): number {\n return 14;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgDisplayBase\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgDisplayBase {\n surfaceId: number = 0;\n box: SpiceRect = new SpiceRect();\n clip: SpiceClip = new SpiceClip();\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n this.surfaceId = dv.getUint32(at, true); at += 4;\n this.box = new SpiceRect();\n at = this.box.fromDataView(dv, at, mb);\n this.clip = new SpiceClip();\n return this.clip.fromDataView(dv, at, mb);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgDisplayDrawCopy\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgDisplayDrawCopy {\n base: SpiceMsgDisplayBase = new SpiceMsgDisplayBase();\n data: SpiceCopy = new SpiceCopy();\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.base = new SpiceMsgDisplayBase();\n at = this.base.fromDataView(dv, at, a);\n this.data = new SpiceCopy();\n this.data.fromDataView(dv, at, a);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgDisplayDrawFill\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgDisplayDrawFill {\n base: SpiceMsgDisplayBase = new SpiceMsgDisplayBase();\n data: SpiceFill = new SpiceFill();\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.base = new SpiceMsgDisplayBase();\n at = this.base.fromDataView(dv, at, a);\n this.data = new SpiceFill();\n this.data.fromDataView(dv, at, a);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgDisplayCopyBits\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgDisplayCopyBits {\n base: SpiceMsgDisplayBase = new SpiceMsgDisplayBase();\n srcPos: SpicePoint = new SpicePoint();\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.base = new SpiceMsgDisplayBase();\n at = this.base.fromDataView(dv, at, a);\n this.srcPos = new SpicePoint();\n this.srcPos.fromDataView(dv, at, a);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgSurfaceCreate\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgSurfaceCreate {\n surface: SpiceSurface = new SpiceSurface();\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.surface = new SpiceSurface();\n this.surface.fromDataView(dv, at, a);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgSurfaceDestroy\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgSurfaceDestroy {\n surfaceId: number = 0;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.surfaceId = dv.getUint32(at, true); at += 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgInputsInit\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgInputsInit {\n keyboardModifiers: number = 0;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): number {\n const dv = new DataView(a);\n this.keyboardModifiers = dv.getUint16(at, true); at += 2;\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgInputsKeyModifiers\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgInputsKeyModifiers {\n keyboardModifiers: number = 0;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): number {\n const dv = new DataView(a);\n this.keyboardModifiers = dv.getUint16(at, true); at += 2;\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgCursorInit\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgCursorInit {\n position: SpicePoint16 = new SpicePoint16();\n trailLength: number = 0;\n trailFrequency: number = 0;\n visible: number = 0;\n cursor: SpiceCursor = new SpiceCursor();\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.position = new SpicePoint16();\n at = this.position.fromDataView(dv, at, a);\n this.trailLength = dv.getUint16(at, true); at += 2;\n this.trailFrequency = dv.getUint16(at, true); at += 2;\n this.visible = dv.getUint8(at); at++;\n this.cursor = new SpiceCursor();\n this.cursor.fromDataView(dv, at, a);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgPlaybackData\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgPlaybackData {\n time: number = 0;\n data: ArrayBuffer | undefined = undefined;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): number {\n const dv = new DataView(a);\n this.time = dv.getUint32(at, true); at += 4;\n if (a.byteLength > at) {\n this.data = a.slice(at);\n at += this.data.byteLength;\n }\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgPlaybackMode\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgPlaybackMode {\n time: number = 0;\n mode: number = 0;\n data: ArrayBuffer | undefined = undefined;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): number {\n const dv = new DataView(a);\n this.time = dv.getUint32(at, true); at += 4;\n this.mode = dv.getUint16(at, true); at += 2;\n if (a.byteLength > at) {\n this.data = a.slice(at);\n at += this.data.byteLength;\n }\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgPlaybackStart\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgPlaybackStart {\n channels: number = 0;\n format: number = 0;\n frequency: number = 0;\n time: number = 0;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): number {\n const dv = new DataView(a);\n this.channels = dv.getUint32(at, true); at += 4;\n this.format = dv.getUint16(at, true); at += 2;\n this.frequency = dv.getUint32(at, true); at += 4;\n this.time = dv.getUint32(at, true); at += 4;\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgCursorSet\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgCursorSet {\n position: SpicePoint16 = new SpicePoint16();\n visible: number = 0;\n cursor: SpiceCursor = new SpiceCursor();\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.position = new SpicePoint16();\n at = this.position.fromDataView(dv, at, a);\n this.visible = dv.getUint8(at); at++;\n this.cursor = new SpiceCursor();\n this.cursor.fromDataView(dv, at, a);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcMousePosition\n//\n// In the TypeScript version, this is a pure data class. The DOM event\n// extraction logic that was in the original constructor is moved to the\n// inputs channel (US-020/US-021) which constructs this message from\n// processed event data.\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcMousePosition implements Serializable {\n x: number;\n y: number;\n buttonsState: number;\n displayId: number;\n\n constructor(x: number = 0, y: number = 0, buttonsState: number = 0, displayId: number = 0) {\n this.x = x;\n this.y = y;\n this.buttonsState = buttonsState;\n this.displayId = displayId;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.x, true); at += 4;\n dv.setUint32(at, this.y, true); at += 4;\n dv.setUint16(at, this.buttonsState, true); at += 2;\n dv.setUint8(at, this.displayId); at += 1;\n }\n\n bufferSize(): number {\n return 11;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcMouseMotion\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcMouseMotion implements Serializable {\n x: number;\n y: number;\n buttonsState: number;\n displayId: number;\n\n constructor(x: number = 0, y: number = 0, buttonsState: number = 0, displayId: number = 0) {\n this.x = x;\n this.y = y;\n this.buttonsState = buttonsState;\n this.displayId = displayId;\n }\n\n /* Same wire format as MousePosition */\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.x, true); at += 4;\n dv.setUint32(at, this.y, true); at += 4;\n dv.setUint16(at, this.buttonsState, true); at += 2;\n dv.setUint8(at, this.displayId); at += 1;\n }\n\n bufferSize(): number {\n return 11;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcMousePress\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcMousePress implements Serializable {\n button: number;\n buttonsState: number;\n\n constructor(button: number = SpiceMouseButton.LEFT, buttonsState: number = SpiceMouseButtonMask.LEFT) {\n this.button = button;\n this.buttonsState = buttonsState;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint8(at, this.button); at++;\n dv.setUint16(at, this.buttonsState, true); at += 2;\n }\n\n bufferSize(): number {\n return 3;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcMouseRelease\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcMouseRelease implements Serializable {\n button: number;\n buttonsState: number;\n\n constructor(button: number = SpiceMouseButton.LEFT, buttonsState: number = 0) {\n this.button = button;\n this.buttonsState = buttonsState;\n }\n\n /* Same wire format as MousePress */\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint8(at, this.button); at++;\n dv.setUint16(at, this.buttonsState, true); at += 2;\n }\n\n bufferSize(): number {\n return 3;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcKeyDown\n//\n// In the TypeScript version, the scancode is passed directly. The\n// keycode_to_start_scan() conversion is the responsibility of the\n// inputs channel (US-020).\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcKeyDown implements Serializable {\n code: number;\n\n constructor(code: number = 0) {\n this.code = code;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.code, true); at += 4;\n }\n\n bufferSize(): number {\n return 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcKeyUp\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcKeyUp implements Serializable {\n code: number;\n\n constructor(code: number = 0) {\n this.code = code;\n }\n\n /* Same wire format as KeyDown */\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.code, true); at += 4;\n }\n\n bufferSize(): number {\n return 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgDisplayStreamCreate\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgDisplayStreamCreate {\n surfaceId: number = 0;\n id: number = 0;\n flags: number = 0;\n codecType: number = 0;\n stamp: bigint = 0n;\n streamWidth: number = 0;\n streamHeight: number = 0;\n srcWidth: number = 0;\n srcHeight: number = 0;\n dest: SpiceRect = new SpiceRect();\n clip: SpiceClip = new SpiceClip();\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.surfaceId = dv.getUint32(at, true); at += 4;\n this.id = dv.getUint32(at, true); at += 4;\n this.flags = dv.getUint8(at); at += 1;\n this.codecType = dv.getUint8(at); at += 1;\n this.stamp = dv.getBigUint64(at, true); at += 8;\n this.streamWidth = dv.getUint32(at, true); at += 4;\n this.streamHeight = dv.getUint32(at, true); at += 4;\n this.srcWidth = dv.getUint32(at, true); at += 4;\n this.srcHeight = dv.getUint32(at, true); at += 4;\n\n this.dest = new SpiceRect();\n at = this.dest.fromDataView(dv, at, a);\n this.clip = new SpiceClip();\n this.clip.fromDataView(dv, at, a);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceStreamDataHeader\n// ---------------------------------------------------------------------------\n\nexport class SpiceStreamDataHeader {\n id: number = 0;\n multiMediaTime: number = 0;\n\n fromDataView(dv: DataView, at: number, _mb: ArrayBuffer): number {\n this.id = dv.getUint32(at, true); at += 4;\n this.multiMediaTime = dv.getUint32(at, true); at += 4;\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgDisplayStreamData\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgDisplayStreamData {\n base: SpiceStreamDataHeader = new SpiceStreamDataHeader();\n dataSize: number = 0;\n data: Uint8Array = new Uint8Array(0);\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n const u8 = new Uint8Array(a);\n this.base = new SpiceStreamDataHeader();\n at = this.base.fromDataView(dv, at, a);\n this.dataSize = dv.getUint32(at, true); at += 4;\n this.data = u8.subarray(at, at + this.dataSize);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgDisplayStreamDataSized\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgDisplayStreamDataSized {\n base: SpiceStreamDataHeader = new SpiceStreamDataHeader();\n width: number = 0;\n height: number = 0;\n dest: SpiceRect = new SpiceRect();\n dataSize: number = 0;\n data: Uint8Array = new Uint8Array(0);\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n const u8 = new Uint8Array(a);\n this.base = new SpiceStreamDataHeader();\n at = this.base.fromDataView(dv, at, a);\n this.width = dv.getUint32(at, true); at += 4;\n this.height = dv.getUint32(at, true); at += 4;\n this.dest = new SpiceRect();\n at = this.dest.fromDataView(dv, at, a);\n this.dataSize = dv.getUint32(at, true); at += 4;\n this.data = u8.subarray(at, at + this.dataSize);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgDisplayStreamClip\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgDisplayStreamClip {\n id: number = 0;\n clip: SpiceClip = new SpiceClip();\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.id = dv.getUint32(at, true); at += 4;\n this.clip = new SpiceClip();\n this.clip.fromDataView(dv, at, a);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgDisplayStreamDestroy\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgDisplayStreamDestroy {\n id: number = 0;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.id = dv.getUint32(at, true); at += 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgDisplayStreamActivateReport\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgDisplayStreamActivateReport {\n streamId: number = 0;\n uniqueId: number = 0;\n maxWindowSize: number = 0;\n timeoutMs: number = 0;\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.streamId = dv.getUint32(at, true); at += 4;\n this.uniqueId = dv.getUint32(at, true); at += 4;\n this.maxWindowSize = dv.getUint32(at, true); at += 4;\n this.timeoutMs = dv.getUint32(at, true); at += 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgcDisplayStreamReport\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgcDisplayStreamReport implements Serializable {\n streamId: number;\n uniqueId: number;\n startFrameMmTime: number = 0;\n endFrameMmTime: number = 0;\n numFrames: number = 0;\n numDrops: number = 0;\n lastFrameDelay: number = 0;\n // TODO - Implement audio delay\n audioDelay: number = -1;\n\n constructor(streamId: number, uniqueId: number) {\n this.streamId = streamId;\n this.uniqueId = uniqueId;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n dv.setUint32(at, this.streamId, true); at += 4;\n dv.setUint32(at, this.uniqueId, true); at += 4;\n dv.setUint32(at, this.startFrameMmTime, true); at += 4;\n dv.setUint32(at, this.endFrameMmTime, true); at += 4;\n dv.setUint32(at, this.numFrames, true); at += 4;\n dv.setUint32(at, this.numDrops, true); at += 4;\n dv.setUint32(at, this.lastFrameDelay, true); at += 4;\n dv.setInt32(at, this.audioDelay, true); at += 4;\n }\n\n bufferSize(): number {\n return 8 * 4;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgDisplayInvalList\n// ---------------------------------------------------------------------------\n\nexport interface InvalResource {\n type: number;\n id: bigint;\n}\n\nexport class SpiceMsgDisplayInvalList {\n count: number = 0;\n resources: InvalResource[] = [];\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n this.count = dv.getUint16(at, true); at += 2;\n this.resources = [];\n for (let i = 0; i < this.count; i++) {\n const type = dv.getUint8(at); at++;\n const id = dv.getBigUint64(at, true); at += 8;\n this.resources.push({ type, id });\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMsgPortInit\n// ---------------------------------------------------------------------------\n\nexport class SpiceMsgPortInit {\n opened: number = 0;\n name: ArrayBuffer = new ArrayBuffer(0);\n\n constructor(a: ArrayBuffer, at?: number) {\n this.fromBuffer(a, at);\n }\n\n fromBuffer(a: ArrayBuffer, at: number = 0): void {\n const dv = new DataView(a);\n const namesize = dv.getUint32(at, true); at += 4;\n const offset = dv.getUint32(at, true); at += 4;\n this.opened = dv.getUint8(at); at += 1;\n this.name = a.slice(offset, offset + namesize - 1);\n }\n}\n","/*\n * NOTE: The AT/MF keyboards can generate (via the 8042) two (MF: three)\n * sets of scancodes. Set3 can only be generated by a MF keyboard.\n * Set2 sends a makecode for keypress, and the same code prefixed by a\n * F0 for keyrelease. This is a little bit ugly to handle. Thus we use\n * here for X386 the PC/XT compatible Set1. This set uses 8bit scancodes.\n * Bit 7 ist set if the key is released. The code E0 switches to a\n * different meaning to add the new MF cursorkeys, while not breaking old\n * applications. E1 is another special prefix. Since I assume that there\n * will be further versions of PC/XT scancode compatible keyboards, we\n * may be in trouble one day.\n *\n * IDEA: 1) Use Set2 on AT84 keyboards and translate it to MF Set3.\n * 2) Use the keyboards native set and translate it to common keysyms.\n */\n\n/*----------------------------------------------------------------------------\n** AT84/MF101/MF102 Keyboard scancode definitions (Set 1).\n** Each value is the make code (pressed) for that key.\n**--------------------------------------------------------------------------*/\nexport const KeyNames = {\n /*\n * definition of the AT84/MF101/MF102 Keyboard:\n * ============================================================\n * Defined Key Cap Glyphs Pressed value\n * Key Name Main Also (hex) (dec)\n * ---------------- ---------- ------- ------ ------\n */\n KEY_Escape: 1, /* Escape 0x01 */\n KEY_1: 2, /* 1 ! 0x02 */\n KEY_2: 3, /* 2 @ 0x03 */\n KEY_3: 4, /* 3 # 0x04 */\n KEY_4: 5, /* 4 $ 0x05 */\n KEY_5: 6, /* 5 % 0x06 */\n KEY_6: 7, /* 6 ^ 0x07 */\n KEY_7: 8, /* 7 & 0x08 */\n KEY_8: 9, /* 8 * 0x09 */\n KEY_9: 10, /* 9 ( 0x0a */\n KEY_0: 11, /* 0 ) 0x0b */\n KEY_Minus: 12, /* - (Minus) _ (Under) 0x0c */\n KEY_Equal: 13, /* = (Equal) + 0x0d */\n KEY_BackSpace: 14, /* Back Space 0x0e */\n KEY_Tab: 15, /* Tab 0x0f */\n KEY_Q: 16, /* Q 0x10 */\n KEY_W: 17, /* W 0x11 */\n KEY_E: 18, /* E 0x12 */\n KEY_R: 19, /* R 0x13 */\n KEY_T: 20, /* T 0x14 */\n KEY_Y: 21, /* Y 0x15 */\n KEY_U: 22, /* U 0x16 */\n KEY_I: 23, /* I 0x17 */\n KEY_O: 24, /* O 0x18 */\n KEY_P: 25, /* P 0x19 */\n KEY_LBrace: 26, /* [ { 0x1a */\n KEY_RBrace: 27, /* ] } 0x1b */\n KEY_Enter: 28, /* Enter 0x1c */\n KEY_LCtrl: 29, /* Ctrl(left) 0x1d */\n KEY_A: 30, /* A 0x1e */\n KEY_S: 31, /* S 0x1f */\n KEY_D: 32, /* D 0x20 */\n KEY_F: 33, /* F 0x21 */\n KEY_G: 34, /* G 0x22 */\n KEY_H: 35, /* H 0x23 */\n KEY_J: 36, /* J 0x24 */\n KEY_K: 37, /* K 0x25 */\n KEY_L: 38, /* L 0x26 */\n KEY_SemiColon: 39, /* ;(SemiColon) :(Colon) 0x27 */\n KEY_Quote: 40, /* ' (Apostr) \" (Quote) 0x28 */\n KEY_Tilde: 41, /* ` (Accent) ~ (Tilde) 0x29 */\n KEY_ShiftL: 42, /* Shift(left) 0x2a */\n KEY_BSlash: 43, /* \\(BckSlash) |(VertBar)0x2b */\n KEY_Z: 44, /* Z 0x2c */\n KEY_X: 45, /* X 0x2d */\n KEY_C: 46, /* C 0x2e */\n KEY_V: 47, /* V 0x2f */\n KEY_B: 48, /* B 0x30 */\n KEY_N: 49, /* N 0x31 */\n KEY_M: 50, /* M 0x32 */\n KEY_Comma: 51, /* , (Comma) < (Less) 0x33 */\n KEY_Period: 52, /* . (Period) >(Greater)0x34 */\n KEY_Slash: 53, /* / (Slash) ? 0x35 */\n KEY_ShiftR: 54, /* Shift(right) 0x36 */\n KEY_KP_Multiply: 55, /* * 0x37 */\n KEY_Alt: 56, /* Alt(left) 0x38 */\n KEY_Space: 57, /* (SpaceBar) 0x39 */\n KEY_CapsLock: 58, /* CapsLock 0x3a */\n KEY_F1: 59, /* F1 0x3b */\n KEY_F2: 60, /* F2 0x3c */\n KEY_F3: 61, /* F3 0x3d */\n KEY_F4: 62, /* F4 0x3e */\n KEY_F5: 63, /* F5 0x3f */\n KEY_F6: 64, /* F6 0x40 */\n KEY_F7: 65, /* F7 0x41 */\n KEY_F8: 66, /* F8 0x42 */\n KEY_F9: 67, /* F9 0x43 */\n KEY_F10: 68, /* F10 0x44 */\n KEY_NumLock: 69, /* NumLock 0x45 */\n KEY_ScrollLock: 70, /* ScrollLock 0x46 */\n KEY_KP_7: 71, /* 7 Home 0x47 */\n KEY_KP_8: 72, /* 8 Up 0x48 */\n KEY_KP_9: 73, /* 9 PgUp 0x49 */\n KEY_KP_Minus: 74, /* - (Minus) 0x4a */\n KEY_KP_4: 75, /* 4 Left 0x4b */\n KEY_KP_5: 76, /* 5 0x4c */\n KEY_KP_6: 77, /* 6 Right 0x4d */\n KEY_KP_Plus: 78, /* + (Plus) 0x4e */\n KEY_KP_1: 79, /* 1 End 0x4f */\n KEY_KP_2: 80, /* 2 Down 0x50 */\n KEY_KP_3: 81, /* 3 PgDown 0x51 */\n KEY_KP_0: 82, /* 0 Insert 0x52 */\n KEY_KP_Decimal: 83, /* . (Decimal) Delete 0x53 */\n KEY_SysReqest: 84, /* SysRequest 0x54 */\n /* NOTUSED 0x55 */\n KEY_Less: 86, /* < (Less) >(Greater) 0x56 */\n KEY_F11: 87, /* F11 0x57 */\n KEY_F12: 88, /* F12 0x58 */\n\n KEY_Prefix0: 96, /* special 0x60 */\n KEY_Prefix1: 97, /* special 0x61 */\n} as const;\n\n/** Type for any valid key name from the KeyNames mapping */\nexport type KeyName = keyof typeof KeyNames;\n\n/** Type for any valid scancode value from the KeyNames mapping */\nexport type Scancode = (typeof KeyNames)[KeyName];\n","/*----------------------------------------------------------------------------\n** Mapping from DOM KeyboardEvent.code values to AT Set 1 scancodes.\n**\n** Extended (grey) keys use the 0xE0 prefix encoding:\n** low byte = 0xE0, high byte = scancode (i.e. 0xE0 | (scancode << 8))\n**\n** @see https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values\n**--------------------------------------------------------------------------*/\n\nexport const codeToScancode: Readonly<Record<string, number>> = {\n /* Row 0: Escape */\n \"Escape\": 0x01,\n\n /* Row 1: Digits */\n \"Digit1\": 0x02,\n \"Digit2\": 0x03,\n \"Digit3\": 0x04,\n \"Digit4\": 0x05,\n \"Digit5\": 0x06,\n \"Digit6\": 0x07,\n \"Digit7\": 0x08,\n \"Digit8\": 0x09,\n \"Digit9\": 0x0A,\n \"Digit0\": 0x0B,\n \"Minus\": 0x0C,\n \"Equal\": 0x0D,\n \"Backspace\": 0x0E,\n\n /* Row 2: QWERTY */\n \"Tab\": 0x0F,\n \"KeyQ\": 0x10,\n \"KeyW\": 0x11,\n \"KeyE\": 0x12,\n \"KeyR\": 0x13,\n \"KeyT\": 0x14,\n \"KeyY\": 0x15,\n \"KeyU\": 0x16,\n \"KeyI\": 0x17,\n \"KeyO\": 0x18,\n \"KeyP\": 0x19,\n \"BracketLeft\": 0x1A,\n \"BracketRight\": 0x1B,\n \"Enter\": 0x1C,\n\n /* Row 3: ASDF */\n \"ControlLeft\": 0x1D,\n \"KeyA\": 0x1E,\n \"KeyS\": 0x1F,\n \"KeyD\": 0x20,\n \"KeyF\": 0x21,\n \"KeyG\": 0x22,\n \"KeyH\": 0x23,\n \"KeyJ\": 0x24,\n \"KeyK\": 0x25,\n \"KeyL\": 0x26,\n \"Semicolon\": 0x27,\n \"Quote\": 0x28,\n \"Backquote\": 0x29,\n\n /* Row 4: ZXCV */\n \"ShiftLeft\": 0x2A,\n \"Backslash\": 0x2B,\n \"KeyZ\": 0x2C,\n \"KeyX\": 0x2D,\n \"KeyC\": 0x2E,\n \"KeyV\": 0x2F,\n \"KeyB\": 0x30,\n \"KeyN\": 0x31,\n \"KeyM\": 0x32,\n \"Comma\": 0x33,\n \"Period\": 0x34,\n \"Slash\": 0x35,\n \"ShiftRight\": 0x36,\n\n /* Numpad and modifiers */\n \"NumpadMultiply\": 0x37,\n \"AltLeft\": 0x38,\n \"Space\": 0x39,\n \"CapsLock\": 0x3A,\n\n /* Function keys */\n \"F1\": 0x3B,\n \"F2\": 0x3C,\n \"F3\": 0x3D,\n \"F4\": 0x3E,\n \"F5\": 0x3F,\n \"F6\": 0x40,\n \"F7\": 0x41,\n \"F8\": 0x42,\n \"F9\": 0x43,\n \"F10\": 0x44,\n\n /* Lock and numpad keys */\n \"Pause\": 0x45,\n \"ScrollLock\": 0x46,\n \"Numpad7\": 0x47,\n \"Numpad8\": 0x48,\n \"Numpad9\": 0x49,\n \"NumpadSubtract\": 0x4A,\n \"Numpad4\": 0x4B,\n \"Numpad5\": 0x4C,\n \"Numpad6\": 0x4D,\n \"NumpadAdd\": 0x4E,\n \"Numpad1\": 0x4F,\n \"Numpad2\": 0x50,\n \"Numpad3\": 0x51,\n \"Numpad0\": 0x52,\n \"NumpadDecimal\": 0x53,\n\n /* Miscellaneous */\n \"PrintScreen\": 0x54,\n \"IntlBackslash\": 0x56,\n \"F11\": 0x57,\n \"F12\": 0x58,\n \"NumpadEqual\": 0x59,\n\n /* Extended function keys */\n \"F13\": 0x64,\n \"F14\": 0x65,\n \"F15\": 0x66,\n \"F16\": 0x67,\n \"F17\": 0x68,\n \"F18\": 0x69,\n \"F19\": 0x6A,\n \"F20\": 0x6B,\n \"F21\": 0x6C,\n \"F22\": 0x6D,\n \"F23\": 0x6E,\n\n /* International keys */\n \"KanaMode\": 0x70,\n \"IntlRo\": 0x73,\n \"F24\": 0x76,\n \"Convert\": 0x79,\n \"NonConvert\": 0x7B,\n \"IntlYen\": 0x7D,\n \"NumpadComma\": 0x7E,\n\n /* Extended (E0-prefixed) keys */\n \"MediaTrackPrevious\": 0xE0 | (0x10 << 8),\n \"MediaTrackNext\": 0xE0 | (0x19 << 8),\n \"NumpadEnter\": 0xE0 | (0x1C << 8),\n \"ControlRight\": 0xE0 | (0x1D << 8),\n \"AudioVolumeMute\": 0xE0 | (0x20 << 8),\n \"LaunchApp2\": 0xE0 | (0x21 << 8),\n \"MediaPlayPause\": 0xE0 | (0x22 << 8),\n \"MediaStop\": 0xE0 | (0x24 << 8),\n \"VolumeDown\": 0xE0 | (0x2E << 8),\n \"VolumeUp\": 0xE0 | (0x30 << 8),\n \"BrowserHome\": 0xE0 | (0x32 << 8),\n \"NumpadDivide\": 0xE0 | (0x35 << 8),\n // Note: PrintScreen also has an E0-prefixed variant for the grey key\n // The last assignment wins in the original JS; here we keep the extended version\n // since the simple 0x54 mapping above handles the base case via keyCode fallback\n \"AltRight\": 0xE0 | (0x38 << 8),\n \"NumLock\": 0xE0 | (0x45 << 8),\n // Note: Pause also has an E0-prefixed variant\n \"Home\": 0xE0 | (0x47 << 8),\n \"ArrowUp\": 0xE0 | (0x48 << 8),\n \"PageUp\": 0xE0 | (0x49 << 8),\n \"ArrowLeft\": 0xE0 | (0x4B << 8),\n \"ArrowRight\": 0xE0 | (0x4D << 8),\n \"End\": 0xE0 | (0x4F << 8),\n \"ArrowDown\": 0xE0 | (0x50 << 8),\n \"PageDown\": 0xE0 | (0x51 << 8),\n \"Insert\": 0xE0 | (0x52 << 8),\n \"Delete\": 0xE0 | (0x53 << 8),\n \"MetaLeft\": 0xE0 | (0x5B << 8),\n \"MetaRight\": 0xE0 | (0x5C << 8),\n \"ContextMenu\": 0xE0 | (0x5D << 8),\n \"Power\": 0xE0 | (0x5E << 8),\n \"BrowserSearch\": 0xE0 | (0x65 << 8),\n \"BrowserFavorites\": 0xE0 | (0x66 << 8),\n \"BrowserRefresh\": 0xE0 | (0x67 << 8),\n \"BrowserStop\": 0xE0 | (0x68 << 8),\n \"BrowserForward\": 0xE0 | (0x69 << 8),\n \"BrowserBack\": 0xE0 | (0x6A << 8),\n \"LaunchApp1\": 0xE0 | (0x6B << 8),\n \"LaunchMail\": 0xE0 | (0x6C << 8),\n \"MediaSelect\": 0xE0 | (0x6D << 8),\n};\n","/*----------------------------------------------------------------------------\n** debug.ts\n** Utility settings and functions for Spice.\n** Converted from utils.js.\n**--------------------------------------------------------------------------*/\n\nimport { KeyNames } from './atKeynames';\nimport { codeToScancode } from './codeToScancode';\n\n// ---------------------------------------------------------------------------\n// Debug flags\n// ---------------------------------------------------------------------------\n\n/** Master debug verbosity level (0 = off, higher = more verbose) */\nexport let DEBUG = 0;\n\n/** Audio playback debug flag (0 = off) */\nexport let PLAYBACK_DEBUG = 0;\n\n/** Video stream debug flag (0 = off) */\nexport let STREAM_DEBUG = 0;\n\n/** When true, render draw commands to debug canvases */\nexport let DUMP_DRAWS = false;\n\n/** When true, dump canvas contents for debugging */\nexport let DUMP_CANVASES = false;\n\n/** Set the master debug verbosity level */\nexport function setDebug(level: number): void\n{\n DEBUG = level;\n}\n\n/** Set the playback debug flag */\nexport function setPlaybackDebug(level: number): void\n{\n PLAYBACK_DEBUG = level;\n}\n\n/** Set the stream debug flag */\nexport function setStreamDebug(level: number): void\n{\n STREAM_DEBUG = level;\n}\n\n/** Set the dump draws flag */\nexport function setDumpDraws(enabled: boolean): void\n{\n DUMP_DRAWS = enabled;\n}\n\n/** Set the dump canvases flag */\nexport function setDumpCanvases(enabled: boolean): void\n{\n DUMP_CANVASES = enabled;\n}\n\n// ---------------------------------------------------------------------------\n// Blank image for GC assistance\n// ---------------------------------------------------------------------------\n\n/**\n * We use an Image temporarily, and the image/src does not get garbage\n * collected as quickly as we might like. This blank image helps with that.\n */\nexport const EMPTY_GIF_IMAGE: string =\n \"data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=\";\n\n// ---------------------------------------------------------------------------\n// ArrayBuffer utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Combine two ArrayBuffers into a new one.\n * FIXME - this can't be optimal. See wire.ts about eliminating the need.\n */\nexport function combineArrayBuffers(a1: ArrayBuffer, a2: ArrayBuffer): ArrayBuffer\n{\n const in1 = new Uint8Array(a1);\n const in2 = new Uint8Array(a2);\n const ret = new ArrayBuffer(a1.byteLength + a2.byteLength);\n const out = new Uint8Array(ret);\n out.set(in1, 0);\n out.set(in2, in1.length);\n return ret;\n}\n\n/**\n * Hex dump an ArrayBuffer to the console for debugging.\n * Collapses repeated all-zero lines with a \".\" indicator.\n */\nexport function hexdumpBuffer(a: ArrayBuffer): void\n{\n const mg = new Uint8Array(a);\n let hex = \"\";\n let str = \"\";\n let lastZeros = 0;\n\n for (let i = 0; i < mg.length; i++)\n {\n const byte = mg[i]!;\n const h = byte.toString(16);\n if (h.length === 1)\n {\n hex += \"0\";\n }\n hex += h + \" \";\n\n if (byte === 10 || byte === 13 || byte === 8)\n {\n str += \".\";\n }\n else\n {\n str += String.fromCharCode(byte);\n }\n\n if ((i % 16 === 15) || (i === (mg.length - 1)))\n {\n let padIdx = i;\n while (padIdx % 16 !== 15)\n {\n hex += \" \";\n padIdx++;\n }\n\n if (lastZeros === 0)\n {\n console.log(hex + \" | \" + str);\n }\n\n if (hex === \"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \")\n {\n if (lastZeros === 1)\n {\n console.log(\".\");\n lastZeros++;\n }\n else if (lastZeros === 0)\n {\n lastZeros++;\n }\n }\n else\n {\n lastZeros = 0;\n }\n\n hex = \"\";\n str = \"\";\n }\n }\n}\n\n/**\n * Convert an ArrayBuffer to a string (treating contents as UTF-16 code units).\n */\nexport function arraybufferToStr(buf: ArrayBuffer): string\n{\n const arr = new Uint16Array(buf);\n let result = \"\";\n for (let i = 0; i < arr.length; i++)\n {\n result += String.fromCharCode(arr[i]!);\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Scancode mapping\n// ---------------------------------------------------------------------------\n\n/*\n * Converting browser keycodes to AT scancodes is very hard.\n * Spice transmits keys using the original AT scan codes, often\n * described as 'Scan Code Set 1'.\n * There is a confusion of other scan codes; Xorg synthesizes its\n * own in the same atKeynames.c file that has the XT codes.\n * Scan code set 2 and 3 are more common, and use different values.\n * Further, there is no formal specification for keycodes\n * returned by browsers, so we have done our mapping largely with\n * empirical testing.\n * There has been little rigorous testing with International keyboards,\n * and this would be an easy area for non English speakers to contribute.\n */\n\n/** Common keyCode-to-scancode mapping (works in most browsers) */\nconst commonScanmap: Record<number, number> = {\n /* Digits */\n ['1'.charCodeAt(0)]: KeyNames.KEY_1,\n ['2'.charCodeAt(0)]: KeyNames.KEY_2,\n ['3'.charCodeAt(0)]: KeyNames.KEY_3,\n ['4'.charCodeAt(0)]: KeyNames.KEY_4,\n ['5'.charCodeAt(0)]: KeyNames.KEY_5,\n ['6'.charCodeAt(0)]: KeyNames.KEY_6,\n ['7'.charCodeAt(0)]: KeyNames.KEY_7,\n ['8'.charCodeAt(0)]: KeyNames.KEY_8,\n ['9'.charCodeAt(0)]: KeyNames.KEY_9,\n ['0'.charCodeAt(0)]: KeyNames.KEY_0,\n\n /* Lock keys and numpad */\n 145: KeyNames.KEY_ScrollLock,\n 103: KeyNames.KEY_KP_7,\n 104: KeyNames.KEY_KP_8,\n 105: KeyNames.KEY_KP_9,\n 100: KeyNames.KEY_KP_4,\n 101: KeyNames.KEY_KP_5,\n 102: KeyNames.KEY_KP_6,\n 107: KeyNames.KEY_KP_Plus,\n 97: KeyNames.KEY_KP_1,\n 98: KeyNames.KEY_KP_2,\n 99: KeyNames.KEY_KP_3,\n 96: KeyNames.KEY_KP_0,\n 109: KeyNames.KEY_Minus,\n 110: KeyNames.KEY_KP_Decimal,\n\n /* Punctuation */\n 191: KeyNames.KEY_Slash,\n 190: KeyNames.KEY_Period,\n 188: KeyNames.KEY_Comma,\n 220: KeyNames.KEY_BSlash,\n 192: KeyNames.KEY_Tilde,\n 222: KeyNames.KEY_Quote,\n 219: KeyNames.KEY_LBrace,\n 221: KeyNames.KEY_RBrace,\n\n /* Letters */\n ['Q'.charCodeAt(0)]: KeyNames.KEY_Q,\n ['W'.charCodeAt(0)]: KeyNames.KEY_W,\n ['E'.charCodeAt(0)]: KeyNames.KEY_E,\n ['R'.charCodeAt(0)]: KeyNames.KEY_R,\n ['T'.charCodeAt(0)]: KeyNames.KEY_T,\n ['Y'.charCodeAt(0)]: KeyNames.KEY_Y,\n ['U'.charCodeAt(0)]: KeyNames.KEY_U,\n ['I'.charCodeAt(0)]: KeyNames.KEY_I,\n ['O'.charCodeAt(0)]: KeyNames.KEY_O,\n ['P'.charCodeAt(0)]: KeyNames.KEY_P,\n ['A'.charCodeAt(0)]: KeyNames.KEY_A,\n ['S'.charCodeAt(0)]: KeyNames.KEY_S,\n ['D'.charCodeAt(0)]: KeyNames.KEY_D,\n ['F'.charCodeAt(0)]: KeyNames.KEY_F,\n ['G'.charCodeAt(0)]: KeyNames.KEY_G,\n ['H'.charCodeAt(0)]: KeyNames.KEY_H,\n ['J'.charCodeAt(0)]: KeyNames.KEY_J,\n ['K'.charCodeAt(0)]: KeyNames.KEY_K,\n ['L'.charCodeAt(0)]: KeyNames.KEY_L,\n ['Z'.charCodeAt(0)]: KeyNames.KEY_Z,\n ['X'.charCodeAt(0)]: KeyNames.KEY_X,\n ['C'.charCodeAt(0)]: KeyNames.KEY_C,\n ['V'.charCodeAt(0)]: KeyNames.KEY_V,\n ['B'.charCodeAt(0)]: KeyNames.KEY_B,\n ['N'.charCodeAt(0)]: KeyNames.KEY_N,\n ['M'.charCodeAt(0)]: KeyNames.KEY_M,\n [' '.charCodeAt(0)]: KeyNames.KEY_Space,\n\n /* Special keys */\n 13: KeyNames.KEY_Enter,\n 27: KeyNames.KEY_Escape,\n 8: KeyNames.KEY_BackSpace,\n 9: KeyNames.KEY_Tab,\n 16: KeyNames.KEY_ShiftL,\n 17: KeyNames.KEY_LCtrl,\n 18: KeyNames.KEY_Alt,\n 20: KeyNames.KEY_CapsLock,\n 44: KeyNames.KEY_SysReqest,\n 144: KeyNames.KEY_NumLock,\n\n /* Function keys */\n 112: KeyNames.KEY_F1,\n 113: KeyNames.KEY_F2,\n 114: KeyNames.KEY_F3,\n 115: KeyNames.KEY_F4,\n 116: KeyNames.KEY_F5,\n 117: KeyNames.KEY_F6,\n 118: KeyNames.KEY_F7,\n 119: KeyNames.KEY_F8,\n 120: KeyNames.KEY_F9,\n 121: KeyNames.KEY_F10,\n 122: KeyNames.KEY_F11,\n 123: KeyNames.KEY_F12,\n\n /* TODO: Break and Print are complex scan codes. XSpice cheats and\n uses Xorg synthesized codes to simplify them. Fixing this will\n require XSpice to handle the scan codes correctly, and then\n fix spice-html5 to send the complex scan codes. */\n 42: 99, // Print, XSpice only\n 19: 101, // Break, XSpice only\n\n /* Handle the so called 'GREY' keys, for the extended keys that\n were grey on the original AT keyboard. These are\n prefixed, as they were on the PS/2 controller, with an\n 0xE0 byte to indicate that they are extended */\n 111: 0xE0 | (KeyNames.KEY_Slash << 8), // KP_Divide\n 106: 0xE0 | (KeyNames.KEY_KP_Multiply << 8), // KP_Multiply\n 36: 0xE0 | (KeyNames.KEY_KP_7 << 8), // Home\n 38: 0xE0 | (KeyNames.KEY_KP_8 << 8), // Up\n 33: 0xE0 | (KeyNames.KEY_KP_9 << 8), // PgUp\n 37: 0xE0 | (KeyNames.KEY_KP_4 << 8), // Left\n 39: 0xE0 | (KeyNames.KEY_KP_6 << 8), // Right\n 35: 0xE0 | (KeyNames.KEY_KP_1 << 8), // End\n 40: 0xE0 | (KeyNames.KEY_KP_2 << 8), // Down\n 34: 0xE0 | (KeyNames.KEY_KP_3 << 8), // PgDown\n 45: 0xE0 | (KeyNames.KEY_KP_0 << 8), // Insert\n 46: 0xE0 | (KeyNames.KEY_KP_Decimal << 8), // Delete\n 91: 0xE0 | (0x5B << 8), // LMeta\n 92: 0xE0 | (0x5C << 8), // RMeta\n 93: 0xE0 | (0x5D << 8), // Menu\n};\n\n/** Firefox/Mozilla-specific keyCode overrides */\nconst firefoxScanmap: Record<number, number> = {\n 173: KeyNames.KEY_Minus,\n 61: KeyNames.KEY_Equal,\n 59: KeyNames.KEY_SemiColon,\n};\n\n/** DOM3-specific keyCode overrides (Chrome, Edge, etc.) */\nconst domScanmap: Record<number, number> = {\n 189: KeyNames.KEY_Minus,\n 187: KeyNames.KEY_Equal,\n 186: KeyNames.KEY_SemiColon,\n};\n\n/**\n * Look up the AT scancode for a given browser keyCode and DOM code string.\n * Prefers the DOM `code` property (KeyboardEvent.code) when available,\n * falling back to the legacy `keyCode` property with browser-specific maps.\n *\n * @param keyCode - The legacy `KeyboardEvent.keyCode` value\n * @param code - The DOM `KeyboardEvent.code` string (e.g. \"KeyA\", \"ArrowUp\")\n * @returns The AT scancode, or undefined if no mapping exists\n */\nexport function getScancode(keyCode: number, code: string): number | undefined\n{\n const codeResult = codeToScancode[code];\n if (codeResult !== undefined)\n {\n return codeResult;\n }\n\n const commonResult = commonScanmap[keyCode];\n if (commonResult !== undefined)\n {\n return commonResult;\n }\n\n /* Fall back to browser-specific maps */\n if (typeof navigator !== \"undefined\" && navigator.userAgent.indexOf(\"Firefox\") !== -1)\n {\n return firefoxScanmap[keyCode];\n }\n else\n {\n return domScanmap[keyCode];\n }\n}\n\n/**\n * Convert a browser keyCode/code to an AT make (press) scancode.\n * Logs an alert if no mapping is found.\n *\n * @param keyCode - The legacy `KeyboardEvent.keyCode` value\n * @param code - The DOM `KeyboardEvent.code` string\n * @returns The AT make scancode, or 0 if unmapped\n */\nexport function keycodeToStartScan(keyCode: number, code: string): number\n{\n const scancode = getScancode(keyCode, code);\n if (scancode === undefined)\n {\n if (typeof alert !== \"undefined\")\n {\n alert('no map for ' + keyCode);\n }\n return 0;\n }\n return scancode;\n}\n\n/**\n * Convert a browser keyCode/code to an AT break (release) scancode.\n * The break code has bit 7 set (single-byte) or bit 15 set (extended).\n *\n * @param keyCode - The legacy `KeyboardEvent.keyCode` value\n * @param code - The DOM `KeyboardEvent.code` string\n * @returns The AT break scancode, or 0 if unmapped\n */\nexport function keycodeToEndScan(keyCode: number, code: string): number\n{\n const scancode = getScancode(keyCode, code);\n if (scancode === undefined)\n {\n return 0;\n }\n\n if (scancode < 0x100)\n {\n return scancode | 0x80;\n }\n else\n {\n return scancode | 0x8000;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Media debug utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Dump the state of an HTMLMediaElement for debugging.\n */\nexport function dumpMediaElement(m: HTMLMediaElement): string\n{\n return \"[networkState \" + m.networkState +\n \"|readyState \" + m.readyState +\n \"|error \" + m.error +\n \"|seeking \" + m.seeking +\n \"|duration \" + m.duration +\n \"|paused \" + m.paused +\n \"|ended \" + m.ended +\n \"|buffered \" + dumpTimeRange(m.buffered) +\n \"]\";\n}\n\n/**\n * Dump the state of a MediaSource for debugging.\n */\nexport function dumpMediaSource(ms: MediaSource): string\n{\n return \"[duration \" + ms.duration +\n \"|readyState \" + ms.readyState + \"]\";\n}\n\n/**\n * Dump the state of a SourceBuffer for debugging.\n */\nexport function dumpSourceBuffer(sb: SourceBuffer): string\n{\n return \"[appendWindowStart \" + sb.appendWindowStart +\n \"|appendWindowEnd \" + sb.appendWindowEnd +\n \"|buffered \" + dumpTimeRange(sb.buffered) +\n \"|timestampOffset \" + sb.timestampOffset +\n \"|updating \" + sb.updating +\n \"]\";\n}\n\n/**\n * Dump a TimeRanges object for debugging.\n */\nexport function dumpTimeRange(tr: TimeRanges | null): string\n{\n if (tr)\n {\n const len = tr.length;\n let ret = \"{len \" + len;\n if (len > 0)\n {\n ret += \"; start \" + tr.start(0) + \"; end \" + tr.end(len - 1);\n }\n ret += \"}\";\n return ret;\n }\n else\n {\n return \"N/A\";\n }\n}\n","/*----------------------------------------------------------------------------\n** wire.ts\n** SpiceWireReader receives binary messages from a WebSocket and\n** reassembles them into complete protocol frames, passing each\n** completed frame to a callback. It optionally saves and relays a\n** header (SpiceMiniData) for mini-message-format processing.\n**\n** Converted from wire.js to TypeScript ES6 class with typed API.\n**--------------------------------------------------------------------------*/\n\nimport { DEBUG } from '../utils/debug';\nimport { SpiceMiniData } from './spicemsg';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Callback invoked when a complete frame has been reassembled.\n * The first argument is the frame data; the second is the optional\n * saved SpiceMiniData header.\n */\nexport type WireCallback = (\n data: ArrayBuffer,\n header: SpiceMiniData | undefined,\n) => void;\n\n/**\n * Minimal interface for the \"connection\" object that owns the WebSocket.\n * SpiceConn will satisfy this once it is implemented (US-014).\n * Using an interface here avoids a circular dependency.\n */\nexport interface WireOwner {\n ws: WebSocket;\n connectionId: number;\n type: number;\n}\n\n// ---------------------------------------------------------------------------\n// SpiceWireReader\n// ---------------------------------------------------------------------------\n\n/**\n * Receives binary data from a WebSocket and reassembles it into complete\n * protocol frames of the requested size, invoking a callback for each\n * completed frame.\n *\n * Usage pattern:\n * 1. Construct with a WireOwner and callback.\n * 2. Call `request(n)` to indicate that n bytes are expected.\n * 3. Incoming WebSocket messages are buffered and, once `n` bytes are\n * available, the callback is invoked with a contiguous ArrayBuffer\n * of exactly `n` bytes.\n * 4. Optionally call `saveHeader(h)` before `request()` to attach a\n * SpiceMiniData header that will be passed to the callback.\n */\nexport class SpiceWireReader {\n /** The connection that owns the WebSocket. */\n private readonly owner: WireOwner;\n\n /** Callback invoked when a complete frame is ready. */\n private readonly callback: WireCallback;\n\n /** Number of bytes needed to complete the current frame (0 = just buffer). */\n private needed: number = 0;\n\n /** Total bytes currently buffered across all entries in `buffers`. */\n private size: number = 0;\n\n /** Queue of ArrayBuffer chunks received from the WebSocket. */\n private buffers: ArrayBuffer[] = [];\n\n /** Optional saved SpiceMiniData header to relay with the next frame. */\n private savedMsgHeader: SpiceMiniData | undefined = undefined;\n\n /** Bound message handler so we can remove the listener on cleanup. */\n private readonly boundOnMessage: (e: MessageEvent<ArrayBuffer>) => void;\n\n constructor(owner: WireOwner, callback: WireCallback)\n {\n this.owner = owner;\n this.callback = callback;\n\n this.boundOnMessage = this.onMessage.bind(this);\n this.owner.ws.binaryType = \"arraybuffer\";\n this.owner.ws.addEventListener(\"message\", this.boundOnMessage);\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /**\n * Request a frame of exactly `n` bytes. When enough data has been\n * buffered, the callback will be invoked.\n */\n request(n: number): void\n {\n this.needed = n;\n }\n\n /**\n * Save a SpiceMiniData header to be passed along with the next frame.\n */\n saveHeader(h: SpiceMiniData): void\n {\n this.savedMsgHeader = h;\n }\n\n /**\n * Clear the saved header.\n */\n clearHeader(): void\n {\n this.savedMsgHeader = undefined;\n }\n\n /**\n * Detach the WebSocket message listener. Call this on connection\n * teardown to avoid processing messages after the connection is closed.\n */\n cleanup(): void\n {\n this.owner.ws.removeEventListener(\"message\", this.boundOnMessage);\n this.buffers = [];\n this.size = 0;\n this.needed = 0;\n this.savedMsgHeader = undefined;\n }\n\n // -----------------------------------------------------------------------\n // Internal\n // -----------------------------------------------------------------------\n\n /**\n * WebSocket \"message\" event handler.\n */\n private onMessage(e: MessageEvent<ArrayBuffer>): void\n {\n DEBUG > 1 && console.log(\">> WebSockets.onmessage\");\n DEBUG > 1 && console.log(\n \"id \" + this.owner.connectionId + \"; type \" + this.owner.type,\n );\n this.inbound(e.data);\n }\n\n /**\n * Process an incoming ArrayBuffer chunk from the WebSocket.\n *\n * If no bytes are currently needed (`needed === 0`), the chunk is simply\n * buffered. Otherwise the method attempts to assemble complete frames\n * and deliver them via the callback.\n */\n private inbound(mb: ArrayBuffer): void\n {\n /* Just buffer if we don't need anything yet */\n if (this.needed === 0)\n {\n this.buffers.push(mb);\n this.size += mb.byteLength;\n return;\n }\n\n /* Optimization — if we have just one inbound block and it is large\n enough, use it directly without copying through the buffer queue. */\n if (this.buffers.length === 0 && mb.byteLength >= this.needed)\n {\n if (mb.byteLength > this.needed)\n {\n this.size = mb.byteLength - this.needed;\n this.buffers.push(mb.slice(this.needed));\n mb = mb.slice(0, this.needed);\n }\n this.callback.call(this.owner, mb,\n this.savedMsgHeader ?? undefined);\n }\n else\n {\n this.buffers.push(mb);\n this.size += mb.byteLength;\n }\n\n /* Assemble complete frames from the buffer queue */\n while (this.size >= this.needed && this.needed > 0)\n {\n let count = 0;\n const frame = new ArrayBuffer(this.needed);\n const view = new Uint8Array(frame);\n\n while (count < frame.byteLength && this.buffers.length > 0)\n {\n const buf = this.buffers.shift();\n if (!buf)\n {\n return;\n }\n const uint8 = new Uint8Array(buf);\n const step = frame.byteLength - count;\n\n if (uint8.length <= step)\n {\n view.set(uint8, count);\n count += uint8.length;\n this.size -= uint8.length;\n }\n else\n {\n const temp = uint8.slice(0, step);\n view.set(temp, count);\n count += temp.length;\n this.size -= temp.length;\n\n this.buffers.unshift(uint8.slice(step).buffer);\n }\n }\n\n this.callback.call(this.owner, frame,\n this.savedMsgHeader ?? undefined);\n }\n }\n}\n\nexport { SpiceWireReader as default };\n","\"use strict\";\n// ---------------------------------------------------------------------------\n// WebM / EBML element serialization interface\n// ---------------------------------------------------------------------------\n\n/**\n * Interface for WebM/EBML elements that can be serialized to an ArrayBuffer.\n * Unlike the protocol Serializable interface, toBuffer returns the new write\n * offset so elements can be composed sequentially.\n */\ninterface WebmElement {\n toBuffer(a: ArrayBuffer, at: number): number;\n bufferSize(): number;\n}\n\n// ---------------------------------------------------------------------------\n// EBML identifiers\n// ---------------------------------------------------------------------------\n\ntype EbmlId = readonly number[];\n\nconst EBML_HEADER: EbmlId = [0x1a, 0x45, 0xdf, 0xa3];\nconst EBML_HEADER_VERSION: EbmlId = [0x42, 0x86];\nconst EBML_HEADER_READ_VERSION: EbmlId = [0x42, 0xf7];\nconst EBML_HEADER_MAX_ID_LENGTH: EbmlId = [0x42, 0xf2];\nconst EBML_HEADER_MAX_SIZE_LENGTH: EbmlId = [0x42, 0xf3];\nconst EBML_HEADER_DOC_TYPE: EbmlId = [0x42, 0x82];\nconst EBML_HEADER_DOC_TYPE_VERSION: EbmlId = [0x42, 0x87];\nconst EBML_HEADER_DOC_TYPE_READ_VERSION: EbmlId = [0x42, 0x85];\n\nconst WEBM_SEGMENT_HEADER: EbmlId = [0x18, 0x53, 0x80, 0x67];\nconst WEBM_SEGMENT_INFORMATION: EbmlId = [0x15, 0x49, 0xA9, 0x66];\n\nconst WEBM_TIMECODE_SCALE: EbmlId = [0x2A, 0xD7, 0xB1];\nconst WEBM_MUXING_APP: EbmlId = [0x4D, 0x80];\nconst WEBM_WRITING_APP: EbmlId = [0x57, 0x41];\n\nconst WEBM_SEEK_HEAD: EbmlId = [0x11, 0x4D, 0x9B, 0x74];\nconst WEBM_SEEK: EbmlId = [0x4D, 0xBB];\nconst WEBM_SEEK_ID: EbmlId = [0x53, 0xAB];\nconst WEBM_SEEK_POSITION: EbmlId = [0x53, 0xAC];\n\nconst WEBM_TRACKS: EbmlId = [0x16, 0x54, 0xAE, 0x6B];\nconst WEBM_TRACK_ENTRY: EbmlId = [0xAE];\nconst WEBM_TRACK_NUMBER: EbmlId = [0xD7];\nconst WEBM_TRACK_UID: EbmlId = [0x73, 0xC5];\nconst WEBM_TRACK_TYPE: EbmlId = [0x83];\nconst WEBM_FLAG_ENABLED: EbmlId = [0xB9];\nconst WEBM_FLAG_DEFAULT: EbmlId = [0x88];\nconst WEBM_FLAG_FORCED: EbmlId = [0x55, 0xAA];\nconst WEBM_FLAG_LACING: EbmlId = [0x9C];\nconst WEBM_MIN_CACHE: EbmlId = [0x6D, 0xE7];\n\nconst WEBM_MAX_BLOCK_ADDITION_ID: EbmlId = [0x55, 0xEE];\nconst WEBM_CODEC_DECODE_ALL: EbmlId = [0xAA];\nconst WEBM_SEEK_PRE_ROLL: EbmlId = [0x56, 0xBB];\nconst WEBM_CODEC_DELAY: EbmlId = [0x56, 0xAA];\nconst WEBM_CODEC_PRIVATE: EbmlId = [0x63, 0xA2];\nconst WEBM_CODEC_ID: EbmlId = [0x86];\n\nconst WEBM_VIDEO: EbmlId = [0xE0];\nconst WEBM_FLAG_INTERLACED: EbmlId = [0x9A];\nconst WEBM_PIXEL_WIDTH: EbmlId = [0xB0];\nconst WEBM_PIXEL_HEIGHT: EbmlId = [0xBA];\n\nconst WEBM_AUDIO: EbmlId = [0xE1];\nconst WEBM_SAMPLING_FREQUENCY: EbmlId = [0xB5];\nconst WEBM_CHANNELS: EbmlId = [0x9F];\n\nconst WEBM_CLUSTER: EbmlId = [0x1F, 0x43, 0xB6, 0x75];\nconst WEBM_TIME_CODE: EbmlId = [0xE7];\nconst WEBM_SIMPLE_BLOCK: EbmlId = [0xA3];\n\n// ---------------------------------------------------------------------------\n// Various OPUS / WebM constants\n// ---------------------------------------------------------------------------\n\nexport const WebmConstants = {\n CLUSTER_SIMPLEBLOCK_FLAG_KEYFRAME: 1 << 7,\n\n OPUS_FREQUENCY: 48000,\n OPUS_CHANNELS: 2,\n\n SPICE_PLAYBACK_CODEC: 'audio/webm; codecs=\"opus\"',\n MAX_CLUSTER_TIME: 1000,\n\n EXPECTED_PACKET_DURATION: 10,\n GAP_DETECTION_THRESHOLD: 50,\n\n SPICE_VP8_CODEC: 'video/webm; codecs=\"vp8\"',\n} as const;\n\n// Backward-compatible alias\nexport const Constants = WebmConstants;\n\n// ---------------------------------------------------------------------------\n// EBML utility functions\n// ---------------------------------------------------------------------------\n\nfunction ebmlWriteU1DataLen(len: number, dv: DataView, at: number): number\n{\n const b = 0x80 | len;\n dv.setUint8(at, b);\n return at + 1;\n}\n\nfunction ebmlWriteU8Value(id: EbmlId, val: number, dv: DataView, at: number): number\n{\n at = ebmlWriteArray(id, dv, at);\n at = ebmlWriteU1DataLen(1, dv, at);\n dv.setUint8(at, val);\n return at + 1;\n}\n\nfunction ebmlWriteU32Value(id: EbmlId, val: number, dv: DataView, at: number): number\n{\n at = ebmlWriteArray(id, dv, at);\n at = ebmlWriteU1DataLen(4, dv, at);\n dv.setUint32(at, val);\n return at + 4;\n}\n\nfunction ebmlWriteU16Value(id: EbmlId, val: number, dv: DataView, at: number): number\n{\n at = ebmlWriteArray(id, dv, at);\n at = ebmlWriteU1DataLen(2, dv, at);\n dv.setUint16(at, val);\n return at + 2;\n}\n\nfunction ebmlWriteFloatValue(id: EbmlId, val: number, dv: DataView, at: number): number\n{\n at = ebmlWriteArray(id, dv, at);\n at = ebmlWriteU1DataLen(4, dv, at);\n dv.setFloat32(at, val);\n return at + 4;\n}\n\nfunction ebmlWriteU64DataLen(len: number, dv: DataView, at: number): number\n{\n /* JavaScript doesn't do 64 bit ints natively, so this cheats and\n just has a max of 32 bits. Fine for our purposes */\n dv.setUint8(at++, 0x01);\n dv.setUint8(at++, 0x00);\n dv.setUint8(at++, 0x00);\n dv.setUint8(at++, 0x00);\n const val = len & 0xFFFFFFFF;\n for (let shift = 24; shift >= 0; shift -= 8)\n {\n dv.setUint8(at++, val >> shift);\n }\n return at;\n}\n\nfunction ebmlWriteArray(arr: EbmlId, dv: DataView, at: number): number\n{\n for (let i = 0; i < arr.length; i++)\n {\n dv.setUint8(at + i, arr[i]!);\n }\n return at + arr.length;\n}\n\nfunction ebmlWriteString(str: string, dv: DataView, at: number): number\n{\n for (let i = 0; i < str.length; i++)\n {\n dv.setUint8(at + i, str.charCodeAt(i));\n }\n return at + str.length;\n}\n\nfunction ebmlWriteData(id: EbmlId, data: string | readonly number[], dv: DataView, at: number): number\n{\n at = ebmlWriteArray(id, dv, at);\n if (data.length < 127)\n {\n at = ebmlWriteU1DataLen(data.length, dv, at);\n }\n else\n {\n at = ebmlWriteU64DataLen(data.length, dv, at);\n }\n if (typeof data === \"string\")\n {\n at = ebmlWriteString(data, dv, at);\n }\n else\n {\n at = ebmlWriteArray(data, dv, at);\n }\n return at;\n}\n\n// ---------------------------------------------------------------------------\n// WebM element classes\n// ---------------------------------------------------------------------------\n\nclass WebmEBMLHeader implements WebmElement\n{\n private readonly id: EbmlId = EBML_HEADER;\n private readonly version: number = 1;\n private readonly readVersion: number = 1;\n private readonly maxIdLength: number = 4;\n private readonly maxSizeLength: number = 8;\n private readonly docType: string = \"webm\";\n private readonly docTypeVersion: number = 2; /* Required for Firefox */\n private readonly docTypeReadVersion: number = 2;\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n\n at = ebmlWriteArray(this.id, dv, at);\n at = ebmlWriteU64DataLen(0x1f, dv, at);\n at = ebmlWriteU8Value(EBML_HEADER_VERSION, this.version, dv, at);\n at = ebmlWriteU8Value(EBML_HEADER_READ_VERSION, this.readVersion, dv, at);\n at = ebmlWriteU8Value(EBML_HEADER_MAX_ID_LENGTH, this.maxIdLength, dv, at);\n at = ebmlWriteU8Value(EBML_HEADER_MAX_SIZE_LENGTH, this.maxSizeLength, dv, at);\n at = ebmlWriteData(EBML_HEADER_DOC_TYPE, this.docType, dv, at);\n at = ebmlWriteU8Value(EBML_HEADER_DOC_TYPE_VERSION, this.docTypeVersion, dv, at);\n at = ebmlWriteU8Value(EBML_HEADER_DOC_TYPE_READ_VERSION, this.docTypeReadVersion, dv, at);\n\n return at;\n }\n\n bufferSize(): number\n {\n return 0x1f + 8 + this.id.length;\n }\n}\n\nclass WebmSegment implements WebmElement\n{\n private readonly id: EbmlId = WEBM_SEGMENT_HEADER;\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n\n at = ebmlWriteArray(this.id, dv, at);\n dv.setUint8(at++, 0xff);\n return at;\n }\n\n bufferSize(): number\n {\n return this.id.length + 1;\n }\n}\n\nclass WebmSegmentInformation implements WebmElement\n{\n private readonly id: EbmlId = WEBM_SEGMENT_INFORMATION;\n private readonly timecodeScale: number = 1000000; /* 1 ms */\n private readonly muxingApp: string = \"spice\";\n private readonly writingApp: string = \"spice-html5\";\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n\n at = ebmlWriteArray(this.id, dv, at);\n at = ebmlWriteU64DataLen(this.bufferSize() - 8 - this.id.length, dv, at);\n at = ebmlWriteU32Value(WEBM_TIMECODE_SCALE, this.timecodeScale, dv, at);\n at = ebmlWriteData(WEBM_MUXING_APP, this.muxingApp, dv, at);\n at = ebmlWriteData(WEBM_WRITING_APP, this.writingApp, dv, at);\n return at;\n }\n\n bufferSize(): number\n {\n return this.id.length + 8 +\n WEBM_TIMECODE_SCALE.length + 1 + 4 +\n WEBM_MUXING_APP.length + 1 + this.muxingApp.length +\n WEBM_WRITING_APP.length + 1 + this.writingApp.length;\n }\n}\n\nexport class WebmAudio implements WebmElement\n{\n private readonly id: EbmlId = WEBM_AUDIO;\n private readonly samplingFrequency: number;\n private readonly channels: number = WebmConstants.OPUS_CHANNELS;\n\n constructor(frequency: number)\n {\n this.samplingFrequency = frequency;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n at = ebmlWriteArray(this.id, dv, at);\n at = ebmlWriteU64DataLen(this.bufferSize() - 8 - this.id.length, dv, at);\n at = ebmlWriteU8Value(WEBM_CHANNELS, this.channels, dv, at);\n at = ebmlWriteFloatValue(WEBM_SAMPLING_FREQUENCY, this.samplingFrequency, dv, at);\n return at;\n }\n\n bufferSize(): number\n {\n return this.id.length + 8 +\n WEBM_SAMPLING_FREQUENCY.length + 1 + 4 +\n WEBM_CHANNELS.length + 1 + 1;\n }\n}\n\nexport class WebmVideo implements WebmElement\n{\n private readonly id: EbmlId = WEBM_VIDEO;\n private readonly flagInterlaced: number = 0;\n readonly width: number;\n readonly height: number;\n\n constructor(width: number, height: number)\n {\n this.width = width;\n this.height = height;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n at = ebmlWriteArray(this.id, dv, at);\n at = ebmlWriteU64DataLen(this.bufferSize() - 8 - this.id.length, dv, at);\n at = ebmlWriteU8Value(WEBM_FLAG_INTERLACED, this.flagInterlaced, dv, at);\n at = ebmlWriteU16Value(WEBM_PIXEL_WIDTH, this.width, dv, at);\n at = ebmlWriteU16Value(WEBM_PIXEL_HEIGHT, this.height, dv, at);\n return at;\n }\n\n bufferSize(): number\n {\n return this.id.length + 8 +\n WEBM_FLAG_INTERLACED.length + 1 + 1 +\n WEBM_PIXEL_WIDTH.length + 1 + 2 +\n WEBM_PIXEL_HEIGHT.length + 1 + 2;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SeekHead (not currently used, but preserved from original)\n// ---------------------------------------------------------------------------\n\nclass WebmSeek implements WebmElement\n{\n private readonly id: EbmlId = WEBM_SEEK;\n pos: number;\n private readonly seekid: EbmlId;\n\n constructor(seekid: EbmlId, pos: number)\n {\n this.seekid = seekid;\n this.pos = pos;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n at = ebmlWriteArray(this.id, dv, at);\n at = ebmlWriteU1DataLen(this.bufferSize() - 1 - this.id.length, dv, at);\n\n at = ebmlWriteData(WEBM_SEEK_ID, this.seekid, dv, at);\n at = ebmlWriteU16Value(WEBM_SEEK_POSITION, this.pos, dv, at);\n\n return at;\n }\n\n bufferSize(): number\n {\n return this.id.length + 1 +\n WEBM_SEEK_ID.length + 1 + this.seekid.length +\n WEBM_SEEK_POSITION.length + 1 + 2;\n }\n}\n\nclass WebmSeekHead implements WebmElement\n{\n private readonly id: EbmlId = WEBM_SEEK_HEAD;\n readonly info: WebmSeek;\n readonly track: WebmSeek;\n\n constructor(infoPos: number, trackPos: number)\n {\n this.info = new WebmSeek(WEBM_SEGMENT_INFORMATION, infoPos);\n this.track = new WebmSeek(WEBM_TRACKS, trackPos);\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n at = ebmlWriteArray(this.id, dv, at);\n at = ebmlWriteU64DataLen(this.bufferSize() - 8 - this.id.length, dv, at);\n\n at = this.info.toBuffer(a, at);\n at = this.track.toBuffer(a, at);\n\n return at;\n }\n\n bufferSize(): number\n {\n return this.id.length + 8 +\n this.info.bufferSize() +\n this.track.bufferSize();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Track entries\n// ---------------------------------------------------------------------------\n\nexport class WebmAudioTrackEntry implements WebmElement\n{\n private readonly id: EbmlId = WEBM_TRACK_ENTRY;\n private readonly number: number = 1;\n private readonly uid: number = 2; // Arbitrary id\n private readonly type: number = 2; // Audio\n private readonly flagEnabled: number = 1;\n private readonly flagDefault: number = 1;\n private readonly flagForced: number = 1;\n private readonly flagLacing: number = 0;\n private readonly minCache: number = 0;\n private readonly maxBlockAdditionId: number = 0;\n private readonly codecDecodeAll: number = 0;\n private readonly seekPreRoll: number = 0;\n private readonly codecDelay: number = 80000000; // Must match codec_private.preskip\n private readonly codecId: string = \"A_OPUS\";\n private readonly audio: WebmAudio;\n\n // See: http://tools.ietf.org/html/draft-terriberry-oggopus-01\n private readonly codecPrivate: readonly number[] = [\n 0x4f, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64, // OpusHead\n 0x01, // Version\n WebmConstants.OPUS_CHANNELS,\n 0x00, 0x0F, // Preskip - 3840 samples - should be 8ms at 48kHz\n 0x80, 0xbb, 0x00, 0x00, // 48000\n 0x00, 0x00, // Output gain\n 0x00 // Channel mapping family\n ];\n\n constructor()\n {\n this.audio = new WebmAudio(WebmConstants.OPUS_FREQUENCY);\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n at = ebmlWriteArray(this.id, dv, at);\n at = ebmlWriteU64DataLen(this.bufferSize() - 8 - this.id.length, dv, at);\n at = ebmlWriteU8Value(WEBM_TRACK_NUMBER, this.number, dv, at);\n at = ebmlWriteU8Value(WEBM_TRACK_UID, this.uid, dv, at);\n at = ebmlWriteU8Value(WEBM_FLAG_ENABLED, this.flagEnabled, dv, at);\n at = ebmlWriteU8Value(WEBM_FLAG_DEFAULT, this.flagDefault, dv, at);\n at = ebmlWriteU8Value(WEBM_FLAG_FORCED, this.flagForced, dv, at);\n at = ebmlWriteU8Value(WEBM_FLAG_LACING, this.flagLacing, dv, at);\n at = ebmlWriteData(WEBM_CODEC_ID, this.codecId, dv, at);\n at = ebmlWriteU8Value(WEBM_MIN_CACHE, this.minCache, dv, at);\n at = ebmlWriteU8Value(WEBM_MAX_BLOCK_ADDITION_ID, this.maxBlockAdditionId, dv, at);\n at = ebmlWriteU8Value(WEBM_CODEC_DECODE_ALL, this.codecDecodeAll, dv, at);\n at = ebmlWriteU32Value(WEBM_CODEC_DELAY, this.codecDelay, dv, at);\n at = ebmlWriteU32Value(WEBM_SEEK_PRE_ROLL, this.seekPreRoll, dv, at);\n at = ebmlWriteU8Value(WEBM_TRACK_TYPE, this.type, dv, at);\n at = ebmlWriteData(WEBM_CODEC_PRIVATE, this.codecPrivate, dv, at);\n\n at = this.audio.toBuffer(a, at);\n return at;\n }\n\n bufferSize(): number\n {\n return this.id.length + 8 +\n WEBM_TRACK_NUMBER.length + 1 + 1 +\n WEBM_TRACK_UID.length + 1 + 1 +\n WEBM_TRACK_TYPE.length + 1 + 1 +\n WEBM_FLAG_ENABLED.length + 1 + 1 +\n WEBM_FLAG_DEFAULT.length + 1 + 1 +\n WEBM_FLAG_FORCED.length + 1 + 1 +\n WEBM_FLAG_LACING.length + 1 + 1 +\n WEBM_MIN_CACHE.length + 1 + 1 +\n WEBM_MAX_BLOCK_ADDITION_ID.length + 1 + 1 +\n WEBM_CODEC_DECODE_ALL.length + 1 + 1 +\n WEBM_SEEK_PRE_ROLL.length + 1 + 4 +\n WEBM_CODEC_DELAY.length + 1 + 4 +\n WEBM_CODEC_ID.length + this.codecId.length + 1 +\n WEBM_CODEC_PRIVATE.length + 1 + this.codecPrivate.length +\n this.audio.bufferSize();\n }\n}\n\nexport class WebmVideoTrackEntry implements WebmElement\n{\n /*\n ** In general, we follow specifications found by looking here:\n ** https://www.webmproject.org/docs/container/\n ** which points here:\n ** https://www.matroska.org/technical/specs/index.html\n ** and here:\n ** https://datatracker.ietf.org/doc/draft-ietf-cellar-matroska/\n ** Our goal is to supply mandatory values, and note where we differ\n ** from the default.\n */\n private readonly id: EbmlId = WEBM_TRACK_ENTRY;\n private readonly number: number = 1;\n private readonly uid: number = 1;\n private readonly type: number = 1; // Video\n private readonly flagEnabled: number = 1;\n private readonly flagDefault: number = 1;\n private readonly flagForced: number = 1; // Different than default; we wish to force\n private readonly flagLacing: number = 1;\n private readonly minCache: number = 0;\n private readonly maxBlockAdditionId: number = 0;\n private readonly codecId: string = \"V_VP8\";\n private readonly codecDecodeAll: number = 1;\n private readonly seekPreRoll: number = 0;\n\n readonly video: WebmVideo;\n\n constructor(width: number, height: number)\n {\n this.video = new WebmVideo(width, height);\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n at = ebmlWriteArray(this.id, dv, at);\n at = ebmlWriteU64DataLen(this.bufferSize() - 8 - this.id.length, dv, at);\n at = ebmlWriteU8Value(WEBM_TRACK_NUMBER, this.number, dv, at);\n at = ebmlWriteU8Value(WEBM_TRACK_UID, this.uid, dv, at);\n at = ebmlWriteU8Value(WEBM_FLAG_ENABLED, this.flagEnabled, dv, at);\n at = ebmlWriteU8Value(WEBM_FLAG_DEFAULT, this.flagDefault, dv, at);\n at = ebmlWriteU8Value(WEBM_FLAG_FORCED, this.flagForced, dv, at);\n at = ebmlWriteU8Value(WEBM_FLAG_LACING, this.flagLacing, dv, at);\n at = ebmlWriteData(WEBM_CODEC_ID, this.codecId, dv, at);\n at = ebmlWriteU8Value(WEBM_MIN_CACHE, this.minCache, dv, at);\n at = ebmlWriteU8Value(WEBM_MAX_BLOCK_ADDITION_ID, this.maxBlockAdditionId, dv, at);\n at = ebmlWriteU8Value(WEBM_CODEC_DECODE_ALL, this.codecDecodeAll, dv, at);\n at = ebmlWriteU32Value(WEBM_SEEK_PRE_ROLL, this.seekPreRoll, dv, at);\n at = ebmlWriteU8Value(WEBM_TRACK_TYPE, this.type, dv, at);\n at = this.video.toBuffer(a, at);\n return at;\n }\n\n bufferSize(): number\n {\n return this.id.length + 8 +\n WEBM_TRACK_NUMBER.length + 1 + 1 +\n WEBM_TRACK_UID.length + 1 + 1 +\n WEBM_FLAG_ENABLED.length + 1 + 1 +\n WEBM_FLAG_DEFAULT.length + 1 + 1 +\n WEBM_FLAG_FORCED.length + 1 + 1 +\n WEBM_FLAG_LACING.length + 1 + 1 +\n WEBM_CODEC_ID.length + this.codecId.length + 1 +\n WEBM_MIN_CACHE.length + 1 + 1 +\n WEBM_MAX_BLOCK_ADDITION_ID.length + 1 + 1 +\n WEBM_CODEC_DECODE_ALL.length + 1 + 1 +\n WEBM_SEEK_PRE_ROLL.length + 1 + 4 +\n WEBM_TRACK_TYPE.length + 1 + 1 +\n this.video.bufferSize();\n }\n}\n\nexport class WebmTracks implements WebmElement\n{\n private readonly id: EbmlId = WEBM_TRACKS;\n private readonly trackEntry: WebmElement;\n\n constructor(entry: WebmAudioTrackEntry | WebmVideoTrackEntry)\n {\n this.trackEntry = entry;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n at = ebmlWriteArray(this.id, dv, at);\n at = ebmlWriteU64DataLen(this.bufferSize() - 8 - this.id.length, dv, at);\n at = this.trackEntry.toBuffer(a, at);\n return at;\n }\n\n bufferSize(): number\n {\n return this.id.length + 8 +\n this.trackEntry.bufferSize();\n }\n}\n\nexport class WebmCluster implements WebmElement\n{\n readonly timecode: number;\n\n constructor(timecode: number)\n {\n this.timecode = timecode;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n at = ebmlWriteArray(WEBM_CLUSTER, dv, at);\n dv.setUint8(at++, 0xff);\n at = ebmlWriteU32Value(WEBM_TIME_CODE, this.timecode, dv, at);\n return at;\n }\n\n bufferSize(): number\n {\n return WEBM_CLUSTER.length + 1 +\n WEBM_TIME_CODE.length + 1 + 4;\n }\n}\n\nexport class WebmSimpleBlock implements WebmElement\n{\n readonly timecode: number;\n readonly data: ArrayBuffer;\n readonly keyframe: boolean;\n\n constructor(timecode: number, data: ArrayBuffer, keyframe: boolean)\n {\n this.timecode = timecode;\n this.data = data;\n this.keyframe = keyframe;\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n const dv = new DataView(a);\n at = ebmlWriteArray(WEBM_SIMPLE_BLOCK, dv, at);\n at = ebmlWriteU64DataLen(this.data.byteLength + 4, dv, at);\n at = ebmlWriteU1DataLen(1, dv, at); // Track #\n dv.setUint16(at, this.timecode); at += 2; // timecode - relative to cluster\n dv.setUint8(at, this.keyframe ? WebmConstants.CLUSTER_SIMPLEBLOCK_FLAG_KEYFRAME : 0); at += 1; // flags\n\n // Copy frame data into the buffer\n const u8src = new Uint8Array(this.data);\n const u8dst = new Uint8Array(a, at, this.data.byteLength);\n u8dst.set(u8src);\n at += this.data.byteLength;\n\n return at;\n }\n\n bufferSize(): number\n {\n return WEBM_SIMPLE_BLOCK.length + 8 +\n 1 + 2 + 1 +\n this.data.byteLength;\n }\n}\n\nexport class WebmHeader implements WebmElement\n{\n private readonly ebml: WebmEBMLHeader;\n private readonly segment: WebmSegment;\n private readonly seekHead: WebmSeekHead;\n private readonly info: WebmSegmentInformation;\n\n constructor()\n {\n this.ebml = new WebmEBMLHeader();\n this.segment = new WebmSegment();\n this.seekHead = new WebmSeekHead(0, 0);\n\n this.seekHead.info.pos = this.segment.bufferSize() + this.seekHead.bufferSize();\n\n this.info = new WebmSegmentInformation();\n\n this.seekHead.track.pos = this.seekHead.info.pos + this.info.bufferSize();\n }\n\n toBuffer(a: ArrayBuffer, at: number = 0): number\n {\n at = this.ebml.toBuffer(a, at);\n at = this.segment.toBuffer(a, at);\n at = this.info.toBuffer(a, at);\n\n return at;\n }\n\n bufferSize(): number\n {\n return this.ebml.bufferSize() +\n this.segment.bufferSize() +\n this.info.bufferSize();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Backward-compatible aliases matching original export names\n// ---------------------------------------------------------------------------\n\nexport {\n WebmAudio as Audio,\n WebmVideo as Video,\n WebmAudioTrackEntry as AudioTrackEntry,\n WebmVideoTrackEntry as VideoTrackEntry,\n WebmTracks as Tracks,\n WebmCluster as Cluster,\n WebmSimpleBlock as SimpleBlock,\n WebmHeader as Header,\n};\n","/*----------------------------------------------------------------------------\n** ticket.ts\n** RSA ticket encryption for SPICE authentication using the\n** Web Crypto API (SubtleCrypto).\n**\n** The SPICE server sends a DER-encoded SubjectPublicKeyInfo (SPKI)\n** RSA public key. We import it with crypto.subtle.importKey(\"spki\")\n** and encrypt the null-terminated password using RSA-OAEP with SHA-1,\n** which is exactly the padding scheme the SPICE protocol requires.\n**\n** This replaces the previous vendored jsbn/rsa/rng/prng4/sha1\n** libraries and the manual OAEP padding implementation.\n**--------------------------------------------------------------------------*/\n\n/**\n * Encrypt a SPICE authentication ticket using RSA-OAEP (SHA-1).\n *\n * Imports the server's DER-encoded SPKI public key via the Web Crypto API,\n * then encrypts the null-terminated password. Returns the ciphertext as\n * an array of bytes.\n *\n * @param derPublicKey - ArrayBuffer containing the DER-encoded SPKI public key\n * @param password - The SPICE password to encrypt (will be null-terminated)\n * @returns Promise resolving to the encrypted ticket as a number[]\n */\nasync function rsaEncrypt(derPublicKey: ArrayBuffer, password: string): Promise<number[]>\n{\n const key = await crypto.subtle.importKey(\n 'spki',\n derPublicKey,\n { name: 'RSA-OAEP', hash: 'SHA-1' },\n false,\n ['encrypt']\n );\n\n // Encode the password as bytes with a null terminator, matching the\n // original implementation which used charCodeAt() per character.\n // For ASCII passwords (the common case) this is byte-identical.\n const passwordBytes = new Uint8Array(password.length + 1);\n for (let i = 0; i < password.length; i++)\n {\n passwordBytes[i] = password.charCodeAt(i) & 0xff;\n }\n passwordBytes[password.length] = 0; // null terminator\n\n const encrypted = await crypto.subtle.encrypt(\n { name: 'RSA-OAEP' },\n key,\n passwordBytes\n );\n\n // Convert ArrayBuffer to number[] for compatibility with sendTicket()\n const u8 = new Uint8Array(encrypted);\n const result: number[] = new Array(u8.length);\n for (let i = 0; i < u8.length; i++)\n {\n result[i] = u8[i]!;\n }\n return result;\n}\n\nexport {\n rsaEncrypt,\n};\n","/*----------------------------------------------------------------------------\n** spiceconn.ts\n** Base TypeScript class for establishing and managing a connection\n** to a SPICE server. Converted from spiceconn.js using ES6 class\n** syntax with full type safety.\n**\n** It provides core functionality to the Main, Display, Inputs,\n** Cursor, Playback, and Port channels — see main.ts for usage.\n**--------------------------------------------------------------------------*/\n\nimport {\n SPICE_MAGIC,\n SPICE_CONNECT_TIMEOUT,\n SpiceCommonCap,\n SpiceLinkErr,\n SpiceMsg,\n SpiceMsgc,\n SpiceMsgcDisplay,\n SpiceChannel,\n SpiceMainCap,\n SpiceDisplayCap,\n SpicePlaybackCap,\n SpiceNotifySeverity,\n} from './enums';\n\nimport {\n SpiceLinkHeader,\n SpiceLinkMess,\n SpiceLinkReply,\n SpiceLinkAuthTicket,\n SpiceLinkAuthReply,\n SpiceMiniData,\n SpiceMsgcDisplayInit,\n SpiceMsgSetAck,\n SpiceMsgcAckSync,\n SpiceMsgNotify,\n Serializable,\n} from './spicemsg';\n\nimport { SpiceWireReader, WireOwner } from './wire';\nimport { DEBUG, hexdumpBuffer } from '../utils/debug';\nimport { WebmConstants } from './webm';\nimport { rsaEncrypt } from './ticket';\n\n// ---------------------------------------------------------------------------\n// Connection state\n// ---------------------------------------------------------------------------\n\n/**\n * Connection states for the SPICE handshake and session lifecycle.\n *\n * Flow: connecting -> start -> link -> ticket -> ready\n * Error/close transitions can happen from any state.\n */\nexport const ConnectionState = {\n /** WebSocket is connecting (initial state). */\n CONNECTING: 'connecting',\n /** WebSocket opened; link header sent, awaiting server link header. */\n START: 'start',\n /** Server link header received; awaiting server link reply. */\n LINK: 'link',\n /** Link reply received; ticket sent, awaiting auth reply. */\n TICKET: 'ticket',\n /** Authenticated; processing protocol messages. */\n READY: 'ready',\n /** Connection is closing (intentional close). */\n CLOSING: 'closing',\n /** An error occurred. */\n ERROR: 'error',\n} as const;\n\nexport type ConnectionStateValue =\n typeof ConnectionState[keyof typeof ConnectionState];\n\n// ---------------------------------------------------------------------------\n// Configuration / options\n// ---------------------------------------------------------------------------\n\n/**\n * Options for constructing a SpiceConn instance.\n */\nexport interface SpiceConnOptions {\n /** WebSocket URI (e.g. \"wss://host:port\"). */\n uri: string;\n\n /** Connection ID (session ID for sub-channels; 0 for main channel). */\n connectionId?: number;\n\n /** SPICE channel type (from SpiceChannel.*). */\n type?: number;\n\n /** Channel ID (for multi-head, typically 0). */\n chanId?: number;\n\n /** Parent connection (for sub-channels that inherit password and messageId). */\n parent?: SpiceConn;\n\n /** Screen element ID for display rendering. */\n screenId?: string;\n\n /** Element ID for debug canvas dumps. */\n dumpId?: string;\n\n /** Element ID for message logging to the DOM. */\n messageId?: string;\n\n /** Password for SPICE ticket authentication. */\n password?: string;\n\n /** Error callback. */\n onerror?: (e: Error) => void;\n\n /** Success callback. */\n onsuccess?: (m: string) => void;\n\n /** Agent ready callback. */\n onagent?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// SpiceConn — base connection class\n// ---------------------------------------------------------------------------\n\n/**\n * Base SPICE connection class. Manages WebSocket lifecycle,\n * SPICE link handshake, ticket authentication, and common\n * message handling (SET_ACK, PING/PONG, NOTIFY).\n *\n * Channel-specific subclasses (Main, Display, Inputs, Cursor,\n * Playback, Port) extend this class and override\n * `processChannelMessage()` to handle their own message types.\n */\nexport class SpiceConn implements WireOwner {\n // -- WireOwner interface --\n ws!: WebSocket;\n connectionId: number;\n type: number;\n\n // -- Connection state --\n state: ConnectionStateValue = ConnectionState.CONNECTING;\n\n // -- Channel info --\n chanId: number;\n\n // -- Parent / inheritance --\n parent: SpiceConn | undefined;\n\n // -- Display/debug IDs --\n screenId: string | undefined;\n dumpId: string | undefined;\n messageId: string | undefined;\n\n // -- Authentication --\n password: string;\n\n // -- Callbacks --\n onerror: ((e: Error) => void) | undefined;\n onsuccess: ((m: string) => void) | undefined;\n onagent: (() => void) | undefined;\n\n // -- Wire reader --\n wireReader!: SpiceWireReader;\n\n // -- Message tracking --\n messagesSent: number = 0;\n\n // -- ACK tracking --\n ackWindow: number = 0;\n msgsUntilAck: number | undefined;\n\n // -- Link handshake state --\n replyHdr: SpiceLinkHeader | undefined;\n replyLink: SpiceLinkReply | undefined;\n authReply: SpiceLinkAuthReply | undefined;\n\n // -- Known-unimplemented warning suppression --\n private warnings: Record<number, boolean> = {};\n\n // -- Timeout handle --\n private timeout: ReturnType<typeof setTimeout> | undefined;\n\n constructor(options: SpiceConnOptions)\n {\n if (!options.uri)\n {\n throw new Error(\"You must specify a uri\");\n }\n\n this.connectionId = options.connectionId ?? 0;\n this.type = options.type ?? SpiceChannel.MAIN;\n this.chanId = options.chanId ?? 0;\n\n if (options.parent !== undefined)\n {\n this.parent = options.parent;\n this.messageId = options.parent.messageId;\n this.password = options.parent.password;\n }\n else\n {\n this.password = options.password ?? '';\n }\n\n if (options.screenId !== undefined)\n {\n this.screenId = options.screenId;\n }\n if (options.dumpId !== undefined)\n {\n this.dumpId = options.dumpId;\n }\n if (options.messageId !== undefined)\n {\n this.messageId = options.messageId;\n }\n if (options.password !== undefined)\n {\n this.password = options.password;\n }\n if (options.onerror !== undefined)\n {\n this.onerror = options.onerror;\n }\n if (options.onsuccess !== undefined)\n {\n this.onsuccess = options.onsuccess;\n }\n if (options.onagent !== undefined)\n {\n this.onagent = options.onagent;\n }\n\n this.ws = new WebSocket(options.uri, 'binary');\n\n if (!this.ws.binaryType)\n {\n throw new Error(\"WebSocket doesn't support binaryType. Try a different browser.\");\n }\n\n this.wireReader = new SpiceWireReader(this, this.processInbound.bind(this));\n\n this.ws.addEventListener('open', () =>\n {\n DEBUG > 0 && console.log(\">> WebSockets.onopen\");\n DEBUG > 0 && console.log(\"id \" + this.connectionId + \"; type \" + this.type);\n\n this.sendHdr();\n this.wireReader.request(new SpiceLinkHeader().bufferSize());\n this.state = ConnectionState.START;\n });\n\n this.ws.addEventListener('error', (e: Event) =>\n {\n const target = e.target as WebSocket | null;\n if (target && 'url' in target)\n {\n this.logErr(\"WebSocket error: Can't connect to websocket on URL: \" + target.url);\n }\n this.reportError(new Error(\"WebSocket error\"));\n });\n\n this.ws.addEventListener('close', () =>\n {\n DEBUG > 0 && console.log(\">> WebSockets.onclose\");\n DEBUG > 0 && console.log(\"id \" + this.connectionId + \"; type \" + this.type);\n\n if (this.state !== ConnectionState.CLOSING &&\n this.state !== ConnectionState.ERROR &&\n this.onerror !== undefined)\n {\n let err: Error;\n if (this.state === ConnectionState.CONNECTING)\n {\n err = new Error(\"Connection refused.\");\n }\n else if (this.state === ConnectionState.START ||\n this.state === ConnectionState.LINK)\n {\n err = new Error(\"Unexpected protocol mismatch.\");\n }\n else if (this.state === ConnectionState.TICKET)\n {\n err = new Error(\"Bad password.\");\n }\n else\n {\n err = new Error(\"Unexpected close while \" + this.state);\n }\n\n this.onerror(err);\n this.logErr(err.toString());\n }\n });\n\n if (this.ws.readyState === 2 || this.ws.readyState === 3)\n {\n throw new Error(\"Unable to connect to \" + options.uri);\n }\n\n this.timeout = setTimeout(() => this.handleTimeout(), SPICE_CONNECT_TIMEOUT);\n }\n\n // -----------------------------------------------------------------------\n // Link handshake: send header + link message\n // -----------------------------------------------------------------------\n\n private sendHdr(): void\n {\n const hdr = new SpiceLinkHeader();\n const msg = new SpiceLinkMess();\n\n msg.connectionId = this.connectionId;\n msg.channelType = this.type;\n msg.channelId = this.chanId;\n\n msg.commonCaps.push(\n (1 << SpiceCommonCap.PROTOCOL_AUTH_SELECTION) |\n (1 << SpiceCommonCap.MINI_HEADER)\n );\n\n if (msg.channelType === SpiceChannel.PLAYBACK)\n {\n let caps = 0;\n if (typeof MediaSource !== 'undefined' &&\n MediaSource.isTypeSupported(WebmConstants.SPICE_PLAYBACK_CODEC))\n {\n caps |= (1 << SpicePlaybackCap.OPUS);\n }\n msg.channelCaps.push(caps);\n }\n else if (msg.channelType === SpiceChannel.MAIN)\n {\n msg.channelCaps.push(\n (1 << SpiceMainCap.AGENT_CONNECTED_TOKENS)\n );\n }\n else if (msg.channelType === SpiceChannel.DISPLAY)\n {\n let caps = (1 << SpiceDisplayCap.SIZED_STREAM) |\n (1 << SpiceDisplayCap.STREAM_REPORT) |\n (1 << SpiceDisplayCap.MULTI_CODEC) |\n (1 << SpiceDisplayCap.CODEC_MJPEG);\n if (typeof MediaSource !== 'undefined' &&\n MediaSource.isTypeSupported(WebmConstants.SPICE_VP8_CODEC))\n {\n caps |= (1 << SpiceDisplayCap.CODEC_VP8);\n }\n msg.channelCaps.push(caps);\n }\n\n hdr.size = msg.bufferSize();\n\n const mb = new ArrayBuffer(hdr.bufferSize() + msg.bufferSize());\n hdr.toBuffer(mb);\n msg.toBuffer(mb, hdr.bufferSize());\n\n DEBUG > 1 && console.log(\"Sending header:\");\n DEBUG > 2 && hexdumpBuffer(mb);\n this.ws.send(mb);\n }\n\n // -----------------------------------------------------------------------\n // Link handshake: send ticket\n // -----------------------------------------------------------------------\n\n private sendTicket(ticket: number[]): void\n {\n const hdr = new SpiceLinkAuthTicket();\n hdr.authMechanism = SpiceCommonCap.AUTH_SPICE;\n hdr.encryptedData = ticket;\n const mb = new ArrayBuffer(hdr.bufferSize());\n\n hdr.toBuffer(mb);\n DEBUG > 1 && console.log(\"Sending ticket:\");\n DEBUG > 2 && hexdumpBuffer(mb);\n this.ws.send(mb);\n }\n\n // -----------------------------------------------------------------------\n // Send a protocol message (mini-header format)\n // -----------------------------------------------------------------------\n\n sendMsg(msg: SpiceMiniData): void\n {\n const mb = new ArrayBuffer(msg.bufferSize());\n msg.toBuffer(mb);\n this.messagesSent++;\n DEBUG > 0 && console.log(\">> hdr \" + this.channelType() + \" type \" + msg.type + \" size \" + mb.byteLength);\n DEBUG > 2 && hexdumpBuffer(mb);\n this.ws.send(mb);\n }\n\n // -----------------------------------------------------------------------\n // Inbound data processing (wire reader callback)\n // -----------------------------------------------------------------------\n\n private processInbound(mb: ArrayBuffer, savedHeader: SpiceMiniData | undefined): void\n {\n DEBUG > 2 && console.log(this.type + \": processing message of size \" + mb.byteLength + \"; state is \" + this.state);\n\n if (this.state === ConnectionState.READY)\n {\n if (savedHeader === undefined)\n {\n const msg = new SpiceMiniData(mb);\n\n if (msg.type > 500)\n {\n if (DEBUG > 0)\n {\n if (typeof alert !== \"undefined\")\n {\n alert(\"Something has gone very wrong; we think we have message of type \" + msg.type);\n }\n }\n }\n\n if (msg.size === 0)\n {\n this.processMessage(msg);\n this.wireReader.request(new SpiceMiniData().bufferSize());\n }\n else\n {\n this.wireReader.request(msg.size);\n this.wireReader.saveHeader(msg);\n }\n }\n else\n {\n savedHeader.data = mb;\n this.processMessage(savedHeader);\n this.wireReader.request(new SpiceMiniData().bufferSize());\n this.wireReader.clearHeader();\n }\n }\n else if (this.state === ConnectionState.START)\n {\n this.replyHdr = new SpiceLinkHeader(mb);\n if (this.replyHdr.magic !== SPICE_MAGIC)\n {\n this.state = ConnectionState.ERROR;\n const e = new Error('Error: magic mismatch: ' + this.replyHdr.magic);\n this.reportError(e);\n }\n else\n {\n // FIXME - Determine major/minor version requirements\n this.wireReader.request(this.replyHdr.size);\n this.state = ConnectionState.LINK;\n }\n }\n else if (this.state === ConnectionState.LINK)\n {\n this.replyLink = new SpiceLinkReply(mb);\n // FIXME - Screen the caps - require minihdr at least, right?\n if (this.replyLink.error)\n {\n this.state = ConnectionState.ERROR;\n const e = new Error('Error: reply link error ' + this.replyLink.error);\n this.reportError(e);\n }\n else\n {\n if (!this.replyLink.pubKeyDer)\n {\n this.state = ConnectionState.ERROR;\n this.reportError(new Error('Error: no public key in server reply'));\n return;\n }\n // Encrypt the password using Web Crypto API (async).\n // The rsaEncrypt function imports the raw DER SPKI key\n // and performs RSA-OAEP encryption with SHA-1.\n rsaEncrypt(this.replyLink.pubKeyDer, this.password)\n .then((encrypted) =>\n {\n this.sendTicket(encrypted);\n this.state = ConnectionState.TICKET;\n this.wireReader.request(new SpiceLinkAuthReply().bufferSize());\n })\n .catch((err: unknown) =>\n {\n this.state = ConnectionState.ERROR;\n const msg = err instanceof Error ? err.message : String(err);\n this.reportError(new Error('RSA encryption failed: ' + msg));\n });\n }\n }\n else if (this.state === ConnectionState.TICKET)\n {\n this.authReply = new SpiceLinkAuthReply(mb);\n if (this.authReply.authCode === SpiceLinkErr.OK)\n {\n DEBUG > 0 && console.log(this.type + ': Connected');\n\n if (this.type === SpiceChannel.DISPLAY)\n {\n // FIXME - pixmap and glz dictionary config info?\n const dinit = new SpiceMsgcDisplayInit();\n const reply = new SpiceMiniData();\n reply.buildMsg(SpiceMsgcDisplay.INIT, dinit);\n DEBUG > 0 && console.log(\"Request display init\");\n this.sendMsg(reply);\n }\n this.state = ConnectionState.READY;\n this.wireReader.request(new SpiceMiniData().bufferSize());\n if (this.timeout !== undefined)\n {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n }\n }\n else\n {\n this.state = ConnectionState.ERROR;\n if (this.authReply.authCode === SpiceLinkErr.PERMISSION_DENIED)\n {\n this.reportError(new Error(\"Permission denied.\"));\n }\n else\n {\n this.reportError(new Error(\"Unexpected link error \" + this.authReply.authCode));\n }\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Common message handling (SET_ACK, PING, NOTIFY)\n // -----------------------------------------------------------------------\n\n private processCommonMessages(msg: SpiceMiniData): boolean\n {\n if (msg.type === SpiceMsg.SET_ACK)\n {\n if (!msg.data)\n {\n this.logWarn(\"SET_ACK message with no data\");\n return true;\n }\n const ack = new SpiceMsgSetAck(msg.data);\n // FIXME - what to do with generation?\n this.ackWindow = ack.window;\n DEBUG > 1 && console.log(this.type + \": set ack to \" + ack.window);\n this.msgsUntilAck = this.ackWindow;\n const ackack = new SpiceMsgcAckSync(ack);\n const reply = new SpiceMiniData();\n reply.buildMsg(SpiceMsgc.ACK_SYNC, ackack);\n this.sendMsg(reply);\n return true;\n }\n\n if (msg.type === SpiceMsg.PING)\n {\n DEBUG > 1 && console.log(\"ping!\");\n const pong = new SpiceMiniData();\n pong.type = SpiceMsgc.PONG;\n if (msg.data)\n {\n pong.data = msg.data.slice(0, 12);\n }\n pong.size = pong.bufferSize();\n this.sendMsg(pong);\n return true;\n }\n\n if (msg.type === SpiceMsg.NOTIFY)\n {\n if (!msg.data)\n {\n this.logWarn(\"NOTIFY message with no data\");\n return true;\n }\n // FIXME - Visibility + what\n const notify = new SpiceMsgNotify(msg.data);\n if (notify.severity === SpiceNotifySeverity.ERROR)\n {\n this.logErr(notify.message);\n }\n else if (notify.severity === SpiceNotifySeverity.WARN)\n {\n this.logWarn(notify.message);\n }\n else\n {\n this.logInfo(notify.message);\n }\n return true;\n }\n\n return false;\n }\n\n // -----------------------------------------------------------------------\n // Process a complete message (common + channel-specific)\n // -----------------------------------------------------------------------\n\n private processMessage(msg: SpiceMiniData): boolean\n {\n const start = Date.now();\n DEBUG > 0 && console.log(\"<< hdr \" + this.channelType() + \" type \" + msg.type + \" size \" + (msg.data && msg.data.byteLength));\n let rc = this.processCommonMessages(msg);\n if (!rc)\n {\n rc = this.processChannelMessage(msg);\n if (!rc)\n {\n this.logWarn(this.channelType() + \": Unknown message type \" + msg.type + \"!\");\n }\n }\n\n if (this.msgsUntilAck !== undefined && this.ackWindow)\n {\n this.msgsUntilAck--;\n if (this.msgsUntilAck <= 0)\n {\n this.msgsUntilAck = this.ackWindow;\n const ack = new SpiceMiniData();\n ack.type = SpiceMsgc.ACK;\n this.sendMsg(ack);\n DEBUG > 1 && console.log(this.type + \": sent ack\");\n }\n }\n\n const delta = Date.now() - start;\n if (DEBUG > 0 || delta > WebmConstants.GAP_DETECTION_THRESHOLD)\n {\n console.log(\"delta \" + this.channelType() + \":\" + msg.type + \" \" + delta);\n }\n return rc;\n }\n\n // -----------------------------------------------------------------------\n // Channel-specific message processing (override in subclasses)\n // -----------------------------------------------------------------------\n\n /**\n * Process a channel-specific message. Subclasses should override\n * this method to handle their own message types.\n *\n * @param msg - The SPICE mini-data message to process\n * @returns true if the message was handled, false otherwise\n */\n protected processChannelMessage(msg: SpiceMiniData): boolean\n {\n this.logErr(this.channelType() + \": No message handlers for this channel; message \" + msg.type);\n return false;\n }\n\n // -----------------------------------------------------------------------\n // Channel type name (for debug logging)\n // -----------------------------------------------------------------------\n\n channelType(): string\n {\n switch (this.type)\n {\n case SpiceChannel.MAIN: return \"main\";\n case SpiceChannel.DISPLAY: return \"display\";\n case SpiceChannel.INPUTS: return \"inputs\";\n case SpiceChannel.CURSOR: return \"cursor\";\n case SpiceChannel.PLAYBACK: return \"playback\";\n case SpiceChannel.RECORD: return \"record\";\n case SpiceChannel.TUNNEL: return \"tunnel\";\n case SpiceChannel.SMARTCARD: return \"smartcard\";\n case SpiceChannel.USBREDIR: return \"usbredir\";\n case SpiceChannel.PORT: return \"port\";\n case SpiceChannel.WEBDAV: return \"webdav\";\n default: return \"unknown-\" + this.type;\n }\n }\n\n // -----------------------------------------------------------------------\n // Logging\n // -----------------------------------------------------------------------\n\n logInfo(...args: string[]): void\n {\n const msg = args.join(\" \");\n console.log(msg);\n if (this.messageId && typeof document !== \"undefined\")\n {\n const container = document.getElementById(this.messageId);\n if (container)\n {\n const p = document.createElement(\"p\");\n p.appendChild(document.createTextNode(msg));\n p.className += \"spice-message-info\";\n container.appendChild(p);\n }\n }\n }\n\n logWarn(...args: string[]): void\n {\n const msg = args.join(\" \");\n console.log(\"WARNING: \" + msg);\n if (this.messageId && typeof document !== \"undefined\")\n {\n const container = document.getElementById(this.messageId);\n if (container)\n {\n const p = document.createElement(\"p\");\n p.appendChild(document.createTextNode(msg));\n p.className += \"spice-message-warning\";\n container.appendChild(p);\n }\n }\n }\n\n logErr(...args: string[]): void\n {\n const msg = args.join(\" \");\n console.log(\"ERROR: \" + msg);\n if (this.messageId && typeof document !== \"undefined\")\n {\n const container = document.getElementById(this.messageId);\n if (container)\n {\n const p = document.createElement(\"p\");\n p.appendChild(document.createTextNode(msg));\n p.className += \"spice-message-error\";\n container.appendChild(p);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Known-unimplemented warning suppression\n // -----------------------------------------------------------------------\n\n knownUnimplemented(type: number, msg: string): void\n {\n if (!this.warnings[type] || DEBUG > 1)\n {\n let str = \"\";\n if (DEBUG <= 1)\n {\n str = \" [ further notices suppressed ]\";\n }\n this.logWarn(\"Unimplemented function \" + type + \"(\" + msg + \")\" + str);\n this.warnings[type] = true;\n }\n }\n\n // -----------------------------------------------------------------------\n // Error / success reporting\n // -----------------------------------------------------------------------\n\n reportError(e: Error): void\n {\n this.logErr(e.toString());\n if (this.onerror !== undefined)\n {\n this.onerror(e);\n }\n else\n {\n throw e;\n }\n }\n\n reportSuccess(m: string): void\n {\n if (this.onsuccess !== undefined)\n {\n this.onsuccess(m);\n }\n }\n\n // -----------------------------------------------------------------------\n // Cleanup / disconnect\n // -----------------------------------------------------------------------\n\n /**\n * Clean disconnect: close WebSocket, clear timers, detach wire reader.\n * Call this when the connection is being intentionally torn down.\n */\n cleanup(): void\n {\n if (this.timeout !== undefined)\n {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n }\n if (this.wireReader)\n {\n this.wireReader.cleanup();\n }\n if (this.ws)\n {\n this.state = ConnectionState.CLOSING;\n this.ws.close();\n }\n }\n\n // -----------------------------------------------------------------------\n // Connection timeout\n // -----------------------------------------------------------------------\n\n private handleTimeout(): void\n {\n const e = new Error(\"Connection timed out.\");\n this.reportError(e);\n }\n}\n\nexport { SpiceConn as default };\n","/*----------------------------------------------------------------------------\n** main.ts\n** TypeScript implementation of the SPICE main connection channel.\n** Converted from main.js using ES6 class syntax.\n**\n** US-015: Core session management — INIT, CHANNELS_LIST, MOUSE_MODE\n** message handling and sub-channel spawning.\n** US-016: VD agent communication — agent data dispatch, clipboard\n** sharing (grab/receive/send/request), file transfer\n** initiation and progress tracking, monitor resize.\n**--------------------------------------------------------------------------*/\n\nimport {\n SpiceMsgMain,\n SpiceMsgcMain,\n SpiceMouseMode,\n SpiceChannel,\n VD_AGENT_MAX_DATA_SIZE,\n VdAgentMsg,\n VdAgentCap,\n VdAgentFileXferStatus,\n VdAgentClipboard,\n} from './enums';\n\nimport {\n SpiceMiniData,\n SpiceMsgMainInit,\n SpiceMsgChannels,\n SpiceMsgMainMouseMode,\n SpiceMsgMainAgentData,\n SpiceMsgMainAgentTokens,\n SpiceMsgcMainMouseModeRequest,\n SpiceMsgcMainAgentStart,\n SpiceMsgcMainAgentData,\n VDAgentAnnounceCapabilities,\n VDAgentMonitorsConfig,\n VDAgentFileXferStatusMessage,\n VDAgentFileXferStartMessage,\n VDAgentFileXferDataMessage,\n SpiceMsgClipboardGrab,\n SpiceMsgClipboardReceive,\n SpiceMsgClipboardRequest,\n SpiceMsgClipboardSend,\n Serializable,\n} from './spicemsg';\n\nimport { SpiceConn, SpiceConnOptions, ConnectionState } from './spiceconn';\nimport { DEBUG } from '../utils/debug';\n\n// ---------------------------------------------------------------------------\n// File transfer task types\n// ---------------------------------------------------------------------------\n\n/**\n * State of an individual file transfer task.\n */\nexport const FileXferState = {\n PENDING: 'pending',\n TRANSFERRING: 'transferring',\n COMPLETED: 'completed',\n FAILED: 'failed',\n CANCELLED: 'cancelled',\n} as const;\n\nexport type FileXferStateValue = typeof FileXferState[keyof typeof FileXferState];\n\n/**\n * Represents a file transfer task managed by the main channel.\n * Tracks state, progress, and the file being transferred.\n */\nexport interface FileXferTask {\n /** Unique task ID assigned by the client */\n id: number;\n /** The File object being transferred */\n file: File;\n /** Current state of the transfer */\n state: FileXferStateValue;\n /** Whether the user has cancelled this transfer */\n cancelled: boolean;\n /** Byte offset for next read (used when re-queued after token exhaustion) */\n readBytes: number;\n}\n\n/**\n * Callback for file transfer progress events.\n */\nexport interface FileXferProgressCallback {\n (taskId: number, bytesTransferred: number, totalBytes: number, filename: string): void;\n}\n\n/**\n * Callback for file transfer completion events.\n */\nexport interface FileXferCompleteCallback {\n (taskId: number, filename: string, error?: string): void;\n}\n\n/**\n * Callback for clipboard events (text received from guest).\n */\nexport interface ClipboardCallback {\n (text: string): void;\n}\n\n// ---------------------------------------------------------------------------\n// Channel map — typed registry for spawned sub-channels\n// ---------------------------------------------------------------------------\n\n/**\n * Interface for sub-channel constructors.\n * Each sub-channel class must accept SpiceConnOptions and extend SpiceConn.\n */\nexport interface ChannelConstructor {\n new (options: SpiceConnOptions): SpiceConn;\n}\n\n/**\n * Typed map of spawned sub-channels, keyed by channel role.\n */\nexport interface ChannelMap {\n display: SpiceConn | undefined;\n inputs: SpiceInputsLike | undefined;\n cursor: SpiceConn | undefined;\n playback: SpiceConn | undefined;\n ports: SpiceConn[];\n extra: SpiceConn[];\n}\n\n/**\n * Minimal interface for an inputs channel that supports mouse mode.\n * Avoids importing the concrete SpiceInputsConn class to prevent\n * circular dependencies.\n */\nexport interface SpiceInputsLike extends SpiceConn {\n mouseMode: number;\n}\n\n// ---------------------------------------------------------------------------\n// Channel factory registry\n// ---------------------------------------------------------------------------\n\n/**\n * Registry of channel constructor factories.\n * Call `registerChannelFactory()` to register constructors for each\n * channel type. This avoids circular imports: the concrete channel\n * classes register themselves at module load time rather than being\n * imported directly by SpiceMainConn.\n */\nconst channelFactories = new Map<number, ChannelConstructor>();\n\n/**\n * Register a channel constructor for a given SPICE channel type.\n *\n * @param type - The SpiceChannel.* constant (e.g., SpiceChannel.DISPLAY)\n * @param ctor - The constructor function for that channel type\n */\nexport function registerChannelFactory(type: number, ctor: ChannelConstructor): void\n{\n channelFactories.set(type, ctor);\n}\n\n// ---------------------------------------------------------------------------\n// SpiceMainConn — master connection class\n// ---------------------------------------------------------------------------\n\n/**\n * The main SPICE connection channel. Handles session init, channel\n * list, mouse mode negotiation, and sub-channel spawning.\n *\n * Invocation: pass a SpiceConnOptions object with at least `uri` and\n * `password`. Optional: `screenId`, `dumpId`, `messageId`, `onerror`,\n * `onsuccess`, `onagent`.\n */\nexport class SpiceMainConn extends SpiceConn {\n // -- Session state --\n mainInit: SpiceMsgMainInit | undefined;\n mouseMode: number = 0;\n ourMmTime: number = 0;\n mmTime: number = 0;\n\n // -- Sub-channels --\n channels: ChannelMap = {\n display: undefined,\n inputs: undefined,\n cursor: undefined,\n playback: undefined,\n ports: [],\n extra: [],\n };\n\n // -- VD Agent state --\n agentConnected: boolean = false;\n agentTokens: number = 0;\n agentMsgQueue: SpiceMiniData[] = [];\n agentCaps: number[] = [0];\n\n // -- File transfer state --\n fileXferTasks: Record<number, FileXferTask> = {};\n fileXferTaskId: number = 0;\n fileXferReadQueue: FileXferTask[] = [];\n\n // -- File transfer callbacks --\n onFileXferProgress: FileXferProgressCallback | undefined;\n onFileXferComplete: FileXferCompleteCallback | undefined;\n\n // -- Clipboard callback --\n onClipboard: ClipboardCallback | undefined;\n\n constructor(options: SpiceConnOptions)\n {\n if (typeof WebSocket === \"undefined\")\n {\n throw new Error(\"WebSocket unavailable. You need to use a different browser.\");\n }\n\n super(options);\n }\n\n // -----------------------------------------------------------------------\n // Channel-specific message processing\n // -----------------------------------------------------------------------\n\n protected override processChannelMessage(msg: SpiceMiniData): boolean\n {\n if (msg.type === SpiceMsgMain.MIGRATE_BEGIN)\n {\n this.knownUnimplemented(msg.type, \"Main Migrate Begin\");\n return true;\n }\n\n if (msg.type === SpiceMsgMain.MIGRATE_CANCEL)\n {\n this.knownUnimplemented(msg.type, \"Main Migrate Cancel\");\n return true;\n }\n\n if (msg.type === SpiceMsgMain.INIT)\n {\n return this.handleInit(msg);\n }\n\n if (msg.type === SpiceMsgMain.MOUSE_MODE)\n {\n return this.handleMouseModeMsg(msg);\n }\n\n if (msg.type === SpiceMsgMain.MULTI_MEDIA_TIME)\n {\n this.knownUnimplemented(msg.type, \"Main Multi Media Time\");\n return true;\n }\n\n if (msg.type === SpiceMsgMain.CHANNELS_LIST)\n {\n return this.handleChannelsList(msg);\n }\n\n if (msg.type === SpiceMsgMain.AGENT_CONNECTED)\n {\n this.connectAgent();\n return true;\n }\n\n if (msg.type === SpiceMsgMain.AGENT_CONNECTED_TOKENS)\n {\n if (msg.data)\n {\n const connectedTokens = new SpiceMsgMainAgentTokens(msg.data);\n this.agentTokens = connectedTokens.numTokens;\n }\n this.connectAgent();\n return true;\n }\n\n if (msg.type === SpiceMsgMain.AGENT_TOKEN)\n {\n return this.handleAgentToken(msg);\n }\n\n if (msg.type === SpiceMsgMain.AGENT_DISCONNECTED)\n {\n this.agentConnected = false;\n return true;\n }\n\n if (msg.type === SpiceMsgMain.AGENT_DATA)\n {\n return this.handleAgentData(msg);\n }\n\n if (msg.type === SpiceMsgMain.MIGRATE_SWITCH_HOST)\n {\n this.knownUnimplemented(msg.type, \"Main Migrate Switch Host\");\n return true;\n }\n\n if (msg.type === SpiceMsgMain.MIGRATE_END)\n {\n this.knownUnimplemented(msg.type, \"Main Migrate End\");\n return true;\n }\n\n if (msg.type === SpiceMsgMain.NAME)\n {\n this.knownUnimplemented(msg.type, \"Main Name\");\n return true;\n }\n\n if (msg.type === SpiceMsgMain.UUID)\n {\n this.knownUnimplemented(msg.type, \"Main UUID\");\n return true;\n }\n\n if (msg.type === SpiceMsgMain.MIGRATE_BEGIN_SEAMLESS)\n {\n this.knownUnimplemented(msg.type, \"Main Migrate Begin Seamless\");\n return true;\n }\n\n if (msg.type === SpiceMsgMain.MIGRATE_DST_SEAMLESS_ACK)\n {\n this.knownUnimplemented(msg.type, \"Main Migrate Dst Seamless ACK\");\n return true;\n }\n\n if (msg.type === SpiceMsgMain.MIGRATE_DST_SEAMLESS_NACK)\n {\n this.knownUnimplemented(msg.type, \"Main Migrate Dst Seamless NACK\");\n return true;\n }\n\n return false;\n }\n\n // -----------------------------------------------------------------------\n // INIT message handling\n // -----------------------------------------------------------------------\n\n private handleInit(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logWarn(\"INIT message with no data\");\n return true;\n }\n\n this.logInfo(\"Connected to \" + this.ws.url);\n this.reportSuccess(\"Connected\");\n\n this.mainInit = new SpiceMsgMainInit(msg.data);\n this.connectionId = this.mainInit.sessionId;\n this.agentTokens = this.mainInit.agentTokens;\n\n if (DEBUG > 0)\n {\n this.logInfo(\n \"session id \" + this.mainInit.sessionId +\n \" ; display_channels_hint \" + this.mainInit.displayChannelsHint +\n \" ; supported_mouse_modes \" + this.mainInit.supportedMouseModes +\n \" ; current_mouse_mode \" + this.mainInit.currentMouseMode +\n \" ; agent_connected \" + this.mainInit.agentConnected +\n \" ; agent_tokens \" + this.mainInit.agentTokens +\n \" ; multi_media_time \" + this.mainInit.multiMediaTime +\n \" ; ram_hint \" + this.mainInit.ramHint\n );\n }\n\n this.ourMmTime = Date.now();\n this.mmTime = this.mainInit.multiMediaTime;\n\n this.handleMouseMode(\n this.mainInit.currentMouseMode,\n this.mainInit.supportedMouseModes\n );\n\n if (this.mainInit.agentConnected)\n {\n this.connectAgent();\n }\n\n // Request the channels list\n const attach = new SpiceMiniData();\n attach.type = SpiceMsgcMain.ATTACH_CHANNELS;\n attach.size = attach.bufferSize();\n this.sendMsg(attach);\n\n return true;\n }\n\n // -----------------------------------------------------------------------\n // CHANNELS_LIST message handling — sub-channel spawning\n // -----------------------------------------------------------------------\n\n private handleChannelsList(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logWarn(\"CHANNELS_LIST message with no data\");\n return true;\n }\n\n DEBUG > 0 && console.log(\"channels\");\n const chans = new SpiceMsgChannels(msg.data);\n\n for (let i = 0; i < chans.channels.length; i++)\n {\n const chanInfo = chans.channels[i]!;\n const connOpts: SpiceConnOptions = {\n uri: this.ws.url,\n parent: this,\n connectionId: this.connectionId,\n type: chanInfo.type,\n chanId: chanInfo.id,\n };\n\n if (chanInfo.type === SpiceChannel.DISPLAY)\n {\n if (chanInfo.id === 0)\n {\n this.channels.display = this.createChannel(\n SpiceChannel.DISPLAY,\n connOpts\n );\n }\n else\n {\n this.logWarn(\n \"The spice-html5 client does not handle multiple heads.\"\n );\n }\n }\n else if (chanInfo.type === SpiceChannel.INPUTS)\n {\n const inputsConn = this.createChannel(\n SpiceChannel.INPUTS,\n connOpts\n );\n if (inputsConn && 'mouseMode' in inputsConn)\n {\n this.channels.inputs = inputsConn as SpiceInputsLike;\n this.channels.inputs.mouseMode = this.mouseMode;\n }\n else if (inputsConn)\n {\n // Fallback: store as generic channel\n this.channels.inputs = inputsConn as SpiceInputsLike;\n }\n }\n else if (chanInfo.type === SpiceChannel.CURSOR)\n {\n this.channels.cursor = this.createChannel(\n SpiceChannel.CURSOR,\n connOpts\n );\n }\n else if (chanInfo.type === SpiceChannel.PLAYBACK)\n {\n this.channels.playback = this.createChannel(\n SpiceChannel.PLAYBACK,\n connOpts\n );\n }\n else if (chanInfo.type === SpiceChannel.PORT)\n {\n const port = this.createChannel(\n SpiceChannel.PORT,\n connOpts\n );\n if (port)\n {\n this.channels.ports.push(port);\n }\n }\n else\n {\n // Unknown channel type — create a basic SpiceConn\n const extra = new SpiceConn(connOpts);\n this.channels.extra.push(extra);\n this.logErr(\"Channel type \" + extra.channelType() + \" not implemented\");\n }\n }\n\n return true;\n }\n\n /**\n * Create a sub-channel using the registered factory, or fall back\n * to a generic SpiceConn if no factory is registered.\n */\n private createChannel(\n type: number,\n options: SpiceConnOptions\n ): SpiceConn | undefined\n {\n const factory = channelFactories.get(type);\n if (factory)\n {\n return new factory(options);\n }\n\n // No factory registered — create a generic connection and warn\n this.logWarn(\n \"No factory registered for channel type \" + type +\n \"; creating generic SpiceConn\"\n );\n return new SpiceConn(options);\n }\n\n // -----------------------------------------------------------------------\n // MOUSE_MODE message handling\n // -----------------------------------------------------------------------\n\n private handleMouseModeMsg(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logWarn(\"MOUSE_MODE message with no data\");\n return true;\n }\n\n const mode = new SpiceMsgMainMouseMode(msg.data);\n DEBUG > 0 && this.logInfo(\n \"Mouse supported modes \" + mode.supportedModes +\n \"; current \" + mode.currentMode\n );\n this.handleMouseMode(mode.currentMode, mode.supportedModes);\n return true;\n }\n\n /**\n * Handle mouse mode: prefer client mode, update inputs channel.\n */\n private handleMouseMode(current: number, supported: number): void\n {\n this.mouseMode = current;\n\n if (current !== SpiceMouseMode.CLIENT &&\n (supported & SpiceMouseMode.CLIENT))\n {\n const modeRequest = new SpiceMsgcMainMouseModeRequest(\n SpiceMouseMode.CLIENT\n );\n const mr = new SpiceMiniData();\n mr.buildMsg(SpiceMsgcMain.MOUSE_MODE_REQUEST, modeRequest);\n this.sendMsg(mr);\n }\n\n if (this.channels.inputs)\n {\n this.channels.inputs.mouseMode = current;\n }\n }\n\n // -----------------------------------------------------------------------\n // Agent connection — stub for US-015; full impl in US-016\n // -----------------------------------------------------------------------\n\n /**\n * Connect to the VD agent. Sends AGENT_START and announces\n * capabilities. Calls the onagent callback if provided.\n */\n connectAgent(): void\n {\n this.agentConnected = true;\n\n const agentStart = new SpiceMsgcMainAgentStart(~0 >>> 0);\n const mr = new SpiceMiniData();\n mr.buildMsg(SpiceMsgcMain.AGENT_START, agentStart);\n this.sendMsg(mr);\n\n this.announceAgentCapabilities(1);\n\n if (this.onagent !== undefined)\n {\n this.onagent();\n }\n }\n\n /**\n * Announce agent capabilities to the server.\n */\n announceAgentCapabilities(request: number): void\n {\n const caps = new VDAgentAnnounceCapabilities(\n request,\n (1 << VdAgentCap.MOUSE_STATE) |\n (1 << VdAgentCap.MONITORS_CONFIG) |\n (1 << VdAgentCap.REPLY) |\n (1 << VdAgentCap.CLIPBOARD_SELECTION) |\n (1 << VdAgentCap.CLIPBOARD_BY_DEMAND)\n );\n this.sendAgentMessage(VdAgentMsg.ANNOUNCE_CAPABILITIES, caps);\n }\n\n // -----------------------------------------------------------------------\n // Agent message sending\n // -----------------------------------------------------------------------\n\n /**\n * Queue a message for delivery to the VD agent, respecting token flow\n * control.\n */\n sendAgentMessageQueue(message?: SpiceMiniData): void\n {\n if (!this.agentConnected)\n {\n return;\n }\n\n if (message)\n {\n this.agentMsgQueue.push(message);\n }\n\n while (this.agentTokens > 0 && this.agentMsgQueue.length > 0)\n {\n const mr = this.agentMsgQueue.shift();\n if (mr)\n {\n this.sendMsg(mr);\n this.agentTokens--;\n }\n }\n }\n\n /**\n * Send a typed message to the VD agent, splitting into chunks if\n * the message exceeds the maximum agent data size.\n */\n sendAgentMessage(type: number, message: Serializable): void\n {\n const agentData = new SpiceMsgcMainAgentData(type, message);\n const maxsize = VD_AGENT_MAX_DATA_SIZE -\n new SpiceMiniData().bufferSize();\n const data = new ArrayBuffer(agentData.bufferSize());\n agentData.toBuffer(data);\n\n let sb = 0;\n while (sb < agentData.bufferSize())\n {\n const eb = Math.min(sb + maxsize, agentData.bufferSize());\n const mr = new SpiceMiniData();\n mr.type = SpiceMsgcMain.AGENT_DATA;\n mr.size = eb - sb;\n mr.data = data.slice(sb, eb);\n this.sendAgentMessageQueue(mr);\n sb = eb;\n }\n }\n\n // -----------------------------------------------------------------------\n // Agent token handling\n // -----------------------------------------------------------------------\n\n private handleAgentToken(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logWarn(\"AGENT_TOKEN message with no data\");\n return true;\n }\n\n const tokens = new SpiceMsgMainAgentTokens(msg.data);\n this.agentTokens += tokens.numTokens;\n this.sendAgentMessageQueue();\n\n // Drain the file transfer read queue while we have tokens\n let remainingTokens = this.agentTokens;\n while (remainingTokens > 0 && this.fileXferReadQueue.length > 0)\n {\n const xferTask = this.fileXferReadQueue.shift();\n if (xferTask)\n {\n this.fileXferRead(xferTask, xferTask.readBytes);\n remainingTokens--;\n }\n }\n\n return true;\n }\n\n // -----------------------------------------------------------------------\n // Agent data handling — full dispatch for US-016\n // -----------------------------------------------------------------------\n\n /**\n * Handle incoming VD agent data. Dispatches to clipboard and file\n * transfer handlers based on agent message type.\n */\n private handleAgentData(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logWarn(\"AGENT_DATA message with no data\");\n return true;\n }\n\n const agentData = new SpiceMsgMainAgentData(msg.data);\n\n if (agentData.type === VdAgentMsg.ANNOUNCE_CAPABILITIES)\n {\n if (agentData.data)\n {\n const agentCapsMsg = new VDAgentAnnounceCapabilities(\n agentData.data\n );\n this.agentCaps = [agentCapsMsg.caps];\n if (agentCapsMsg.request)\n {\n this.announceAgentCapabilities(0);\n }\n }\n return true;\n }\n\n if (agentData.type === VdAgentMsg.FILE_XFER_STATUS)\n {\n if (agentData.data)\n {\n this.handleFileXferStatus(\n new VDAgentFileXferStatusMessage(agentData.data)\n );\n }\n return true;\n }\n\n if (agentData.type === VdAgentMsg.CLIPBOARD_GRAB)\n {\n this.handleClipboardGrab();\n return true;\n }\n\n if (agentData.type === VdAgentMsg.CLIPBOARD)\n {\n this.handleClipboardReceive(agentData);\n return true;\n }\n\n if (agentData.type === VdAgentMsg.CLIPBOARD_REQUEST)\n {\n this.handleClipboardSend();\n return true;\n }\n\n if (agentData.type === VdAgentMsg.CLIPBOARD_RELEASE)\n {\n // Currently we don't need to do anything when the agent\n // releases the clipboard\n return true;\n }\n\n return false;\n }\n\n // -----------------------------------------------------------------------\n // File transfer — initiation and progress tracking\n // -----------------------------------------------------------------------\n\n /**\n * Start a file transfer to the guest. Creates a tracking task and\n * sends the VD_AGENT_FILE_XFER_START message to the agent.\n */\n fileXferStart(file: File): void\n {\n const taskId = this.fileXferTaskId++;\n const task: FileXferTask = {\n id: taskId,\n file: file,\n state: FileXferState.PENDING,\n cancelled: false,\n readBytes: 0,\n };\n this.fileXferTasks[taskId] = task;\n\n const xferStart = new VDAgentFileXferStartMessage(\n taskId,\n file.name,\n file.size\n );\n this.sendAgentMessage(VdAgentMsg.FILE_XFER_START, xferStart);\n }\n\n /**\n * Handle a file transfer status message from the agent.\n * Dispatches based on status result code.\n */\n private handleFileXferStatus(\n fileXferStatus: VDAgentFileXferStatusMessage\n ): void\n {\n const xferTask = this.fileXferTasks[fileXferStatus.id];\n if (!xferTask)\n {\n return;\n }\n\n let xferError: string | undefined;\n\n switch (fileXferStatus.result)\n {\n case VdAgentFileXferStatus.CAN_SEND_DATA:\n xferTask.state = FileXferState.TRANSFERRING;\n this.fileXferRead(xferTask);\n return;\n case VdAgentFileXferStatus.CANCELLED:\n xferError = \"transfer is cancelled by spice agent\";\n xferTask.state = FileXferState.CANCELLED;\n break;\n case VdAgentFileXferStatus.ERROR:\n xferError = \"some errors occurred in the spice agent\";\n xferTask.state = FileXferState.FAILED;\n break;\n case VdAgentFileXferStatus.SUCCESS:\n xferTask.state = FileXferState.COMPLETED;\n break;\n default:\n xferError = \"unhandled status type: \" + fileXferStatus.result;\n xferTask.state = FileXferState.FAILED;\n break;\n }\n\n this.fileXferCompleted(xferTask, xferError);\n }\n\n /**\n * Read a chunk of file data and send it to the agent.\n * If no agent tokens are available, queues the task for later.\n */\n private fileXferRead(fileXferTask: FileXferTask, startByte?: number): void\n {\n const FILE_XFER_CHUNK_SIZE = 32 * VD_AGENT_MAX_DATA_SIZE;\n\n if (!fileXferTask ||\n !this.fileXferTasks[fileXferTask.id] ||\n (startByte !== undefined && startByte > 0 &&\n startByte === fileXferTask.file.size))\n {\n return;\n }\n\n if (fileXferTask.cancelled)\n {\n const xferStatus = new VDAgentFileXferStatusMessage(\n fileXferTask.id,\n VdAgentFileXferStatus.CANCELLED\n );\n this.sendAgentMessage(\n VdAgentMsg.FILE_XFER_STATUS,\n xferStatus\n );\n fileXferTask.state = FileXferState.CANCELLED;\n delete this.fileXferTasks[fileXferTask.id];\n return;\n }\n\n const sb = startByte ?? 0;\n const eb = Math.min(\n sb + FILE_XFER_CHUNK_SIZE,\n fileXferTask.file.size\n );\n\n if (!this.agentTokens)\n {\n fileXferTask.readBytes = sb;\n this.fileXferReadQueue.push(fileXferTask);\n return;\n }\n\n const reader = new FileReader();\n reader.onload = (e: ProgressEvent<FileReader>): void =>\n {\n const result = e.target?.result;\n if (!(result instanceof ArrayBuffer))\n {\n return;\n }\n\n const xferData = new VDAgentFileXferDataMessage(\n fileXferTask.id,\n result.byteLength,\n result\n );\n this.sendAgentMessage(\n VdAgentMsg.FILE_XFER_DATA,\n xferData\n );\n this.fileXferRead(fileXferTask, eb);\n\n // Notify progress callback\n if (this.onFileXferProgress)\n {\n this.onFileXferProgress(\n fileXferTask.id,\n eb,\n fileXferTask.file.size,\n fileXferTask.file.name\n );\n }\n };\n\n const slice = fileXferTask.file.slice(sb, eb);\n reader.readAsArrayBuffer(slice);\n }\n\n /**\n * Mark a file transfer as completed (success or failure) and\n * clean up the task.\n */\n private fileXferCompleted(\n fileXferTask: FileXferTask,\n error?: string\n ): void\n {\n if (error)\n {\n this.logErr(error);\n fileXferTask.state = FileXferState.FAILED;\n }\n else\n {\n this.logInfo(\n \"transfer of '\" + fileXferTask.file.name +\n \"' was successful\"\n );\n fileXferTask.state = FileXferState.COMPLETED;\n }\n\n // Notify completion callback\n if (this.onFileXferComplete)\n {\n this.onFileXferComplete(\n fileXferTask.id,\n fileXferTask.file.name,\n error\n );\n }\n\n delete this.fileXferTasks[fileXferTask.id];\n }\n\n /**\n * Cancel an in-progress file transfer by task ID.\n * The transfer will be cancelled on the next read attempt.\n */\n cancelFileXfer(taskId: number): void\n {\n const task = this.fileXferTasks[taskId];\n if (task)\n {\n task.cancelled = true;\n task.state = FileXferState.CANCELLED;\n }\n }\n\n // -----------------------------------------------------------------------\n // Clipboard handling\n // -----------------------------------------------------------------------\n\n /**\n * Handle clipboard grab from the agent. The agent is indicating\n * that it has clipboard data; we respond by requesting it.\n */\n private handleClipboardGrab(): void\n {\n DEBUG > 1 && console.log(\"handling clipboard grab from agent\");\n\n const clipboardType = VdAgentClipboard.UTF8_TEXT;\n const clipboardRequest = new SpiceMsgClipboardRequest(\n clipboardType,\n this.agentCaps\n );\n this.sendAgentMessage(\n VdAgentMsg.CLIPBOARD_REQUEST,\n clipboardRequest\n );\n }\n\n /**\n * Handle clipboard data received from the agent.\n * Writes UTF-8 text to the browser clipboard if available.\n */\n private handleClipboardReceive(\n agentData: SpiceMsgMainAgentData\n ): void\n {\n DEBUG > 1 && console.log(\"received clipboard data from agent\");\n\n if (!agentData.data)\n {\n return;\n }\n\n const receivedClipboard = new SpiceMsgClipboardReceive(\n { data: agentData.data },\n this.agentCaps\n );\n\n if (receivedClipboard.type === VdAgentClipboard.UTF8_TEXT)\n {\n const text = receivedClipboard.getText();\n\n // Notify clipboard callback if registered\n if (this.onClipboard)\n {\n this.onClipboard(text);\n }\n\n // Write to browser clipboard if available\n if (typeof navigator !== 'undefined' &&\n navigator.clipboard &&\n navigator.clipboard.writeText)\n {\n navigator.clipboard.writeText(text).catch(\n (err: unknown) =>\n {\n console.warn(\n \"Failed to write to navigator clipboard:\",\n err\n );\n }\n );\n }\n }\n else\n {\n console.log(\n \"Unsupported clipboard type:\",\n receivedClipboard.type\n );\n }\n }\n\n /**\n * Handle clipboard data request from the agent. The agent wants\n * the browser's clipboard data; we read it and send it back.\n */\n private handleClipboardSend(): void\n {\n DEBUG > 1 && console.log(\"sending clipboard data to agent\");\n\n if (typeof navigator !== 'undefined' &&\n navigator.clipboard &&\n navigator.clipboard.readText)\n {\n navigator.clipboard.readText().then(\n (text: string) =>\n {\n const clipboardType = VdAgentClipboard.UTF8_TEXT;\n const clipboardMsg = new SpiceMsgClipboardSend(\n clipboardType,\n text,\n this.agentCaps\n );\n this.sendAgentMessage(\n VdAgentMsg.CLIPBOARD,\n clipboardMsg\n );\n }\n ).catch(\n (err: unknown) =>\n {\n console.log(\"Failed to read clipboard:\", err);\n }\n );\n }\n }\n\n /**\n * Send a clipboard grab to the agent. Tells the agent that the\n * browser has clipboard data and the agent should request it.\n */\n sendClipboardGrab(): void\n {\n DEBUG > 1 && console.log(\n \"browser is asking agent to grab clipboard\"\n );\n\n const clipboardType = VdAgentClipboard.UTF8_TEXT;\n const grabMessage = new SpiceMsgClipboardGrab(\n clipboardType,\n this.agentCaps\n );\n this.sendAgentMessage(\n VdAgentMsg.CLIPBOARD_GRAB,\n grabMessage\n );\n }\n\n // -----------------------------------------------------------------------\n // Resize window — delegates to VD agent\n // -----------------------------------------------------------------------\n\n /**\n * Send a monitor configuration message to resize the guest display.\n */\n resizeWindow(\n flags: number,\n width: number,\n height: number,\n depth: number,\n x: number,\n y: number\n ): void\n {\n const monitorsConfig = new VDAgentMonitorsConfig(\n flags,\n width,\n height,\n depth,\n x,\n y\n );\n this.sendAgentMessage(VdAgentMsg.MONITORS_CONFIG, monitorsConfig);\n }\n\n // -----------------------------------------------------------------------\n // Relative time\n // -----------------------------------------------------------------------\n\n /**\n * Shift current time to attempt to get a time matching that of the\n * server.\n */\n relativeNow(): number\n {\n return (Date.now() - this.ourMmTime) + this.mmTime;\n }\n\n // -----------------------------------------------------------------------\n // Stop / cleanup\n // -----------------------------------------------------------------------\n\n /**\n * Stop the main connection and all sub-channels.\n */\n stop(): void\n {\n this.state = ConnectionState.CLOSING;\n\n if (this.channels.inputs)\n {\n this.channels.inputs.cleanup();\n this.channels.inputs = undefined;\n }\n\n if (this.channels.cursor)\n {\n this.channels.cursor.cleanup();\n this.channels.cursor = undefined;\n }\n\n if (this.channels.display)\n {\n this.channels.display.cleanup();\n this.channels.display = undefined;\n }\n\n if (this.channels.playback)\n {\n this.channels.playback.cleanup();\n this.channels.playback = undefined;\n }\n\n for (const port of this.channels.ports)\n {\n port.cleanup();\n }\n this.channels.ports = [];\n\n this.cleanup();\n\n for (const extra of this.channels.extra)\n {\n extra.cleanup();\n }\n this.channels.extra = [];\n }\n}\n\nexport { SpiceMainConn as default };\n","/*----------------------------------------------------------------------------\n** filexfer.ts\n** File transfer UI helpers and drag-and-drop event handlers.\n**\n** Provides:\n** - SpiceFileXferTask: progress bar UI for file transfers\n** - handleFileDragover / handleFileDrop: drag-and-drop handlers\n**\n** The actual file transfer state machine and chunking logic lives in\n** main.ts (SpiceMainConn). This module provides the UI layer that the\n** React component or vanilla HTML integration can use.\n**\n** Converted from filexfer.js to TypeScript with full type safety.\n**--------------------------------------------------------------------------*/\n\n// ---------------------------------------------------------------------------\n// Progress bar container ID used in the original spice.html\n// ---------------------------------------------------------------------------\n\nconst XFER_AREA_ID = 'spice-xfer-area';\n\n// ---------------------------------------------------------------------------\n// SpiceFileXferTask — progress bar UI for a single file transfer\n// ---------------------------------------------------------------------------\n\n/**\n * Manages the progress bar DOM element for a single file transfer.\n *\n * The caller creates an instance with a task ID and File, then calls\n * `createProgressbar()` to inject the DOM elements, `updateProgressbar()`\n * as data is transferred, and `removeProgressbar()` when done.\n */\nexport class SpiceFileXferTask\n{\n /** Unique task ID (matches main channel's fileXferTasks key). */\n readonly id: number;\n\n /** The file being transferred. */\n readonly file: File;\n\n /** Whether the user has cancelled via the cancel button. */\n cancelled = false;\n\n /** Container div holding the progress bar and cancel button. */\n private progressbarContainer: HTMLDivElement | undefined = undefined;\n\n /** The <progress> element. */\n private progressbar: HTMLProgressElement | undefined = undefined;\n\n constructor(id: number, file: File)\n {\n this.id = id;\n this.file = file;\n }\n\n /**\n * Create and append the progress bar UI to the transfer area.\n *\n * Looks for an element with id `spice-xfer-area` in the document.\n * If not found, the progress bar is not created.\n *\n * @param xferAreaId - Optional custom container element ID\n * (defaults to 'spice-xfer-area')\n */\n createProgressbar(xferAreaId: string = XFER_AREA_ID): void\n {\n if (typeof document === 'undefined')\n {\n return;\n }\n\n const xferArea = document.getElementById(xferAreaId);\n if (!xferArea)\n {\n return;\n }\n\n const cancel = document.createElement(\"input\");\n this.progressbarContainer = document.createElement(\"div\");\n this.progressbar = document.createElement(\"progress\");\n\n cancel.type = 'button';\n cancel.value = 'Cancel';\n cancel.style.cssFloat = 'right';\n cancel.onclick = (): void =>\n {\n this.cancelled = true;\n this.removeProgressbar();\n };\n\n this.progressbar.setAttribute('max', String(this.file.size));\n this.progressbar.setAttribute('value', '0');\n this.progressbar.style.width = '100%';\n this.progressbar.style.margin = '4px auto';\n this.progressbar.style.display = 'inline-block';\n\n this.progressbarContainer.style.width = '90%';\n this.progressbarContainer.style.margin = 'auto';\n this.progressbarContainer.style.padding = '4px';\n this.progressbarContainer.textContent = this.file.name;\n\n this.progressbarContainer.appendChild(cancel);\n this.progressbarContainer.appendChild(this.progressbar);\n\n xferArea.appendChild(this.progressbarContainer);\n }\n\n /**\n * Update the progress bar value.\n *\n * @param value - Bytes transferred so far\n */\n updateProgressbar(value: number): void\n {\n if (this.progressbar)\n {\n this.progressbar.setAttribute('value', String(value));\n }\n }\n\n /**\n * Remove the progress bar from the DOM.\n */\n removeProgressbar(): void\n {\n if (this.progressbarContainer && this.progressbarContainer.parentNode)\n {\n this.progressbarContainer.parentNode.removeChild(this.progressbarContainer);\n }\n this.progressbarContainer = undefined;\n this.progressbar = undefined;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Drag-and-drop event handlers\n// ---------------------------------------------------------------------------\n\n/**\n * Interface for the connection object that supports file transfer.\n * Avoids importing SpiceMainConn directly to prevent circular deps.\n */\nexport interface FileXferConnection\n{\n fileXferStart(file: File): void;\n}\n\n/**\n * Handle dragover events on the drop target.\n * Prevents default to allow dropping and sets the drop effect to 'copy'.\n */\nexport function handleFileDragover(e: DragEvent): void\n{\n e.stopPropagation();\n e.preventDefault();\n if (e.dataTransfer)\n {\n e.dataTransfer.dropEffect = 'copy';\n }\n}\n\n/**\n * Handle drop events on the drop target.\n * Initiates a file transfer for each dropped file (skipping directories).\n *\n * @param e - The drop event\n * @param connection - The SPICE main connection to start transfers on\n */\nexport function handleFileDrop(e: DragEvent, connection: FileXferConnection): void\n{\n e.stopPropagation();\n e.preventDefault();\n\n if (!e.dataTransfer)\n {\n return;\n }\n\n const files = e.dataTransfer.files;\n for (let i = files.length - 1; i >= 0; i--)\n {\n const file = files[i];\n if (file && file.type) // skip directories (they have no type)\n {\n connection.fileXferStart(file);\n }\n }\n}\n","/*----------------------------------------------------------------------------\n** resize.ts\n** Window resize logic for dynamic screen resizing via VD agent.\n**\n** Provides debounced resize handling that:\n** - Computes available width/height from the container element\n** - Rounds dimensions to multiples of 8 (Xorg requirement)\n** - Sends monitor configuration via the main channel's resizeWindow()\n**\n** The original resize.js used a global `window.spice_connection` and\n** direct DOM queries. This TypeScript version accepts explicit\n** connection and element references, and supports both manual\n** resize handling and ResizeObserver-based monitoring.\n**\n** Converted from resize.js to TypeScript with full type safety.\n**--------------------------------------------------------------------------*/\n\n// ---------------------------------------------------------------------------\n// Interface for the connection object that supports resize\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal interface for a connection that supports window resize.\n * Avoids importing SpiceMainConn directly to prevent circular deps.\n */\nexport interface ResizableConnection\n{\n /** Screen element ID */\n screenId: string | undefined;\n /** Message element ID */\n messageId: string | undefined;\n /** Send a resize request to the guest */\n resizeWindow(flags: number, width: number, height: number, depth: number, x: number, y: number): void;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Debounce delay in ms before sending resize to the server. */\nconst RESIZE_DEBOUNCE_MS = 200;\n\n/** Xorg requires dimensions be multiples of 8. */\nconst DIMENSION_ALIGNMENT = 8;\n\n/** Bottom margin in pixels. */\nconst BOTTOM_MARGIN = 20;\n\n// ---------------------------------------------------------------------------\n// Resize helper — computes dimensions and sends resize request\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the available screen dimensions and send a resize request.\n *\n * Width is taken from the screen element's clientWidth.\n * Height is computed from the window inner height, minus the message\n * area and a bottom margin, then rounded down to a multiple of 8.\n *\n * @param connection - The SPICE main connection\n */\nexport function resizeHelper(connection: ResizableConnection): void\n{\n if (typeof document === 'undefined' || typeof window === 'undefined')\n {\n return;\n }\n\n if (!connection.screenId)\n {\n return;\n }\n\n const screenEl = document.getElementById(connection.screenId);\n if (!screenEl)\n {\n return;\n }\n\n let w = screenEl.clientWidth;\n let h = window.innerHeight - BOTTOM_MARGIN;\n\n // Adjust for the message/debug console area\n if (connection.messageId)\n {\n const m = document.getElementById(connection.messageId);\n if (m !== null)\n {\n if (window.getComputedStyle(m).getPropertyValue(\"display\") === 'none')\n {\n // Console is hidden; subtract its CSS height\n const mh = parseInt(\n window.getComputedStyle(m).getPropertyValue(\"height\"),\n 10\n );\n if (!isNaN(mh))\n {\n h = h - mh;\n }\n }\n else\n {\n // Console is visible; subtract its actual height\n h = h - m.offsetHeight - m.clientHeight;\n }\n }\n }\n\n // Xorg requires dimensions be a multiple of 8; round down\n if (h % DIMENSION_ALIGNMENT > 0)\n {\n h -= (h % DIMENSION_ALIGNMENT);\n }\n\n if (w % DIMENSION_ALIGNMENT > 0)\n {\n w -= (w % DIMENSION_ALIGNMENT);\n }\n\n connection.resizeWindow(0, w, h, 32, 0, 0);\n}\n\n// ---------------------------------------------------------------------------\n// Debounced resize handler\n// ---------------------------------------------------------------------------\n\n/**\n * Manages debounced resize events for a SPICE connection.\n *\n * Call `handleResize()` on each resize event; it debounces to avoid\n * flooding the server with resize requests. Call `cleanup()` to\n * cancel any pending timer.\n */\nexport class SpiceResizeHandler\n{\n private connection: ResizableConnection;\n private resizeTimer: ReturnType<typeof setTimeout> | undefined = undefined;\n private debounceMs: number;\n\n /**\n * @param connection - The SPICE main connection\n * @param debounceMs - Debounce delay in ms (default 200)\n */\n constructor(connection: ResizableConnection, debounceMs: number = RESIZE_DEBOUNCE_MS)\n {\n this.connection = connection;\n this.debounceMs = debounceMs;\n }\n\n /**\n * Handle a resize event. Debounces: cancels any pending timer\n * and starts a new one.\n */\n handleResize = (): void =>\n {\n if (this.resizeTimer !== undefined)\n {\n clearTimeout(this.resizeTimer);\n this.resizeTimer = undefined;\n }\n\n this.resizeTimer = setTimeout(() =>\n {\n resizeHelper(this.connection);\n this.resizeTimer = undefined;\n }, this.debounceMs);\n };\n\n /**\n * Cancel any pending resize timer.\n */\n cleanup(): void\n {\n if (this.resizeTimer !== undefined)\n {\n clearTimeout(this.resizeTimer);\n this.resizeTimer = undefined;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// ResizeObserver-based container monitoring\n// ---------------------------------------------------------------------------\n\n/**\n * Monitor a container element for size changes using ResizeObserver.\n *\n * Returns a cleanup function that disconnects the observer.\n * Falls back gracefully if ResizeObserver is unavailable (SSR or old browsers).\n *\n * @param container - The element to observe\n * @param connection - The SPICE main connection\n * @param debounceMs - Debounce delay in ms (default 200)\n * @returns A cleanup function, or undefined if ResizeObserver is unavailable\n */\nexport function observeContainerResize(\n container: HTMLElement,\n connection: ResizableConnection,\n debounceMs: number = RESIZE_DEBOUNCE_MS\n): (() => void) | undefined\n{\n if (typeof ResizeObserver === 'undefined')\n {\n return undefined;\n }\n\n const handler = new SpiceResizeHandler(connection, debounceMs);\n\n const observer = new ResizeObserver((): void =>\n {\n handler.handleResize();\n });\n\n observer.observe(container);\n\n return (): void =>\n {\n observer.disconnect();\n handler.cleanup();\n };\n}\n","\"use strict\";\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\n\nimport { SpiceMainConn } from '../protocol/main';\nimport { SpiceDisplayConn } from '../protocol/display';\nimport { SpiceInputsConn } from '../protocol/inputs';\nimport { handleFileDragover, handleFileDrop } from '../protocol/filexfer';\nimport { resizeHelper, observeContainerResize } from '../protocol/resize';\n\nimport type { SpiceConnOptions } from '../protocol/spiceconn';\nimport type {\n ClipboardCallback,\n FileXferProgressCallback,\n FileXferCompleteCallback,\n} from '../protocol/main';\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\n/** Connection configuration props. */\nexport interface SpiceConnectionProps {\n /** WebSocket host (e.g. \"localhost\"). */\n host: string;\n /** WebSocket port number. */\n port: number;\n /** SPICE password for ticket authentication. */\n password?: string;\n /** Authentication token (set as a cookie for nova-spiceproxy). */\n token?: string;\n /** WebSocket protocol scheme (\"ws\" or \"wss\"). Defaults to \"ws\". */\n scheme?: \"ws\" | \"wss\";\n /** WebSocket path (e.g. \"websockify\"). */\n path?: string;\n}\n\n/** Display behaviour props. */\nexport interface SpiceDisplayOptions {\n /** Whether to scale the display to fit the container. */\n scale?: boolean;\n /** Whether to enable dynamic guest resizing to match the container. */\n resize?: boolean;\n /** Whether to resize the guest to fit the container div. */\n fitContainer?: boolean;\n}\n\n/** Feature-toggle props. */\nexport interface SpiceFeatureToggles {\n /** Enable keyboard input forwarding. Default: true. */\n enableKeyboard?: boolean;\n /** Enable mouse input forwarding. Default: true. */\n enableMouse?: boolean;\n /** Enable clipboard sharing. Default: true. */\n enableClipboard?: boolean;\n /** Enable file transfer (drag-and-drop). Default: true. */\n enableFileTransfer?: boolean;\n /** Enable audio playback. Default: true. */\n enableAudio?: boolean;\n}\n\n/** Audio props. */\nexport interface SpiceAudioProps {\n /** Audio volume (0.0 – 1.0). */\n volume?: number;\n /** Whether audio is muted. */\n muted?: boolean;\n}\n\n/** Event callback props. */\nexport interface SpiceEventCallbacks {\n /** Called when the SPICE connection is established. */\n onConnect?: () => void;\n /** Called when the SPICE connection is closed. */\n onDisconnect?: () => void;\n /** Called when a connection error occurs. */\n onError?: (error: Error) => void;\n /** Called when the display is resized (width, height in pixels). */\n onResize?: (width: number, height: number) => void;\n /** Called when clipboard text is received from the guest. */\n onClipboard?: ClipboardCallback;\n /** Called to report file transfer progress. */\n onFileTransferProgress?: FileXferProgressCallback;\n /** Called when a file transfer completes. */\n onFileTransferComplete?: FileXferCompleteCallback;\n /** Called when data is received on a port channel. */\n onPortData?: (portName: string, data: ArrayBuffer) => void;\n}\n\n/** Full set of SpiceDisplay component props. */\nexport interface SpiceDisplayProps extends SpiceEventCallbacks {\n /** Connection settings. */\n connection: SpiceConnectionProps;\n /** Display options. */\n display?: SpiceDisplayOptions;\n /** Feature toggles. */\n features?: SpiceFeatureToggles;\n /** Audio settings. */\n audio?: SpiceAudioProps;\n /** CSS class name applied to the outer div. */\n className?: string;\n /** Inline styles applied to the outer div. */\n style?: React.CSSProperties;\n}\n\n/** Imperative handle exposed via ref. */\nexport interface SpiceDisplayHandle {\n /** Send Ctrl+Alt+Delete to the guest. */\n sendCtrlAltDel: () => void;\n /** Disconnect from the SPICE server. */\n disconnect: () => void;\n /** Reconnect using current props. */\n reconnect: () => void;\n /** Get the underlying SpiceMainConn instance, if connected. */\n getConnection: () => SpiceMainConn | null;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_SCREEN_ID = \"spice-screen\";\n\nfunction buildUri(conn: SpiceConnectionProps): string\n{\n const scheme = conn.scheme ?? \"ws\";\n let uri = `${scheme}://${conn.host}:${conn.port}`;\n if (conn.path)\n {\n uri += conn.path.startsWith(\"/\") ? conn.path : `/${conn.path}`;\n }\n return uri;\n}\n\nfunction setTokenCookie(token: string): void\n{\n if (typeof document === \"undefined\") return;\n const date = new Date();\n date.setTime(date.getTime() + 24 * 60 * 60 * 1000); // 1 day\n document.cookie = `token=${token}; expires=${date.toUTCString()}; path=/`;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * React component that renders a SPICE remote desktop session.\n *\n * Usage:\n * ```tsx\n * <SpiceDisplay\n * ref={spiceRef}\n * connection={{ host: \"localhost\", port: 5900, password: \"secret\" }}\n * features={{ enableKeyboard: true, enableMouse: true }}\n * onConnect={() => console.log(\"connected\")}\n * onError={(e) => console.error(e)}\n * />\n * ```\n */\nexport const SpiceDisplay = forwardRef<SpiceDisplayHandle, SpiceDisplayProps>(\n function SpiceDisplay(props, ref)\n {\n const {\n connection: connProps,\n display: displayProps,\n features,\n audio: _audio,\n className,\n style,\n onConnect,\n onDisconnect,\n onError,\n onResize,\n onClipboard,\n onFileTransferProgress,\n onFileTransferComplete,\n onPortData,\n } = props;\n\n // Refs\n const containerRef = useRef<HTMLDivElement>(null);\n const screenRef = useRef<HTMLDivElement>(null);\n const connRef = useRef<SpiceMainConn | null>(null);\n const cleanupRef = useRef<(() => void) | null>(null);\n\n // Stable callback refs — avoid re-connecting on callback identity changes\n const callbacksRef = useRef({\n onConnect,\n onDisconnect,\n onError,\n onResize,\n onClipboard,\n onFileTransferProgress,\n onFileTransferComplete,\n onPortData,\n });\n callbacksRef.current = {\n onConnect,\n onDisconnect,\n onError,\n onResize,\n onClipboard,\n onFileTransferProgress,\n onFileTransferComplete,\n onPortData,\n };\n\n // Feature defaults\n const enableKeyboard = features?.enableKeyboard ?? true;\n const enableMouse = features?.enableMouse ?? true;\n const enableClipboard = features?.enableClipboard ?? true;\n const enableFileTransfer = features?.enableFileTransfer ?? true;\n const fitContainer = displayProps?.fitContainer ?? false;\n\n // Generate a stable screen id for this component instance\n const [screenId] = useState(() => `spice-screen-${Math.random().toString(36).slice(2, 9)}`);\n\n // ---------------------------------------------------------------\n // Imperative handle\n // ---------------------------------------------------------------\n\n const disconnect = useCallback(() =>\n {\n if (cleanupRef.current)\n {\n cleanupRef.current();\n cleanupRef.current = null;\n }\n if (connRef.current)\n {\n connRef.current.stop();\n connRef.current = null;\n }\n callbacksRef.current.onDisconnect?.();\n }, []);\n\n const connect = useCallback(() =>\n {\n // SSR guard\n if (typeof document === \"undefined\") return;\n\n // Clean up any previous connection\n disconnect();\n\n // Set token cookie if provided\n if (connProps.token)\n {\n setTokenCookie(connProps.token);\n }\n\n const uri = buildUri(connProps);\n const cbs = callbacksRef.current;\n\n const options: SpiceConnOptions = {\n uri,\n screenId,\n password: connProps.password ?? \"\",\n onerror: (e: Error) =>\n {\n callbacksRef.current.onError?.(e);\n },\n onsuccess: () =>\n {\n callbacksRef.current.onConnect?.();\n },\n onagent: () =>\n {\n const sc = connRef.current;\n if (!sc) return;\n\n // Wire up callbacks\n if (callbacksRef.current.onClipboard)\n {\n sc.onClipboard = (text: string) =>\n callbacksRef.current.onClipboard?.(text);\n }\n sc.onFileXferProgress = (taskId, bytes, total, filename) =>\n callbacksRef.current.onFileTransferProgress?.(taskId, bytes, total, filename);\n sc.onFileXferComplete = (taskId, filename, error) =>\n callbacksRef.current.onFileTransferComplete?.(taskId, filename, error);\n\n // Set up display surface callback\n const display = sc.channels.display as SpiceDisplayConn | undefined;\n if (display)\n {\n display.onSurface = (surfaceId, width, height, created) =>\n {\n if (created)\n {\n callbacksRef.current.onResize?.(width, height);\n }\n };\n }\n\n // Set up resize handling\n if (fitContainer && containerRef.current)\n {\n resizeHelper(sc);\n const cleanupObserver = observeContainerResize(\n containerRef.current,\n sc,\n );\n if (cleanupObserver)\n {\n const prevCleanup = cleanupRef.current;\n cleanupRef.current = () =>\n {\n cleanupObserver();\n prevCleanup?.();\n };\n }\n }\n\n // Set up file transfer (drag-and-drop)\n if (enableFileTransfer && containerRef.current)\n {\n const container = containerRef.current;\n const dragHandler = (e: Event) =>\n handleFileDragover(e as DragEvent);\n const dropHandler = (e: Event) =>\n handleFileDrop(e as DragEvent, sc);\n container.addEventListener(\"dragover\", dragHandler, false);\n container.addEventListener(\"drop\", dropHandler, false);\n\n const prevCleanup = cleanupRef.current;\n cleanupRef.current = () =>\n {\n container.removeEventListener(\"dragover\", dragHandler, false);\n container.removeEventListener(\"drop\", dropHandler, false);\n prevCleanup?.();\n };\n }\n\n // Set up port data callback\n if (callbacksRef.current.onPortData)\n {\n for (const port of sc.channels.ports)\n {\n const portConn = port as { onPortData?: (name: string, data: ArrayBuffer) => void };\n portConn.onPortData = (name, data) =>\n callbacksRef.current.onPortData?.(name, data);\n }\n }\n },\n };\n\n try\n {\n connRef.current = new SpiceMainConn(options);\n }\n catch (e)\n {\n const err = e instanceof Error ? e : new Error(String(e));\n cbs.onError?.(err);\n }\n }, [connProps.host, connProps.port, connProps.password, connProps.token,\n connProps.scheme, connProps.path, screenId, disconnect,\n enableFileTransfer, fitContainer, enableClipboard]);\n\n useImperativeHandle(ref, () => ({\n sendCtrlAltDel: () =>\n {\n const sc = connRef.current;\n if (!sc) return;\n const inputs = sc.channels.inputs as SpiceInputsConn | undefined;\n inputs?.sendCtrlAltDel();\n },\n disconnect,\n reconnect: connect,\n getConnection: () => connRef.current,\n }), [disconnect, connect]);\n\n // ---------------------------------------------------------------\n // Keyboard & mouse event wiring\n // ---------------------------------------------------------------\n\n useEffect(() =>\n {\n const screenEl = screenRef.current;\n if (!screenEl) return;\n\n const getInputs = (): SpiceInputsConn | undefined =>\n {\n const sc = connRef.current;\n if (!sc) return undefined;\n return sc.channels.inputs as SpiceInputsConn | undefined;\n };\n\n const handlers: Array<[string, EventListener]> = [];\n\n if (enableKeyboard)\n {\n const onKeyDown = (e: Event) =>\n {\n const inputs = getInputs();\n inputs?.handleKeyDown(e as KeyboardEvent);\n };\n const onKeyUp = (e: Event) =>\n {\n const inputs = getInputs();\n inputs?.handleKeyUp(e as KeyboardEvent);\n };\n handlers.push([\"keydown\", onKeyDown], [\"keyup\", onKeyUp]);\n }\n\n if (enableMouse)\n {\n const onMouseMove = (e: Event) =>\n {\n const inputs = getInputs();\n inputs?.handleMouseMove(e as MouseEvent);\n };\n const onMouseDown = (e: Event) =>\n {\n const inputs = getInputs();\n inputs?.handleMouseDown(e as MouseEvent);\n };\n const onMouseUp = (e: Event) =>\n {\n const inputs = getInputs();\n inputs?.handleMouseUp(e as MouseEvent);\n };\n const onWheel = (e: Event) =>\n {\n const inputs = getInputs();\n inputs?.handleMouseWheel(e as WheelEvent);\n };\n const onContextMenu = (e: Event) =>\n {\n const inputs = getInputs();\n inputs?.handleContextMenu(e as MouseEvent);\n };\n handlers.push(\n [\"mousemove\", onMouseMove],\n [\"mousedown\", onMouseDown],\n [\"mouseup\", onMouseUp],\n [\"wheel\", onWheel],\n [\"contextmenu\", onContextMenu],\n );\n }\n\n for (const [event, handler] of handlers)\n {\n screenEl.addEventListener(event, handler);\n }\n\n return () =>\n {\n for (const [event, handler] of handlers)\n {\n screenEl.removeEventListener(event, handler);\n }\n };\n }, [enableKeyboard, enableMouse]);\n\n // ---------------------------------------------------------------\n // Connection lifecycle\n // ---------------------------------------------------------------\n\n useEffect(() =>\n {\n connect();\n return () =>\n {\n disconnect();\n };\n }, [connect, disconnect]);\n\n // ---------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n ...style,\n }}\n >\n <div\n ref={screenRef}\n id={screenId}\n tabIndex={0}\n style={{\n outline: \"none\",\n width: \"100%\",\n height: \"100%\",\n }}\n />\n </div>\n );\n }\n);\n\nSpiceDisplay.displayName = \"SpiceDisplay\";\n\nexport default SpiceDisplay;\n","\"use strict\";\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport { SpiceMainConn } from '../protocol/main';\nimport { SpiceDisplayConn } from '../protocol/display';\nimport { SpiceInputsConn } from '../protocol/inputs';\nimport {\n SpiceMiniData,\n SpiceMsgcKeyDown,\n SpiceMsgcKeyUp,\n SpiceMsgcMousePosition,\n SpiceMsgcMousePress,\n SpiceMsgcMouseRelease,\n} from '../protocol/spicemsg';\nimport { SpiceMsgcInputs } from '../protocol/enums';\n\nimport type { SpiceConnOptions } from '../protocol/spiceconn';\nimport type {\n ClipboardCallback,\n FileXferProgressCallback,\n FileXferCompleteCallback,\n} from '../protocol/main';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** SPICE connection status. */\nexport type SpiceStatus =\n | \"disconnected\"\n | \"connecting\"\n | \"connected\"\n | \"error\";\n\n/** Display resolution. */\nexport interface SpiceResolution {\n width: number;\n height: number;\n}\n\n/** Configuration object for connect(). */\nexport interface SpiceConfig {\n /** WebSocket URI (e.g. \"ws://localhost:5900\"). */\n uri: string;\n /** SPICE password. */\n password?: string;\n /** DOM element ID where canvases will be appended. */\n screenId?: string;\n /** DOM element ID for debug output. */\n dumpId?: string;\n /** DOM element ID for log messages. */\n messageId?: string;\n}\n\n/** Callbacks the hook consumer can supply. */\nexport interface UseSpiceCallbacks {\n /** Called when the SPICE connection succeeds. */\n onConnect?: () => void;\n /** Called when the connection is closed. */\n onDisconnect?: () => void;\n /** Called on connection error. */\n onError?: (error: Error) => void;\n /** Called when the display resolution changes. */\n onResize?: (width: number, height: number) => void;\n /** Called when clipboard text is received from the guest. */\n onClipboard?: ClipboardCallback;\n /** Called to report file transfer progress. */\n onFileTransferProgress?: FileXferProgressCallback;\n /** Called when a file transfer completes. */\n onFileTransferComplete?: FileXferCompleteCallback;\n}\n\n/** Options accepted by the useSpice hook. */\nexport interface UseSpiceOptions {\n /** React ref to a canvas or div element for display rendering. */\n canvasRef?: React.RefObject<HTMLElement | null>;\n /** Callbacks. */\n callbacks?: UseSpiceCallbacks;\n}\n\n/** Control methods returned by the hook. */\nexport interface SpiceControls {\n /** Initiate a SPICE connection. */\n connect: (config: SpiceConfig) => void;\n /** Disconnect from the SPICE server. */\n disconnect: () => void;\n /** Send an AT scancode key-down event. */\n sendKeyDown: (scancode: number) => void;\n /** Send an AT scancode key-up event. */\n sendKeyUp: (scancode: number) => void;\n /** Send an absolute mouse position. */\n sendMouseMove: (x: number, y: number) => void;\n /** Send a mouse button press or release. */\n sendMouseButton: (button: number, pressed: boolean) => void;\n /** Send clipboard text to the guest. */\n sendClipboard: (text: string) => void;\n /** Request a guest display resolution change. */\n setResolution: (width: number, height: number) => void;\n /** Send Ctrl+Alt+Delete. */\n sendCtrlAltDel: () => void;\n /** Get the underlying SpiceMainConn instance, if connected. */\n getConnection: () => SpiceMainConn | null;\n}\n\n/** Return value of the useSpice hook. */\nexport interface UseSpiceReturn {\n /** Current connection status. */\n status: SpiceStatus;\n /** Last connection error, or null. */\n error: Error | null;\n /** Current display resolution, or null if no primary surface. */\n resolution: SpiceResolution | null;\n /** Number of active surfaces. */\n surfaces: number;\n /** Control methods. */\n controls: SpiceControls;\n}\n\n// ---------------------------------------------------------------------------\n// Hook implementation\n// ---------------------------------------------------------------------------\n\nconst SSR = typeof document === \"undefined\";\n\n/**\n * Low-level React hook for managing a SPICE connection with full control\n * over the connection lifecycle and input events.\n *\n * Usage:\n * ```tsx\n * function MyComponent() {\n * const containerRef = useRef<HTMLDivElement>(null);\n * const { status, resolution, controls } = useSpice({\n * canvasRef: containerRef,\n * callbacks: { onConnect: () => console.log(\"connected\") },\n * });\n *\n * useEffect(() => {\n * controls.connect({ uri: \"ws://localhost:5900\", password: \"secret\" });\n * return () => controls.disconnect();\n * }, [controls]);\n *\n * return <div ref={containerRef} />;\n * }\n * ```\n */\nexport function useSpice(options?: UseSpiceOptions): UseSpiceReturn\n{\n const [status, setStatus] = useState<SpiceStatus>(\"disconnected\");\n const [error, setError] = useState<Error | null>(null);\n const [resolution, setResolution] = useState<SpiceResolution | null>(null);\n const [surfaces, setSurfaces] = useState(0);\n\n const connRef = useRef<SpiceMainConn | null>(null);\n\n // Stable callback refs\n const callbacksRef = useRef(options?.callbacks);\n callbacksRef.current = options?.callbacks;\n\n const canvasRef = options?.canvasRef;\n\n // ---------------------------------------------------------------\n // Core methods\n // ---------------------------------------------------------------\n\n const disconnect = useCallback(() =>\n {\n if (connRef.current)\n {\n connRef.current.stop();\n connRef.current = null;\n }\n setStatus(\"disconnected\");\n setResolution(null);\n setSurfaces(0);\n callbacksRef.current?.onDisconnect?.();\n }, []);\n\n const doConnect = useCallback((config: SpiceConfig) =>\n {\n if (SSR) return;\n\n // Clean up previous connection\n disconnect();\n\n setStatus(\"connecting\");\n setError(null);\n\n // Determine screen ID: prefer config, then use canvasRef element's id\n let screenId = config.screenId;\n if (!screenId && canvasRef?.current)\n {\n // Ensure the canvas ref element has an id\n if (!canvasRef.current.id)\n {\n canvasRef.current.id = `spice-screen-${Math.random().toString(36).slice(2, 9)}`;\n }\n screenId = canvasRef.current.id;\n }\n\n const spiceOpts: SpiceConnOptions = {\n uri: config.uri,\n screenId,\n dumpId: config.dumpId,\n messageId: config.messageId,\n password: config.password ?? \"\",\n onerror: (e: Error) =>\n {\n setStatus(\"error\");\n setError(e);\n callbacksRef.current?.onError?.(e);\n },\n onsuccess: () =>\n {\n setStatus(\"connected\");\n callbacksRef.current?.onConnect?.();\n },\n onagent: () =>\n {\n const sc = connRef.current;\n if (!sc) return;\n\n // Wire clipboard\n if (callbacksRef.current?.onClipboard)\n {\n sc.onClipboard = (text: string) =>\n callbacksRef.current?.onClipboard?.(text);\n }\n\n // Wire file transfer callbacks\n sc.onFileXferProgress = (taskId, bytes, total, filename) =>\n callbacksRef.current?.onFileTransferProgress?.(taskId, bytes, total, filename);\n sc.onFileXferComplete = (taskId, filename, err) =>\n callbacksRef.current?.onFileTransferComplete?.(taskId, filename, err);\n\n // Wire display surface callback\n const display = sc.channels.display as SpiceDisplayConn | undefined;\n if (display)\n {\n display.onSurface = (_surfaceId, width, height, created) =>\n {\n // Count surfaces\n const surfaceCount = Object.keys(display.surfaces).length;\n setSurfaces(surfaceCount);\n\n if (created)\n {\n // Update resolution from primary surface\n const primary = display.getPrimarySurface();\n if (primary)\n {\n setResolution({ width: primary.width, height: primary.height });\n }\n callbacksRef.current?.onResize?.(width, height);\n }\n else\n {\n // Surface destroyed — recheck primary\n const primary = display.getPrimarySurface();\n if (primary)\n {\n setResolution({ width: primary.width, height: primary.height });\n }\n else\n {\n setResolution(null);\n }\n }\n };\n }\n },\n };\n\n try\n {\n connRef.current = new SpiceMainConn(spiceOpts);\n }\n catch (e)\n {\n const err = e instanceof Error ? e : new Error(String(e));\n setStatus(\"error\");\n setError(err);\n callbacksRef.current?.onError?.(err);\n }\n }, [disconnect, canvasRef]);\n\n // ---------------------------------------------------------------\n // Input control methods\n // ---------------------------------------------------------------\n\n const getInputs = useCallback((): SpiceInputsConn | undefined =>\n {\n const sc = connRef.current;\n if (!sc) return undefined;\n return sc.channels.inputs as SpiceInputsConn | undefined;\n }, []);\n\n const sendKeyDown = useCallback((scancode: number) =>\n {\n const inputs = getInputs();\n if (!inputs) return;\n const msg = new SpiceMiniData();\n const payload = new SpiceMsgcKeyDown(scancode);\n msg.buildMsg(SpiceMsgcInputs.KEY_DOWN, payload);\n inputs.sendMsg(msg);\n }, [getInputs]);\n\n const sendKeyUp = useCallback((scancode: number) =>\n {\n const inputs = getInputs();\n if (!inputs) return;\n const msg = new SpiceMiniData();\n const payload = new SpiceMsgcKeyUp(scancode);\n msg.buildMsg(SpiceMsgcInputs.KEY_UP, payload);\n inputs.sendMsg(msg);\n }, [getInputs]);\n\n const sendMouseMove = useCallback((x: number, y: number) =>\n {\n const inputs = getInputs();\n if (!inputs) return;\n const msg = new SpiceMiniData();\n const payload = new SpiceMsgcMousePosition(x, y, inputs.buttonState, 0);\n msg.buildMsg(SpiceMsgcInputs.MOUSE_POSITION, payload);\n inputs.sendMsg(msg);\n }, [getInputs]);\n\n const sendMouseButton = useCallback((button: number, pressed: boolean) =>\n {\n const inputs = getInputs();\n if (!inputs) return;\n const msg = new SpiceMiniData();\n if (pressed)\n {\n const payload = new SpiceMsgcMousePress(button, inputs.buttonState);\n msg.buildMsg(SpiceMsgcInputs.MOUSE_PRESS, payload);\n }\n else\n {\n const payload = new SpiceMsgcMouseRelease(button, inputs.buttonState);\n msg.buildMsg(SpiceMsgcInputs.MOUSE_RELEASE, payload);\n }\n inputs.sendMsg(msg);\n }, [getInputs]);\n\n const sendClipboard = useCallback((_text: string) =>\n {\n const sc = connRef.current;\n if (!sc) return;\n // Signal the guest that the client has clipboard data\n sc.sendClipboardGrab();\n }, []);\n\n const changeResolution = useCallback((width: number, height: number) =>\n {\n const sc = connRef.current;\n if (!sc) return;\n sc.resizeWindow(0, width, height, 32, 0, 0);\n }, []);\n\n const sendCtrlAltDel = useCallback(() =>\n {\n const inputs = getInputs();\n inputs?.sendCtrlAltDel();\n }, [getInputs]);\n\n const getConnection = useCallback(() => connRef.current, []);\n\n // ---------------------------------------------------------------\n // Cleanup on unmount\n // ---------------------------------------------------------------\n\n useEffect(() =>\n {\n return () =>\n {\n if (connRef.current)\n {\n connRef.current.stop();\n connRef.current = null;\n }\n };\n }, []);\n\n // ---------------------------------------------------------------\n // Return\n // ---------------------------------------------------------------\n\n const controls: SpiceControls = {\n connect: doConnect,\n disconnect,\n sendKeyDown,\n sendKeyUp,\n sendMouseMove,\n sendMouseButton,\n sendClipboard,\n setResolution: changeResolution,\n sendCtrlAltDel,\n getConnection,\n };\n\n return {\n status,\n error,\n resolution,\n surfaces,\n controls,\n };\n}\n\nexport default useSpice;\n","/*----------------------------------------------------------------------------\n** quic.ts\n** QUIC image decompression module.\n** Faithfully converted from quic.js.\n** Implements QUIC RGB, RGBA, and GRAY decompression with typed channel\n** state, model, bucket, and arithmetic coding structures.\n**--------------------------------------------------------------------------*/\n\nimport { type SpiceQuicData } from './spicetype';\n\n// ---------------------------------------------------------------------------\n// QUIC image type constants (local to QUIC codec, not in shared enums)\n// ---------------------------------------------------------------------------\n\nexport const QuicImageType = {\n INVALID: 0,\n GRAY: 1,\n RGB16: 2,\n RGB24: 3,\n RGB32: 4,\n RGBA: 5,\n} as const;\n\nexport type QuicImageTypeValue = (typeof QuicImageType)[keyof typeof QuicImageType];\n\n// ---------------------------------------------------------------------------\n// QUIC model/codec constants\n// ---------------------------------------------------------------------------\n\nconst DEFevol = 3;\nconst DEFwmimax = 6;\nconst DEFwminext = 2048;\nconst DEFmaxclen = 26;\nconst evol: number = DEFevol;\nconst wmimax: number = DEFwmimax;\nconst wminext: number = DEFwminext;\n\n// ---------------------------------------------------------------------------\n// Pixel layout constants for rgb32\n// ---------------------------------------------------------------------------\n\nconst rgb32_pixel_pad = 3;\nconst rgb32_pixel_r = 2;\nconst rgb32_pixel_g = 1;\nconst rgb32_pixel_b = 0;\nconst rgb32_pixel_size = 4;\n\n// ---------------------------------------------------------------------------\n// Family structures for Golomb coding\n// ---------------------------------------------------------------------------\n\ninterface QuicFamily {\n nGRcodewords: number[];\n notGRcwlen: number[];\n notGRprefixmask: number[];\n notGRsuffixlen: number[];\n xlatU2L: number[];\n xlatL2U: number[];\n}\n\nfunction createFamily(): QuicFamily {\n return {\n nGRcodewords: [0, 0, 0, 0, 0, 0, 0, 0],\n notGRcwlen: [0, 0, 0, 0, 0, 0, 0, 0],\n notGRprefixmask: [0, 0, 0, 0, 0, 0, 0, 0],\n notGRsuffixlen: [0, 0, 0, 0, 0, 0, 0, 0],\n xlatU2L: [],\n xlatL2U: [],\n };\n}\n\nconst family_5bpc: QuicFamily = createFamily();\nconst family_8bpc: QuicFamily = createFamily();\n\n// ---------------------------------------------------------------------------\n// Lookup tables\n// ---------------------------------------------------------------------------\n\nconst bppmask: number[] = [\n 0x00000000,\n 0x00000001, 0x00000003, 0x00000007, 0x0000000f,\n 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,\n 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,\n 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,\n 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,\n 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,\n 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,\n 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,\n];\n\nconst zeroLUT: number[] = [];\n\nconst besttrigtab: number[][] = [\n [550, 900, 800, 700, 500, 350, 300, 200, 180, 180, 160],\n [110, 550, 900, 800, 550, 400, 350, 250, 140, 160, 140],\n [100, 120, 550, 900, 700, 500, 400, 300, 220, 250, 160],\n];\n\nconst J: number[] = [\n 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6,\n 7, 7, 8, 9, 10, 11, 12, 13, 14, 15,\n];\n\nconst lzeroes: number[] = [\n 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0,\n];\n\nconst tabrand_chaos: number[] = [\n 0x02c57542, 0x35427717, 0x2f5a2153, 0x9244f155, 0x7bd26d07, 0x354c6052,\n 0x57329b28, 0x2993868e, 0x6cd8808c, 0x147b46e0, 0x99db66af, 0xe32b4cac,\n 0x1b671264, 0x9d433486, 0x62a4c192, 0x06089a4b, 0x9e3dce44, 0xdaabee13,\n 0x222425ea, 0xa46f331d, 0xcd589250, 0x8bb81d7f, 0xc8b736b9, 0x35948d33,\n 0xd7ac7fd0, 0x5fbe2803, 0x2cfbc105, 0x013dbc4e, 0x7a37820f, 0x39f88e9e,\n 0xedd58794, 0xc5076689, 0xfcada5a4, 0x64c2f46d, 0xb3ba3243, 0x8974b4f9,\n 0x5a05aebd, 0x20afcd00, 0x39e2b008, 0x88a18a45, 0x600bde29, 0xf3971ace,\n 0xf37b0a6b, 0x7041495b, 0x70b707ab, 0x06beffbb, 0x4206051f, 0xe13c4ee3,\n 0xc1a78327, 0x91aa067c, 0x8295f72a, 0x732917a6, 0x1d871b4d, 0x4048f136,\n 0xf1840e7e, 0x6a6048c1, 0x696cb71a, 0x7ff501c3, 0x0fc6310b, 0x57e0f83d,\n 0x8cc26e74, 0x11a525a2, 0x946934c7, 0x7cd888f0, 0x8f9d8604, 0x4f86e73b,\n 0x04520316, 0xdeeea20c, 0xf1def496, 0x67687288, 0xf540c5b2, 0x22401484,\n 0x3478658a, 0xc2385746, 0x01979c2c, 0x5dad73c8, 0x0321f58b, 0xf0fedbee,\n 0x92826ddf, 0x284bec73, 0x5b1a1975, 0x03df1e11, 0x20963e01, 0xa17cf12b,\n 0x740d776e, 0xa7a6bf3c, 0x01b5cce4, 0x1118aa76, 0xfc6fac0a, 0xce927e9b,\n 0x00bf2567, 0x806f216c, 0xbca69056, 0x795bd3e9, 0xc9dc4557, 0x8929b6c2,\n 0x789d52ec, 0x3f3fbf40, 0xb9197368, 0xa38c15b5, 0xc3b44fa8, 0xca8333b0,\n 0xb7e8d590, 0xbe807feb, 0xbf5f8360, 0xd99e2f5c, 0x372928e1, 0x7c757c4c,\n 0x0db5b154, 0xc01ede02, 0x1fc86e78, 0x1f3985be, 0xb4805c77, 0x00c880fa,\n 0x974c1b12, 0x35ab0214, 0xb2dc840d, 0x5b00ae37, 0xd313b026, 0xb260969d,\n 0x7f4c8879, 0x1734c4d3, 0x49068631, 0xb9f6a021, 0x6b863e6f, 0xcee5debf,\n 0x29f8c9fb, 0x53dd6880, 0x72b61223, 0x1f67a9fd, 0x0a0f6993, 0x13e59119,\n 0x11cca12e, 0xfe6b6766, 0x16b6effc, 0x97918fc4, 0xc2b8a563, 0x94f2f741,\n 0x0bfa8c9a, 0xd1537ae8, 0xc1da349c, 0x873c60ca, 0x95005b85, 0x9b5c080e,\n 0xbc8abbd9, 0xe1eab1d2, 0x6dac9070, 0x4ea9ebf1, 0xe0cf30d4, 0x1ef5bd7b,\n 0xd161043e, 0x5d2fa2e2, 0xff5d3cae, 0x86ed9f87, 0x2aa1daa1, 0xbd731a34,\n 0x9e8f4b22, 0xb1c2c67a, 0xc21758c9, 0xa182215d, 0xccb01948, 0x8d168df7,\n 0x04238cfe, 0x368c3dbc, 0x0aeadca5, 0xbad21c24, 0x0a71fee5, 0x9fc5d872,\n 0x54c152c6, 0xfc329483, 0x6783384a, 0xeddb3e1c, 0x65f90e30, 0x884ad098,\n 0xce81675a, 0x4b372f7d, 0x68bf9a39, 0x43445f1e, 0x40f8d8cb, 0x90d5acb6,\n 0x4cd07282, 0x349eeb06, 0x0c9d5332, 0x520b24ef, 0x80020447, 0x67976491,\n 0x2f931ca3, 0xfe9b0535, 0xfcd30220, 0x61a9e6cc, 0xa487d8d7, 0x3f7c5dd1,\n 0x7d0127c5, 0x48f51d15, 0x60dea871, 0xc9a91cb7, 0x58b53bb3, 0x9d5e0b2d,\n 0x624a78b4, 0x30dbee1b, 0x9bdf22e7, 0x1df5c299, 0x2d5643a7, 0xf4dd35ff,\n 0x03ca8fd6, 0x53b47ed8, 0x6f2c19aa, 0xfeb0c1f4, 0x49e54438, 0x2f2577e6,\n 0xbf876969, 0x72440ea9, 0xfa0bafb8, 0x74f5b3a0, 0x7dd357cd, 0x89ce1358,\n 0x6ef2cdda, 0x1e7767f3, 0xa6be9fdb, 0x4f5f88f8, 0xba994a3a, 0x08ca6b65,\n 0xe0893818, 0x9e00a16a, 0xf42bfc8f, 0x9972eedc, 0x749c8b51, 0x32c05f5e,\n 0xd706805f, 0x6bfbb7cf, 0xd9210a10, 0x31a1db97, 0x923a9559, 0x37a7a1f6,\n 0x059f8861, 0xca493e62, 0x65157e81, 0x8f6467dd, 0xab85ff9f, 0x9331aff2,\n 0x8616b9f5, 0xedbd5695, 0xee7e29b1, 0x313ac44f, 0xb903112f, 0x432ef649,\n 0xdc0a36c0, 0x61cf2bba, 0x81474925, 0xa8b6c7ad, 0xee5931de, 0xb2f8158d,\n 0x59fb7409, 0x2e3dfaed, 0x9af25a3f, 0xe1fed4d5,\n];\n\n// ---------------------------------------------------------------------------\n// Helper functions\n// ---------------------------------------------------------------------------\n\nfunction ceilLog2(val: number): number {\n if (val === 1) {\n return 0;\n }\n\n let result = 1;\n val -= 1;\n while ((val = val >>> 1)) {\n result++;\n }\n\n return result;\n}\n\nfunction familyInit(family: QuicFamily, bpc: number, limit: number): void {\n for (let l = 0; l < bpc; l++) {\n let altprefixlen = limit - bpc;\n const bppmaskVal = bppmask[bpc - l]!;\n if (altprefixlen > bppmaskVal) {\n altprefixlen = bppmaskVal;\n }\n\n const altcodewords = bppmask[bpc]! + 1 - (altprefixlen << l);\n family.nGRcodewords[l] = (altprefixlen << l);\n family.notGRcwlen[l] = altprefixlen + ceilLog2(altcodewords);\n family.notGRprefixmask[l] = (bppmask[32 - altprefixlen]!) >>> 0;\n family.notGRsuffixlen[l] = ceilLog2(altcodewords);\n }\n\n /* decorrelate_init */\n const pixelbitmask = bppmask[bpc]!;\n const pixelbitmaskshr = pixelbitmask >>> 1;\n for (let s = 0; s <= pixelbitmask; s++) {\n if (s <= pixelbitmaskshr) {\n family.xlatU2L[s] = s << 1;\n } else {\n family.xlatU2L[s] = ((pixelbitmask - s) << 1) + 1;\n }\n }\n\n /* correlate_init */\n for (let s = 0; s <= pixelbitmask; s++) {\n if (s & 0x01) {\n family.xlatL2U[s] = pixelbitmask - (s >>> 1);\n } else {\n family.xlatL2U[s] = (s >>> 1);\n }\n }\n}\n\nfunction quicImageBpc(type: number): number {\n switch (type) {\n case QuicImageType.GRAY:\n return 8;\n case QuicImageType.RGB16:\n return 5;\n case QuicImageType.RGB24:\n return 8;\n case QuicImageType.RGB32:\n return 8;\n case QuicImageType.RGBA:\n return 8;\n case QuicImageType.INVALID:\n default:\n console.log(\"quic: bad image type\\n\");\n return 0;\n }\n}\n\nfunction cntLZeroes(bits: number): number {\n if (bits & 0xff800000) {\n return lzeroes[bits >>> 24]!;\n } else if (bits & 0xffff8000) {\n return 8 + lzeroes[(bits >>> 16) & 0x000000ff]!;\n } else if (bits & 0xffffff80) {\n return 16 + lzeroes[(bits >>> 8) & 0x000000ff]!;\n } else {\n return 24 + lzeroes[bits & 0x000000ff]!;\n }\n}\n\ninterface GolombResult {\n codewordlen: number;\n rc: number;\n}\n\nfunction golombDecoding8bpc(l: number, bits: number): GolombResult {\n let rc: number;\n let cwlen: number;\n\n if (bits < 0 || bits > family_8bpc.notGRprefixmask[l]!) {\n const zeroprefix = cntLZeroes(bits);\n cwlen = zeroprefix + 1 + l;\n rc = (zeroprefix << l) | (bits >> (32 - cwlen)) & bppmask[l]!;\n } else {\n cwlen = family_8bpc.notGRcwlen[l]!;\n rc = family_8bpc.nGRcodewords[l]! + ((bits >> (32 - cwlen)) & bppmask[family_8bpc.notGRsuffixlen[l]!]!);\n }\n return { codewordlen: cwlen, rc: rc };\n}\n\nfunction golombCodeLen8bpc(n: number, l: number): number {\n if (n < family_8bpc.nGRcodewords[l]!) {\n return (n >>> l) + 1 + l;\n } else {\n return family_8bpc.notGRcwlen[l]!;\n }\n}\n\n// ---------------------------------------------------------------------------\n// QuicModel\n// ---------------------------------------------------------------------------\n\nclass QuicModel {\n levels: number;\n nBuckets: number = 0;\n nBucketsPtrs: number = 0;\n repfirst: number = 0;\n firstsize: number = 0;\n repnext: number = 0;\n mulsize: number = 0;\n\n constructor(bpc: number) {\n let bend = 0;\n\n this.levels = 0x1 << bpc;\n\n switch (evol) {\n case 1:\n this.repfirst = 3;\n this.firstsize = 1;\n this.repnext = 2;\n this.mulsize = 2;\n break;\n case 3:\n this.repfirst = 1;\n this.firstsize = 1;\n this.repnext = 1;\n this.mulsize = 2;\n break;\n case 5:\n this.repfirst = 1;\n this.firstsize = 1;\n this.repnext = 1;\n this.mulsize = 4;\n break;\n case 0:\n case 2:\n case 4:\n console.log(\"quic: findmodelparams(): evol value obsolete!!!\\n\");\n break;\n default:\n console.log(\"quic: findmodelparams(): evol out of range!!!\\n\");\n }\n\n let repcntr = this.repfirst + 1;\n let bsize = this.firstsize;\n\n do {\n let bstart: number;\n if (this.nBuckets) {\n bstart = bend + 1;\n } else {\n bstart = 0;\n }\n\n if (!--repcntr) {\n repcntr = this.repnext;\n bsize *= this.mulsize;\n }\n\n bend = bstart + bsize - 1;\n if (bend + bsize >= this.levels) {\n bend = this.levels - 1;\n }\n\n if (!this.nBucketsPtrs) {\n this.nBucketsPtrs = this.levels;\n }\n\n this.nBuckets++;\n } while (bend < this.levels - 1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// QuicBucket\n// ---------------------------------------------------------------------------\n\nclass QuicBucket {\n bestcode: number = 0;\n counters: number[] = [0, 0, 0, 0, 0, 0, 0, 0];\n\n reste(bpp: number): void {\n this.bestcode = bpp;\n this.counters = [0, 0, 0, 0, 0, 0, 0, 0];\n }\n\n updateModel8bpc(state: CommonState, curval: number, bpp: number): void {\n let bestcode = bpp - 1;\n let bestcodelen = (this.counters[bestcode] =\n (this.counters[bestcode] ?? 0) + golombCodeLen8bpc(curval, bestcode));\n\n for (let i = bpp - 2; i >= 0; i--) {\n const ithcodelen = (this.counters[i] =\n (this.counters[i] ?? 0) + golombCodeLen8bpc(curval, i));\n\n if (ithcodelen < bestcodelen) {\n bestcode = i;\n bestcodelen = ithcodelen;\n }\n }\n\n this.bestcode = bestcode;\n\n if (bestcodelen > state.wmTrigger) {\n for (let i = 0; i < bpp; i++) {\n this.counters[i] = (this.counters[i] ?? 0) >>> 1;\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// QuicFamilyStat\n// ---------------------------------------------------------------------------\n\nclass QuicFamilyStat {\n bucketsPtrs: QuicBucket[] = [];\n bucketsBuf: QuicBucket[] = [];\n\n fillModelStructures(model: QuicModel): boolean {\n let bend = 0;\n let bnumber = 0;\n\n let repcntr = model.repfirst + 1;\n let bsize = model.firstsize;\n\n do {\n let bstart: number;\n if (bnumber) {\n bstart = bend + 1;\n } else {\n bstart = 0;\n }\n\n if (!--repcntr) {\n repcntr = model.repnext;\n bsize *= model.mulsize;\n }\n\n bend = bstart + bsize - 1;\n if (bend + bsize >= model.levels) {\n bend = model.levels - 1;\n }\n\n const bucket = new QuicBucket();\n this.bucketsBuf[bnumber] = bucket;\n\n for (let i = bstart; i <= bend; i++) {\n this.bucketsPtrs[i] = bucket;\n }\n\n bnumber++;\n } while (bend < model.levels - 1);\n return true;\n }\n}\n\n// ---------------------------------------------------------------------------\n// CorrelateRow\n// ---------------------------------------------------------------------------\n\ninterface CorrelateRow {\n zero: number;\n row: number[];\n}\n\n// ---------------------------------------------------------------------------\n// QuicChannel\n// ---------------------------------------------------------------------------\n\nclass QuicChannel {\n state: CommonState;\n familyStat8bpc: QuicFamilyStat;\n familyStat5bpc: QuicFamilyStat;\n correlateRow: CorrelateRow;\n model8bpc: QuicModel;\n model5bpc: QuicModel;\n bucketsPtrs: QuicBucket[] = [];\n\n constructor(model8bpc: QuicModel, model5bpc: QuicModel) {\n this.state = new CommonState();\n this.familyStat8bpc = new QuicFamilyStat();\n this.familyStat5bpc = new QuicFamilyStat();\n this.correlateRow = { zero: 0, row: [] };\n this.model8bpc = model8bpc;\n this.model5bpc = model5bpc;\n\n this.familyStat8bpc.fillModelStructures(this.model8bpc);\n this.familyStat5bpc.fillModelStructures(this.model5bpc);\n }\n\n reste(bpc: number): boolean {\n this.correlateRow = { zero: 0, row: [] };\n\n if (bpc === 8) {\n for (let j = 0; j < this.model8bpc.nBuckets; j++) {\n this.familyStat8bpc.bucketsBuf[j]!.reste(7);\n }\n this.bucketsPtrs = this.familyStat8bpc.bucketsPtrs;\n } else if (bpc === 5) {\n for (let j = 0; j < this.model5bpc.nBuckets; j++) {\n this.familyStat8bpc.bucketsBuf[j]!.reste(4);\n }\n this.bucketsPtrs = this.familyStat5bpc.bucketsPtrs;\n } else {\n console.log(\"quic: bad bpc \" + bpc + \"\\n\");\n return false;\n }\n\n this.state.reste();\n return true;\n }\n}\n\n// ---------------------------------------------------------------------------\n// CommonState\n// ---------------------------------------------------------------------------\n\nclass CommonState {\n waitcnt: number = 0;\n tabrandSeed: number = 0xff;\n wmTrigger: number = 0;\n wmidx: number = 0;\n wmileft: number = wminext;\n melcstate: number = 0;\n melclen: number = 0;\n melcorder: number = 0;\n\n setWmTrigger(): void {\n let wm = this.wmidx;\n if (wm > 10) {\n wm = 10;\n }\n\n this.wmTrigger = besttrigtab[Math.floor(evol / 2)]![wm]!;\n }\n\n reste(): void {\n this.waitcnt = 0;\n this.tabrandSeed = 0x0ff;\n this.wmidx = 0;\n this.wmileft = wminext;\n\n this.setWmTrigger();\n\n this.melcstate = 0;\n this.melclen = J[0]!;\n this.melcorder = 1 << this.melclen;\n }\n\n tabrand(): number {\n this.tabrandSeed++;\n return tabrand_chaos[this.tabrandSeed & 0x0ff]!;\n }\n}\n\n// ---------------------------------------------------------------------------\n// QuicEncoder (the main decoder engine, name kept for fidelity with original)\n// ---------------------------------------------------------------------------\n\nclass QuicEncoder {\n type: number = 0;\n width: number = 0;\n height: number = 0;\n ioIdx: number = 0;\n ioAvailableBits: number = 0;\n ioWord: number = 0;\n ioNextWord: number = 0;\n ioNow: Uint8Array = new Uint8Array(0);\n ioEnd: number = 0;\n rowsCompleted: number = 0;\n\n rgbState: CommonState = new CommonState();\n model8bpc: QuicModel;\n model5bpc: QuicModel;\n channels: QuicChannel[];\n\n constructor() {\n this.model8bpc = new QuicModel(8);\n this.model5bpc = new QuicModel(5);\n this.channels = [];\n\n for (let i = 0; i < 4; i++) {\n this.channels.push(new QuicChannel(this.model8bpc, this.model5bpc));\n }\n }\n\n reste(ioPtr: Uint8Array): boolean {\n this.rgbState.reste();\n\n this.ioNow = ioPtr;\n this.ioEnd = this.ioNow.length;\n this.ioIdx = 0;\n this.rowsCompleted = 0;\n return true;\n }\n\n readIoWord(): void {\n if (this.ioIdx >= this.ioEnd) {\n throw new Error(\"quic: out of data\");\n }\n this.ioNextWord =\n (this.ioNow[this.ioIdx++]!) |\n (this.ioNow[this.ioIdx++]! << 8) |\n (this.ioNow[this.ioIdx++]! << 16) |\n (this.ioNow[this.ioIdx++]! << 24);\n }\n\n decodeEatbits(len: number): void {\n this.ioWord = this.ioWord << len;\n\n const delta = this.ioAvailableBits - len;\n if (delta >= 0) {\n this.ioAvailableBits = delta;\n this.ioWord |= this.ioNextWord >>> this.ioAvailableBits;\n } else {\n const absDelta = -1 * delta;\n this.ioWord |= this.ioNextWord << absDelta;\n this.readIoWord();\n this.ioAvailableBits = 32 - absDelta;\n this.ioWord |= this.ioNextWord >>> this.ioAvailableBits;\n }\n }\n\n decodeEat32bits(): void {\n this.decodeEatbits(16);\n this.decodeEatbits(16);\n }\n\n resteChannels(bpc: number): boolean {\n for (let i = 0; i < 4; i++) {\n if (!this.channels[i]!.reste(bpc)) {\n return false;\n }\n }\n return true;\n }\n\n quicDecodeBegin(ioPtr: Uint8Array): boolean {\n if (!this.reste(ioPtr)) {\n return false;\n }\n\n this.ioIdx = 0;\n this.ioNextWord =\n (this.ioNow[this.ioIdx++]!) |\n (this.ioNow[this.ioIdx++]! << 8) |\n (this.ioNow[this.ioIdx++]! << 16) |\n (this.ioNow[this.ioIdx++]! << 24);\n this.ioWord = this.ioNextWord;\n this.ioAvailableBits = 0;\n\n const magic = this.ioWord;\n this.decodeEat32bits();\n if (magic !== 0x43495551) { /* QUIC */\n console.log(\"quic: bad magic \" + magic.toString(16));\n return false;\n }\n\n const version = this.ioWord;\n this.decodeEat32bits();\n if (version !== ((0 << 16) | (0 & 0xffff))) {\n console.log(\"quic: bad version \" + version.toString(16));\n return false;\n }\n\n this.type = this.ioWord;\n this.decodeEat32bits();\n\n this.width = this.ioWord;\n this.decodeEat32bits();\n\n this.height = this.ioWord;\n this.decodeEat32bits();\n\n const bpc = quicImageBpc(this.type);\n\n if (!this.resteChannels(bpc)) {\n return false;\n }\n\n return true;\n }\n\n // -----------------------------------------------------------------------\n // RGB32 row 0 segment decompression\n // -----------------------------------------------------------------------\n\n quicRgb32UncompressRow0Seg(\n i: number, curRow: Uint8Array, end: number,\n waitmask: number, bpc: number, bpcMask: number\n ): void {\n const nChannels = 3;\n let stopidx: number;\n let c: number;\n let a: GolombResult;\n\n if (!i) {\n curRow[rgb32_pixel_pad] = 0;\n c = 0;\n do {\n a = golombDecoding8bpc(\n this.channels[c]!.bucketsPtrs[this.channels[c]!.correlateRow.zero]!.bestcode,\n this.ioWord\n );\n this.channels[c]!.correlateRow.row[0] = a.rc;\n curRow[2 - c] = (family_8bpc.xlatL2U[a.rc]! & 0xFF);\n this.decodeEatbits(a.codewordlen);\n } while (++c < nChannels);\n\n if (this.rgbState.waitcnt) {\n --this.rgbState.waitcnt;\n } else {\n this.rgbState.waitcnt = (this.rgbState.tabrand() & waitmask);\n c = 0;\n do {\n this.channels[c]!.bucketsPtrs[this.channels[c]!.correlateRow.zero]!\n .updateModel8bpc(\n this.rgbState,\n this.channels[c]!.correlateRow.row[0]!,\n bpc\n );\n } while (++c < nChannels);\n }\n stopidx = ++i + this.rgbState.waitcnt;\n } else {\n stopidx = i + this.rgbState.waitcnt;\n }\n\n while (stopidx < end) {\n for (; i <= stopidx; i++) {\n curRow[(i * rgb32_pixel_size) + rgb32_pixel_pad] = 0;\n c = 0;\n do {\n a = golombDecoding8bpc(\n this.channels[c]!.bucketsPtrs[this.channels[c]!.correlateRow.row[i - 1]!]!.bestcode,\n this.ioWord\n );\n this.channels[c]!.correlateRow.row[i] = a.rc;\n curRow[(i * rgb32_pixel_size) + (2 - c)] =\n (family_8bpc.xlatL2U[a.rc]! + curRow[((i - 1) * rgb32_pixel_size) + (2 - c)]!) & bpcMask;\n this.decodeEatbits(a.codewordlen);\n } while (++c < nChannels);\n }\n c = 0;\n do {\n this.channels[c]!.bucketsPtrs[this.channels[c]!.correlateRow.row[stopidx - 1]!]!\n .updateModel8bpc(\n this.rgbState,\n this.channels[c]!.correlateRow.row[stopidx]!,\n bpc\n );\n } while (++c < nChannels);\n stopidx = i + (this.rgbState.tabrand() & waitmask);\n }\n\n for (; i < end; i++) {\n curRow[(i * rgb32_pixel_size) + rgb32_pixel_pad] = 0;\n c = 0;\n do {\n a = golombDecoding8bpc(\n this.channels[c]!.bucketsPtrs[this.channels[c]!.correlateRow.row[i - 1]!]!.bestcode,\n this.ioWord\n );\n this.channels[c]!.correlateRow.row[i] = a.rc;\n curRow[(i * rgb32_pixel_size) + (2 - c)] =\n (family_8bpc.xlatL2U[a.rc]! + curRow[((i - 1) * rgb32_pixel_size) + (2 - c)]!) & bpcMask;\n this.decodeEatbits(a.codewordlen);\n } while (++c < nChannels);\n }\n this.rgbState.waitcnt = stopidx - end;\n }\n\n // -----------------------------------------------------------------------\n // RGB32 row 0 full decompression\n // -----------------------------------------------------------------------\n\n quicRgb32UncompressRow0(curRow: Uint8Array): void {\n const bpc = 8;\n const bpcMask = 0xff;\n let pos = 0;\n let width = this.width;\n\n while ((wmimax > this.rgbState.wmidx) && (this.rgbState.wmileft <= width)) {\n if (this.rgbState.wmileft) {\n this.quicRgb32UncompressRow0Seg(\n pos, curRow,\n pos + this.rgbState.wmileft,\n bppmask[this.rgbState.wmidx]!,\n bpc, bpcMask\n );\n pos += this.rgbState.wmileft;\n width -= this.rgbState.wmileft;\n }\n\n this.rgbState.wmidx++;\n this.rgbState.setWmTrigger();\n this.rgbState.wmileft = wminext;\n }\n\n if (width) {\n this.quicRgb32UncompressRow0Seg(\n pos, curRow, pos + width,\n bppmask[this.rgbState.wmidx]!, bpc, bpcMask\n );\n if (wmimax > this.rgbState.wmidx) {\n this.rgbState.wmileft -= width;\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // RGB32 row N segment decompression (with run-length encoding)\n // -----------------------------------------------------------------------\n\n quicRgb32UncompressRowSeg(\n prevRow: Uint8Array, curRow: Uint8Array, i: number, end: number,\n bpc: number, bpcMask: number\n ): void {\n const nChannels = 3;\n const waitmask = bppmask[this.rgbState.wmidx]!;\n\n let a: GolombResult;\n let runIndex = 0;\n let runEnd = 0;\n let stopidx = 0;\n let c: number;\n\n if (!i) {\n curRow[rgb32_pixel_pad] = 0;\n\n c = 0;\n do {\n a = golombDecoding8bpc(\n this.channels[c]!.bucketsPtrs[this.channels[c]!.correlateRow.zero]!.bestcode,\n this.ioWord\n );\n this.channels[c]!.correlateRow.row[0] = a.rc;\n curRow[2 - c] =\n (family_8bpc.xlatL2U[this.channels[c]!.correlateRow.row[0]!]! + prevRow[2 - c]!) & bpcMask;\n this.decodeEatbits(a.codewordlen);\n } while (++c < nChannels);\n\n if (this.rgbState.waitcnt) {\n --this.rgbState.waitcnt;\n } else {\n this.rgbState.waitcnt = (this.rgbState.tabrand() & waitmask);\n c = 0;\n do {\n this.channels[c]!.bucketsPtrs[this.channels[c]!.correlateRow.zero]!\n .updateModel8bpc(\n this.rgbState,\n this.channels[c]!.correlateRow.row[0]!,\n bpc\n );\n } while (++c < nChannels);\n }\n stopidx = ++i + this.rgbState.waitcnt;\n } else {\n stopidx = i + this.rgbState.waitcnt;\n }\n\n for (;;) {\n let rc = 0;\n while (stopidx < end && !rc) {\n for (; i <= stopidx && !rc; i++) {\n const pixel = i * rgb32_pixel_size;\n const pixelm1 = (i - 1) * rgb32_pixel_size;\n const pixelm2 = (i - 2) * rgb32_pixel_size;\n\n if (prevRow[pixelm1 + rgb32_pixel_r]! === prevRow[pixel + rgb32_pixel_r]! &&\n prevRow[pixelm1 + rgb32_pixel_g]! === prevRow[pixel + rgb32_pixel_g]! &&\n prevRow[pixelm1 + rgb32_pixel_b]! === prevRow[pixel + rgb32_pixel_b]!) {\n if (runIndex !== i && i > 2 &&\n (curRow[pixelm1 + rgb32_pixel_r]! === curRow[pixelm2 + rgb32_pixel_r]! &&\n curRow[pixelm1 + rgb32_pixel_g]! === curRow[pixelm2 + rgb32_pixel_g]! &&\n curRow[pixelm1 + rgb32_pixel_b]! === curRow[pixelm2 + rgb32_pixel_b]!)) {\n /* do run */\n this.rgbState.waitcnt = stopidx - i;\n runIndex = i;\n runEnd = i + this.decodeRun(this.rgbState);\n\n for (; i < runEnd; i++) {\n const px = i * rgb32_pixel_size;\n const pxm1 = (i - 1) * rgb32_pixel_size;\n curRow[px + rgb32_pixel_pad] = 0;\n curRow[px + rgb32_pixel_r] = curRow[pxm1 + rgb32_pixel_r]!;\n curRow[px + rgb32_pixel_g] = curRow[pxm1 + rgb32_pixel_g]!;\n curRow[px + rgb32_pixel_b] = curRow[pxm1 + rgb32_pixel_b]!;\n }\n\n if (i === end) {\n return;\n } else {\n stopidx = i + this.rgbState.waitcnt;\n rc = 1;\n break;\n }\n }\n }\n\n c = 0;\n curRow[pixel + rgb32_pixel_pad] = 0;\n do {\n const cc = this.channels[c]!;\n const cr = cc.correlateRow;\n\n a = golombDecoding8bpc(cc.bucketsPtrs[cr.row[i - 1]!]!.bestcode, this.ioWord);\n cr.row[i] = a.rc;\n curRow[pixel + (2 - c)] =\n (family_8bpc.xlatL2U[a.rc]! +\n ((curRow[pixelm1 + (2 - c)]! + prevRow[pixel + (2 - c)]!) >> 1)) & bpcMask;\n this.decodeEatbits(a.codewordlen);\n } while (++c < nChannels);\n }\n if (rc) {\n break;\n }\n\n c = 0;\n do {\n this.channels[c]!.bucketsPtrs[this.channels[c]!.correlateRow.row[stopidx - 1]!]!\n .updateModel8bpc(\n this.rgbState,\n this.channels[c]!.correlateRow.row[stopidx]!,\n bpc\n );\n } while (++c < nChannels);\n\n stopidx = i + (this.rgbState.tabrand() & waitmask);\n }\n\n for (; i < end && !rc; i++) {\n const pixel = i * rgb32_pixel_size;\n const pixelm1 = (i - 1) * rgb32_pixel_size;\n const pixelm2 = (i - 2) * rgb32_pixel_size;\n\n if (prevRow[pixelm1 + rgb32_pixel_r]! === prevRow[pixel + rgb32_pixel_r]! &&\n prevRow[pixelm1 + rgb32_pixel_g]! === prevRow[pixel + rgb32_pixel_g]! &&\n prevRow[pixelm1 + rgb32_pixel_b]! === prevRow[pixel + rgb32_pixel_b]!) {\n if (runIndex !== i && i > 2 &&\n (curRow[pixelm1 + rgb32_pixel_r]! === curRow[pixelm2 + rgb32_pixel_r]! &&\n curRow[pixelm1 + rgb32_pixel_g]! === curRow[pixelm2 + rgb32_pixel_g]! &&\n curRow[pixelm1 + rgb32_pixel_b]! === curRow[pixelm2 + rgb32_pixel_b]!)) {\n /* do run */\n this.rgbState.waitcnt = stopidx - i;\n runIndex = i;\n runEnd = i + this.decodeRun(this.rgbState);\n\n for (; i < runEnd; i++) {\n const px = i * rgb32_pixel_size;\n const pxm1 = (i - 1) * rgb32_pixel_size;\n curRow[px + rgb32_pixel_pad] = 0;\n curRow[px + rgb32_pixel_r] = curRow[pxm1 + rgb32_pixel_r]!;\n curRow[px + rgb32_pixel_g] = curRow[pxm1 + rgb32_pixel_g]!;\n curRow[px + rgb32_pixel_b] = curRow[pxm1 + rgb32_pixel_b]!;\n }\n\n if (i === end) {\n return;\n } else {\n stopidx = i + this.rgbState.waitcnt;\n rc = 1;\n break;\n }\n }\n }\n\n curRow[pixel + rgb32_pixel_pad] = 0;\n c = 0;\n do {\n a = golombDecoding8bpc(\n this.channels[c]!.bucketsPtrs[this.channels[c]!.correlateRow.row[i - 1]!]!.bestcode,\n this.ioWord\n );\n this.channels[c]!.correlateRow.row[i] = a.rc;\n curRow[pixel + (2 - c)] =\n (family_8bpc.xlatL2U[a.rc]! +\n ((curRow[pixelm1 + (2 - c)]! + prevRow[pixel + (2 - c)]!) >> 1)) & bpcMask;\n this.decodeEatbits(a.codewordlen);\n } while (++c < nChannels);\n }\n\n if (!rc) {\n this.rgbState.waitcnt = stopidx - end;\n return;\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Run-length decoding\n // -----------------------------------------------------------------------\n\n decodeRun(state: CommonState): number {\n let runlen = 0;\n\n do {\n const x = (~(this.ioWord >>> 24) >>> 0) & 0xff;\n const temp = zeroLUT[x]!;\n\n for (let hits = 1; hits <= temp; hits++) {\n runlen += state.melcorder;\n\n if (state.melcstate < 32) {\n state.melclen = J[++state.melcstate]!;\n state.melcorder = (1 << state.melclen);\n }\n }\n if (temp !== 8) {\n this.decodeEatbits(temp + 1);\n break;\n }\n this.decodeEatbits(8);\n } while (true);\n\n if (state.melclen) {\n runlen += this.ioWord >>> (32 - state.melclen);\n this.decodeEatbits(state.melclen);\n }\n\n if (state.melcstate) {\n state.melclen = J[--state.melcstate]!;\n state.melcorder = (1 << state.melclen);\n }\n\n return runlen;\n }\n\n // -----------------------------------------------------------------------\n // RGB32 row N full decompression\n // -----------------------------------------------------------------------\n\n quicRgb32UncompressRow(prevRow: Uint8Array, curRow: Uint8Array): void {\n const bpc = 8;\n const bpcMask = 0xff;\n let pos = 0;\n let width = this.width;\n\n while ((wmimax > this.rgbState.wmidx) && (this.rgbState.wmileft <= width)) {\n if (this.rgbState.wmileft) {\n this.quicRgb32UncompressRowSeg(\n prevRow, curRow, pos,\n pos + this.rgbState.wmileft, bpc, bpcMask\n );\n pos += this.rgbState.wmileft;\n width -= this.rgbState.wmileft;\n }\n\n this.rgbState.wmidx++;\n this.rgbState.setWmTrigger();\n this.rgbState.wmileft = wminext;\n }\n\n if (width) {\n this.quicRgb32UncompressRowSeg(\n prevRow, curRow, pos,\n pos + width, bpc, bpcMask\n );\n if (wmimax > this.rgbState.wmidx) {\n this.rgbState.wmileft -= width;\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Four-channel (alpha) row 0 segment decompression\n // -----------------------------------------------------------------------\n\n quicFourUncompressRow0Seg(\n channel: QuicChannel, i: number,\n correlateRow: CorrelateRow, curRow: Uint8Array, end: number,\n waitmask: number, bpc: number, bpcMask: number\n ): void {\n let stopidx: number;\n let a: GolombResult;\n\n if (i === 0) {\n a = golombDecoding8bpc(\n channel.bucketsPtrs[correlateRow.zero]!.bestcode,\n this.ioWord\n );\n correlateRow.row[0] = a.rc;\n curRow[rgb32_pixel_pad] = family_8bpc.xlatL2U[a.rc]!;\n this.decodeEatbits(a.codewordlen);\n\n if (channel.state.waitcnt) {\n --channel.state.waitcnt;\n } else {\n channel.state.waitcnt = (channel.state.tabrand() & waitmask);\n channel.bucketsPtrs[correlateRow.zero]!\n .updateModel8bpc(channel.state, correlateRow.row[0]!, bpc);\n }\n stopidx = ++i + channel.state.waitcnt;\n } else {\n stopidx = i + channel.state.waitcnt;\n }\n\n while (stopidx < end) {\n let pbucket: QuicBucket | undefined;\n\n for (; i <= stopidx; i++) {\n pbucket = channel.bucketsPtrs[correlateRow.row[i - 1]!];\n\n a = golombDecoding8bpc(pbucket!.bestcode, this.ioWord);\n correlateRow.row[i] = a.rc;\n curRow[(i * rgb32_pixel_size) + rgb32_pixel_pad] =\n (family_8bpc.xlatL2U[a.rc]! + curRow[((i - 1) * rgb32_pixel_size) + rgb32_pixel_pad]!) & bpcMask;\n this.decodeEatbits(a.codewordlen);\n }\n\n pbucket!.updateModel8bpc(channel.state, correlateRow.row[stopidx]!, bpc);\n\n stopidx = i + (channel.state.tabrand() & waitmask);\n }\n\n for (; i < end; i++) {\n a = golombDecoding8bpc(\n channel.bucketsPtrs[correlateRow.row[i - 1]!]!.bestcode,\n this.ioWord\n );\n\n correlateRow.row[i] = a.rc;\n curRow[(i * rgb32_pixel_size) + rgb32_pixel_pad] =\n (family_8bpc.xlatL2U[a.rc]! + curRow[((i - 1) * rgb32_pixel_size) + rgb32_pixel_pad]!) & bpcMask;\n this.decodeEatbits(a.codewordlen);\n }\n channel.state.waitcnt = stopidx - end;\n }\n\n // -----------------------------------------------------------------------\n // Four-channel (alpha) row 0 full decompression\n // -----------------------------------------------------------------------\n\n quicFourUncompressRow0(channel: QuicChannel, curRow: Uint8Array): void {\n const bpc = 8;\n const bpcMask = 0xff;\n const correlateRow = channel.correlateRow;\n let pos = 0;\n let width = this.width;\n\n while ((wmimax > channel.state.wmidx) && (channel.state.wmileft <= width)) {\n if (channel.state.wmileft) {\n this.quicFourUncompressRow0Seg(\n channel, pos, correlateRow, curRow,\n pos + channel.state.wmileft, bppmask[channel.state.wmidx]!,\n bpc, bpcMask\n );\n pos += channel.state.wmileft;\n width -= channel.state.wmileft;\n }\n\n channel.state.wmidx++;\n channel.state.setWmTrigger();\n channel.state.wmileft = wminext;\n }\n\n if (width) {\n this.quicFourUncompressRow0Seg(\n channel, pos, correlateRow, curRow, pos + width,\n bppmask[channel.state.wmidx]!, bpc, bpcMask\n );\n if (wmimax > channel.state.wmidx) {\n channel.state.wmileft -= width;\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Four-channel (alpha) row N segment decompression (with run-length)\n // -----------------------------------------------------------------------\n\n quicFourUncompressRowSeg(\n channel: QuicChannel,\n correlateRow: CorrelateRow, prevRow: Uint8Array, curRow: Uint8Array,\n i: number, end: number, bpc: number, bpcMask: number\n ): void {\n const waitmask = bppmask[channel.state.wmidx]!;\n let stopidx: number;\n\n let runIndex = 0;\n let runEnd: number;\n\n let a: GolombResult;\n\n if (i === 0) {\n a = golombDecoding8bpc(\n channel.bucketsPtrs[correlateRow.zero]!.bestcode,\n this.ioWord\n );\n\n correlateRow.row[0] = a.rc;\n curRow[rgb32_pixel_pad] =\n (family_8bpc.xlatL2U[a.rc]! + prevRow[rgb32_pixel_pad]!) & bpcMask;\n this.decodeEatbits(a.codewordlen);\n\n if (channel.state.waitcnt) {\n --channel.state.waitcnt;\n } else {\n channel.state.waitcnt = (channel.state.tabrand() & waitmask);\n channel.bucketsPtrs[correlateRow.zero]!\n .updateModel8bpc(channel.state, correlateRow.row[0]!, bpc);\n }\n stopidx = ++i + channel.state.waitcnt;\n } else {\n stopidx = i + channel.state.waitcnt;\n }\n\n for (;;) {\n let rc = 0;\n while (stopidx < end && !rc) {\n let pbucket: QuicBucket | undefined;\n for (; i <= stopidx && !rc; i++) {\n const pixel = i * rgb32_pixel_size;\n const pixelm1 = (i - 1) * rgb32_pixel_size;\n const pixelm2 = (i - 2) * rgb32_pixel_size;\n\n if (prevRow[pixelm1 + rgb32_pixel_pad]! === prevRow[pixel + rgb32_pixel_pad]!) {\n if (runIndex !== i && i > 2 &&\n curRow[pixelm1 + rgb32_pixel_pad]! === curRow[pixelm2 + rgb32_pixel_pad]!) {\n /* do run */\n channel.state.waitcnt = stopidx - i;\n runIndex = i;\n\n runEnd = i + this.decodeRun(channel.state);\n\n for (; i < runEnd; i++) {\n const px = i * rgb32_pixel_size;\n const pxm1 = (i - 1) * rgb32_pixel_size;\n curRow[px + rgb32_pixel_pad] = curRow[pxm1 + rgb32_pixel_pad]!;\n }\n\n if (i === end) {\n return;\n } else {\n stopidx = i + channel.state.waitcnt;\n rc = 1;\n break;\n }\n }\n }\n\n pbucket = channel.bucketsPtrs[correlateRow.row[i - 1]!];\n a = golombDecoding8bpc(pbucket!.bestcode, this.ioWord);\n correlateRow.row[i] = a.rc;\n curRow[pixel + rgb32_pixel_pad] =\n (family_8bpc.xlatL2U[a.rc]! +\n ((curRow[pixelm1 + rgb32_pixel_pad]! + prevRow[pixel + rgb32_pixel_pad]!) >> 1)) & bpcMask;\n this.decodeEatbits(a.codewordlen);\n }\n if (rc) {\n break;\n }\n\n pbucket!.updateModel8bpc(channel.state, correlateRow.row[stopidx]!, bpc);\n\n stopidx = i + (channel.state.tabrand() & waitmask);\n }\n\n for (; i < end && !rc; i++) {\n const pixel = i * rgb32_pixel_size;\n const pixelm1 = (i - 1) * rgb32_pixel_size;\n const pixelm2 = (i - 2) * rgb32_pixel_size;\n if (prevRow[pixelm1 + rgb32_pixel_pad]! === prevRow[pixel + rgb32_pixel_pad]!) {\n if (runIndex !== i && i > 2 &&\n curRow[pixelm1 + rgb32_pixel_pad]! === curRow[pixelm2 + rgb32_pixel_pad]!) {\n /* do run */\n channel.state.waitcnt = stopidx - i;\n runIndex = i;\n\n runEnd = i + this.decodeRun(channel.state);\n\n for (; i < runEnd; i++) {\n const px = i * rgb32_pixel_size;\n const pxm1 = (i - 1) * rgb32_pixel_size;\n curRow[px + rgb32_pixel_pad] = curRow[pxm1 + rgb32_pixel_pad]!;\n }\n\n if (i === end) {\n return;\n } else {\n stopidx = i + channel.state.waitcnt;\n rc = 1;\n break;\n }\n }\n }\n\n a = golombDecoding8bpc(\n channel.bucketsPtrs[correlateRow.row[i - 1]!]!.bestcode,\n this.ioWord\n );\n correlateRow.row[i] = a.rc;\n curRow[pixel + rgb32_pixel_pad] =\n (family_8bpc.xlatL2U[a.rc]! +\n ((curRow[pixelm1 + rgb32_pixel_pad]! + prevRow[pixel + rgb32_pixel_pad]!) >> 1)) & bpcMask;\n this.decodeEatbits(a.codewordlen);\n }\n\n if (!rc) {\n channel.state.waitcnt = stopidx - end;\n return;\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Four-channel (alpha) row N full decompression\n // -----------------------------------------------------------------------\n\n quicFourUncompressRow(\n channel: QuicChannel, prevRow: Uint8Array, curRow: Uint8Array\n ): void {\n const bpc = 8;\n const bpcMask = 0xff;\n const correlateRow = channel.correlateRow;\n let pos = 0;\n let width = this.width;\n\n while ((wmimax > channel.state.wmidx) && (channel.state.wmileft <= width)) {\n if (channel.state.wmileft) {\n this.quicFourUncompressRowSeg(\n channel, correlateRow, prevRow, curRow, pos,\n pos + channel.state.wmileft, bpc, bpcMask\n );\n pos += channel.state.wmileft;\n width -= channel.state.wmileft;\n }\n\n channel.state.wmidx++;\n channel.state.setWmTrigger();\n channel.state.wmileft = wminext;\n }\n\n if (width) {\n this.quicFourUncompressRowSeg(\n channel, correlateRow, prevRow, curRow, pos,\n pos + width, bpc, bpcMask\n );\n if (wmimax > channel.state.wmidx) {\n channel.state.wmileft -= width;\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Main decode dispatcher\n // -----------------------------------------------------------------------\n\n quicDecode(buf: Uint8Array, stride: number): boolean {\n switch (this.type) {\n case QuicImageType.RGB32:\n case QuicImageType.RGB24:\n this.channels[0]!.correlateRow.zero = 0;\n this.channels[1]!.correlateRow.zero = 0;\n this.channels[2]!.correlateRow.zero = 0;\n this.quicRgb32UncompressRow0(buf);\n\n this.rowsCompleted++;\n for (let row = 1; row < this.height; row++) {\n const prev = buf;\n buf = prev.subarray(stride);\n this.channels[0]!.correlateRow.zero = this.channels[0]!.correlateRow.row[0]!;\n this.channels[1]!.correlateRow.zero = this.channels[1]!.correlateRow.row[0]!;\n this.channels[2]!.correlateRow.zero = this.channels[2]!.correlateRow.row[0]!;\n this.quicRgb32UncompressRow(prev, buf);\n this.rowsCompleted++;\n }\n break;\n\n case QuicImageType.RGB16:\n console.log(\"quic: unsupported output format\\n\");\n return false;\n\n case QuicImageType.RGBA:\n this.channels[0]!.correlateRow.zero = 0;\n this.channels[1]!.correlateRow.zero = 0;\n this.channels[2]!.correlateRow.zero = 0;\n this.quicRgb32UncompressRow0(buf);\n\n this.channels[3]!.correlateRow.zero = 0;\n this.quicFourUncompressRow0(this.channels[3]!, buf);\n\n this.rowsCompleted++;\n for (let row = 1; row < this.height; row++) {\n const prev = buf;\n buf = prev.subarray(stride);\n\n this.channels[0]!.correlateRow.zero = this.channels[0]!.correlateRow.row[0]!;\n this.channels[1]!.correlateRow.zero = this.channels[1]!.correlateRow.row[0]!;\n this.channels[2]!.correlateRow.zero = this.channels[2]!.correlateRow.row[0]!;\n this.quicRgb32UncompressRow(prev, buf);\n\n this.channels[3]!.correlateRow.zero = this.channels[3]!.correlateRow.row[0]!;\n this.quicFourUncompressRow(this.channels[3]!, prev, buf);\n this.rowsCompleted++;\n }\n break;\n\n case QuicImageType.GRAY:\n console.log(\"quic: unsupported output format\\n\");\n return false;\n\n case QuicImageType.INVALID:\n default:\n console.log(\"quic: bad image type\\n\");\n return false;\n }\n return true;\n }\n\n // -----------------------------------------------------------------------\n // Simple decode entry point\n // -----------------------------------------------------------------------\n\n simpleQuicDecode(buf: Uint8Array): Uint8Array | null {\n const stride = 4; /* FIXME - proper stride calc please */\n if (!this.quicDecodeBegin(buf)) {\n return null;\n }\n if (this.type !== QuicImageType.RGB32 &&\n this.type !== QuicImageType.RGB24 &&\n this.type !== QuicImageType.RGBA) {\n return null;\n }\n const out = new Uint8Array(this.width * this.height * 4);\n out[0] = 69;\n if (this.quicDecode(out, this.width * stride)) {\n return out;\n }\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module-level encoder instance (singleton, matching original pattern)\n// ---------------------------------------------------------------------------\n\nlet encoder: QuicEncoder | null = null;\n\nfunction getEncoder(): QuicEncoder {\n if (!encoder) {\n encoder = new QuicEncoder();\n }\n return encoder;\n}\n\n// ---------------------------------------------------------------------------\n// SpiceQuic — public deserialization type implementing SpiceQuicData\n// ---------------------------------------------------------------------------\n\nexport class SpiceQuic implements SpiceQuicData {\n data_size: number = 0;\n outptr: Uint8Array | null = null;\n type: number = 0;\n width: number = 0;\n height: number = 0;\n\n fromDataView(dv: DataView, at: number, mb: ArrayBuffer): number {\n const enc = getEncoder();\n this.data_size = dv.getUint32(at, true);\n at += 4;\n const buf = new Uint8Array(mb.slice(at));\n const result = enc.simpleQuicDecode(buf);\n this.outptr = result;\n if (result) {\n this.type = enc.type;\n this.width = enc.width;\n this.height = enc.height;\n }\n at += buf.length;\n return at;\n }\n}\n\n// ---------------------------------------------------------------------------\n// QUIC → web ImageData conversion\n// ---------------------------------------------------------------------------\n\nexport function convertSpiceQuicToWeb(\n context: CanvasRenderingContext2D,\n spiceQuic: SpiceQuicData\n): ImageData | undefined {\n if (!spiceQuic.outptr) {\n return undefined;\n }\n const ret = context.createImageData(spiceQuic.width, spiceQuic.height);\n const totalPixels = ret.width * ret.height * 4;\n for (let i = 0; i < totalPixels; i += 4) {\n ret.data[i + 0] = spiceQuic.outptr[i + 2]!;\n ret.data[i + 1] = spiceQuic.outptr[i + 1]!;\n ret.data[i + 2] = spiceQuic.outptr[i + 0]!;\n if (spiceQuic.type !== QuicImageType.RGBA) {\n ret.data[i + 3] = 255;\n } else {\n ret.data[i + 3] = 255 - spiceQuic.outptr[i + 3]!;\n }\n }\n return ret;\n}\n\n// ---------------------------------------------------------------------------\n// Module initialization (runs once on import)\n// ---------------------------------------------------------------------------\n\nfamilyInit(family_8bpc, 8, DEFmaxclen);\nfamilyInit(family_5bpc, 5, DEFmaxclen);\n\n/* init_zeroLUT */\n{\n let j = 1;\n let k = 1;\n let l = 8;\n for (let i = 0; i < 256; ++i) {\n zeroLUT[i] = l;\n --k;\n if (k === 0) {\n k = j;\n --l;\n j *= 2;\n }\n }\n}\n\n// Pre-initialize the encoder singleton\nencoder = new QuicEncoder();\n\nexport {\n QuicEncoder,\n QuicModel,\n QuicBucket,\n QuicChannel,\n QuicFamilyStat,\n CommonState,\n};\n","/*----------------------------------------------------------------------------\n** lz.ts\n** Functions for handling SPICE_IMAGE_TYPE_LZ_RGB\n** Adapted from lz.c via lz.js.\n**--------------------------------------------------------------------------*/\n\nimport { LzImageType } from './enums.js';\nimport { LzRgbHeader } from './spicetype.js';\n\n/**\n * LZ RGB32 decompression.\n *\n * Decompresses an LZ-compressed stream into a pixel buffer. When `type`\n * is `LzImageType.RGB32`, full 3-byte BGR pixels are decoded (with an\n * optional default alpha of 255). When `type` is `LzImageType.RGBA`,\n * only the alpha channel (byte offset +3 of each pixel) is decoded.\n *\n * @param inBuf Compressed input bytes.\n * @param at Starting offset into inBuf.\n * @param outBuf Destination pixel buffer (Uint8ClampedArray from\n * ImageData.data — 4 bytes per pixel in RGBA order).\n * @param type Decompression mode: RGB32 (full pixel) or RGBA\n * (alpha-only pass).\n * @param defaultAlpha When true and type is RGB32, set alpha to 255 for\n * every pixel.\n * @returns The encoder position after decompression (points to the last\n * byte consumed, suitable as the starting offset for a\n * subsequent RGBA pass).\n */\nfunction lzRgb32Decompress(\n inBuf: Uint8Array,\n at: number,\n outBuf: Uint8ClampedArray,\n type: number,\n defaultAlpha: boolean,\n): number {\n let encoder = at;\n let op = 0;\n\n for (\n let ctrl = inBuf[encoder++]!;\n (op * 4) < outBuf.length;\n ctrl = inBuf[encoder++]!\n ) {\n let ref = op;\n let len = ctrl >> 5;\n const ofs_base = (ctrl & 31) << 8;\n let ofs = ofs_base;\n\n if (ctrl >= 32) {\n // Back-reference: copy from previously decoded output\n let code: number;\n len--;\n\n if (len === 7 - 1) {\n do {\n code = inBuf[encoder++]!;\n len += code;\n } while (code === 255);\n }\n code = inBuf[encoder++]!;\n ofs += code;\n\n if (code === 255) {\n if ((ofs - code) === (31 << 8)) {\n ofs = inBuf[encoder++]! << 8;\n ofs += inBuf[encoder++]!;\n ofs += 8191;\n }\n }\n len += 1;\n if (type === LzImageType.RGBA) {\n len += 2;\n }\n\n ofs += 1;\n\n ref -= ofs;\n if (ref === (op - 1)) {\n // Run-length: replicate a single pixel\n const b = ref;\n for (; len; --len) {\n if (type === LzImageType.RGBA) {\n outBuf[(op * 4) + 3] = outBuf[(b * 4) + 3]!;\n } else {\n for (let i = 0; i < 4; i++) {\n outBuf[(op * 4) + i] = outBuf[(b * 4) + i]!;\n }\n }\n op++;\n }\n } else {\n // Copy from back-reference\n for (; len; --len) {\n if (type === LzImageType.RGBA) {\n outBuf[(op * 4) + 3] = outBuf[(ref * 4) + 3]!;\n } else {\n for (let i = 0; i < 4; i++) {\n outBuf[(op * 4) + i] = outBuf[(ref * 4) + i]!;\n }\n }\n op++;\n ref++;\n }\n }\n } else {\n // Literal run\n ctrl++;\n\n if (type === LzImageType.RGBA) {\n outBuf[(op * 4) + 3] = inBuf[encoder++]!;\n } else {\n // BGR → RGB swap\n outBuf[(op * 4) + 0] = inBuf[encoder + 2]!;\n outBuf[(op * 4) + 1] = inBuf[encoder + 1]!;\n outBuf[(op * 4) + 2] = inBuf[encoder + 0]!;\n if (defaultAlpha) {\n outBuf[(op * 4) + 3] = 255;\n }\n encoder += 3;\n }\n op++;\n\n for (--ctrl; ctrl; ctrl--) {\n if (type === LzImageType.RGBA) {\n outBuf[(op * 4) + 3] = inBuf[encoder++]!;\n } else {\n // BGR → RGB swap\n outBuf[(op * 4) + 0] = inBuf[encoder + 2]!;\n outBuf[(op * 4) + 1] = inBuf[encoder + 1]!;\n outBuf[(op * 4) + 2] = inBuf[encoder + 0]!;\n if (defaultAlpha) {\n outBuf[(op * 4) + 3] = 255;\n }\n encoder += 3;\n }\n op++;\n }\n }\n }\n return encoder - 1;\n}\n\n/**\n * Flip an ImageData vertically (in-place).\n *\n * Used to convert bottom-up row ordering (SPICE default) to the\n * top-down ordering expected by the HTML Canvas ImageData API.\n *\n * @param img The ImageData to flip.\n */\nfunction flipImageData(img: ImageData): void {\n const wb = img.width * 4;\n const h = img.height;\n let tempH = h;\n const buff = new Uint8Array(img.width * img.height * 4);\n while (tempH--) {\n buff.set(img.data.subarray(tempH * wb, (tempH + 1) * wb), (h - tempH - 1) * wb);\n }\n img.data.set(buff);\n}\n\n/**\n * Convert a SPICE LZ-compressed image to a web-compatible ImageData.\n *\n * Supports LZ_IMAGE_TYPE_RGB32 (opaque), LZ_IMAGE_TYPE_RGBA\n * (two-pass: RGB then alpha), and LZ_IMAGE_TYPE_XXXA (alpha-only).\n *\n * The RGB pass decodes BGR pixels with a channel swap to produce RGB\n * in the output ImageData. For RGBA images, a second alpha-only pass\n * fills in the alpha channel. Bottom-up images (the SPICE default)\n * are flipped after the RGB pass so the alpha pass references correct\n * pixel positions.\n *\n * @param context A 2D canvas rendering context (used only to call\n * createImageData for the correct backing store).\n * @param lzImage The deserialized LZ header from the protocol,\n * containing type, width, height, top_down flag,\n * and compressed data.\n * @returns An ImageData with RGBA pixels, or undefined if the LZ\n * image type is not supported.\n */\nexport function convertSpiceLzToWeb(\n context: CanvasRenderingContext2D,\n lzImage: LzRgbHeader,\n): ImageData | undefined {\n if (\n lzImage.type === LzImageType.RGB32 ||\n lzImage.type === LzImageType.RGBA\n ) {\n const u8 = new Uint8Array(lzImage.data);\n const ret = context.createImageData(lzImage.width, lzImage.height);\n\n // First pass: decode RGB pixels (with default alpha=255 for\n // non-RGBA images)\n const at = lzRgb32Decompress(\n u8,\n 0,\n ret.data,\n LzImageType.RGB32,\n lzImage.type !== LzImageType.RGBA,\n );\n\n if (!lzImage.top_down) {\n flipImageData(ret);\n }\n\n if (lzImage.type === LzImageType.RGBA) {\n // Second pass: decode alpha channel\n lzRgb32Decompress(u8, at, ret.data, LzImageType.RGBA, false);\n }\n\n return ret;\n } else if (lzImage.type === LzImageType.XXXA) {\n const u8 = new Uint8Array(lzImage.data);\n const ret = context.createImageData(lzImage.width, lzImage.height);\n lzRgb32Decompress(u8, 0, ret.data, LzImageType.RGBA, false);\n return ret;\n }\n\n return undefined;\n}\n","/*----------------------------------------------------------------------------\n** bitmap.ts\n** Handle SPICE_IMAGE_TYPE_BITMAP\n**\n** Converts a SPICE bitmap (BGRx or BGRA pixel format) to a web-\n** compatible ImageData object suitable for canvas putImageData().\n**--------------------------------------------------------------------------*/\n\nimport { SpiceBitmapFmt, SpiceBitmapFlags } from './enums.js';\nimport { SpiceBitmap } from './spicetype.js';\n\n/**\n * Convert a SPICE protocol bitmap to a web-compatible ImageData.\n *\n * SPICE bitmaps use BGRx (32BIT) or BGRA (RGBA) pixel order, while\n * the HTML Canvas API expects RGBA. This function swaps the red and\n * blue channels and handles the top-down vs bottom-up row ordering.\n *\n * Only 32-bit (BGRx) and RGBA (BGRA) formats are supported. Other\n * formats return `undefined`.\n *\n * @param context A 2D canvas rendering context (used only to call\n * createImageData for the correct backing store).\n * @param spiceBitmap The deserialized SpiceBitmap from the protocol.\n * @returns An ImageData with RGBA pixels, or undefined if the bitmap\n * format is not supported.\n */\nexport function convertSpiceBitmapToWeb(\n context: CanvasRenderingContext2D,\n spiceBitmap: SpiceBitmap,\n): ImageData | undefined {\n // Only 32-bit formats are supported\n if (\n spiceBitmap.format !== SpiceBitmapFmt._32BIT &&\n spiceBitmap.format !== SpiceBitmapFmt.RGBA\n ) {\n return undefined;\n }\n\n const u8 = new Uint8Array(spiceBitmap.data);\n const width = spiceBitmap.x;\n const height = spiceBitmap.y;\n const stride = spiceBitmap.stride;\n\n // Determine starting source offset and per-row adjustment.\n // SPICE bitmaps default to bottom-up row order unless TOP_DOWN\n // flag is set. For bottom-up, we start at the last row and work\n // backwards.\n let srcOffset = 0;\n let srcDec = 0;\n if (!(spiceBitmap.flags & SpiceBitmapFlags.TOP_DOWN)) {\n srcOffset = (height - 1) * stride;\n srcDec = 2 * stride;\n }\n\n const ret = context.createImageData(width, height);\n const dst = ret.data;\n\n // Walk every row. `offset` is the destination index (always\n // top-down in ImageData). `srcOffset` is the source index which\n // may walk top-down or bottom-up depending on the flag above.\n //\n // The outer loop condition uses `offset < height * stride` to\n // match the original bitmap.js iteration pattern exactly.\n for (let offset = 0; offset < height * stride; srcOffset -= srcDec) {\n for (let x = 0; x < width; x++, offset += 4, srcOffset += 4) {\n // BGR → RGB channel swap\n dst[offset + 0] = u8[srcOffset + 2]!;\n dst[offset + 1] = u8[srcOffset + 1]!;\n dst[offset + 2] = u8[srcOffset + 0]!;\n\n // FIXME - We effectively treat all images as having\n // SPICE_IMAGE_FLAGS_HIGH_BITS_SET\n if (spiceBitmap.format === SpiceBitmapFmt._32BIT) {\n dst[offset + 3] = 255;\n } else {\n // NOTE: The original code reads u8[src_offset] (byte 0\n // of the pixel) as alpha. This matches the original\n // bitmap.js behavior faithfully.\n dst[offset + 3] = u8[srcOffset]!;\n }\n }\n }\n\n return ret;\n}\n","/*----------------------------------------------------------------------------\n** display.ts\n** TypeScript implementation of the SPICE display channel.\n** Converted from display.js using ES6 class syntax.\n**\n** US-017: Connection and surface management — surface create/destroy,\n** image cache, multiple surface support, event hooking.\n** US-018: Draw operations and image decompression — DRAW_COPY,\n** DRAW_FILL, COPY_BITS, JPEG/JPEG_ALPHA asynchronous draw.\n** US-019: VP8 and MJPEG video streaming via MediaSource API.\n**--------------------------------------------------------------------------*/\n\nimport {\n SpiceChannel,\n SpiceMsgDisplay,\n SpiceMsgcDisplay,\n SpiceSurfaceFmt,\n SpiceImageType,\n SpiceImageFlags,\n SpiceRopd,\n SpiceClipType,\n SpiceBrushType,\n SpiceBitmapFmt,\n LzImageType,\n SpiceVideoCodecType,\n SPICE_SURFACE_FLAGS_PRIMARY,\n} from './enums';\n\nimport {\n SpiceMiniData,\n SpiceMsgSurfaceCreate,\n SpiceMsgSurfaceDestroy,\n SpiceMsgDisplayInvalList,\n SpiceMsgDisplayDrawCopy,\n SpiceMsgDisplayDrawFill,\n SpiceMsgDisplayCopyBits,\n SpiceMsgDisplayBase,\n SpiceMsgDisplayStreamCreate,\n SpiceMsgDisplayStreamData,\n SpiceMsgDisplayStreamDataSized,\n SpiceMsgDisplayStreamClip,\n SpiceMsgDisplayStreamDestroy,\n SpiceMsgDisplayStreamActivateReport,\n SpiceMsgcDisplayStreamReport,\n} from './spicemsg';\n\nimport {\n SpiceRect,\n SpiceImage,\n SpiceImageDescriptor,\n} from './spicetype';\n\nimport { SpiceConn, SpiceConnOptions } from './spiceconn';\nimport { registerChannelFactory } from './main';\nimport { convertSpiceQuicToWeb, QuicImageType } from './quic';\nimport { convertSpiceLzToWeb } from './lz';\nimport { convertSpiceBitmapToWeb } from './bitmap';\nimport { DEBUG, STREAM_DEBUG, DUMP_DRAWS, DUMP_CANVASES, EMPTY_GIF_IMAGE, dumpMediaElement, dumpMediaSource, dumpSourceBuffer } from '../utils/debug';\nimport {\n WebmConstants,\n WebmHeader,\n WebmVideoTrackEntry,\n WebmTracks,\n WebmCluster,\n WebmSimpleBlock,\n} from './webm';\n\n// ---------------------------------------------------------------------------\n// Canvas wrapper — typed extension of HTMLCanvasElement with context\n// ---------------------------------------------------------------------------\n\n/**\n * Internal canvas wrapper that holds a reference to the 2D context.\n * The original display.js attached `context` directly to the canvas\n * element; this interface makes that explicit in TypeScript.\n */\ninterface SpiceCanvas {\n canvas: HTMLCanvasElement;\n context: CanvasRenderingContext2D;\n}\n\n// ---------------------------------------------------------------------------\n// Surface metadata\n// ---------------------------------------------------------------------------\n\n/**\n * Runtime surface state maintained by the display channel.\n * One entry exists per active surface (primary or off-screen).\n */\nexport interface SurfaceEntry {\n /** Surface ID from the SPICE protocol. */\n surfaceId: number;\n /** Width in pixels. */\n width: number;\n /** Height in pixels. */\n height: number;\n /** Pixel format (SpiceSurfaceFmt.*). */\n format: number;\n /** Surface flags (e.g. SPICE_SURFACE_FLAGS_PRIMARY). */\n flags: number;\n /** Canvas and its 2D context. */\n canvas: SpiceCanvas;\n /** Counter of draw operations (for debug canvas naming). */\n drawCount: number;\n}\n\n// ---------------------------------------------------------------------------\n// Image cache\n// ---------------------------------------------------------------------------\n\n/**\n * Image cache keyed by the 64-bit image descriptor ID (as bigint).\n * Values are ImageData objects that can be put directly onto a canvas\n * context.\n */\nexport type ImageCache = Record<string, ImageData>;\n\n// ---------------------------------------------------------------------------\n// Stream state (US-019)\n// ---------------------------------------------------------------------------\n\n/**\n * Stream entry type for video streams (VP8 and MJPEG).\n * Tracks the video element, MediaSource, SourceBuffer, frame queue,\n * timing state, and stream report for one active stream.\n */\nexport interface StreamEntry {\n /** Stream ID from the SPICE protocol. */\n id: number;\n /** Surface associated with this stream. */\n surfaceId: number;\n /** Video codec type (SpiceVideoCodecType.*). */\n codecType: number;\n /** Stream dimensions. */\n streamWidth: number;\n streamHeight: number;\n /** Destination rectangle. */\n dest: { left: number; top: number; right: number; bottom: number };\n /** Clip region. */\n clip: { type: number } | undefined;\n /** MJPEG frames currently loading. */\n framesLoading: number;\n /** VP8 video element. */\n video: HTMLVideoElement | undefined;\n /** VP8 MediaSource. */\n media: MediaSource | undefined;\n /** VP8 SourceBuffer. */\n sourceBuffer: SourceBuffer | undefined;\n /** VP8 frame queue. */\n queue: Array<{ msgMmtime: number; mb: ArrayBuffer }>;\n /** VP8 start time. */\n startTime: number;\n /** VP8 cluster time. */\n clusterTime: number;\n /** VP8 append state. */\n appendOkay: boolean;\n /** VP8/MJPEG current frame. */\n currentFrame: { msgMmtime: number; mb?: ArrayBuffer } | undefined;\n /** Stream report (if active). */\n report: SpiceMsgcDisplayStreamReport | undefined;\n /** Max window size for report. */\n maxWindowSize: number;\n /** Timeout in ms for report. */\n timeoutMs: number;\n}\n\n// ---------------------------------------------------------------------------\n// Callbacks for display events\n// ---------------------------------------------------------------------------\n\n/**\n * Callback fired when the primary surface is created or destroyed.\n */\nexport interface DisplaySurfaceCallback {\n (surfaceId: number, width: number, height: number, created: boolean): void;\n}\n\n// ---------------------------------------------------------------------------\n// DrawCopyHelper parameter — typed structure for draw_copy_helper\n// ---------------------------------------------------------------------------\n\n/**\n * Internal parameter object for drawCopyHelper.\n * Aggregates all information needed to paint an image onto a surface.\n */\ninterface DrawCopyParams {\n base: SpiceMsgDisplayBase;\n srcArea: SpiceRect;\n imageData: ImageData;\n tag: string;\n hasAlpha: boolean;\n descriptor: SpiceImageDescriptor | null;\n}\n\n// ---------------------------------------------------------------------------\n// SpiceDisplayConn\n// ---------------------------------------------------------------------------\n\n/**\n * SPICE display channel. Manages surface creation/destruction,\n * image caching, draw operations, and video streaming.\n *\n * US-017 scope: surface lifecycle, image cache, event hooking.\n * US-018 scope: draw COPY/FILL/COPY_BITS, image decompression dispatch.\n * US-019 scope: VP8 and MJPEG video streaming via MediaSource API.\n */\nexport class SpiceDisplayConn extends SpiceConn {\n // -- Surfaces --\n surfaces: Record<number, SurfaceEntry> = {};\n primarySurface: number | undefined;\n\n // -- Image cache --\n cache: ImageCache = {};\n\n // -- Streams (US-019) --\n streams: Record<number, StreamEntry> = {};\n\n // -- Event listeners --\n private focusListener: (() => void) | undefined;\n\n // -- Display callbacks --\n onSurface: DisplaySurfaceCallback | undefined;\n\n constructor(options: SpiceConnOptions)\n {\n super(options);\n }\n\n // -----------------------------------------------------------------------\n // Channel message dispatcher\n // -----------------------------------------------------------------------\n\n protected override processChannelMessage(msg: SpiceMiniData): boolean\n {\n if (msg.type === SpiceMsgDisplay.MODE)\n {\n this.knownUnimplemented(msg.type, \"Display Mode\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.MARK)\n {\n this.knownUnimplemented(msg.type, \"Display Mark\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.RESET)\n {\n DEBUG > 2 && console.log(\"Display reset\");\n const surface = this.surfaces[this.primarySurface!];\n if (surface)\n {\n surface.canvas.context.restore();\n }\n return true;\n }\n\n // -- Draw operations (US-018) --\n if (msg.type === SpiceMsgDisplay.DRAW_COPY)\n {\n return this.handleDrawCopy(msg);\n }\n\n if (msg.type === SpiceMsgDisplay.DRAW_FILL)\n {\n return this.handleDrawFill(msg);\n }\n\n if (msg.type === SpiceMsgDisplay.DRAW_OPAQUE)\n {\n this.knownUnimplemented(msg.type, \"Display Draw Opaque\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.DRAW_BLEND)\n {\n this.knownUnimplemented(msg.type, \"Display Draw Blend\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.DRAW_BLACKNESS)\n {\n this.knownUnimplemented(msg.type, \"Display Draw Blackness\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.DRAW_WHITENESS)\n {\n this.knownUnimplemented(msg.type, \"Display Draw Whiteness\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.DRAW_INVERS)\n {\n this.knownUnimplemented(msg.type, \"Display Draw Invers\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.DRAW_ROP3)\n {\n this.knownUnimplemented(msg.type, \"Display Draw ROP3\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.DRAW_STROKE)\n {\n this.knownUnimplemented(msg.type, \"Display Draw Stroke\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.DRAW_TRANSPARENT)\n {\n this.knownUnimplemented(msg.type, \"Display Draw Transparent\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.DRAW_ALPHA_BLEND)\n {\n this.knownUnimplemented(msg.type, \"Display Draw Alpha Blend\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.DRAW_COMPOSITE)\n {\n this.knownUnimplemented(msg.type, \"Display Draw Composite\");\n return true;\n }\n\n // -- Copy bits (US-018) --\n if (msg.type === SpiceMsgDisplay.COPY_BITS)\n {\n return this.handleCopyBits(msg);\n }\n\n // -- Surface create/destroy (US-017) --\n if (msg.type === SpiceMsgDisplay.SURFACE_CREATE)\n {\n return this.handleSurfaceCreate(msg);\n }\n\n if (msg.type === SpiceMsgDisplay.SURFACE_DESTROY)\n {\n return this.handleSurfaceDestroy(msg);\n }\n\n // -- Streams (US-019) --\n if (msg.type === SpiceMsgDisplay.STREAM_CREATE)\n {\n return this.handleStreamCreate(msg);\n }\n\n if (msg.type === SpiceMsgDisplay.STREAM_DATA ||\n msg.type === SpiceMsgDisplay.STREAM_DATA_SIZED)\n {\n return this.handleStreamData(msg);\n }\n\n if (msg.type === SpiceMsgDisplay.STREAM_ACTIVATE_REPORT)\n {\n return this.handleStreamActivateReport(msg);\n }\n\n if (msg.type === SpiceMsgDisplay.STREAM_CLIP)\n {\n return this.handleStreamClip(msg);\n }\n\n if (msg.type === SpiceMsgDisplay.STREAM_DESTROY)\n {\n return this.handleStreamDestroy(msg);\n }\n\n if (msg.type === SpiceMsgDisplay.STREAM_DESTROY_ALL)\n {\n this.knownUnimplemented(msg.type, \"Display Stream Destroy All\");\n return true;\n }\n\n // -- Cache invalidation --\n if (msg.type === SpiceMsgDisplay.INVAL_LIST)\n {\n return this.handleInvalList(msg);\n }\n\n if (msg.type === SpiceMsgDisplay.INVAL_ALL_PIXMAPS)\n {\n this.knownUnimplemented(msg.type, \"Display Inval All Pixmaps\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.INVAL_PALETTE)\n {\n this.knownUnimplemented(msg.type, \"Display Inval Palette\");\n return true;\n }\n\n if (msg.type === SpiceMsgDisplay.INVAL_ALL_PALETTES)\n {\n this.knownUnimplemented(msg.type, \"Inval All Palettes\");\n return true;\n }\n\n // -- Monitors config --\n if (msg.type === SpiceMsgDisplay.MONITORS_CONFIG)\n {\n this.knownUnimplemented(msg.type, \"Display Monitors Config\");\n return true;\n }\n\n return false;\n }\n\n // -----------------------------------------------------------------------\n // Draw Copy (US-018)\n // -----------------------------------------------------------------------\n\n /**\n * Handle SPICE_MSG_DISPLAY_DRAW_COPY.\n * Dispatches image decompression based on the source bitmap type:\n * QUIC, LZ_RGB, BITMAP, JPEG, JPEG_ALPHA, FROM_CACHE, SURFACE.\n */\n private handleDrawCopy(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logErr(\"DrawCopy with no data\");\n return false;\n }\n\n const drawCopy = new SpiceMsgDisplayDrawCopy(msg.data);\n\n DEBUG > 1 && this.logDraw(\"DrawCopy\", drawCopy);\n\n if (!drawCopy.base.box.isSameSize(drawCopy.data.srcArea))\n {\n this.logWarn(\"FIXME: DrawCopy src_area is a different size than base.box; we do not handle that yet.\");\n }\n if (drawCopy.base.clip.type !== SpiceClipType.NONE)\n {\n this.logWarn(\"FIXME: DrawCopy we don't handle clipping yet\");\n }\n if (drawCopy.data.ropDescriptor !== SpiceRopd.OP_PUT)\n {\n this.logWarn(\"FIXME: DrawCopy we don't handle ropd type: \" + drawCopy.data.ropDescriptor);\n }\n if (drawCopy.data.mask.flags)\n {\n this.logWarn(\"FIXME: DrawCopy we don't handle mask flag: \" + drawCopy.data.mask.flags);\n }\n if (drawCopy.data.mask.bitmap)\n {\n this.logWarn(\"FIXME: DrawCopy we don't handle mask\");\n }\n\n if (drawCopy.data && drawCopy.data.srcBitmap)\n {\n const srcBitmap = drawCopy.data.srcBitmap;\n const descriptor = srcBitmap.descriptor;\n\n if (descriptor.flags &&\n descriptor.flags !== SpiceImageFlags.CACHE_ME &&\n descriptor.flags !== SpiceImageFlags.HIGH_BITS_SET)\n {\n this.logWarn(\"FIXME: DrawCopy unhandled image flags: \" + descriptor.flags);\n DEBUG <= 1 && this.logDraw(\"DrawCopy\", drawCopy);\n }\n\n // -- QUIC --\n if (descriptor.type === SpiceImageType.QUIC)\n {\n const surface = this.surfaces[drawCopy.base.surfaceId];\n if (!surface)\n {\n this.logWarn(\"DrawCopy QUIC: no surface \" + drawCopy.base.surfaceId);\n return false;\n }\n if (!srcBitmap.quic)\n {\n this.logWarn(\"FIXME: DrawCopy could not handle this QUIC file.\");\n return false;\n }\n const sourceImg = convertSpiceQuicToWeb(surface.canvas.context, srcBitmap.quic);\n if (!sourceImg)\n {\n this.logWarn(\"FIXME: DrawCopy QUIC decompression failed.\");\n return false;\n }\n\n return this.drawCopyHelper({\n base: drawCopy.base,\n srcArea: drawCopy.data.srcArea,\n imageData: sourceImg,\n tag: \"copyquic.\" + srcBitmap.quic.type,\n hasAlpha: srcBitmap.quic.type === QuicImageType.RGBA,\n descriptor: descriptor,\n });\n }\n\n // -- FROM_CACHE / FROM_CACHE_LOSSLESS --\n if (descriptor.type === SpiceImageType.FROM_CACHE ||\n descriptor.type === SpiceImageType.FROM_CACHE_LOSSLESS)\n {\n const cachedImage = this.cache[String(descriptor.id)];\n if (!cachedImage)\n {\n this.logWarn(\"FIXME: DrawCopy did not find image id \" + descriptor.id + \" in cache.\");\n return false;\n }\n\n return this.drawCopyHelper({\n base: drawCopy.base,\n srcArea: drawCopy.data.srcArea,\n imageData: cachedImage,\n tag: \"copycache.\" + descriptor.id,\n hasAlpha: true, /* FIXME - may want this to be false... */\n descriptor: descriptor,\n });\n /* FIXME - LOSSLESS CACHE ramifications not understood or handled */\n }\n\n // -- SURFACE --\n if (descriptor.type === SpiceImageType.SURFACE)\n {\n if (srcBitmap.surfaceId === null)\n {\n this.logWarn(\"DrawCopy SURFACE: no surfaceId on srcBitmap\");\n return false;\n }\n const sourceSurface = this.surfaces[srcBitmap.surfaceId];\n if (!sourceSurface)\n {\n this.logWarn(\"DrawCopy SURFACE: source surface \" + srcBitmap.surfaceId + \" not found\");\n return false;\n }\n\n const sourceContext = sourceSurface.canvas.context;\n const srcArea = drawCopy.data.srcArea;\n\n const sourceImg = sourceContext.getImageData(\n srcArea.left, srcArea.top,\n srcArea.right - srcArea.left,\n srcArea.bottom - srcArea.top\n );\n\n const computedSrcArea = new SpiceRect();\n computedSrcArea.top = 0;\n computedSrcArea.left = 0;\n computedSrcArea.right = sourceImg.width;\n computedSrcArea.bottom = sourceImg.height;\n\n return this.drawCopyHelper({\n base: drawCopy.base,\n srcArea: computedSrcArea,\n imageData: sourceImg,\n tag: \"copysurf.\" + srcBitmap.surfaceId,\n hasAlpha: sourceSurface.format !== SpiceSurfaceFmt._32_xRGB,\n descriptor: descriptor,\n });\n }\n\n // -- JPEG --\n if (descriptor.type === SpiceImageType.JPEG)\n {\n if (!srcBitmap.jpeg)\n {\n this.logWarn(\"FIXME: DrawCopy could not handle this JPEG file.\");\n return false;\n }\n\n this.handleDrawJpeg(\n drawCopy.base,\n descriptor,\n srcBitmap.jpeg.data,\n null, // no alpha\n drawCopy.base.surfaceId\n );\n return true;\n }\n\n // -- JPEG_ALPHA --\n if (descriptor.type === SpiceImageType.JPEG_ALPHA)\n {\n if (!srcBitmap.jpegAlpha)\n {\n this.logWarn(\"FIXME: DrawCopy could not handle this JPEG ALPHA file.\");\n return false;\n }\n\n // Decode alpha channel from LZ if surface is ARGB\n let alphaImg: ImageData | undefined;\n const surface = this.surfaces[drawCopy.base.surfaceId];\n if (surface && surface.format === SpiceSurfaceFmt._32_ARGB)\n {\n alphaImg = convertSpiceLzToWeb(surface.canvas.context, srcBitmap.jpegAlpha.alpha) ?? undefined;\n }\n\n this.handleDrawJpeg(\n drawCopy.base,\n descriptor,\n srcBitmap.jpegAlpha.data,\n alphaImg ?? null,\n drawCopy.base.surfaceId\n );\n return true;\n }\n\n // -- BITMAP --\n if (descriptor.type === SpiceImageType.BITMAP)\n {\n const surface = this.surfaces[drawCopy.base.surfaceId];\n if (!surface)\n {\n this.logWarn(\"DrawCopy BITMAP: no surface \" + drawCopy.base.surfaceId);\n return false;\n }\n if (!srcBitmap.bitmap)\n {\n this.logErr(\"null bitmap\");\n return false;\n }\n\n const sourceImg = convertSpiceBitmapToWeb(surface.canvas.context, srcBitmap.bitmap);\n if (!sourceImg)\n {\n this.logWarn(\"FIXME: Unable to interpret bitmap of format: \" +\n srcBitmap.bitmap.format);\n return false;\n }\n\n return this.drawCopyHelper({\n base: drawCopy.base,\n srcArea: drawCopy.data.srcArea,\n imageData: sourceImg,\n tag: \"bitmap.\" + srcBitmap.bitmap.format,\n hasAlpha: srcBitmap.bitmap.format !== SpiceBitmapFmt._32BIT,\n descriptor: descriptor,\n });\n }\n\n // -- LZ_RGB --\n if (descriptor.type === SpiceImageType.LZ_RGB)\n {\n const surface = this.surfaces[drawCopy.base.surfaceId];\n if (!surface)\n {\n this.logWarn(\"DrawCopy LZ_RGB: no surface \" + drawCopy.base.surfaceId);\n return false;\n }\n if (!srcBitmap.lzRgb)\n {\n this.logErr(\"null lz_rgb\");\n return false;\n }\n\n const sourceImg = convertSpiceLzToWeb(surface.canvas.context, srcBitmap.lzRgb);\n if (!sourceImg)\n {\n this.logWarn(\"FIXME: Unable to interpret bitmap of type: \" +\n srcBitmap.lzRgb.type);\n return false;\n }\n\n return this.drawCopyHelper({\n base: drawCopy.base,\n srcArea: drawCopy.data.srcArea,\n imageData: sourceImg,\n tag: \"lz_rgb.\" + srcBitmap.lzRgb.type,\n hasAlpha: srcBitmap.lzRgb.type === LzImageType.RGBA,\n descriptor: descriptor,\n });\n }\n\n // -- Unhandled type --\n this.logWarn(\"FIXME: DrawCopy unhandled image type: \" + descriptor.type);\n this.logDraw(\"DrawCopy\", drawCopy);\n return false;\n }\n\n this.logWarn(\"FIXME: DrawCopy no src_bitmap.\");\n return false;\n }\n\n // -----------------------------------------------------------------------\n // Draw Fill (US-018)\n // -----------------------------------------------------------------------\n\n /**\n * Handle SPICE_MSG_DISPLAY_DRAW_FILL.\n * Currently only handles solid brush fills.\n */\n private handleDrawFill(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logErr(\"DrawFill with no data\");\n return false;\n }\n\n const drawFill = new SpiceMsgDisplayDrawFill(msg.data);\n\n DEBUG > 1 && this.logDraw(\"DrawFill\", drawFill);\n\n if (drawFill.data.ropDescriptor !== SpiceRopd.OP_PUT)\n {\n this.logWarn(\"FIXME: DrawFill we don't handle ropd type: \" + drawFill.data.ropDescriptor);\n }\n if (drawFill.data.mask.flags)\n {\n this.logWarn(\"FIXME: DrawFill we don't handle mask flag: \" + drawFill.data.mask.flags);\n }\n if (drawFill.data.mask.bitmap)\n {\n this.logWarn(\"FIXME: DrawFill we don't handle mask\");\n }\n\n if (drawFill.data.brush.type === SpiceBrushType.SOLID)\n {\n // FIXME - do brushes ever have alpha?\n const color = drawFill.data.brush.color & 0xffffff;\n const colorStr = \"rgb(\" + (color >> 16) + \", \" + ((color >> 8) & 0xff) + \", \" + (color & 0xff) + \")\";\n\n const surface = this.surfaces[drawFill.base.surfaceId];\n if (!surface)\n {\n this.logWarn(\"DrawFill: no surface \" + drawFill.base.surfaceId);\n return false;\n }\n\n surface.canvas.context.fillStyle = colorStr;\n surface.canvas.context.fillRect(\n drawFill.base.box.left, drawFill.base.box.top,\n drawFill.base.box.right - drawFill.base.box.left,\n drawFill.base.box.bottom - drawFill.base.box.top\n );\n\n if (DUMP_DRAWS && this.parent && this.parent.dumpId && typeof document !== 'undefined')\n {\n const debugCanvas = document.createElement(\"canvas\");\n debugCanvas.setAttribute('width', String(surface.canvas.canvas.width));\n debugCanvas.setAttribute('height', String(surface.canvas.canvas.height));\n debugCanvas.setAttribute('id', \"fillbrush.\" + drawFill.base.surfaceId + \".\" + surface.drawCount);\n const debugCtx = debugCanvas.getContext(\"2d\");\n if (debugCtx)\n {\n debugCtx.fillStyle = colorStr;\n debugCtx.fillRect(\n drawFill.base.box.left, drawFill.base.box.top,\n drawFill.base.box.right - drawFill.base.box.left,\n drawFill.base.box.bottom - drawFill.base.box.top\n );\n }\n const dumpEl = document.getElementById(this.parent.dumpId);\n if (dumpEl)\n {\n dumpEl.appendChild(debugCanvas);\n }\n }\n\n surface.drawCount++;\n }\n else\n {\n this.logWarn(\"FIXME: DrawFill can't handle brush type: \" + drawFill.data.brush.type);\n }\n\n return true;\n }\n\n // -----------------------------------------------------------------------\n // Copy Bits (US-018)\n // -----------------------------------------------------------------------\n\n /**\n * Handle SPICE_MSG_DISPLAY_COPY_BITS.\n * Copies a region within the same surface.\n */\n private handleCopyBits(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logErr(\"CopyBits with no data\");\n return false;\n }\n\n const copyBits = new SpiceMsgDisplayCopyBits(msg.data);\n\n DEBUG > 1 && this.logDraw(\"CopyBits\", copyBits);\n\n const surface = this.surfaces[copyBits.base.surfaceId];\n if (!surface)\n {\n this.logWarn(\"CopyBits: no surface \" + copyBits.base.surfaceId);\n return false;\n }\n\n const sourceContext = surface.canvas.context;\n\n let width = surface.canvas.canvas.width - copyBits.srcPos.x;\n let height = surface.canvas.canvas.height - copyBits.srcPos.y;\n if (width > (copyBits.base.box.right - copyBits.base.box.left))\n {\n width = copyBits.base.box.right - copyBits.base.box.left;\n }\n if (height > (copyBits.base.box.bottom - copyBits.base.box.top))\n {\n height = copyBits.base.box.bottom - copyBits.base.box.top;\n }\n\n const sourceImg = sourceContext.getImageData(\n copyBits.srcPos.x, copyBits.srcPos.y, width, height\n );\n putImageDataWithAlpha(sourceContext, sourceImg,\n copyBits.base.box.left, copyBits.base.box.top);\n\n if (DUMP_DRAWS && this.parent && this.parent.dumpId && typeof document !== 'undefined')\n {\n const debugCanvas = document.createElement(\"canvas\");\n debugCanvas.setAttribute('width', String(width));\n debugCanvas.setAttribute('height', String(height));\n debugCanvas.setAttribute('id', \"copybits\" + copyBits.base.surfaceId + \".\" + surface.drawCount);\n const debugCtx = debugCanvas.getContext(\"2d\");\n if (debugCtx)\n {\n debugCtx.putImageData(sourceImg, 0, 0);\n }\n const dumpEl = document.getElementById(this.parent.dumpId);\n if (dumpEl)\n {\n dumpEl.appendChild(debugCanvas);\n }\n }\n\n surface.drawCount++;\n return true;\n }\n\n // -----------------------------------------------------------------------\n // Draw Copy Helper (US-018)\n // -----------------------------------------------------------------------\n\n /**\n * Common helper for all draw copy operations.\n * Handles alpha blending, image caching (CACHE_ME flag), and debug dumps.\n *\n * @param o - Aggregated draw parameters\n * @returns true on success\n */\n private drawCopyHelper(o: DrawCopyParams): boolean\n {\n const surface = this.surfaces[o.base.surfaceId];\n if (!surface)\n {\n this.logWarn(\"drawCopyHelper: no surface \" + o.base.surfaceId);\n return false;\n }\n\n const canvas = surface.canvas;\n\n if (o.hasAlpha)\n {\n /* FIXME - This is based on trial + error, not a serious thoughtful\n analysis of what Spice requires. See display.js for more. */\n if (surface.format === SpiceSurfaceFmt._32_xRGB)\n {\n stripAlpha(o.imageData);\n canvas.context.putImageData(o.imageData, o.base.box.left, o.base.box.top);\n }\n else\n {\n putImageDataWithAlpha(canvas.context, o.imageData,\n o.base.box.left, o.base.box.top);\n }\n }\n else\n {\n canvas.context.putImageData(o.imageData, o.base.box.left, o.base.box.top);\n }\n\n if (o.srcArea.left > 0 || o.srcArea.top > 0)\n {\n this.logWarn(\"FIXME: DrawCopy not shifting draw copies just yet...\");\n }\n\n if (o.descriptor && (o.descriptor.flags & SpiceImageFlags.CACHE_ME))\n {\n this.cache[String(o.descriptor.id)] = o.imageData;\n }\n\n if (DUMP_DRAWS && this.parent && this.parent.dumpId && typeof document !== 'undefined')\n {\n const debugCanvas = document.createElement(\"canvas\");\n debugCanvas.setAttribute('width', String(o.imageData.width));\n debugCanvas.setAttribute('height', String(o.imageData.height));\n debugCanvas.setAttribute('id', o.tag + \".\" +\n surface.drawCount + \".\" +\n o.base.surfaceId + \"@\" + o.base.box.left + \"x\" + o.base.box.top);\n const debugCtx = debugCanvas.getContext(\"2d\");\n if (debugCtx)\n {\n debugCtx.putImageData(o.imageData, 0, 0);\n }\n const dumpEl = document.getElementById(this.parent.dumpId);\n if (dumpEl)\n {\n dumpEl.appendChild(debugCanvas);\n }\n }\n\n surface.drawCount++;\n return true;\n }\n\n // -----------------------------------------------------------------------\n // JPEG draw handler (asynchronous — Image.onload)\n // -----------------------------------------------------------------------\n\n /**\n * Handle JPEG and JPEG_ALPHA draw copy operations.\n * Because JPEG decoding is asynchronous (via Image element onload),\n * this method creates an Image element, sets up the onload handler,\n * and returns immediately.\n *\n * @param base - The display base (surface, box, clip)\n * @param descriptor - The image descriptor (for caching)\n * @param jpegData - The raw JPEG data as ArrayBuffer\n * @param alphaImg - Optional alpha channel ImageData (for JPEG_ALPHA)\n * @param surfaceId - The target surface ID\n */\n private handleDrawJpeg(\n base: SpiceMsgDisplayBase,\n descriptor: SpiceImageDescriptor,\n jpegData: ArrayBuffer,\n alphaImg: ImageData | null,\n surfaceId: number\n ): void\n {\n if (typeof document === 'undefined')\n {\n this.logWarn(\"Cannot handle JPEG draw: no document (SSR).\");\n return;\n }\n\n // Convert binary JPEG data to data URI\n let tmpstr = \"data:image/jpeg,\";\n const qdv = new Uint8Array(jpegData);\n for (let i = 0; i < qdv.length; i++)\n {\n tmpstr += '%';\n if (qdv[i]! < 16)\n {\n tmpstr += '0';\n }\n tmpstr += qdv[i]!.toString(16);\n }\n\n const img = new Image();\n\n // Use arrow function closure to capture `this` and parameters\n img.onload = () =>\n {\n let context: CanvasRenderingContext2D;\n let useTempCanvas = false;\n\n const surface = this.surfaces[surfaceId];\n if (!surface)\n {\n // Surface destroyed before JPEG loaded — use temp canvas\n // to avoid errors but discard the result\n DEBUG > 2 && this.logInfo(\"Discarding jpeg; presumed lost surface \" + surfaceId);\n const tempCanvas = document.createElement(\"canvas\");\n tempCanvas.setAttribute('width', String(base.box.right));\n tempCanvas.setAttribute('height', String(base.box.bottom));\n const tempCtx = tempCanvas.getContext(\"2d\");\n if (!tempCtx)\n {\n return;\n }\n context = tempCtx;\n useTempCanvas = true;\n }\n else\n {\n context = surface.canvas.context;\n }\n\n if (alphaImg)\n {\n // JPEG_ALPHA: composite JPEG with alpha channel\n const c = document.createElement(\"canvas\");\n const t = c.getContext(\"2d\");\n if (!t)\n {\n return;\n }\n c.setAttribute('width', String(alphaImg.width));\n c.setAttribute('height', String(alphaImg.height));\n t.putImageData(alphaImg, 0, 0);\n t.globalCompositeOperation = 'source-in';\n t.drawImage(img, 0, 0);\n\n context.drawImage(c, base.box.left, base.box.top);\n\n if (descriptor.flags & SpiceImageFlags.CACHE_ME)\n {\n this.cache[String(descriptor.id)] =\n t.getImageData(0, 0, alphaImg.width, alphaImg.height);\n }\n }\n else\n {\n // Plain JPEG\n context.drawImage(img, base.box.left, base.box.top);\n\n // Give the GC a clue to recycle this; avoids memory leaks during video\n img.onload = null;\n img.src = EMPTY_GIF_IMAGE;\n\n if (descriptor.flags & SpiceImageFlags.CACHE_ME)\n {\n this.cache[String(descriptor.id)] =\n context.getImageData(base.box.left, base.box.top,\n base.box.right - base.box.left,\n base.box.bottom - base.box.top);\n }\n }\n\n if (!useTempCanvas && surface)\n {\n if (DUMP_DRAWS && this.parent && this.parent.dumpId)\n {\n const debugCanvas = document.createElement(\"canvas\");\n debugCanvas.setAttribute('id', \"jpeg.\" + surfaceId + \".\" +\n surface.drawCount + \".\" +\n surfaceId + \"@\" + base.box.left + \"x\" + base.box.top);\n const debugCtx = debugCanvas.getContext(\"2d\");\n if (debugCtx)\n {\n debugCtx.drawImage(img, 0, 0);\n }\n const dumpEl = document.getElementById(this.parent.dumpId);\n if (dumpEl)\n {\n dumpEl.appendChild(debugCanvas);\n }\n }\n\n surface.drawCount++;\n }\n };\n\n img.src = tmpstr;\n }\n\n // -----------------------------------------------------------------------\n // Debug draw logging\n // -----------------------------------------------------------------------\n\n /**\n * Log detailed information about a draw command for debugging.\n * Faithfully reproduced from the original display.js log_draw method.\n *\n * @param prefix - Label prefix (e.g. \"DrawCopy\", \"DrawFill\")\n * @param draw - The draw message (DrawCopy, DrawFill, CopyBits, etc.)\n */\n private logDraw(prefix: string, draw: { base: SpiceMsgDisplayBase; data?: DrawData; srcPos?: { x: number; y: number } }): void\n {\n const surface = this.surfaces[draw.base.surfaceId];\n if (!surface)\n {\n return;\n }\n\n let str = prefix + \".\" + draw.base.surfaceId + \".\" + surface.drawCount + \": \";\n str += \"base.box \" + draw.base.box.left + \", \" + draw.base.box.top + \" to \" +\n draw.base.box.right + \", \" + draw.base.box.bottom;\n str += \"; clip.type \" + draw.base.clip.type;\n\n const data = draw.data;\n if (data)\n {\n if ('srcArea' in data)\n {\n const srcArea = data.srcArea as SpiceRect;\n str += \"; src_area \" + srcArea.left + \", \" + srcArea.top + \" to \"\n + srcArea.right + \", \" + srcArea.bottom;\n }\n\n if ('srcBitmap' in data && data.srcBitmap)\n {\n const bitmap = data.srcBitmap as SpiceImage;\n str += \"; src_bitmap id: \" + bitmap.descriptor.id;\n str += \"; src_bitmap width \" + bitmap.descriptor.width + \", height \" + bitmap.descriptor.height;\n str += \"; src_bitmap type \" + bitmap.descriptor.type + \", flags \" + bitmap.descriptor.flags;\n if (bitmap.surfaceId !== null)\n {\n str += \"; src_bitmap surface_id \" + bitmap.surfaceId;\n }\n if (bitmap.bitmap)\n {\n str += \"; BITMAP format \" + bitmap.bitmap.format +\n \"; flags \" + bitmap.bitmap.flags +\n \"; x \" + bitmap.bitmap.x +\n \"; y \" + bitmap.bitmap.y +\n \"; stride \" + bitmap.bitmap.stride;\n }\n if (bitmap.quic)\n {\n str += \"; QUIC type \" + bitmap.quic.type +\n \"; width \" + bitmap.quic.width +\n \"; height \" + bitmap.quic.height;\n }\n if (bitmap.lzRgb)\n {\n str += \"; LZ_RGB length \" + bitmap.lzRgb.length +\n \"; magic \" + bitmap.lzRgb.magic +\n \"; version 0x\" + bitmap.lzRgb.version.toString(16) +\n \"; type \" + bitmap.lzRgb.type +\n \"; width \" + bitmap.lzRgb.width +\n \"; height \" + bitmap.lzRgb.height +\n \"; stride \" + bitmap.lzRgb.stride +\n \"; top down \" + bitmap.lzRgb.top_down;\n }\n }\n else if ('srcBitmap' in data)\n {\n str += \"; src_bitmap is null\";\n }\n\n if ('brush' in data)\n {\n const brush = data.brush as { type: number; color: number; pattern?: { pat: SpiceImage | null; pos: { x: number; y: number } } | null };\n if (brush.type === SpiceBrushType.SOLID)\n {\n str += \"; brush.color 0x\" + brush.color.toString(16);\n }\n if (brush.type === SpiceBrushType.PATTERN && brush.pattern)\n {\n str += \"; brush.pat \";\n if (brush.pattern.pat !== null)\n {\n str += \"[SpiceImage]\";\n }\n else\n {\n str += \"[null]\";\n }\n str += \" at \" + brush.pattern.pos.x + \", \" + brush.pattern.pos.y;\n }\n }\n\n if ('ropDescriptor' in data)\n {\n str += \"; rop_descriptor \" + (data as { ropDescriptor: number }).ropDescriptor;\n }\n if ('scaleMode' in data)\n {\n str += \"; scale_mode \" + (data as { scaleMode: number }).scaleMode;\n }\n if ('mask' in data)\n {\n const mask = data.mask as { flags: number; pos: { x: number; y: number }; bitmap: SpiceImage | null };\n str += \"; mask.flags \" + mask.flags;\n str += \"; mask.pos \" + mask.pos.x + \", \" + mask.pos.y;\n if (mask.bitmap !== null)\n {\n str += \"; mask.bitmap width \" + mask.bitmap.descriptor.width + \", height \" + mask.bitmap.descriptor.height;\n str += \"; mask.bitmap type \" + mask.bitmap.descriptor.type + \", flags \" + mask.bitmap.descriptor.flags;\n }\n else\n {\n str += \"; mask.bitmap is null\";\n }\n }\n }\n\n console.log(str);\n }\n\n // -----------------------------------------------------------------------\n // Stream Create (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Handle SPICE_MSG_DISPLAY_STREAM_CREATE.\n * Creates a new stream entry. For VP8, also creates a <video> element\n * and a MediaSource with a SourceBuffer for WebM/VP8 frames. For\n * MJPEG, just initialises the frame counter.\n */\n private handleStreamCreate(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logErr(\"StreamCreate with no data\");\n return false;\n }\n\n const m = new SpiceMsgDisplayStreamCreate(msg.data);\n\n STREAM_DEBUG > 0 && console.log(\n this.channelType() + \": MsgStreamCreate id\" + m.id +\n \"; type \" + m.codecType +\n \"; width \" + m.streamWidth +\n \"; height \" + m.streamHeight +\n \"; left \" + m.dest.left +\n \"; top \" + m.dest.top\n );\n\n if (this.streams[m.id])\n {\n console.log(\"Stream \" + m.id + \" already exists\");\n }\n\n // Build stream entry\n const entry: StreamEntry = {\n id: m.id,\n surfaceId: m.surfaceId,\n codecType: m.codecType,\n streamWidth: m.streamWidth,\n streamHeight: m.streamHeight,\n dest: { left: m.dest.left, top: m.dest.top, right: m.dest.right, bottom: m.dest.bottom },\n clip: undefined,\n framesLoading: 0,\n video: undefined,\n media: undefined,\n sourceBuffer: undefined,\n queue: [],\n startTime: 0,\n clusterTime: 0,\n appendOkay: false,\n currentFrame: undefined,\n report: undefined,\n maxWindowSize: 0,\n timeoutMs: 0,\n };\n\n this.streams[m.id] = entry;\n\n if (m.codecType === SpiceVideoCodecType.VP8)\n {\n if (typeof MediaSource === 'undefined' || typeof document === 'undefined')\n {\n this.logWarn(\"VP8 streaming requires MediaSource API — not available.\");\n return true;\n }\n\n const media = new MediaSource();\n const v = document.createElement(\"video\");\n v.src = URL.createObjectURL(media);\n\n v.setAttribute('muted', 'true');\n v.setAttribute('autoplay', 'true');\n v.setAttribute('width', String(m.streamWidth));\n v.setAttribute('height', String(m.streamHeight));\n\n let left = m.dest.left;\n let top = m.dest.top;\n const surface = this.surfaces[m.surfaceId];\n if (surface)\n {\n left += surface.canvas.canvas.offsetLeft;\n top += surface.canvas.canvas.offsetTop;\n }\n\n if (this.parent && this.parent.screenId)\n {\n const screenEl = document.getElementById(this.parent.screenId);\n if (screenEl)\n {\n screenEl.appendChild(v);\n }\n }\n v.setAttribute('style',\n \"pointer-events:none; position: absolute; top:\" + top + \"px; left:\" + left + \"px;\");\n\n entry.video = v;\n entry.media = media;\n\n // Wire up MediaSource events using arrow functions to capture stream/conn\n media.addEventListener('sourceopen', () =>\n {\n this.handleVideoSourceOpen(entry);\n }, false);\n media.addEventListener('sourceended', () =>\n {\n this.logErr('Video source unexpectedly ended.');\n }, false);\n media.addEventListener('sourceclosed', () =>\n {\n this.logErr('Video source unexpectedly closed.');\n }, false);\n }\n else if (m.codecType === SpiceVideoCodecType.MJPEG)\n {\n entry.framesLoading = 0;\n }\n else\n {\n console.log(\"Unhandled stream codec: \" + m.codecType);\n }\n\n return true;\n }\n\n // -----------------------------------------------------------------------\n // Stream Data (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Handle SPICE_MSG_DISPLAY_STREAM_DATA and STREAM_DATA_SIZED.\n * Dispatches to VP8 or MJPEG handler depending on stream codec.\n */\n private handleStreamData(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logErr(\"StreamData with no data\");\n return false;\n }\n\n const isSized = (msg.type === SpiceMsgDisplay.STREAM_DATA_SIZED);\n const m = isSized\n ? new SpiceMsgDisplayStreamDataSized(msg.data)\n : new SpiceMsgDisplayStreamData(msg.data);\n\n const stream = this.streams[m.base.id];\n if (!stream)\n {\n console.log(\"no stream for data\");\n return false;\n }\n\n const mainConn = this.parent as (SpiceConn & { relativeNow?: () => number }) | undefined;\n const relativeNow = mainConn && typeof mainConn.relativeNow === 'function'\n ? mainConn.relativeNow()\n : 0;\n const timeUntilDue = m.base.multiMediaTime - relativeNow;\n\n if (stream.codecType === SpiceVideoCodecType.MJPEG)\n {\n this.processMjpegStreamData(stream, m, timeUntilDue);\n }\n\n if (stream.codecType === SpiceVideoCodecType.VP8)\n {\n this.processVideoStreamData(stream, m);\n }\n\n return true;\n }\n\n // -----------------------------------------------------------------------\n // Stream Activate Report (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Handle SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT.\n * Sets up a stream report object for quality feedback.\n */\n private handleStreamActivateReport(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logErr(\"StreamActivateReport with no data\");\n return false;\n }\n\n const m = new SpiceMsgDisplayStreamActivateReport(msg.data);\n\n const report = new SpiceMsgcDisplayStreamReport(m.streamId, m.uniqueId);\n const stream = this.streams[m.streamId];\n if (stream)\n {\n stream.report = report;\n stream.maxWindowSize = m.maxWindowSize;\n stream.timeoutMs = m.timeoutMs;\n }\n\n return true;\n }\n\n // -----------------------------------------------------------------------\n // Stream Clip (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Handle SPICE_MSG_DISPLAY_STREAM_CLIP.\n * Updates the clip region for a given stream.\n */\n private handleStreamClip(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logErr(\"StreamClip with no data\");\n return false;\n }\n\n const m = new SpiceMsgDisplayStreamClip(msg.data);\n STREAM_DEBUG > 1 && console.log(this.channelType() + \": MsgStreamClip id\" + m.id);\n\n const stream = this.streams[m.id];\n if (stream)\n {\n stream.clip = m.clip;\n }\n return true;\n }\n\n // -----------------------------------------------------------------------\n // Stream Destroy (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Handle SPICE_MSG_DISPLAY_STREAM_DESTROY.\n * Tears down the video element and MediaSource for VP8 streams,\n * then removes the stream entry.\n */\n private handleStreamDestroy(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logErr(\"StreamDestroy with no data\");\n return false;\n }\n\n const m = new SpiceMsgDisplayStreamDestroy(msg.data);\n STREAM_DEBUG > 0 && console.log(this.channelType() + \": MsgStreamDestroy id\" + m.id);\n\n const stream = this.streams[m.id];\n if (stream)\n {\n if (stream.codecType === SpiceVideoCodecType.VP8 && stream.video)\n {\n if (typeof document !== 'undefined' && this.parent && this.parent.screenId)\n {\n const screenEl = document.getElementById(this.parent.screenId);\n if (screenEl && stream.video.parentNode === screenEl)\n {\n screenEl.removeChild(stream.video);\n }\n }\n stream.sourceBuffer = undefined;\n stream.media = undefined;\n stream.video = undefined;\n }\n delete this.streams[m.id];\n }\n\n return true;\n }\n\n // -----------------------------------------------------------------------\n // VP8 — MediaSource handler (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Called when the MediaSource for a VP8 stream enters 'sourceopen'.\n * Adds a SourceBuffer for VP8/WebM, sends the WebM header + tracks,\n * and wires up buffer events.\n */\n private handleVideoSourceOpen(stream: StreamEntry): void\n {\n if (stream.sourceBuffer)\n {\n return; // already opened\n }\n\n if (!stream.media)\n {\n this.logErr(\"handleVideoSourceOpen: no MediaSource on stream \" + stream.id);\n return;\n }\n\n let sb: SourceBuffer;\n try\n {\n sb = stream.media.addSourceBuffer(WebmConstants.SPICE_VP8_CODEC);\n }\n catch (e: unknown)\n {\n this.logErr(\"Codec \" + WebmConstants.SPICE_VP8_CODEC + \" not available.\");\n return;\n }\n\n stream.sourceBuffer = sb;\n\n // Listen for debug video events\n this.listenForVideoEvents(stream);\n\n // Build WebM header + tracks buffer\n const h = new WebmHeader();\n const te = new WebmVideoTrackEntry(stream.streamWidth, stream.streamHeight);\n const t = new WebmTracks(te);\n\n const mb = new ArrayBuffer(h.bufferSize() + t.bufferSize());\n let offset = h.toBuffer(mb);\n t.toBuffer(mb, offset);\n\n sb.addEventListener('error', () =>\n {\n this.logErr(\"source_buffer error\");\n }, false);\n\n sb.addEventListener('updateend', () =>\n {\n this.handleAppendVideoBufferDone(stream);\n }, false);\n\n this.appendVideoBuffer(stream, mb);\n }\n\n // -----------------------------------------------------------------------\n // VP8 — append buffer (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Append an ArrayBuffer to the VP8 stream's SourceBuffer.\n * Sets appendOkay to false until the updateend event fires.\n */\n private appendVideoBuffer(stream: StreamEntry, mb: ArrayBuffer): void\n {\n if (!stream.sourceBuffer)\n {\n return;\n }\n try\n {\n stream.appendOkay = false;\n stream.sourceBuffer.appendBuffer(mb);\n }\n catch (e: unknown)\n {\n const message = e instanceof Error ? e.message : String(e);\n this.logErr(\"Error invoking appendBuffer: \" + message);\n }\n }\n\n // -----------------------------------------------------------------------\n // VP8 — updateend handler (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Called when the SourceBuffer finishes appending.\n * Sends stream reports, drains the queue, advances the video\n * currentTime if it falls behind, and attempts to play if paused.\n */\n private handleAppendVideoBufferDone(stream: StreamEntry): void\n {\n // Send stream report for the current frame\n if (stream.currentFrame && stream.report)\n {\n const mainConn = this.parent as (SpiceConn & { relativeNow?: () => number }) | undefined;\n const relativeNow = mainConn && typeof mainConn.relativeNow === 'function'\n ? mainConn.relativeNow()\n : 0;\n this.processStreamDataReport(\n stream, stream.currentFrame.msgMmtime,\n stream.currentFrame.msgMmtime - relativeNow\n );\n }\n\n // Drain the queue\n if (stream.queue.length > 0)\n {\n const next = stream.queue.shift()!;\n stream.currentFrame = { msgMmtime: next.msgMmtime };\n if (next.mb)\n {\n this.appendVideoBuffer(stream, next.mb);\n }\n }\n else\n {\n stream.appendOkay = true;\n }\n\n if (!stream.video)\n {\n STREAM_DEBUG > 0 &&\n console.log(\"Stream id \" + stream.id + \" received updateend after video is gone.\");\n return;\n }\n\n // Advance video currentTime if it falls behind the buffered range\n if (stream.video.buffered.length > 0)\n {\n const lastStart = stream.video.buffered.start(stream.video.buffered.length - 1);\n if (stream.video.currentTime < lastStart)\n {\n console.log(\"Video appears to have fallen behind; advancing to \" + lastStart);\n stream.video.currentTime = lastStart;\n }\n }\n\n /* Modern browsers try not to auto play video. */\n if (stream.video.paused && stream.video.readyState >= 2)\n {\n stream.video.play().catch(() => { /* ignore autoplay rejection */ });\n }\n\n STREAM_DEBUG > 1 && stream.video &&\n console.log(stream.video.currentTime + \":id \" + stream.id +\n \" updateend \" + dumpMediaElement(stream.video));\n }\n\n // -----------------------------------------------------------------------\n // VP8 — push or queue frame (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Either immediately append to SourceBuffer if ready, or queue\n * the frame for later append when the current operation completes.\n */\n private pushOrQueue(\n stream: StreamEntry,\n msgMmtime: number,\n mb: ArrayBuffer\n ): void\n {\n if (stream.appendOkay)\n {\n stream.currentFrame = { msgMmtime };\n this.appendVideoBuffer(stream, mb);\n }\n else\n {\n stream.queue.push({ msgMmtime, mb });\n }\n }\n\n // -----------------------------------------------------------------------\n // VP8 — simple block (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Create a WebM SimpleBlock element for a VP8 frame and push/queue it.\n */\n private videoSimpleBlock(\n stream: StreamEntry,\n msg: SpiceMsgDisplayStreamData | SpiceMsgDisplayStreamDataSized,\n keyframe: boolean\n ): void\n {\n const simple = new WebmSimpleBlock(\n msg.base.multiMediaTime - stream.clusterTime,\n msg.data.slice().buffer as ArrayBuffer,\n keyframe\n );\n const mb = new ArrayBuffer(simple.bufferSize());\n simple.toBuffer(mb);\n\n this.pushOrQueue(stream, msg.base.multiMediaTime, mb);\n }\n\n // -----------------------------------------------------------------------\n // VP8 — new cluster (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Start a new WebM Cluster (keyframe), then immediately emit a\n * SimpleBlock with the same frame data.\n */\n private newVideoCluster(\n stream: StreamEntry,\n msg: SpiceMsgDisplayStreamData | SpiceMsgDisplayStreamDataSized\n ): void\n {\n stream.clusterTime = msg.base.multiMediaTime;\n const c = new WebmCluster(stream.clusterTime - stream.startTime);\n\n const mb = new ArrayBuffer(c.bufferSize());\n c.toBuffer(mb);\n\n this.pushOrQueue(stream, msg.base.multiMediaTime, mb);\n\n this.videoSimpleBlock(stream, msg, true);\n }\n\n // -----------------------------------------------------------------------\n // VP8 — process stream data (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Process a VP8 video stream data message.\n * Starts a new cluster on the first frame or when the cluster\n * time exceeds MAX_CLUSTER_TIME, otherwise emits a simple block.\n */\n private processVideoStreamData(\n stream: StreamEntry,\n msg: SpiceMsgDisplayStreamData | SpiceMsgDisplayStreamDataSized\n ): void\n {\n if (stream.startTime === 0)\n {\n stream.startTime = msg.base.multiMediaTime;\n this.newVideoCluster(stream, msg);\n }\n else if (msg.base.multiMediaTime - stream.clusterTime >= WebmConstants.MAX_CLUSTER_TIME)\n {\n this.newVideoCluster(stream, msg);\n }\n else\n {\n this.videoSimpleBlock(stream, msg, false);\n }\n }\n\n // -----------------------------------------------------------------------\n // MJPEG — process stream data (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Process an MJPEG stream data frame.\n * Rate control: if a frame is late and another is currently loading,\n * the new frame is dropped to help the browser keep up.\n * Otherwise, the JPEG data is turned into a data URI, a SpiceMsgDisplayBase\n * is constructed from the stream state, and the existing handleDrawJpeg\n * path is reused for rendering.\n */\n private processMjpegStreamData(\n stream: StreamEntry,\n m: SpiceMsgDisplayStreamData | SpiceMsgDisplayStreamDataSized,\n timeUntilDue: number\n ): void\n {\n /* Rate control: if we are behind and already loading a frame, drop */\n if (timeUntilDue < 0 && stream.framesLoading > 0)\n {\n if (stream.report)\n {\n stream.report.numDrops++;\n }\n return;\n }\n\n if (typeof document === 'undefined')\n {\n return;\n }\n\n // Build JPEG data URI from the raw stream data\n let tmpstr = \"data:image/jpeg,\";\n for (let i = 0; i < m.data.length; i++)\n {\n tmpstr += '%';\n if (m.data[i]! < 16)\n {\n tmpstr += '0';\n }\n tmpstr += m.data[i]!.toString(16);\n }\n\n // Construct a display base from the stream state\n const strmBase = new SpiceMsgDisplayBase();\n strmBase.surfaceId = stream.surfaceId;\n // Use per-frame dest if sized, else stream dest\n const dest = ('dest' in m && m instanceof SpiceMsgDisplayStreamDataSized)\n ? m.dest\n : stream.dest;\n strmBase.box = new SpiceRect();\n strmBase.box.left = dest.left;\n strmBase.box.top = dest.top;\n strmBase.box.right = dest.right;\n strmBase.box.bottom = dest.bottom;\n\n // Create the image and load the JPEG\n const img = new Image();\n const streamId = stream.id;\n const msgMmtime = m.base.multiMediaTime;\n\n img.onload = () =>\n {\n const activeStream = this.streams[streamId];\n if (activeStream)\n {\n activeStream.framesLoading--;\n }\n\n let context: CanvasRenderingContext2D;\n let useTempCanvas = false;\n\n const surface = this.surfaces[strmBase.surfaceId];\n if (!surface)\n {\n DEBUG > 2 && this.logInfo(\"Discarding mjpeg; presumed lost surface \" + strmBase.surfaceId);\n const tempCanvas = document.createElement(\"canvas\");\n tempCanvas.setAttribute('width', String(strmBase.box.right));\n tempCanvas.setAttribute('height', String(strmBase.box.bottom));\n const tempCtx = tempCanvas.getContext(\"2d\");\n if (!tempCtx)\n {\n return;\n }\n context = tempCtx;\n useTempCanvas = true;\n }\n else\n {\n context = surface.canvas.context;\n }\n\n // Plain MJPEG draw (no alpha channel)\n context.drawImage(img, strmBase.box.left, strmBase.box.top);\n\n // GC hint\n img.onload = null;\n img.src = EMPTY_GIF_IMAGE;\n\n if (!useTempCanvas && surface)\n {\n if (DUMP_DRAWS && this.parent && this.parent.dumpId)\n {\n const debugCanvas = document.createElement(\"canvas\");\n debugCanvas.setAttribute('id', \"mjpeg.\" + streamId + \".\" +\n surface.drawCount + \".\" +\n strmBase.surfaceId + \"@\" + strmBase.box.left + \"x\" + strmBase.box.top);\n const debugCtx = debugCanvas.getContext(\"2d\");\n if (debugCtx)\n {\n debugCtx.drawImage(img, 0, 0);\n }\n const dumpEl = document.getElementById(this.parent.dumpId);\n if (dumpEl)\n {\n dumpEl.appendChild(debugCanvas);\n }\n }\n\n surface.drawCount++;\n }\n\n // Stream report\n if (activeStream && activeStream.report)\n {\n const mainConn = this.parent as (SpiceConn & { relativeNow?: () => number }) | undefined;\n const relNow = mainConn && typeof mainConn.relativeNow === 'function'\n ? mainConn.relativeNow()\n : 0;\n this.processStreamDataReport(activeStream, msgMmtime, msgMmtime - relNow);\n }\n };\n img.src = tmpstr;\n\n stream.framesLoading++;\n }\n\n // -----------------------------------------------------------------------\n // Stream data report (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Accumulate stream quality data and send a report to the server\n * when the window is full or the timeout has expired.\n */\n private processStreamDataReport(\n stream: StreamEntry,\n msgMmtime: number,\n timeUntilDue: number\n ): void\n {\n if (!stream.report)\n {\n return;\n }\n\n stream.report.numFrames++;\n if (stream.report.startFrameMmTime === 0)\n {\n stream.report.startFrameMmTime = msgMmtime;\n }\n\n if (stream.report.numFrames > stream.maxWindowSize ||\n (msgMmtime - stream.report.startFrameMmTime) > stream.timeoutMs)\n {\n stream.report.endFrameMmTime = msgMmtime;\n stream.report.lastFrameDelay = timeUntilDue;\n\n const msg = new SpiceMiniData();\n msg.buildMsg(SpiceMsgcDisplay.STREAM_REPORT, stream.report);\n this.sendMsg(msg);\n\n stream.report.startFrameMmTime = 0;\n stream.report.numFrames = 0;\n stream.report.numDrops = 0;\n }\n }\n\n // -----------------------------------------------------------------------\n // VP8 — video debug event listeners (US-019)\n // -----------------------------------------------------------------------\n\n /**\n * Attach debug event listeners to a VP8 stream's video element.\n * The level of verbosity is controlled by STREAM_DEBUG.\n */\n private listenForVideoEvents(stream: StreamEntry): void\n {\n if (!stream.video)\n {\n return;\n }\n\n const video = stream.video;\n\n const debugHandler = (e: Event) =>\n {\n if (stream.video)\n {\n if (STREAM_DEBUG > 0 || stream.video.buffered.length > 1)\n {\n console.log(stream.video.currentTime + \":id \" + stream.id +\n \" event \" + e.type + dumpMediaElement(stream.video));\n }\n }\n\n if (STREAM_DEBUG > 1 && stream.media)\n {\n console.log(\" media_source \" + dumpMediaSource(stream.media));\n }\n\n if (STREAM_DEBUG > 1 && stream.sourceBuffer)\n {\n console.log(\" source_buffer \" + dumpSourceBuffer(stream.sourceBuffer));\n }\n\n if (STREAM_DEBUG > 1 || stream.queue.length > 1)\n {\n console.log(\" queue len \" + stream.queue.length + \"; append_okay: \" + stream.appendOkay);\n }\n };\n\n const video0Events = [\"abort\", \"error\"];\n const video1Events = [\n \"loadstart\", \"suspend\", \"emptied\", \"stalled\", \"loadedmetadata\",\n \"loadeddata\", \"canplay\", \"canplaythrough\", \"playing\", \"waiting\",\n \"seeking\", \"seeked\", \"ended\", \"durationchange\", \"play\", \"pause\",\n \"ratechange\",\n ];\n const video2Events = [\"timeupdate\", \"progress\", \"resize\", \"volumechange\"];\n\n video0Events.forEach((name) => video.addEventListener(name, debugHandler));\n if (STREAM_DEBUG > 0)\n {\n video1Events.forEach((name) => video.addEventListener(name, debugHandler));\n }\n if (STREAM_DEBUG > 1)\n {\n video2Events.forEach((name) => video.addEventListener(name, debugHandler));\n }\n }\n\n // -----------------------------------------------------------------------\n // Surface create\n // -----------------------------------------------------------------------\n\n private handleSurfaceCreate(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logErr(\"SurfaceCreate with no data\");\n return false;\n }\n\n const m = new SpiceMsgSurfaceCreate(msg.data);\n\n DEBUG > 1 && console.log(\n this.channelType() + \": MsgSurfaceCreate id \" + m.surface.surfaceId +\n \"; \" + m.surface.width + \"x\" + m.surface.height +\n \"; format \" + m.surface.format +\n \"; flags \" + m.surface.flags\n );\n\n if (m.surface.format !== SpiceSurfaceFmt._32_xRGB &&\n m.surface.format !== SpiceSurfaceFmt._32_ARGB)\n {\n this.logWarn(\"FIXME: cannot handle surface format \" + m.surface.format + \" yet.\");\n return false;\n }\n\n // Create canvas for this surface (SSR-safe: guard with typeof check)\n if (typeof document === 'undefined')\n {\n this.logWarn(\"Cannot create surface canvas: no document (SSR).\");\n return false;\n }\n\n const canvasEl = document.createElement(\"canvas\");\n canvasEl.setAttribute('width', String(m.surface.width));\n canvasEl.setAttribute('height', String(m.surface.height));\n canvasEl.setAttribute('id', \"spice_surface_\" + m.surface.surfaceId);\n canvasEl.setAttribute('tabindex', String(m.surface.surfaceId));\n\n const ctx = canvasEl.getContext(\"2d\");\n if (!ctx)\n {\n this.logErr(\"Failed to get 2D context for surface \" + m.surface.surfaceId);\n return false;\n }\n\n // Debug: dump canvases if enabled\n if (DUMP_CANVASES && this.parent && this.parent.dumpId)\n {\n const dumpEl = document.getElementById(this.parent.dumpId);\n if (dumpEl)\n {\n dumpEl.appendChild(canvasEl);\n }\n }\n\n const spiceCanvas: SpiceCanvas = {\n canvas: canvasEl,\n context: ctx,\n };\n\n const entry: SurfaceEntry = {\n surfaceId: m.surface.surfaceId,\n width: m.surface.width,\n height: m.surface.height,\n format: m.surface.format,\n flags: m.surface.flags,\n canvas: spiceCanvas,\n drawCount: 0,\n };\n\n this.surfaces[m.surface.surfaceId] = entry;\n\n // Primary surface setup\n if (m.surface.flags & SPICE_SURFACE_FLAGS_PRIMARY)\n {\n this.primarySurface = m.surface.surfaceId;\n\n /* This .save() is done entirely to enable SPICE_MSG_DISPLAY_RESET */\n ctx.save();\n\n if (this.parent && this.parent.screenId)\n {\n const screenEl = document.getElementById(this.parent.screenId);\n if (screenEl)\n {\n screenEl.appendChild(canvasEl);\n /* Leave width dynamic, but correctly set the height */\n screenEl.style.height = m.surface.height + \"px\";\n }\n }\n\n this.hookEvents();\n }\n\n // Notify callback\n if (this.onSurface)\n {\n this.onSurface(m.surface.surfaceId, m.surface.width, m.surface.height, true);\n }\n\n return true;\n }\n\n // -----------------------------------------------------------------------\n // Surface destroy\n // -----------------------------------------------------------------------\n\n private handleSurfaceDestroy(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logErr(\"SurfaceDestroy with no data\");\n return false;\n }\n\n const m = new SpiceMsgSurfaceDestroy(msg.data);\n DEBUG > 1 && console.log(this.channelType() + \": MsgSurfaceDestroy id \" + m.surfaceId);\n\n this.deleteSurface(m.surfaceId);\n return true;\n }\n\n // -----------------------------------------------------------------------\n // Surface deletion\n // -----------------------------------------------------------------------\n\n /**\n * Remove a surface from the internal registry and the DOM.\n *\n * @param surfaceId - The surface ID to remove\n */\n deleteSurface(surfaceId: number): void\n {\n const surface = this.surfaces[surfaceId];\n if (!surface)\n {\n return;\n }\n\n if (typeof document !== 'undefined')\n {\n const canvasEl = surface.canvas.canvas;\n\n if (DUMP_CANVASES && this.parent && this.parent.dumpId)\n {\n const dumpEl = document.getElementById(this.parent.dumpId);\n if (dumpEl && canvasEl.parentNode === dumpEl)\n {\n dumpEl.removeChild(canvasEl);\n }\n }\n\n if (this.primarySurface === surfaceId)\n {\n this.unhookEvents();\n this.primarySurface = undefined;\n\n if (this.parent && this.parent.screenId)\n {\n const screenEl = document.getElementById(this.parent.screenId);\n if (screenEl && canvasEl.parentNode === screenEl)\n {\n screenEl.removeChild(canvasEl);\n }\n }\n }\n }\n\n // Notify callback\n if (this.onSurface)\n {\n this.onSurface(surfaceId, surface.width, surface.height, false);\n }\n\n delete this.surfaces[surfaceId];\n }\n\n // -----------------------------------------------------------------------\n // Destroy all surfaces\n // -----------------------------------------------------------------------\n\n /**\n * Destroy all surfaces. Called during channel teardown.\n */\n destroySurfaces(): void\n {\n const ids = Object.keys(this.surfaces).map(Number);\n for (const id of ids)\n {\n this.deleteSurface(id);\n }\n }\n\n // -----------------------------------------------------------------------\n // Image cache invalidation\n // -----------------------------------------------------------------------\n\n private handleInvalList(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n this.logErr(\"InvalList with no data\");\n return false;\n }\n\n const m = new SpiceMsgDisplayInvalList(msg.data);\n DEBUG > 1 && console.log(this.channelType() + \": MsgInvalList \" + m.count + \" items\");\n\n for (let i = 0; i < m.count; i++)\n {\n const resource = m.resources[i];\n if (resource)\n {\n const key = String(resource.id);\n if (this.cache[key] !== undefined)\n {\n delete this.cache[key];\n }\n }\n }\n return true;\n }\n\n // -----------------------------------------------------------------------\n // Image cache helpers\n // -----------------------------------------------------------------------\n\n /**\n * Store an image in the cache, keyed by its descriptor ID.\n *\n * @param id - The image descriptor ID (bigint)\n * @param imageData - The ImageData to cache\n */\n cacheImage(id: bigint, imageData: ImageData): void\n {\n this.cache[String(id)] = imageData;\n }\n\n /**\n * Retrieve a cached image by its descriptor ID.\n *\n * @param id - The image descriptor ID (bigint)\n * @returns The cached ImageData, or undefined if not found\n */\n getCachedImage(id: bigint): ImageData | undefined\n {\n return this.cache[String(id)];\n }\n\n /**\n * Check whether an image is in the cache.\n *\n * @param id - The image descriptor ID (bigint)\n * @returns true if the image is cached\n */\n hasImageInCache(id: bigint): boolean\n {\n return this.cache[String(id)] !== undefined;\n }\n\n // -----------------------------------------------------------------------\n // Surface accessors\n // -----------------------------------------------------------------------\n\n /**\n * Get a surface entry by its ID.\n *\n * @param surfaceId - The surface ID\n * @returns The surface entry, or undefined if not found\n */\n getSurface(surfaceId: number): SurfaceEntry | undefined\n {\n return this.surfaces[surfaceId];\n }\n\n /**\n * Get the primary surface entry.\n *\n * @returns The primary surface entry, or undefined\n */\n getPrimarySurface(): SurfaceEntry | undefined\n {\n if (this.primarySurface === undefined)\n {\n return undefined;\n }\n return this.surfaces[this.primarySurface];\n }\n\n // -----------------------------------------------------------------------\n // Event hooking / unhooking\n // -----------------------------------------------------------------------\n\n /**\n * Hook input and focus events onto the primary surface canvas.\n * This enables keyboard, mouse, and clipboard interaction.\n *\n * Note: Actual input event handler registration will be done by\n * the inputs channel or component layer. This method sets up the\n * canvas for focus/blur and clipboard grab.\n */\n hookEvents(): void\n {\n if (this.primarySurface === undefined)\n {\n return;\n }\n\n const surface = this.surfaces[this.primarySurface];\n if (!surface)\n {\n return;\n }\n\n const canvasEl = surface.canvas.canvas;\n\n // Focus handler for clipboard grab\n if (this.parent)\n {\n const mainConn = this.parent as SpiceConn & { sendClipboardGrab?: () => void };\n if (typeof mainConn.sendClipboardGrab === 'function')\n {\n this.focusListener = () => mainConn.sendClipboardGrab!();\n\n // Send host clipboard when the canvas is rendered initially\n this.focusListener();\n // Register focus event to grab host clipboard when the canvas gets focus\n canvasEl.addEventListener('focus', this.focusListener);\n }\n }\n\n canvasEl.focus();\n }\n\n /**\n * Unhook events from the primary surface canvas.\n */\n unhookEvents(): void\n {\n if (this.primarySurface === undefined)\n {\n return;\n }\n\n const surface = this.surfaces[this.primarySurface];\n if (!surface)\n {\n return;\n }\n\n const canvasEl = surface.canvas.canvas;\n\n if (this.focusListener)\n {\n canvasEl.removeEventListener('focus', this.focusListener);\n this.focusListener = undefined;\n }\n }\n\n // -----------------------------------------------------------------------\n // Cleanup\n // -----------------------------------------------------------------------\n\n override cleanup(): void\n {\n this.destroySurfaces();\n this.cache = {};\n this.streams = {};\n super.cleanup();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module-level helper functions (US-018)\n// ---------------------------------------------------------------------------\n\n/**\n * putImageData does not support alpha blending or compositing.\n * To draw ImageData with alpha, we render it onto a temporary canvas\n * and then use drawImage (which does handle alpha) to composite it\n * onto the target context.\n *\n * @param context - Target 2D rendering context\n * @param d - ImageData to draw with alpha blending\n * @param x - Target X position\n * @param y - Target Y position\n */\nfunction putImageDataWithAlpha(\n context: CanvasRenderingContext2D,\n d: ImageData,\n x: number,\n y: number\n): void\n{\n if (typeof document === 'undefined')\n {\n return;\n }\n const c = document.createElement(\"canvas\");\n const t = c.getContext(\"2d\");\n if (!t)\n {\n return;\n }\n c.setAttribute('width', String(d.width));\n c.setAttribute('height', String(d.height));\n t.putImageData(d, 0, 0);\n context.drawImage(c, x, y, d.width, d.height);\n}\n\n/**\n * Spice sends images with alpha=0 for surfaces with no alpha channel.\n * In that case we force alpha to 255 so the image is fully opaque.\n * Without this fix, images on xRGB surfaces would be invisible.\n *\n * @param d - ImageData whose alpha channel to strip (set to 255)\n */\nfunction stripAlpha(d: ImageData): void\n{\n for (let i = 0; i < (d.width * d.height * 4); i += 4)\n {\n d.data[i + 3] = 255;\n }\n}\n\n// ---------------------------------------------------------------------------\n// DrawData type — union of data shapes used by logDraw\n// ---------------------------------------------------------------------------\n\n/**\n * Internal type representing the `data` property of draw messages.\n * Used only by logDraw for debug output — includes SpiceCopy and\n * SpiceFill fields in a structural union.\n */\ninterface DrawData {\n srcArea?: SpiceRect;\n srcBitmap?: SpiceImage | null;\n brush?: { type: number; color: number; pattern?: { pat: SpiceImage | null; pos: { x: number; y: number } } | null };\n ropDescriptor?: number;\n scaleMode?: number;\n mask?: { flags: number; pos: { x: number; y: number }; bitmap: SpiceImage | null };\n}\n\n// ---------------------------------------------------------------------------\n// Register channel factory\n// ---------------------------------------------------------------------------\n\nregisterChannelFactory(SpiceChannel.DISPLAY, SpiceDisplayConn);\n","// ---------------------------------------------------------------------------\n// SpiceInputsConn — SPICE inputs channel (keyboard + mouse)\n//\n// US-020: Keyboard input channel\n// US-021: Mouse input channel (to be added in a subsequent story)\n// ---------------------------------------------------------------------------\n\nimport { SpiceConn, type SpiceConnOptions } from './spiceconn';\nimport {\n SpiceChannel,\n SpiceMsgInputs,\n SpiceMsgcInputs,\n SpiceMouseMode,\n SpiceMouseButton,\n SpiceMouseButtonMask,\n SPICE_INPUT_MOTION_ACK_BUNCH,\n} from './enums';\nimport { registerChannelFactory } from './main';\nimport {\n SpiceMiniData,\n SpiceMsgInputsInit,\n SpiceMsgInputsKeyModifiers,\n SpiceMsgcKeyDown,\n SpiceMsgcKeyUp,\n SpiceMsgcMousePosition,\n SpiceMsgcMouseMotion,\n SpiceMsgcMousePress,\n SpiceMsgcMouseRelease,\n type Serializable,\n} from './spicemsg';\nimport { KeyNames } from '../utils/atKeynames';\nimport { keycodeToStartScan, keycodeToEndScan, DEBUG } from '../utils/debug';\n\n// ---------------------------------------------------------------------------\n// Helper — build a SpiceMiniData message from a type + serializable payload\n// ---------------------------------------------------------------------------\n\nfunction buildInputMsg(type: number, payload: Serializable): SpiceMiniData\n{\n const msg = new SpiceMiniData();\n msg.buildMsg(type, payload);\n return msg;\n}\n\n// ---------------------------------------------------------------------------\n// Mouse button mapping helpers (US-021)\n// ---------------------------------------------------------------------------\n\n/**\n * Map a DOM MouseEvent.button value to a SPICE mouse button constant.\n *\n * DOM button mapping:\n * 0 = left, 1 = middle, 2 = right, 3 = back, 4 = forward\n *\n * SPICE button mapping:\n * 1 = left, 2 = middle, 3 = right, 4 = up (scroll), 5 = down (scroll)\n */\nfunction domButtonToSpice(domButton: number): number\n{\n switch (domButton)\n {\n case 0: return SpiceMouseButton.LEFT;\n case 1: return SpiceMouseButton.MIDDLE;\n case 2: return SpiceMouseButton.RIGHT;\n default: return SpiceMouseButton.INVALID;\n }\n}\n\n/**\n * Map DOM MouseEvent.buttons bitmask to a SPICE buttons_state mask.\n *\n * DOM buttons bitmask:\n * 1 = primary (left), 2 = secondary (right), 4 = auxiliary (middle)\n *\n * SPICE mask:\n * bit 0 = left, bit 1 = middle, bit 2 = right\n */\nfunction domButtonsToMask(domButtons: number): number\n{\n let mask = 0;\n if (domButtons & 1) { mask |= SpiceMouseButtonMask.LEFT; }\n if (domButtons & 4) { mask |= SpiceMouseButtonMask.MIDDLE; }\n if (domButtons & 2) { mask |= SpiceMouseButtonMask.RIGHT; }\n return mask;\n}\n\n// ---------------------------------------------------------------------------\n// Modifier key state\n//\n// These track the browser-side modifier state so we can detect when\n// focus changes cause the keyboard to go out of sync. -1 means\n// \"not yet initialised\"; it will be set on the first key event.\n// ---------------------------------------------------------------------------\n\ninterface ModifierState {\n shift: number; // -1 | 0 (false) | 1 (true)\n ctrl: number;\n alt: number;\n meta: number;\n}\n\n/** Meta key scancode (MetaLeft in AT extended encoding) */\nconst META_SCANCODE = 0xE0 | (0x5B << 8);\n\n// ---------------------------------------------------------------------------\n// SpiceInputsConn\n// ---------------------------------------------------------------------------\n\nexport class SpiceInputsConn extends SpiceConn {\n // -- Mouse state (initialised here for US-021) --\n mouseX: number | undefined = undefined;\n mouseY: number | undefined = undefined;\n buttonState: number = 0;\n waitingForAck: number = 0;\n\n // -- Mouse mode (set by SpiceMainConn via SpiceInputsLike) --\n mouseMode: number = 0;\n\n // -- Keyboard modifier state (channel-local; only relevant while\n // this connection is alive) --\n keyboardModifiers: number = 0;\n\n private modifiers: ModifierState = {\n shift: -1,\n ctrl: -1,\n alt: -1,\n meta: -1,\n };\n\n constructor(options: SpiceConnOptions)\n {\n super(options);\n }\n\n // -----------------------------------------------------------------------\n // Process server messages\n // -----------------------------------------------------------------------\n\n protected override processChannelMessage(msg: SpiceMiniData): boolean\n {\n if (msg.type === SpiceMsgInputs.INIT)\n {\n if (!msg.data) { return true; }\n const init = new SpiceMsgInputsInit(msg.data);\n this.keyboardModifiers = init.keyboardModifiers;\n DEBUG > 1 && console.log(\"MsgInputsInit - modifier \" + this.keyboardModifiers);\n // FIXME - We don't do anything with the keyboard modifiers...\n return true;\n }\n\n if (msg.type === SpiceMsgInputs.KEY_MODIFIERS)\n {\n if (!msg.data) { return true; }\n const key = new SpiceMsgInputsKeyModifiers(msg.data);\n this.keyboardModifiers = key.keyboardModifiers;\n DEBUG > 1 && console.log(\"MsgInputsKeyModifiers - modifier \" + this.keyboardModifiers);\n // FIXME - We don't do anything with the keyboard modifiers...\n return true;\n }\n\n if (msg.type === SpiceMsgInputs.MOUSE_MOTION_ACK)\n {\n DEBUG > 1 && console.log(\"mouse motion ack\");\n this.waitingForAck -= SPICE_INPUT_MOTION_ACK_BUNCH;\n return true;\n }\n\n return false;\n }\n\n // -----------------------------------------------------------------------\n // Keyboard — public handler methods\n //\n // These are designed to be called from the React component or\n // other DOM event handling layer. They accept the native\n // KeyboardEvent, do scancode translation, modifier sync, and\n // send the appropriate SPICE message.\n // -----------------------------------------------------------------------\n\n /**\n * Handle a DOM `keydown` event.\n *\n * Translates the browser key event to an AT scancode and sends\n * SPICE_MSGC_INPUTS_KEY_DOWN. Also checks and syncs modifier\n * key state.\n */\n handleKeyDown(e: KeyboardEvent): void\n {\n const scancode = keycodeToStartScan(e.keyCode, e.code);\n if (scancode === 0)\n {\n return;\n }\n\n this.checkAndUpdateModifiers(e, scancode);\n\n const key = new SpiceMsgcKeyDown(scancode);\n const outMsg = buildInputMsg(SpiceMsgcInputs.KEY_DOWN, key);\n if (this.state === 'ready')\n {\n this.sendMsg(outMsg);\n }\n\n e.preventDefault();\n }\n\n /**\n * Handle a DOM `keyup` event.\n *\n * Translates the browser key event to an AT break scancode and\n * sends SPICE_MSGC_INPUTS_KEY_UP.\n */\n handleKeyUp(e: KeyboardEvent): void\n {\n const scancode = keycodeToEndScan(e.keyCode, e.code);\n if (scancode === 0)\n {\n return;\n }\n\n this.checkAndUpdateModifiers(e, scancode);\n\n const key = new SpiceMsgcKeyUp(scancode);\n const outMsg = buildInputMsg(SpiceMsgcInputs.KEY_UP, key);\n if (this.state === 'ready')\n {\n this.sendMsg(outMsg);\n }\n\n e.preventDefault();\n }\n\n // -----------------------------------------------------------------------\n // Ctrl+Alt+Del helper\n // -----------------------------------------------------------------------\n\n /**\n * Send the Ctrl+Alt+Del key sequence to the guest.\n *\n * Temporarily presses Ctrl and Alt (if not already held), sends\n * Delete press/release, then restores original modifier state.\n */\n sendCtrlAltDel(): void\n {\n if (this.state !== 'ready')\n {\n return;\n }\n\n this.updateModifier(true, KeyNames.KEY_LCtrl);\n this.updateModifier(true, KeyNames.KEY_Alt);\n\n const deleteCode = KeyNames.KEY_KP_Decimal;\n const downKey = new SpiceMsgcKeyDown(deleteCode);\n const downMsg = buildInputMsg(SpiceMsgcInputs.KEY_DOWN, downKey);\n this.sendMsg(downMsg);\n\n // Send key-up with bit 7 set (break code)\n const upKey = new SpiceMsgcKeyUp(deleteCode | 0x80);\n const upMsg = buildInputMsg(SpiceMsgcInputs.KEY_UP, upKey);\n this.sendMsg(upMsg);\n\n if (this.modifiers.ctrl === 0)\n {\n this.updateModifier(false, KeyNames.KEY_LCtrl);\n }\n if (this.modifiers.alt === 0)\n {\n this.updateModifier(false, KeyNames.KEY_Alt);\n }\n }\n\n // -----------------------------------------------------------------------\n // Modifier sync helpers (private)\n // -----------------------------------------------------------------------\n\n /**\n * Send a single modifier key press or release.\n *\n * @param state - true = press, false = release\n * @param code - AT make scancode for the modifier key\n */\n private updateModifier(state: boolean, code: number): void\n {\n const msg = state\n ? buildInputMsg(SpiceMsgcInputs.KEY_DOWN, new SpiceMsgcKeyDown(code))\n : buildInputMsg(SpiceMsgcInputs.KEY_UP, new SpiceMsgcKeyUp(code | 0x80));\n\n this.sendMsg(msg);\n }\n\n /**\n * Check the DOM event's modifier flags against our tracked state.\n * If they're out of sync (e.g. because the user alt-tabbed away\n * and released a modifier while we didn't have focus), send\n * corrective press/release messages.\n *\n * @param e - The KeyboardEvent from the browser\n * @param code - The AT scancode (make or break) for the key event\n */\n private checkAndUpdateModifiers(e: KeyboardEvent, code: number): void\n {\n // Initialise modifier state on first key event\n if (this.modifiers.shift === -1)\n {\n this.modifiers.shift = e.shiftKey ? 1 : 0;\n this.modifiers.ctrl = e.ctrlKey ? 1 : 0;\n this.modifiers.alt = e.altKey ? 1 : 0;\n this.modifiers.meta = e.metaKey ? 1 : 0;\n }\n\n // Track state changes from the key being pressed/released\n if (code === KeyNames.KEY_ShiftL)\n {\n this.modifiers.shift = 1;\n }\n else if (code === KeyNames.KEY_Alt)\n {\n this.modifiers.alt = 1;\n }\n else if (code === KeyNames.KEY_LCtrl)\n {\n this.modifiers.ctrl = 1;\n }\n else if (code === META_SCANCODE)\n {\n this.modifiers.meta = 1;\n }\n else if (code === (0x80 | KeyNames.KEY_ShiftL))\n {\n this.modifiers.shift = 0;\n }\n else if (code === (0x80 | KeyNames.KEY_Alt))\n {\n this.modifiers.alt = 0;\n }\n else if (code === (0x80 | KeyNames.KEY_LCtrl))\n {\n this.modifiers.ctrl = 0;\n }\n else if (code === (0x8000 | META_SCANCODE))\n {\n this.modifiers.meta = 0;\n }\n\n // Sync with browser reality\n if (this.state !== 'ready')\n {\n return;\n }\n\n if (this.modifiers.shift !== (e.shiftKey ? 1 : 0))\n {\n console.log(\"Shift state out of sync\");\n this.updateModifier(e.shiftKey, KeyNames.KEY_ShiftL);\n this.modifiers.shift = e.shiftKey ? 1 : 0;\n }\n if (this.modifiers.alt !== (e.altKey ? 1 : 0))\n {\n console.log(\"Alt state out of sync\");\n this.updateModifier(e.altKey, KeyNames.KEY_Alt);\n this.modifiers.alt = e.altKey ? 1 : 0;\n }\n if (this.modifiers.ctrl !== (e.ctrlKey ? 1 : 0))\n {\n console.log(\"Ctrl state out of sync\");\n this.updateModifier(e.ctrlKey, KeyNames.KEY_LCtrl);\n this.modifiers.ctrl = e.ctrlKey ? 1 : 0;\n }\n if (this.modifiers.meta !== (e.metaKey ? 1 : 0))\n {\n console.log(\"Meta state out of sync\");\n this.updateModifier(e.metaKey, META_SCANCODE);\n this.modifiers.meta = e.metaKey ? 1 : 0;\n }\n }\n\n // -----------------------------------------------------------------------\n // Mouse — public handler methods (US-021)\n //\n // These translate DOM MouseEvent / WheelEvent into SPICE messages.\n // The React component (or other DOM layer) calls these directly.\n // -----------------------------------------------------------------------\n\n /**\n * Handle a DOM `mousemove` event.\n *\n * In client mode, sends absolute mouse position.\n * In server mode, sends relative mouse motion (using movementX/Y\n * which requires Pointer Lock API).\n *\n * @param e - The MouseEvent from the browser\n * @param displayId - The display ID (usually 0)\n */\n handleMouseMove(e: MouseEvent, displayId: number = 0): void\n {\n if (this.state !== 'ready')\n {\n return;\n }\n\n // Throttle: skip if too many un-acked motions are queued\n if (this.waitingForAck >= 2 * SPICE_INPUT_MOTION_ACK_BUNCH)\n {\n DEBUG > 0 && console.log(\"Discarding mouse motion\");\n return;\n }\n\n if (this.mouseMode === SpiceMouseMode.CLIENT)\n {\n const move = new SpiceMsgcMousePosition(\n e.offsetX, e.offsetY, this.buttonState, displayId\n );\n const msg = buildInputMsg(SpiceMsgcInputs.MOUSE_POSITION, move);\n this.sendMsg(msg);\n }\n else\n {\n const move = new SpiceMsgcMouseMotion(\n e.movementX, e.movementY, this.buttonState, displayId\n );\n const msg = buildInputMsg(SpiceMsgcInputs.MOUSE_MOTION, move);\n this.sendMsg(msg);\n }\n\n this.waitingForAck++;\n }\n\n /**\n * Handle a DOM `mousedown` event.\n *\n * Translates the DOM button number to a SPICE mouse button,\n * updates the local button state mask, and sends a mouse press.\n *\n * @param e - The MouseEvent from the browser\n */\n handleMouseDown(e: MouseEvent): void\n {\n if (this.state !== 'ready')\n {\n return;\n }\n\n const button = domButtonToSpice(e.button);\n this.buttonState = domButtonsToMask(e.buttons);\n\n const press = new SpiceMsgcMousePress(button, this.buttonState);\n const msg = buildInputMsg(SpiceMsgcInputs.MOUSE_PRESS, press);\n this.sendMsg(msg);\n\n e.preventDefault();\n }\n\n /**\n * Handle a DOM `mouseup` event.\n *\n * @param e - The MouseEvent from the browser\n */\n handleMouseUp(e: MouseEvent): void\n {\n if (this.state !== 'ready')\n {\n return;\n }\n\n const button = domButtonToSpice(e.button);\n this.buttonState = domButtonsToMask(e.buttons);\n\n const release = new SpiceMsgcMouseRelease(button, this.buttonState);\n const msg = buildInputMsg(SpiceMsgcInputs.MOUSE_RELEASE, release);\n this.sendMsg(msg);\n\n e.preventDefault();\n }\n\n /**\n * Handle a DOM `wheel` event (scroll up/down).\n *\n * Sends both a press and immediate release for the scroll button.\n *\n * @param e - The WheelEvent from the browser\n */\n handleMouseWheel(e: WheelEvent): void\n {\n if (this.state !== 'ready')\n {\n return;\n }\n\n const button = e.deltaY < 0\n ? SpiceMouseButton.UP\n : SpiceMouseButton.DOWN;\n\n const press = new SpiceMsgcMousePress(button, 0);\n const pressMsg = buildInputMsg(SpiceMsgcInputs.MOUSE_PRESS, press);\n this.sendMsg(pressMsg);\n\n const release = new SpiceMsgcMouseRelease(button, 0);\n const releaseMsg = buildInputMsg(SpiceMsgcInputs.MOUSE_RELEASE, release);\n this.sendMsg(releaseMsg);\n\n e.preventDefault();\n }\n\n /**\n * Handle a DOM `contextmenu` event (right-click menu).\n * Simply prevents the default browser context menu.\n *\n * @param e - The MouseEvent from the browser\n */\n handleContextMenu(e: MouseEvent): void\n {\n e.preventDefault();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Register channel factory\n// ---------------------------------------------------------------------------\n\nregisterChannelFactory(SpiceChannel.INPUTS, SpiceInputsConn);\n","/*----------------------------------------------------------------------------\n** png.ts\n** Create PNG data URIs from raw RGBA pixel data using the Canvas API.\n**\n** Uses a temporary HTMLCanvasElement to convert raw RGBA pixel data into\n** a proper PNG data URI via toDataURL(\"image/png\"). This replaces the\n** previous manual PNG construction (CRC32, IHDR, IDAT, IEND chunks,\n** zlib headers) with a single browser-native call, fixing a known zlib\n** checksum bug in the process.\n**\n** Used by the cursor channel to create CSS cursor images.\n**--------------------------------------------------------------------------*/\n\n\n/**\n * Create a PNG data URI from raw RGBA pixel data.\n *\n * Returns a full `data:image/png;base64,...` string suitable for use\n * as a CSS `url()` value or an `<img>` element's `src` attribute.\n *\n * @param width - Image width in pixels\n * @param height - Image height in pixels\n * @param bytes - Raw RGBA pixel data (4 bytes per pixel, row-major)\n * @returns A data URI string containing the PNG image\n */\nfunction createRgbaPng(width: number, height: number, bytes: ArrayBuffer): string\n{\n if (typeof document === 'undefined')\n {\n throw new Error('No document available for canvas-based PNG creation');\n }\n\n const u8 = new Uint8Array(bytes);\n const clamped = new Uint8ClampedArray(u8.buffer, u8.byteOffset, u8.byteLength);\n const imageData = new ImageData(clamped, width, height);\n\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx)\n {\n throw new Error('Failed to get 2d context from canvas');\n }\n ctx.putImageData(imageData, 0, 0);\n return canvas.toDataURL('image/png');\n}\n\nexport {\n createRgbaPng,\n};\n","/*----------------------------------------------------------------------------\n** simulatecursor.ts\n** Fallback cursor simulation for browsers that do not support\n** data URI cursors (originally for IE10). Provides:\n** - A pre-loaded cursor cache keyed by SHA-1 hash\n** - A positioned <img> element that tracks mouse movement\n** - ICO binary header construction for .cur file generation\n**\n** Converted from simulatecursor.js to TypeScript with full type safety.\n**--------------------------------------------------------------------------*/\n\nimport type { SpiceCursorHeader } from './spicetype';\n\n// ---------------------------------------------------------------------------\n// SHA-1 via Web Crypto API\n//\n// Only used for cursor deduplication hashing; not security-critical.\n// ---------------------------------------------------------------------------\n\nasync function sha1(input: string): Promise<string>\n{\n const data = new TextEncoder().encode(input);\n const hashBuffer = await crypto.subtle.digest('SHA-1', data);\n const bytes = new Uint8Array(hashBuffer);\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\n// ---------------------------------------------------------------------------\n// Cursor info passed from the cursor channel\n// ---------------------------------------------------------------------------\n\nexport interface CursorData\n{\n header: SpiceCursorHeader;\n data: ArrayBuffer;\n}\n\n// ---------------------------------------------------------------------------\n// Simulated cursor image element\n// ---------------------------------------------------------------------------\n\ninterface SimulatedCursorElement extends HTMLImageElement\n{\n spiceScreen: HTMLElement;\n spiceHotX: number;\n spiceHotY: number;\n}\n\nfunction asSimulatedCursor(img: HTMLImageElement, screen: HTMLElement): SimulatedCursorElement\n{\n const el = img as SimulatedCursorElement;\n el.spiceScreen = screen;\n el.spiceHotX = 0;\n el.spiceHotY = 0;\n return el;\n}\n\n// ---------------------------------------------------------------------------\n// SpiceSimulateCursor — static utility for cursor fallback\n// ---------------------------------------------------------------------------\n\n/** Pre-loaded cursor cache: SHA-1 hash -> .cur file URL */\nconst cursorCache: Record<string, string> = {};\n\n/** Set of unknown cursor hashes we've already warned about */\nconst unknownCursors: Record<string, string> = {};\n\nlet warned = false;\n\n/**\n * Register a pre-loaded cursor file for a given hash.\n *\n * @param hash - SHA-1 hash of the cursor's PNG + hotspot\n * @param value - URL to a pre-built .cur file\n */\nfunction addCursor(hash: string, value: string): void\n{\n cursorCache[hash] = value;\n}\n\n/**\n * Record an unknown cursor and log instructions for creating a static\n * cursor file to avoid simulation on future loads.\n */\nfunction unknownCursor(hash: string, dataUrl: string): void\n{\n if (!warned)\n {\n warned = true;\n if (typeof window !== 'undefined' && typeof window.alert === 'function')\n {\n window.alert(\n \"This browser does not support dynamic cursors. \" +\n \"This page will now simulate cursors with images, \" +\n \"which will be imperfect. We recommend using Chrome or Firefox instead. \" +\n \"\\n\\nIf you need to use this browser, you can create a static cursor \" +\n \"file for each cursor your application uses. \" +\n \"View the console log for more information on creating static cursors for your environment.\"\n );\n }\n }\n\n if (!unknownCursors[hash])\n {\n unknownCursors[hash] = dataUrl;\n console.log(\n 'Unknown cursor. Simulation required. To avoid simulation for this cursor, ' +\n 'create and include a custom javascript file, and add the following line:'\n );\n console.log(\n 'SpiceSimulateCursor.addCursor(\"' + hash + '\", \"<your cursor url here>\");'\n );\n }\n}\n\n/**\n * Duplicate a mouse event and dispatch it on the target element.\n *\n * The simulated cursor image sits on top of the screen element, so we\n * need to forward mouse events through to the underlying screen.\n */\nfunction duplicateMouseEvent(e: MouseEvent, target: HTMLElement): boolean\n{\n const evt = new MouseEvent(e.type, {\n bubbles: true,\n cancelable: true,\n view: e.view,\n detail: e.detail,\n screenX: e.screenX,\n screenY: e.screenY,\n clientX: e.clientX,\n clientY: e.clientY,\n ctrlKey: e.ctrlKey,\n altKey: e.altKey,\n shiftKey: e.shiftKey,\n metaKey: e.metaKey,\n button: e.button,\n relatedTarget: e.relatedTarget,\n });\n return target.dispatchEvent(evt);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/** Owning cursor channel state needed for simulation */\nexport interface CursorOwner\n{\n parent: { screenId: string | undefined } | undefined;\n simulatedCursor: SimulatedCursorElement | undefined;\n simulatedCursorHandler: ((e: MouseEvent) => void) | undefined;\n}\n\n/**\n * Attempt to simulate the cursor when CSS data URI cursors are not\n * supported. First tries preloaded cursors from the cache; if that\n * also fails, creates a positioned `<img>` element that tracks the\n * mouse to visually represent the cursor.\n *\n * @param owner - The cursor channel connection (stores simulated cursor state)\n * @param cursor - Cursor data with header and pixel data\n * @param screen - The screen HTML element\n * @param dataUrl - PNG data URI string (from createRgbaPng)\n */\nasync function simulateCursor(\n owner: CursorOwner,\n cursor: CursorData,\n screen: HTMLElement,\n dataUrl: string\n): Promise<void>\n{\n if (typeof document === 'undefined')\n return;\n\n const cursorSha = await sha1(\n dataUrl + ' ' + cursor.header.hotSpotX + ' ' + cursor.header.hotSpotY\n );\n\n // Try pre-loaded cursor cache\n const cached = cursorCache[cursorSha];\n if (cached !== undefined)\n {\n const curstr = 'url(' + cached + '), default';\n screen.style.cursor = curstr;\n }\n\n if (typeof window !== 'undefined' && window.getComputedStyle(screen, null).cursor === 'auto')\n {\n unknownCursor(cursorSha, dataUrl);\n\n screen.style.cursor = 'none';\n\n if (!owner.simulatedCursor)\n {\n const img = asSimulatedCursor(document.createElement('img'), screen);\n\n img.style.position = 'absolute';\n img.style.display = 'none';\n img.style.overflow = 'hidden';\n\n img.spiceScreen = screen;\n\n const handler = (e: MouseEvent): void =>\n {\n duplicateMouseEvent(e, screen);\n };\n img.addEventListener('mousemove', handler);\n owner.simulatedCursorHandler = handler;\n\n screen.appendChild(img);\n owner.simulatedCursor = img;\n }\n\n owner.simulatedCursor.src = dataUrl;\n\n owner.simulatedCursor.spiceHotX = cursor.header.hotSpotX;\n owner.simulatedCursor.spiceHotY = cursor.header.hotSpotY;\n\n owner.simulatedCursor.style.pointerEvents = 'none';\n }\n else\n {\n if (owner.simulatedCursor)\n {\n owner.simulatedCursor.spiceScreen.removeChild(owner.simulatedCursor);\n owner.simulatedCursor = undefined;\n }\n }\n}\n\n/**\n * Clean up a simulated cursor element if one exists.\n */\nfunction cleanupSimulatedCursor(owner: CursorOwner): void\n{\n if (owner.simulatedCursor)\n {\n if (owner.simulatedCursorHandler)\n {\n owner.simulatedCursor.removeEventListener('mousemove', owner.simulatedCursorHandler);\n owner.simulatedCursorHandler = undefined;\n }\n if (owner.simulatedCursor.parentNode)\n {\n owner.simulatedCursor.parentNode.removeChild(owner.simulatedCursor);\n }\n owner.simulatedCursor = undefined;\n }\n}\n\nexport const SpiceSimulateCursor = {\n addCursor,\n simulateCursor,\n cleanupSimulatedCursor,\n};\n","/*----------------------------------------------------------------------------\n** cursor.ts\n** Drive the SPICE Cursor Channel.\n**\n** Handles server cursor messages: INIT, SET, MOVE, HIDE, TRAIL, RESET,\n** INVAL_ONE, INVAL_ALL. Uses createRgbaPng to build CSS data-URI\n** cursors, with SpiceSimulateCursor as a fallback for browsers that\n** do not support data URI cursors.\n**\n** Converted from cursor.js to TypeScript with full type safety.\n**--------------------------------------------------------------------------*/\n\nimport { SpiceConn, type SpiceConnOptions } from './spiceconn';\nimport {\n SpiceChannel,\n SpiceMsgCursor,\n SpiceCursorFlags,\n SpiceCursorType,\n SpiceMouseMode,\n} from './enums';\nimport { registerChannelFactory } from './main';\nimport {\n SpiceMiniData,\n SpiceMsgCursorInit,\n SpiceMsgCursorSet,\n} from './spicemsg';\nimport { createRgbaPng } from './png';\nimport {\n SpiceSimulateCursor,\n type CursorOwner,\n type CursorData,\n} from './simulatecursor';\nimport { DEBUG } from '../utils/debug';\n\n// ---------------------------------------------------------------------------\n// Type for the parent connection's inputs channel\n// ---------------------------------------------------------------------------\n\ninterface InputsWithMouse\n{\n mouseMode: number;\n mousex: number;\n mousey: number;\n}\n\ninterface ParentWithInputs\n{\n screenId: string | undefined;\n inputs: InputsWithMouse | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// SpiceCursorConn — SPICE cursor channel\n// ---------------------------------------------------------------------------\n\nexport class SpiceCursorConn extends SpiceConn implements CursorOwner\n{\n /** Simulated cursor <img> element (fallback for unsupported browsers). */\n simulatedCursor: CursorOwner['simulatedCursor'] = undefined;\n\n /** Event handler stored for cleanup */\n simulatedCursorHandler: CursorOwner['simulatedCursorHandler'] = undefined;\n\n constructor(options: SpiceConnOptions)\n {\n super(options);\n }\n\n // -----------------------------------------------------------------------\n // Channel message processing\n // -----------------------------------------------------------------------\n\n protected override processChannelMessage(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n return true;\n }\n\n if (msg.type === SpiceMsgCursor.INIT)\n {\n const cursorInit = new SpiceMsgCursorInit(msg.data);\n DEBUG > 1 && console.log(\"SpiceMsgCursorInit\");\n\n const p = this.parent as ParentWithInputs | undefined;\n if (p && p.inputs &&\n p.inputs.mouseMode === SpiceMouseMode.SERVER)\n {\n // FIXME - this imagines that the server actually\n // provides the current cursor position,\n // instead of 0,0. As of May 11, 2012,\n // that assumption was false :-(.\n p.inputs.mousex = cursorInit.position.x;\n p.inputs.mousey = cursorInit.position.y;\n }\n // FIXME - We don't handle most of the parameters here...\n return true;\n }\n\n if (msg.type === SpiceMsgCursor.SET)\n {\n const cursorSet = new SpiceMsgCursorSet(msg.data);\n DEBUG > 1 && console.log(\"SpiceMsgCursorSet\");\n\n if (cursorSet.cursor.flags & SpiceCursorFlags.NONE)\n {\n const screen = this.getScreen();\n if (screen)\n {\n screen.style.cursor = \"none\";\n }\n return true;\n }\n\n if (cursorSet.cursor.flags > 0)\n {\n this.logWarn(\"FIXME: No support for cursor flags \" + cursorSet.cursor.flags);\n }\n\n if (cursorSet.cursor.header &&\n cursorSet.cursor.header.type !== SpiceCursorType.ALPHA)\n {\n this.logWarn(\n \"FIXME: No support for cursor type \" + cursorSet.cursor.header.type\n );\n return false;\n }\n\n if (cursorSet.cursor.header)\n {\n this.setCursor({\n header: cursorSet.cursor.header,\n data: cursorSet.cursor.data,\n });\n }\n\n return true;\n }\n\n if (msg.type === SpiceMsgCursor.MOVE)\n {\n this.knownUnimplemented(msg.type, \"Cursor Move\");\n return true;\n }\n\n if (msg.type === SpiceMsgCursor.HIDE)\n {\n DEBUG > 1 && console.log(\"SpiceMsgCursorHide\");\n const screen = this.getScreen();\n if (screen)\n {\n screen.style.cursor = \"none\";\n }\n return true;\n }\n\n if (msg.type === SpiceMsgCursor.TRAIL)\n {\n this.knownUnimplemented(msg.type, \"Cursor Trail\");\n return true;\n }\n\n if (msg.type === SpiceMsgCursor.RESET)\n {\n DEBUG > 1 && console.log(\"SpiceMsgCursorReset\");\n const screen = this.getScreen();\n if (screen)\n {\n screen.style.cursor = \"auto\";\n }\n return true;\n }\n\n if (msg.type === SpiceMsgCursor.INVAL_ONE)\n {\n this.knownUnimplemented(msg.type, \"Cursor Inval One\");\n return true;\n }\n\n if (msg.type === SpiceMsgCursor.INVAL_ALL)\n {\n DEBUG > 1 && console.log(\"SpiceMsgCursorInvalAll\");\n // FIXME - There may be something useful to do here...\n return true;\n }\n\n return false;\n }\n\n // -----------------------------------------------------------------------\n // Set cursor via CSS data URI (with simulate fallback)\n // -----------------------------------------------------------------------\n\n private setCursor(cursor: CursorData): void\n {\n const dataUrl = createRgbaPng(\n cursor.header.width,\n cursor.header.height,\n cursor.data\n );\n\n const curstr =\n 'url(' + dataUrl + ') ' +\n cursor.header.hotSpotX + ' ' + cursor.header.hotSpotY +\n ', default';\n\n const screen = this.getScreen();\n if (!screen)\n {\n return;\n }\n\n screen.style.cursor = 'auto';\n screen.style.cursor = curstr;\n\n if (typeof window !== 'undefined' &&\n window.getComputedStyle(screen, null).cursor === 'auto')\n {\n SpiceSimulateCursor.simulateCursor(\n this,\n cursor,\n screen,\n dataUrl\n );\n }\n }\n\n // -----------------------------------------------------------------------\n // Get the screen element\n // -----------------------------------------------------------------------\n\n private getScreen(): HTMLElement | null\n {\n if (typeof document === 'undefined')\n {\n return null;\n }\n const p = this.parent as ParentWithInputs | undefined;\n const screenId = p ? p.screenId : this.screenId;\n if (!screenId)\n {\n return null;\n }\n return document.getElementById(screenId);\n }\n\n // -----------------------------------------------------------------------\n // Cleanup\n // -----------------------------------------------------------------------\n\n override cleanup(): void\n {\n SpiceSimulateCursor.cleanupSimulatedCursor(this);\n super.cleanup();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Register with channel factory\n// ---------------------------------------------------------------------------\n\nregisterChannelFactory(SpiceChannel.CURSOR, SpiceCursorConn);\n","/*----------------------------------------------------------------------------\n** playback.ts\n** Drive the SPICE Playback channel (sound out).\n**\n** Handles audio playback via the MediaSource API, constructing WebM\n** containers with Opus-encoded audio data. Supports START, STOP,\n** DATA, MODE, VOLUME, MUTE, and LATENCY messages.\n**\n** Converted from playback.js to TypeScript with full type safety.\n**--------------------------------------------------------------------------*/\n\nimport { SpiceConn, type SpiceConnOptions } from './spiceconn';\nimport {\n SpiceChannel,\n SpiceMsgPlayback,\n SpiceAudioDataMode,\n SpiceAudioFmt,\n} from './enums';\nimport { registerChannelFactory } from './main';\nimport {\n SpiceMiniData,\n SpiceMsgPlaybackStart,\n SpiceMsgPlaybackData,\n SpiceMsgPlaybackMode,\n} from './spicemsg';\nimport {\n WebmConstants,\n WebmHeader,\n WebmAudioTrackEntry,\n WebmTracks,\n WebmCluster,\n WebmSimpleBlock,\n} from './webm';\nimport {\n PLAYBACK_DEBUG,\n dumpMediaElement,\n dumpMediaSource,\n dumpSourceBuffer,\n} from '../utils/debug';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Condense a queue of ArrayBuffers into a single ArrayBuffer.\n * If the queue has only one element, just dequeue it.\n */\nfunction condenseQueue(queue: ArrayBuffer[]): ArrayBuffer\n{\n if (queue.length === 1)\n {\n return queue.shift()!;\n }\n\n let len = 0;\n for (let i = 0; i < queue.length; i++)\n {\n len += queue[i]!.byteLength;\n }\n\n const mb = new ArrayBuffer(len);\n const tmp = new Uint8Array(mb);\n let offset = 0;\n for (let i = 0; i < queue.length; i++)\n {\n tmp.set(new Uint8Array(queue[i]!), offset);\n offset += queue[i]!.byteLength;\n }\n queue.length = 0;\n return mb;\n}\n\n// ---------------------------------------------------------------------------\n// SpicePlaybackConn — SPICE playback channel\n// ---------------------------------------------------------------------------\n\nexport class SpicePlaybackConn extends SpiceConn\n{\n /** Queued ArrayBuffers waiting to be appended to the SourceBuffer. */\n private queue: ArrayBuffer[] = [];\n\n /** Whether the SourceBuffer is ready for a new appendBuffer call. */\n private appendOkay = false;\n\n /** Timestamp of the first audio packet (ms), used as WebM time base. */\n private startTime = 0;\n\n /** Timestamp of the start of the current WebM cluster (ms). */\n private clusterTime = 0;\n\n /** Last received data timestamp, for gap detection / smoothing. */\n private lastDataTime = 0;\n\n /** Total bytes written to the WebM stream (for debug). */\n private bytesWritten = 0;\n\n /** The MediaSource driving the <audio> element. */\n private mediaSource: MediaSource | undefined = undefined;\n\n /** The SourceBuffer for appending WebM data. */\n private sourceBuffer: SourceBuffer | undefined = undefined;\n\n /** The <audio> element used for playback. */\n private audioElement: HTMLAudioElement | undefined = undefined;\n\n // -- Bound event handlers for proper cleanup --\n\n private readonly onSourceOpen = (): void => { this.handleSourceOpen(); };\n private readonly onSourceEnded = (): void => { this.handleSourceEnded(); };\n private readonly onSourceClosed = (): void => { this.handleSourceClosed(); };\n private readonly onSourceBufferError = (e: Event): void => { this.handleSourceBufferError(e); };\n private readonly onAppendBufferDone = (): void => { this.handleAppendBufferDone(); };\n\n constructor(options: SpiceConnOptions)\n {\n super(options);\n }\n\n // -----------------------------------------------------------------------\n // Channel message processing\n // -----------------------------------------------------------------------\n\n protected override processChannelMessage(msg: SpiceMiniData): boolean\n {\n if (!msg.data)\n {\n return true;\n }\n\n if (typeof MediaSource === 'undefined')\n {\n this.logErr('MediaSource API is not available');\n return false;\n }\n\n if (msg.type === SpiceMsgPlayback.START)\n {\n const start = new SpiceMsgPlaybackStart(msg.data);\n\n PLAYBACK_DEBUG > 0 && console.log(\n \"PlaybackStart; frequency \" + start.frequency\n );\n\n if (start.frequency !== WebmConstants.OPUS_FREQUENCY)\n {\n this.logErr('This player cannot handle frequency ' + start.frequency);\n return false;\n }\n\n if (start.channels !== WebmConstants.OPUS_CHANNELS)\n {\n this.logErr('This player cannot handle ' + start.channels + ' channels');\n return false;\n }\n\n if (start.format !== SpiceAudioFmt.S16)\n {\n this.logErr('This player cannot handle format ' + start.format);\n return false;\n }\n\n if (!this.sourceBuffer)\n {\n this.mediaSource = new MediaSource();\n\n this.audioElement = document.createElement(\"audio\");\n this.audioElement.setAttribute('autoplay', 'true');\n this.audioElement.src = URL.createObjectURL(this.mediaSource);\n\n const screenId = this.parent ? this.parent.screenId : this.screenId;\n if (screenId)\n {\n const screen = document.getElementById(screenId);\n if (screen)\n {\n screen.appendChild(this.audioElement);\n }\n }\n\n this.mediaSource.addEventListener('sourceopen', this.onSourceOpen, false);\n this.mediaSource.addEventListener('sourceended', this.onSourceEnded, false);\n this.mediaSource.addEventListener('sourceclosed', this.onSourceClosed, false);\n\n this.bytesWritten = 0;\n\n return true;\n }\n }\n\n if (msg.type === SpiceMsgPlayback.DATA)\n {\n const data = new SpiceMsgPlaybackData(msg.data);\n\n if (!this.sourceBuffer)\n {\n return true;\n }\n\n // Handle audio underruns: if we've fallen behind, skip ahead\n if (this.audioElement &&\n this.audioElement.readyState >= 3 &&\n this.audioElement.buffered.length > 1 &&\n this.audioElement.currentTime === this.audioElement.buffered.end(0) &&\n this.audioElement.currentTime < this.audioElement.buffered.start(\n this.audioElement.buffered.length - 1\n ))\n {\n const newTime = this.audioElement.buffered.start(\n this.audioElement.buffered.length - 1\n );\n console.log(\n \"Audio underrun: we appear to have fallen behind; advancing to \" + newTime\n );\n this.audioElement.currentTime = newTime;\n }\n\n /* Around version 45, Firefox started being very particular about the\n time stamps put into the Opus stream. The time stamps from the Spice\n server are somewhat irregular. They mostly arrive every 10 ms, but\n sometimes it is 11, or sometimes with two time stamps the same in a\n row.\n\n In theory, the sequence mode should be appropriate for us, but as of\n 09/27/2016, I was unable to make sequence mode work with Firefox.\n\n Thus, we end up with an inelegant hack. Essentially, we force every\n packet to have a 10ms time delta, unless there is an obvious gap in\n time stream, in which case we will resync. */\n\n if (this.startTime !== 0 &&\n data.time !== (this.lastDataTime + WebmConstants.EXPECTED_PACKET_DURATION))\n {\n if (Math.abs(data.time - (WebmConstants.EXPECTED_PACKET_DURATION + this.lastDataTime)) <\n WebmConstants.MAX_CLUSTER_TIME)\n {\n PLAYBACK_DEBUG > 1 && console.log(\n \"Hacking time of \" + data.time + \" to \" +\n (this.lastDataTime + WebmConstants.EXPECTED_PACKET_DURATION)\n );\n data.time = this.lastDataTime + WebmConstants.EXPECTED_PACKET_DURATION;\n }\n else\n {\n PLAYBACK_DEBUG > 1 && console.log(\n \"Apparent gap in audio time; now is \" + data.time +\n \" last was \" + this.lastDataTime\n );\n }\n }\n\n this.lastDataTime = data.time;\n\n PLAYBACK_DEBUG > 1 && console.log(\n \"PlaybackData; time \" + data.time +\n \"; length \" + (data.data ? data.data.byteLength : 0)\n );\n\n if (this.startTime === 0)\n {\n this.startPlayback(data);\n }\n else if (data.time - this.clusterTime >= WebmConstants.MAX_CLUSTER_TIME)\n {\n this.newCluster(data);\n }\n else\n {\n this.simpleBlock(data, false);\n }\n\n return true;\n }\n\n if (msg.type === SpiceMsgPlayback.MODE)\n {\n const mode = new SpiceMsgPlaybackMode(msg.data);\n if (mode.mode !== SpiceAudioDataMode.OPUS)\n {\n this.logErr('This player cannot handle mode ' + mode.mode);\n this.sourceBuffer = undefined;\n }\n return true;\n }\n\n if (msg.type === SpiceMsgPlayback.STOP)\n {\n PLAYBACK_DEBUG > 0 && console.log(\"PlaybackStop\");\n if (this.sourceBuffer)\n {\n this.stopPlayback();\n return true;\n }\n }\n\n if (msg.type === SpiceMsgPlayback.VOLUME)\n {\n this.knownUnimplemented(msg.type, \"Playback Volume\");\n return true;\n }\n\n if (msg.type === SpiceMsgPlayback.MUTE)\n {\n this.knownUnimplemented(msg.type, \"Playback Mute\");\n return true;\n }\n\n if (msg.type === SpiceMsgPlayback.LATENCY)\n {\n this.knownUnimplemented(msg.type, \"Playback Latency\");\n return true;\n }\n\n return false;\n }\n\n // -----------------------------------------------------------------------\n // WebM stream construction\n // -----------------------------------------------------------------------\n\n /** Begin playback: write the WebM header + tracks, then start the first cluster. */\n private startPlayback(data: SpiceMsgPlaybackData): void\n {\n if (!this.sourceBuffer)\n {\n return;\n }\n\n this.startTime = data.time;\n\n const h = new WebmHeader();\n const te = new WebmAudioTrackEntry();\n const t = new WebmTracks(te);\n\n const mb = new ArrayBuffer(h.bufferSize() + t.bufferSize());\n\n this.bytesWritten = h.toBuffer(mb, 0);\n this.bytesWritten = t.toBuffer(mb, this.bytesWritten);\n\n this.sourceBuffer.addEventListener('error', this.onSourceBufferError, false);\n this.sourceBuffer.addEventListener('updateend', this.onAppendBufferDone, false);\n this.appendBuffer(mb);\n\n this.newCluster(data);\n }\n\n /** Start a new WebM cluster at the given data's timestamp. */\n private newCluster(data: SpiceMsgPlaybackData): void\n {\n this.clusterTime = data.time;\n\n const c = new WebmCluster(data.time - this.startTime);\n\n const mb = new ArrayBuffer(c.bufferSize());\n this.bytesWritten += c.toBuffer(mb, 0);\n\n if (this.appendOkay)\n {\n this.appendBuffer(mb);\n }\n else\n {\n this.queue.push(mb);\n }\n\n this.simpleBlock(data, true);\n }\n\n /** Write a simple block for a single audio packet. */\n private simpleBlock(data: SpiceMsgPlaybackData, keyframe: boolean): void\n {\n if (!data.data)\n {\n return;\n }\n\n const sb = new WebmSimpleBlock(\n data.time - this.clusterTime,\n data.data.slice(0) as ArrayBuffer,\n keyframe\n );\n const mb = new ArrayBuffer(sb.bufferSize());\n\n this.bytesWritten += sb.toBuffer(mb, 0);\n\n if (this.appendOkay)\n {\n this.appendBuffer(mb);\n }\n else\n {\n this.queue.push(mb);\n }\n }\n\n // -----------------------------------------------------------------------\n // SourceBuffer management\n // -----------------------------------------------------------------------\n\n /** Safely call appendBuffer, marking appendOkay false. */\n private appendBuffer(buf: ArrayBuffer): void\n {\n if (!this.sourceBuffer)\n {\n return;\n }\n\n try\n {\n this.sourceBuffer.appendBuffer(buf);\n this.appendOkay = false;\n }\n catch (e: unknown)\n {\n const msg = e instanceof Error ? e.message : String(e);\n this.logErr(\"Error invoking appendBuffer: \" + msg);\n }\n }\n\n /** Stop playback: remove audio element, release resources. */\n private stopPlayback(): void\n {\n if (this.audioElement)\n {\n const screenId = this.parent ? this.parent.screenId : this.screenId;\n if (screenId && typeof document !== 'undefined')\n {\n const screen = document.getElementById(screenId);\n if (screen && this.audioElement.parentNode === screen)\n {\n screen.removeChild(this.audioElement);\n }\n }\n URL.revokeObjectURL(this.audioElement.src);\n }\n\n this.removeMediaSourceListeners();\n\n if (this.sourceBuffer)\n {\n this.sourceBuffer.removeEventListener('error', this.onSourceBufferError, false);\n this.sourceBuffer.removeEventListener('updateend', this.onAppendBufferDone, false);\n }\n\n this.sourceBuffer = undefined;\n this.mediaSource = undefined;\n this.audioElement = undefined;\n\n this.appendOkay = false;\n this.queue = [];\n this.startTime = 0;\n }\n\n // -----------------------------------------------------------------------\n // MediaSource event handlers\n // -----------------------------------------------------------------------\n\n private handleSourceOpen(): void\n {\n if (!this.mediaSource || this.sourceBuffer)\n {\n return;\n }\n\n this.sourceBuffer = this.mediaSource.addSourceBuffer(\n WebmConstants.SPICE_PLAYBACK_CODEC\n );\n\n if (!this.sourceBuffer)\n {\n this.logErr('Codec ' + WebmConstants.SPICE_PLAYBACK_CODEC + ' not available.');\n return;\n }\n\n this.listenForAudioEvents();\n\n this.sourceBuffer.mode = \"segments\";\n\n // FIXME - Experimentation with segments and sequences was unsatisfying.\n // Switching to sequence did not solve our gap problem,\n // but the browsers didn't fully support the time seek capability\n // we would expect to gain from 'segments'.\n // Segments worked at the time of this patch, so segments it is for now.\n }\n\n private handleSourceEnded(): void\n {\n this.logErr('Audio source unexpectedly ended.');\n }\n\n private handleSourceClosed(): void\n {\n this.logErr('Audio source unexpectedly closed.');\n }\n\n private handleSourceBufferError(e: Event): void\n {\n this.logErr('source_buffer error ' + (e instanceof ErrorEvent ? e.message : 'unknown'));\n }\n\n private handleAppendBufferDone(): void\n {\n this.logPlaybackDebugEvent('updateend');\n\n if (this.queue.length > 0)\n {\n const mb = condenseQueue(this.queue);\n this.appendBuffer(mb);\n }\n else\n {\n this.appendOkay = true;\n }\n }\n\n // -----------------------------------------------------------------------\n // Debug event listening\n // -----------------------------------------------------------------------\n\n private logPlaybackDebugEvent(eventType: string): void\n {\n if (PLAYBACK_DEBUG > 1 && this.audioElement)\n {\n console.log(\n this.audioElement.currentTime + \": event \" + eventType +\n dumpMediaElement(this.audioElement)\n );\n }\n\n if (PLAYBACK_DEBUG > 1 && this.mediaSource)\n {\n console.log(\" media_source \" + dumpMediaSource(this.mediaSource));\n }\n\n if (PLAYBACK_DEBUG > 1 && this.sourceBuffer)\n {\n console.log(\" source_buffer \" + dumpSourceBuffer(this.sourceBuffer));\n }\n\n if ((PLAYBACK_DEBUG > 0 || this.queue.length > 1))\n {\n console.log(\n ' queue len ' + this.queue.length +\n '; append_okay: ' + this.appendOkay\n );\n }\n }\n\n /** Attach debug event listeners to the <audio> element. */\n private listenForAudioEvents(): void\n {\n if (!this.audioElement)\n {\n return;\n }\n\n const audio = this.audioElement;\n\n // Level 0: always listen for errors\n const audio0Events = [\"abort\", \"error\"];\n\n // Level 1: standard audio lifecycle events\n const audio1Events = [\n \"loadstart\", \"suspend\", \"emptied\", \"stalled\", \"loadedmetadata\",\n \"loadeddata\", \"canplay\", \"canplaythrough\", \"playing\", \"waiting\",\n \"seeking\", \"seeked\", \"ended\", \"durationchange\", \"timeupdate\",\n \"play\", \"pause\", \"ratechange\",\n ];\n\n // Level 2: verbose events\n const audio2Events = [\"progress\", \"resize\", \"volumechange\"];\n\n const debugHandler = (e: Event): void =>\n {\n this.logPlaybackDebugEvent(e.type);\n };\n\n for (const name of audio0Events)\n {\n audio.addEventListener(name, debugHandler);\n }\n\n if (PLAYBACK_DEBUG > 0)\n {\n for (const name of audio1Events)\n {\n audio.addEventListener(name, debugHandler);\n }\n }\n\n if (PLAYBACK_DEBUG > 1)\n {\n for (const name of audio2Events)\n {\n audio.addEventListener(name, debugHandler);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // MediaSource listener cleanup\n // -----------------------------------------------------------------------\n\n private removeMediaSourceListeners(): void\n {\n if (this.mediaSource)\n {\n this.mediaSource.removeEventListener('sourceopen', this.onSourceOpen, false);\n this.mediaSource.removeEventListener('sourceended', this.onSourceEnded, false);\n this.mediaSource.removeEventListener('sourceclosed', this.onSourceClosed, false);\n }\n }\n\n // -----------------------------------------------------------------------\n // Cleanup\n // -----------------------------------------------------------------------\n\n override cleanup(): void\n {\n if (this.sourceBuffer)\n {\n this.stopPlayback();\n }\n super.cleanup();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Register with channel factory\n// ---------------------------------------------------------------------------\n\nregisterChannelFactory(SpiceChannel.PLAYBACK, SpicePlaybackConn);\n","\"use strict\";\nimport { SpiceChannel, SpiceMsgPort, SpiceMsgcPort } from './enums';\nimport { SpiceMiniData, SpiceMsgPortInit } from './spicemsg';\nimport { SpiceConn, SpiceConnOptions } from './spiceconn';\nimport { registerChannelFactory } from './main';\nimport { DEBUG } from '../utils/debug';\n\n// ---------------------------------------------------------------------------\n// Callback interfaces\n// ---------------------------------------------------------------------------\n\n/**\n * Callback invoked when the port channel receives initialization data.\n */\nexport interface PortInitCallback {\n (portName: string, opened: boolean): void;\n}\n\n/**\n * Callback invoked when the port channel receives a port event.\n */\nexport interface PortEventCallback {\n (portName: string, eventData: Uint8Array): void;\n}\n\n/**\n * Callback invoked when the port channel receives data.\n */\nexport interface PortDataCallback {\n (portName: string, data: ArrayBuffer): void;\n}\n\n// ---------------------------------------------------------------------------\n// Extended options for port channel\n// ---------------------------------------------------------------------------\n\nexport interface SpicePortConnOptions extends SpiceConnOptions {\n onPortInit?: PortInitCallback;\n onPortEvent?: PortEventCallback;\n onPortData?: PortDataCallback;\n}\n\n// ---------------------------------------------------------------------------\n// SpicePortConn\n// ---------------------------------------------------------------------------\n\nexport class SpicePortConn extends SpiceConn {\n\n portName: string | null = null;\n portOpened: boolean = false;\n\n onPortInit: PortInitCallback | undefined;\n onPortEvent: PortEventCallback | undefined;\n onPortData: PortDataCallback | undefined;\n\n constructor(options: SpiceConnOptions)\n {\n super(options);\n DEBUG > 0 && console.log(\"SPICE port: created SPICE port channel\");\n const portOpts = options as Partial<SpicePortConnOptions>;\n this.onPortInit = portOpts.onPortInit;\n this.onPortEvent = portOpts.onPortEvent;\n this.onPortData = portOpts.onPortData;\n }\n\n protected override processChannelMessage(msg: SpiceMiniData): boolean\n {\n if (msg.type === SpiceMsgPort.INIT)\n {\n if (this.portName === null)\n {\n if (!msg.data)\n {\n this.logWarn(\"SPICE port: INIT message with no data\");\n return false;\n }\n const m = new SpiceMsgPortInit(msg.data);\n this.portName = new TextDecoder().decode(m.name);\n this.portOpened = m.opened !== 0;\n DEBUG > 0 && console.log(\"SPICE port: Port\", this.portName, \"initialized\");\n\n if (this.onPortInit)\n {\n this.onPortInit(this.portName, this.portOpened);\n }\n return true;\n }\n\n DEBUG > 0 && console.log(\"SPICE port: Port\", this.portName, \"is already initialized.\");\n return true;\n }\n\n if (msg.type === SpiceMsgPort.EVENT)\n {\n if (!msg.data)\n {\n this.logWarn(\"SPICE port: EVENT message with no data\");\n return false;\n }\n\n DEBUG > 0 && console.log(\"SPICE port: Port event received for\", this.portName);\n\n if (this.onPortEvent && this.portName !== null)\n {\n this.onPortEvent(this.portName, new Uint8Array(msg.data));\n }\n return true;\n }\n\n if (msg.type === SpiceMsgPort.SPICEVMC_DATA)\n {\n if (!msg.data)\n {\n this.logWarn(\"SPICE port: DATA message with no data\");\n return false;\n }\n\n DEBUG > 0 && console.log(\"SPICE port: Data received in port\", this.portName);\n\n if (this.onPortData && this.portName !== null)\n {\n this.onPortData(this.portName, msg.data);\n }\n return true;\n }\n\n DEBUG > 0 && console.log(\"SPICE port: message type not recognized:\", msg.type);\n return false;\n }\n\n /**\n * Send data to the port channel.\n */\n sendPortData(data: ArrayBuffer): void\n {\n const msg = new SpiceMiniData();\n const payload = {\n toBuffer(a: ArrayBuffer, at: number = 0): void\n {\n new Uint8Array(a, at).set(new Uint8Array(data));\n },\n bufferSize(): number\n {\n return data.byteLength;\n },\n };\n msg.buildMsg(SpiceMsgcPort.SPICEVMC_DATA, payload);\n this.sendMsg(msg);\n }\n\n /**\n * Send a port event.\n */\n sendPortEvent(eventData: ArrayBuffer): void\n {\n const msg = new SpiceMiniData();\n const payload = {\n toBuffer(a: ArrayBuffer, at: number = 0): void\n {\n new Uint8Array(a, at).set(new Uint8Array(eventData));\n },\n bufferSize(): number\n {\n return eventData.byteLength;\n },\n };\n msg.buildMsg(SpiceMsgcPort.EVENT, payload);\n this.sendMsg(msg);\n }\n\n override cleanup(): void\n {\n super.cleanup();\n this.onPortInit = undefined;\n this.onPortEvent = undefined;\n this.onPortData = undefined;\n }\n}\n\n// Register with the channel factory so SpiceMainConn can instantiate port channels\nregisterChannelFactory(SpiceChannel.PORT, SpicePortConn);\n\nexport { SpicePortConn as default };\n","/**\n * Typed ArrayBuffer utility functions for the SPICE protocol.\n *\n * The original spicearraybuffer.js was a polyfill for ArrayBuffer.prototype.slice\n * in IE 10. Modern browsers all support ArrayBuffer.prototype.slice natively,\n * so no polyfill is needed. This module provides typed helper functions for\n * common ArrayBuffer operations used throughout the protocol layer.\n */\n\n/**\n * Safely slice an ArrayBuffer with bounds clamping.\n *\n * Behaves identically to ArrayBuffer.prototype.slice but clamps negative\n * indices and out-of-bounds values instead of throwing.\n *\n * @param buffer - The source ArrayBuffer to slice.\n * @param start - Start byte offset (inclusive). Negative values count from end. Defaults to 0.\n * @param end - End byte offset (exclusive). Negative values count from end. Defaults to buffer.byteLength.\n * @returns A new ArrayBuffer containing the sliced bytes.\n */\nfunction arrayBufferSlice(buffer: ArrayBuffer, start?: number, end?: number): ArrayBuffer {\n let s = start ?? 0;\n let e = end ?? buffer.byteLength;\n\n if (e < 0) {\n e = buffer.byteLength + e;\n }\n if (s < 0) {\n s = buffer.byteLength + s;\n }\n if (s < 0) {\n s = 0;\n }\n if (e < 0) {\n e = 0;\n }\n if (e > buffer.byteLength) {\n e = buffer.byteLength;\n }\n if (s > e) {\n s = e;\n }\n\n return buffer.slice(s, e);\n}\n\n/**\n * Concatenate multiple ArrayBuffers into a single ArrayBuffer.\n *\n * @param buffers - The ArrayBuffers to concatenate.\n * @returns A new ArrayBuffer containing all bytes in order.\n */\nfunction concatArrayBuffers(...buffers: ArrayBuffer[]): ArrayBuffer {\n let totalLength = 0;\n for (const buf of buffers) {\n totalLength += buf.byteLength;\n }\n\n const result = new ArrayBuffer(totalLength);\n const out = new Uint8Array(result);\n let offset = 0;\n\n for (const buf of buffers) {\n out.set(new Uint8Array(buf), offset);\n offset += buf.byteLength;\n }\n\n return result;\n}\n\n/**\n * Create a new ArrayBuffer initialized with the contents of a Uint8Array.\n *\n * @param data - The source byte array.\n * @returns A new ArrayBuffer containing a copy of the data.\n */\nfunction arrayBufferFromUint8Array(data: Uint8Array): ArrayBuffer {\n const buffer = new ArrayBuffer(data.byteLength);\n new Uint8Array(buffer).set(data);\n return buffer;\n}\n\n/**\n * Compare two ArrayBuffers for byte equality.\n *\n * @param a - First ArrayBuffer.\n * @param b - Second ArrayBuffer.\n * @returns true if both buffers have identical length and contents.\n */\nfunction arrayBuffersEqual(a: ArrayBuffer, b: ArrayBuffer): boolean {\n if (a.byteLength !== b.byteLength) {\n return false;\n }\n const viewA = new Uint8Array(a);\n const viewB = new Uint8Array(b);\n for (let i = 0; i < viewA.byteLength; i++) {\n if (viewA[i] !== viewB[i]) {\n return false;\n }\n }\n return true;\n}\n\nexport {\n arrayBufferSlice,\n concatArrayBuffers,\n arrayBufferFromUint8Array,\n arrayBuffersEqual,\n};\n","/**\n * Typed DataView wrapper for the SPICE protocol.\n *\n * The original spicedataview.js was a manual DataView polyfill for old\n * Firefox versions that lacked DataView support. Modern browsers all\n * provide DataView natively, so no polyfill is needed.\n *\n * This module provides:\n * - SpiceDataView: a thin typed wrapper around the standard DataView\n * with SPICE-specific convenience methods (e.g., 64-bit BigInt reads,\n * typed sub-view creation).\n * - Helper functions for creating DataViews from various sources.\n *\n * Per codebase convention, new protocol code should use standard DataView\n * directly with getBigUint64/setBigUint64 for 64-bit fields (bigint).\n * This module exists for compatibility and as a typed alternative.\n */\n\n/**\n * A typed wrapper around standard DataView with SPICE-specific conveniences.\n *\n * Provides the same API as DataView, plus:\n * - Getters/setters for 64-bit unsigned integers as bigint (delegates to\n * standard getBigUint64/setBigUint64)\n * - A subview() method for creating DataViews over sub-regions\n * - Access to the underlying Uint8Array for byte-level operations\n * - A remaining() helper for protocol message parsing\n */\nclass SpiceDataView {\n /** The underlying standard DataView. */\n readonly dv: DataView;\n /** The underlying buffer as a Uint8Array for direct byte access. */\n readonly u8: Uint8Array;\n\n /**\n * Create a SpiceDataView over an ArrayBuffer or ArrayBufferLike.\n *\n * @param buffer - The source buffer.\n * @param byteOffset - Optional byte offset into the buffer. Defaults to 0.\n * @param byteLength - Optional number of bytes. Defaults to remainder of buffer.\n */\n constructor(buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number) {\n if (byteOffset !== undefined && byteLength !== undefined) {\n this.dv = new DataView(buffer, byteOffset, byteLength);\n this.u8 = new Uint8Array(buffer, byteOffset, byteLength);\n } else if (byteOffset !== undefined) {\n this.dv = new DataView(buffer, byteOffset);\n this.u8 = new Uint8Array(buffer, byteOffset);\n } else {\n this.dv = new DataView(buffer);\n this.u8 = new Uint8Array(buffer);\n }\n }\n\n /** The ArrayBuffer backing this view. */\n get buffer(): ArrayBufferLike {\n return this.dv.buffer;\n }\n\n /** The byte offset into the buffer. */\n get byteOffset(): number {\n return this.dv.byteOffset;\n }\n\n /** The byte length of this view. */\n get byteLength(): number {\n return this.dv.byteLength;\n }\n\n // -----------------------------------------------------------------------\n // Standard DataView read methods (typed pass-through)\n // -----------------------------------------------------------------------\n\n getUint8(byteOffset: number): number {\n return this.dv.getUint8(byteOffset);\n }\n\n getInt8(byteOffset: number): number {\n return this.dv.getInt8(byteOffset);\n }\n\n getUint16(byteOffset: number, littleEndian?: boolean): number {\n return this.dv.getUint16(byteOffset, littleEndian);\n }\n\n getInt16(byteOffset: number, littleEndian?: boolean): number {\n return this.dv.getInt16(byteOffset, littleEndian);\n }\n\n getUint32(byteOffset: number, littleEndian?: boolean): number {\n return this.dv.getUint32(byteOffset, littleEndian);\n }\n\n getInt32(byteOffset: number, littleEndian?: boolean): number {\n return this.dv.getInt32(byteOffset, littleEndian);\n }\n\n getFloat32(byteOffset: number, littleEndian?: boolean): number {\n return this.dv.getFloat32(byteOffset, littleEndian);\n }\n\n getFloat64(byteOffset: number, littleEndian?: boolean): number {\n return this.dv.getFloat64(byteOffset, littleEndian);\n }\n\n /**\n * Read an unsigned 64-bit integer as a bigint.\n *\n * The original SpiceDataView.getUint64 returned a lossy JavaScript number.\n * This version uses the standard getBigUint64 for full precision.\n */\n getBigUint64(byteOffset: number, littleEndian?: boolean): bigint {\n return this.dv.getBigUint64(byteOffset, littleEndian);\n }\n\n /**\n * Read a signed 64-bit integer as a bigint.\n */\n getBigInt64(byteOffset: number, littleEndian?: boolean): bigint {\n return this.dv.getBigInt64(byteOffset, littleEndian);\n }\n\n // -----------------------------------------------------------------------\n // Standard DataView write methods (typed pass-through)\n // -----------------------------------------------------------------------\n\n setUint8(byteOffset: number, value: number): void {\n this.dv.setUint8(byteOffset, value);\n }\n\n setInt8(byteOffset: number, value: number): void {\n this.dv.setInt8(byteOffset, value);\n }\n\n setUint16(byteOffset: number, value: number, littleEndian?: boolean): void {\n this.dv.setUint16(byteOffset, value, littleEndian);\n }\n\n setInt16(byteOffset: number, value: number, littleEndian?: boolean): void {\n this.dv.setInt16(byteOffset, value, littleEndian);\n }\n\n setUint32(byteOffset: number, value: number, littleEndian?: boolean): void {\n this.dv.setUint32(byteOffset, value, littleEndian);\n }\n\n setInt32(byteOffset: number, value: number, littleEndian?: boolean): void {\n this.dv.setInt32(byteOffset, value, littleEndian);\n }\n\n setFloat32(byteOffset: number, value: number, littleEndian?: boolean): void {\n this.dv.setFloat32(byteOffset, value, littleEndian);\n }\n\n setFloat64(byteOffset: number, value: number, littleEndian?: boolean): void {\n this.dv.setFloat64(byteOffset, value, littleEndian);\n }\n\n /**\n * Write an unsigned 64-bit integer from a bigint.\n *\n * The original SpiceDataView.setUint64 accepted a lossy JavaScript number.\n * This version uses the standard setBigUint64 for full precision.\n */\n setBigUint64(byteOffset: number, value: bigint, littleEndian?: boolean): void {\n this.dv.setBigUint64(byteOffset, value, littleEndian);\n }\n\n /**\n * Write a signed 64-bit integer from a bigint.\n */\n setBigInt64(byteOffset: number, value: bigint, littleEndian?: boolean): void {\n this.dv.setBigInt64(byteOffset, value, littleEndian);\n }\n\n // -----------------------------------------------------------------------\n // SPICE-specific convenience methods\n // -----------------------------------------------------------------------\n\n /**\n * Create a sub-view of this SpiceDataView.\n *\n * Useful for parsing nested protocol structures at a known offset.\n *\n * @param byteOffset - Offset relative to this view's start.\n * @param byteLength - Optional length. Defaults to remainder.\n * @returns A new SpiceDataView over the sub-region.\n */\n subview(byteOffset: number, byteLength?: number): SpiceDataView {\n const absOffset = this.dv.byteOffset + byteOffset;\n return new SpiceDataView(this.dv.buffer, absOffset, byteLength);\n }\n\n /**\n * Get the number of bytes remaining from the given offset to the end.\n *\n * Useful during protocol message parsing to determine how many bytes\n * are left for variable-length trailing data.\n *\n * @param currentOffset - The current parse offset within this view.\n * @returns Number of remaining bytes.\n */\n remaining(currentOffset: number): number {\n return this.dv.byteLength - currentOffset;\n }\n\n /**\n * Extract a copy of a byte range as a new Uint8Array.\n *\n * @param byteOffset - Start offset within this view.\n * @param byteLength - Number of bytes to extract. Defaults to remainder.\n * @returns A new Uint8Array copy of the specified range.\n */\n getBytes(byteOffset: number, byteLength?: number): Uint8Array {\n const len = byteLength ?? (this.dv.byteLength - byteOffset);\n return new Uint8Array(this.dv.buffer.slice(\n this.dv.byteOffset + byteOffset,\n this.dv.byteOffset + byteOffset + len,\n ));\n }\n\n /**\n * Copy bytes into this view's buffer at the given offset.\n *\n * @param byteOffset - Destination offset within this view.\n * @param data - Source bytes to copy.\n */\n setBytes(byteOffset: number, data: Uint8Array): void {\n this.u8.set(data, byteOffset);\n }\n}\n\n/**\n * Create a SpiceDataView from an ArrayBuffer.\n *\n * @param buffer - The source ArrayBuffer.\n * @param byteOffset - Optional byte offset.\n * @param byteLength - Optional byte length.\n * @returns A new SpiceDataView.\n */\nfunction createSpiceDataView(\n buffer: ArrayBufferLike,\n byteOffset?: number,\n byteLength?: number,\n): SpiceDataView {\n return new SpiceDataView(buffer, byteOffset, byteLength);\n}\n\n/**\n * Create a standard DataView from an ArrayBuffer.\n *\n * Convenience function that mirrors the original SpiceDataView constructor\n * signature but returns a standard DataView. Useful for migrating call sites\n * incrementally.\n *\n * @param buffer - The source ArrayBuffer.\n * @param byteOffset - Optional byte offset.\n * @param byteLength - Optional byte length.\n * @returns A new standard DataView.\n */\nfunction createDataView(\n buffer: ArrayBufferLike,\n byteOffset?: number,\n byteLength?: number,\n): DataView {\n if (byteOffset !== undefined && byteLength !== undefined) {\n return new DataView(buffer, byteOffset, byteLength);\n } else if (byteOffset !== undefined) {\n return new DataView(buffer, byteOffset);\n }\n return new DataView(buffer);\n}\n\nexport {\n SpiceDataView,\n createSpiceDataView,\n createDataView,\n};\n","\"use strict\";\n// ---------------------------------------------------------------------------\n// spice-html5-react — Main package entry point\n//\n// This file exports the public API of the package.\n// ---------------------------------------------------------------------------\n\n/** Package version. */\nexport const VERSION = '0.1.0';\n\n// ---------------------------------------------------------------------------\n// React components\n// ---------------------------------------------------------------------------\n\nexport { SpiceDisplay } from './components/SpiceDisplay';\n\nexport type {\n SpiceConnectionProps,\n SpiceDisplayOptions,\n SpiceFeatureToggles,\n SpiceAudioProps,\n SpiceEventCallbacks,\n SpiceDisplayProps,\n SpiceDisplayHandle,\n} from './components/SpiceDisplay';\n\n// ---------------------------------------------------------------------------\n// React hooks\n// ---------------------------------------------------------------------------\n\nexport { useSpice } from './hooks/useSpice';\n\nexport type {\n SpiceStatus,\n SpiceResolution,\n SpiceConfig,\n UseSpiceCallbacks,\n UseSpiceOptions,\n SpiceControls,\n UseSpiceReturn,\n} from './hooks/useSpice';\n\n// ---------------------------------------------------------------------------\n// Protocol layer\n// ---------------------------------------------------------------------------\n\nexport * from './protocol';\n"],"names":["SPICE_MAGIC","SPICE_VERSION_MAJOR","SPICE_VERSION_MINOR","SPICE_CONNECT_TIMEOUT","SpiceCommonCap","SPICE_TICKET_KEY_PAIR_LENGTH","SPICE_TICKET_PUBKEY_BYTES","SpiceLinkErr","SpiceMsg","SpiceMsgMain","SpiceMsgc","SpiceMsgcMain","SpiceMsgDisplay","SpiceMsgcDisplay","SpiceMsgInputs","SpiceMsgcInputs","SpiceMsgCursor","SpiceMsgPlayback","SpiceMsgPort","SpiceMsgcPort","SpicePlaybackCap","SpiceMainCap","SpiceDisplayCap","SpiceAudioDataMode","SpiceAudioFmt","SpiceChannel","SPICE_SURFACE_FLAGS_PRIMARY","SpiceNotifySeverity","SpiceMouseMode","SpiceClipType","SpiceImageType","SpiceImageFlags","SpiceBitmapFlags","SpiceBitmapFmt","SpiceCursorFlags","SpiceMouseButtonMask","SpiceMouseButton","SpiceBrushType","SpiceSurfaceFmt","SpiceRopd","LzImageType","SPICE_INPUT_MOTION_ACK_BUNCH","SpiceCursorType","SpiceVideoCodecType","VD_AGENT_PROTOCOL","VD_AGENT_MAX_DATA_SIZE","VdAgentMsg","VdAgentCap","VdAgentFileXferStatus","VdAgentClipboard","Constants","spiceQuicFactory","registerSpiceQuicFactory","factory","SpiceChannelId","dv","at","_mb","SpiceRect","r","SpiceClipRects","mb","rect","SpiceClip","SpiceImageDescriptor","SpicePalette","SpiceBitmap","offset","SpicePoint","SpicePoint16","SpiceImage","jpegDataSize","jpegDataBuf","length","initialAt","magic","i","version","type","width","height","stride","topDown","headerSize","data","flags","jpegSize","dataSize","jpegData","alphaLength","alphaInitialAt","alphaMagic","alphaVersion","alphaType","alphaWidth","alphaHeight","alphaStride","alphaTopDown","alphaHeaderSize","alphaData","SpiceQMask","SpicePattern","SpiceBrush","SpiceFill","SpiceCopy","SpiceCursorHeader","SpiceCursor","SpiceSurface","SpiceLinkHeader","a","SpiceLinkMess","origAt","numCommonCaps","numChannelCaps","capsOffset","SpiceLinkReply","SpiceLinkAuthTicket","keyBytes","SpiceLinkAuthReply","SpiceMiniData","u8arr","target","inType","extra","SpiceMsgChannels","chan","hasClipboardSelection","caps","cap0","SpiceMsgClipboardGrab","SpiceMsgClipboardReceive","agentData","SpiceMsgClipboardRequest","SpiceMsgClipboardSend","text","payload","payloadLength","SpiceMsgMainInit","SpiceMsgMainMouseMode","SpiceMsgMainAgentData","SpiceMsgMainAgentTokens","SpiceMsgSetAck","SpiceMsgcAckSync","ack","SpiceMsgcMainMouseModeRequest","mode","SpiceMsgcMainAgentStart","numTokens","SpiceMsgcMainAgentData","VDAgentAnnounceCapabilities","requestOrBuffer","VDAgentMonitorsConfig","depth","x","y","VDAgentFileXferStatusMessage","idOrBuffer","result","VDAgentFileXferStartMessage","id","name","size","VDAgentFileXferDataMessage","SpiceMsgNotify","c","SpiceMsgcDisplayInit","SpiceMsgDisplayBase","SpiceMsgDisplayDrawCopy","SpiceMsgDisplayDrawFill","SpiceMsgDisplayCopyBits","SpiceMsgSurfaceCreate","SpiceMsgSurfaceDestroy","SpiceMsgInputsInit","SpiceMsgInputsKeyModifiers","SpiceMsgCursorInit","SpiceMsgPlaybackData","SpiceMsgPlaybackMode","SpiceMsgPlaybackStart","SpiceMsgCursorSet","SpiceMsgcMousePosition","buttonsState","displayId","SpiceMsgcMouseMotion","SpiceMsgcMousePress","button","SpiceMsgcMouseRelease","SpiceMsgcKeyDown","code","SpiceMsgcKeyUp","SpiceMsgDisplayStreamCreate","SpiceStreamDataHeader","SpiceMsgDisplayStreamData","u8","SpiceMsgDisplayStreamDataSized","SpiceMsgDisplayStreamClip","SpiceMsgDisplayStreamDestroy","SpiceMsgDisplayStreamActivateReport","SpiceMsgcDisplayStreamReport","streamId","uniqueId","SpiceMsgDisplayInvalList","SpiceMsgPortInit","namesize","KeyNames","codeToScancode","DEBUG","EMPTY_GIF_IMAGE","commonScanmap","firefoxScanmap","domScanmap","getScancode","keyCode","codeResult","commonResult","keycodeToStartScan","scancode","keycodeToEndScan","dumpMediaElement","m","dumpTimeRange","tr","len","ret","SpiceWireReader","owner","callback","n","h","e","count","frame","view","buf","uint8","step","temp","EBML_HEADER","EBML_HEADER_VERSION","EBML_HEADER_READ_VERSION","EBML_HEADER_MAX_ID_LENGTH","EBML_HEADER_MAX_SIZE_LENGTH","EBML_HEADER_DOC_TYPE","EBML_HEADER_DOC_TYPE_VERSION","EBML_HEADER_DOC_TYPE_READ_VERSION","WEBM_SEGMENT_HEADER","WEBM_SEGMENT_INFORMATION","WEBM_TIMECODE_SCALE","WEBM_MUXING_APP","WEBM_WRITING_APP","WEBM_SEEK_HEAD","WEBM_SEEK","WEBM_SEEK_ID","WEBM_SEEK_POSITION","WEBM_TRACKS","WEBM_TRACK_ENTRY","WEBM_TRACK_NUMBER","WEBM_TRACK_UID","WEBM_TRACK_TYPE","WEBM_FLAG_ENABLED","WEBM_FLAG_DEFAULT","WEBM_FLAG_FORCED","WEBM_FLAG_LACING","WEBM_MIN_CACHE","WEBM_MAX_BLOCK_ADDITION_ID","WEBM_CODEC_DECODE_ALL","WEBM_SEEK_PRE_ROLL","WEBM_CODEC_DELAY","WEBM_CODEC_PRIVATE","WEBM_CODEC_ID","WEBM_VIDEO","WEBM_FLAG_INTERLACED","WEBM_PIXEL_WIDTH","WEBM_PIXEL_HEIGHT","WEBM_AUDIO","WEBM_SAMPLING_FREQUENCY","WEBM_CHANNELS","WEBM_CLUSTER","WEBM_TIME_CODE","WEBM_SIMPLE_BLOCK","WebmConstants","ebmlWriteU1DataLen","b","ebmlWriteU8Value","val","ebmlWriteArray","ebmlWriteU32Value","ebmlWriteU16Value","ebmlWriteFloatValue","ebmlWriteU64DataLen","shift","arr","ebmlWriteString","str","ebmlWriteData","WebmEBMLHeader","WebmSegment","WebmSegmentInformation","WebmAudio","frequency","WebmVideo","WebmSeek","seekid","pos","WebmSeekHead","infoPos","trackPos","WebmAudioTrackEntry","WebmVideoTrackEntry","WebmTracks","entry","WebmCluster","timecode","WebmSimpleBlock","keyframe","u8src","WebmHeader","rsaEncrypt","derPublicKey","password","key","passwordBytes","encrypted","ConnectionState","SpiceConn","options","err","hdr","msg","ticket","savedHeader","dinit","reply","ackack","pong","notify","start","rc","delta","args","container","p","FileXferState","channelFactories","registerChannelFactory","ctor","SpiceMainConn","connectedTokens","attach","chans","chanInfo","connOpts","inputsConn","port","current","supported","modeRequest","mr","agentStart","request","message","maxsize","sb","eb","tokens","remainingTokens","xferTask","agentCapsMsg","file","taskId","task","xferStart","fileXferStatus","xferError","fileXferTask","startByte","FILE_XFER_CHUNK_SIZE","xferStatus","reader","_a","xferData","slice","error","clipboardType","clipboardRequest","receivedClipboard","clipboardMsg","grabMessage","monitorsConfig","XFER_AREA_ID","SpiceFileXferTask","xferAreaId","xferArea","cancel","value","handleFileDragover","handleFileDrop","connection","files","RESIZE_DEBOUNCE_MS","DIMENSION_ALIGNMENT","BOTTOM_MARGIN","resizeHelper","screenEl","w","mh","SpiceResizeHandler","debounceMs","observeContainerResize","handler","observer","buildUri","conn","uri","setTokenCookie","token","date","SpiceDisplay","forwardRef","props","ref","connProps","displayProps","features","_audio","className","style","onConnect","onDisconnect","onError","onResize","onClipboard","onFileTransferProgress","onFileTransferComplete","onPortData","containerRef","useRef","screenRef","connRef","cleanupRef","callbacksRef","enableKeyboard","enableMouse","enableClipboard","enableFileTransfer","fitContainer","screenId","useState","disconnect","useCallback","_b","connect","cbs","sc","bytes","total","filename","display","surfaceId","created","cleanupObserver","prevCleanup","dragHandler","dropHandler","portConn","useImperativeHandle","inputs","useEffect","getInputs","handlers","onKeyDown","onKeyUp","onMouseMove","onMouseDown","onMouseUp","onWheel","onContextMenu","event","jsx","SSR","useSpice","status","setStatus","setError","resolution","setResolution","surfaces","setSurfaces","canvasRef","doConnect","config","spiceOpts","_surfaceId","surfaceCount","primary","sendKeyDown","sendKeyUp","sendMouseMove","sendMouseButton","pressed","sendClipboard","_text","changeResolution","sendCtrlAltDel","getConnection","QuicImageType","DEFevol","DEFwmimax","DEFwminext","DEFmaxclen","evol","wmimax","wminext","rgb32_pixel_pad","rgb32_pixel_r","rgb32_pixel_g","rgb32_pixel_b","rgb32_pixel_size","createFamily","family_5bpc","family_8bpc","bppmask","zeroLUT","besttrigtab","J","lzeroes","tabrand_chaos","ceilLog2","familyInit","family","bpc","limit","l","altprefixlen","bppmaskVal","altcodewords","pixelbitmask","pixelbitmaskshr","s","quicImageBpc","cntLZeroes","bits","golombDecoding8bpc","cwlen","zeroprefix","golombCodeLen8bpc","QuicModel","bend","repcntr","bsize","bstart","QuicBucket","bpp","state","curval","bestcode","bestcodelen","ithcodelen","QuicFamilyStat","model","bnumber","bucket","QuicChannel","model8bpc","model5bpc","CommonState","j","wm","QuicEncoder","ioPtr","absDelta","curRow","end","waitmask","bpcMask","stopidx","prevRow","runIndex","runEnd","pixel","pixelm1","pixelm2","px","pxm1","cc","cr","runlen","hits","channel","correlateRow","pbucket","row","prev","out","encoder","getEncoder","SpiceQuic","enc","convertSpiceQuicToWeb","context","spiceQuic","totalPixels","k","lzRgb32Decompress","inBuf","outBuf","defaultAlpha","op","ctrl","ofs","flipImageData","img","wb","tempH","buff","convertSpiceLzToWeb","lzImage","convertSpiceBitmapToWeb","spiceBitmap","srcOffset","srcDec","dst","SpiceDisplayConn","surface","drawCopy","srcBitmap","descriptor","sourceImg","cachedImage","sourceSurface","sourceContext","srcArea","computedSrcArea","alphaImg","drawFill","color","colorStr","copyBits","putImageDataWithAlpha","o","canvas","stripAlpha","base","tmpstr","qdv","useTempCanvas","tempCanvas","tempCtx","t","prefix","draw","bitmap","brush","mask","media","v","left","top","stream","mainConn","relativeNow","timeUntilDue","report","te","next","lastStart","msgMmtime","simple","strmBase","dest","activeStream","relNow","video","debugHandler","canvasEl","ctx","spiceCanvas","ids","resource","imageData","d","buildInputMsg","domButtonToSpice","domButton","domButtonsToMask","domButtons","META_SCANCODE","SpiceInputsConn","init","outMsg","deleteCode","downKey","downMsg","upKey","upMsg","move","press","release","pressMsg","releaseMsg","createRgbaPng","clamped","sha1","input","hashBuffer","asSimulatedCursor","screen","el","cursorCache","unknownCursors","warned","addCursor","hash","unknownCursor","dataUrl","duplicateMouseEvent","evt","simulateCursor","cursor","cursorSha","cached","curstr","cleanupSimulatedCursor","SpiceSimulateCursor","SpiceCursorConn","cursorInit","cursorSet","condenseQueue","queue","tmp","SpicePlaybackConn","newTime","eventType","audio","audio0Events","SpicePortConn","portOpts","eventData","arrayBufferSlice","buffer","concatArrayBuffers","buffers","totalLength","arrayBufferFromUint8Array","arrayBuffersEqual","viewA","viewB","SpiceDataView","byteOffset","byteLength","littleEndian","absOffset","currentOffset","createSpiceDataView","createDataView","VERSION"],"mappings":"yIAUaA,GAAc,OACdC,GAAsB,EACtBC,GAAsB,EACtBC,GAAwB,IAMxBC,GAAiB,CAC1B,wBAAyB,EACzB,WAAY,EACZ,UAAW,EACX,YAAa,CACjB,EAMaC,GAA+B,KAC/BC,GAA4B,IAM5BC,GAAe,CACxB,GAAI,EACJ,MAAO,EACP,cAAe,EACf,aAAc,EACd,iBAAkB,EAClB,aAAc,EACd,eAAgB,EAChB,kBAAmB,EACnB,kBAAmB,EACnB,sBAAuB,CAC3B,EAMaC,GAAW,CACpB,QAAS,EACT,aAAc,EACd,QAAS,EACT,KAAM,EACN,kBAAmB,EACnB,cAAe,EACf,OAAQ,EACR,KAAM,CACV,EAMaC,EAAe,CACxB,cAAe,IACf,eAAgB,IAChB,KAAM,IACN,cAAe,IACf,WAAY,IACZ,iBAAkB,IAClB,gBAAiB,IACjB,mBAAoB,IACpB,WAAY,IACZ,YAAa,IACb,oBAAqB,IACrB,YAAa,IACb,KAAM,IACN,KAAM,IACN,uBAAwB,IACxB,uBAAwB,IACxB,yBAA0B,IAC1B,0BAA2B,IAC3B,IAAK,GACT,EAMaC,GAAY,CACrB,SAAU,EACV,IAAK,EACL,KAAM,EACN,mBAAoB,EACpB,aAAc,EACd,cAAe,CACnB,EAMaC,GAAgB,CACzB,YAAa,IACb,kBAAmB,IACnB,sBAAuB,IACvB,gBAAiB,IACjB,mBAAoB,IACpB,YAAa,IACb,WAAY,IACZ,YAAa,IACb,YAAa,IACb,IAAK,GACT,EAMaC,EAAkB,CAC3B,KAAM,IACN,KAAM,IACN,MAAO,IACP,UAAW,IACX,WAAY,IACZ,kBAAmB,IACnB,cAAe,IACf,mBAAoB,IACpB,cAAe,IACf,YAAa,IACb,YAAa,IACb,eAAgB,IAChB,mBAAoB,IACpB,UAAW,IACX,YAAa,IACb,UAAW,IACX,WAAY,IACZ,eAAgB,IAChB,eAAgB,IAChB,YAAa,IACb,UAAW,IACX,YAAa,IACb,UAAW,IACX,iBAAkB,IAClB,iBAAkB,IAClB,eAAgB,IAChB,gBAAiB,IACjB,kBAAmB,IACnB,gBAAiB,IACjB,eAAgB,IAChB,uBAAwB,GAC5B,EAMaC,GAAmB,CAC5B,KAAM,IACN,cAAe,GACnB,EAMaC,GAAiB,CAC1B,KAAM,IACN,cAAe,IACf,iBAAkB,GACtB,EAMaC,EAAkB,CAC3B,SAAU,IACV,OAAQ,IACR,cAAe,IACf,aAAc,IACd,eAAgB,IAChB,YAAa,IACb,cAAe,GACnB,EAMaC,GAAiB,CAC1B,KAAM,IACN,MAAO,IACP,IAAK,IACL,KAAM,IACN,KAAM,IACN,MAAO,IACP,UAAW,IACX,UAAW,GACf,EAMaC,GAAmB,CAC5B,KAAM,IACN,KAAM,IACN,MAAO,IACP,KAAM,IACN,OAAQ,IACR,KAAM,IACN,QAAS,GACb,EAMaC,GAAe,CACxB,cAAe,IACf,KAAM,IACN,MAAO,IACP,IAAK,GACT,EAMaC,GAAgB,CACzB,cAAe,IACf,MAAO,IACP,IAAK,GACT,EAMaC,GAAmB,CAC5B,WAAY,EACZ,OAAQ,EACR,QAAS,EACT,KAAM,CACV,EAMaC,GAAe,CACxB,sBAAuB,EACvB,cAAe,EACf,uBAAwB,EACxB,iBAAkB,CACtB,EAMaC,EAAkB,CAC3B,aAAc,EACd,gBAAiB,EACjB,UAAW,EACX,WAAY,EACZ,cAAe,EACf,gBAAiB,EACjB,iBAAkB,EAClB,WAAY,EACZ,YAAa,EACb,YAAa,EACb,UAAW,EACf,EAMaC,GAAqB,CAC9B,QAAS,EACT,IAAK,EACL,WAAY,EACZ,KAAM,CACV,EAMaC,GAAgB,CACzB,QAAS,EACT,IAAK,CACT,EAMaC,EAAe,CACxB,KAAM,EACN,QAAS,EACT,OAAQ,EACR,OAAQ,EACR,SAAU,EACV,OAAQ,EACR,OAAQ,EACR,UAAW,EACX,SAAU,EACV,KAAM,GACN,OAAQ,EACZ,EAMaC,GAA8B,EAM9BC,GAAsB,CAC/B,KAAM,EACN,KAAM,EACN,MAAO,CACX,EAMaC,GAAiB,CAC1B,OAAS,EACT,OAAS,EACT,KAAM,CACV,EAMaC,GAAgB,CACzB,KAAM,EACN,MAAO,CACX,EAMaC,EAAiB,CAC1B,OAAQ,EACR,KAAM,EACN,SAAU,EACV,OAAQ,IACR,OAAQ,IACR,QAAS,IACT,WAAY,IACZ,QAAS,IACT,KAAM,IACN,oBAAqB,IACrB,aAAc,IACd,WAAY,GAChB,EAMaC,GAAkB,CAC3B,SAAW,EACX,cAAgB,EAChB,iBAAmB,CACvB,EAMaC,GAAmB,CAC5B,aAAe,EACf,eAAiB,EACjB,SAAW,EACX,KAAM,CACV,EAMaC,GAAiB,CAC1B,QAAS,EACT,SAAU,EACV,SAAU,EACV,SAAU,EACV,SAAU,EACV,MAAO,EACP,OAAQ,EACR,OAAQ,EACR,OAAQ,EACR,KAAM,CACV,EAMaC,GAAmB,CAC5B,KAAO,EACP,SAAW,EACX,WAAa,EACb,KAAM,CACV,EAMaC,GAAuB,CAChC,KAAO,EACP,OAAS,EACT,MAAQ,EACR,KAAM,CACV,EAMaC,GAAmB,CAC5B,QAAS,EACT,KAAM,EACN,OAAQ,EACR,MAAO,EACP,GAAI,EACJ,KAAM,CACV,EAMaC,GAAiB,CAC1B,KAAM,EACN,MAAO,EACP,QAAS,CACb,EAMaC,GAAkB,CAC3B,QAAS,EACT,KAAM,EACN,KAAM,EACN,QAAS,GACT,SAAU,GACV,QAAS,GACT,SAAU,EACd,EAMaC,GAAY,CACrB,WAAa,EACb,aAAe,EACf,YAAc,EACd,OAAS,EACT,MAAQ,GACR,OAAS,GACT,OAAS,GACT,aAAe,IACf,aAAe,IACf,UAAY,IACZ,WAAa,KACb,KAAM,IACV,EAMaC,EAAc,CACvB,QAAS,EACT,QAAS,EACT,QAAS,EACT,QAAS,EACT,QAAS,EACT,KAAM,EACN,MAAO,EACP,MAAO,EACP,MAAO,EACP,KAAM,EACN,KAAM,EACV,EAMaC,GAA+B,EAM/BC,GAAkB,CAC3B,MAAO,EACP,KAAM,EACN,OAAQ,EACR,OAAQ,EACR,QAAS,EACT,QAAS,EACT,QAAS,CACb,EAMaC,GAAsB,CAC/B,MAAO,EACP,IAAK,CACT,EAMaC,GAAoB,EACpBC,GAAyB,KAMzBC,EAAa,CACtB,YAAa,EACb,gBAAiB,EACjB,MAAO,EACP,UAAW,EACX,eAAgB,EAChB,sBAAuB,EACvB,eAAgB,EAChB,kBAAmB,EACnB,kBAAmB,EACnB,gBAAiB,GACjB,iBAAkB,GAClB,eAAgB,GAChB,oBAAqB,GACrB,cAAe,EACnB,EAMaC,EAAa,CACtB,YAAa,EACb,gBAAiB,EACjB,MAAO,EACP,UAAW,EACX,eAAgB,EAChB,oBAAqB,EACrB,oBAAqB,EACrB,uBAAwB,EACxB,iBAAkB,EAClB,mBAAoB,EACpB,cAAe,GACf,IAAK,EACT,EAMaC,GAAwB,CACjC,cAAe,EACf,UAAW,EACX,MAAO,EACP,QAAS,CACb,EAMaC,GAAmB,CAC5B,KAAM,EACN,UAAW,EACX,UAAW,EACX,UAAW,EACX,WAAY,EACZ,UAAW,CACf,EAUaC,GAAY,CACrB,YAAAlD,GACA,oBAAAC,GACA,oBAAAC,GACA,sBAAAC,GAGA,yCAA0CC,GAAe,wBACzD,4BAA6BA,GAAe,WAC5C,2BAA4BA,GAAe,UAC3C,6BAA8BA,GAAe,YAG7C,6BAAAC,GACA,0BAAAC,GAGA,kBAAmBC,GAAa,GAChC,qBAAsBA,GAAa,MACnC,6BAA8BA,GAAa,cAC3C,4BAA6BA,GAAa,aAC1C,gCAAiCA,GAAa,iBAC9C,4BAA6BA,GAAa,aAC1C,8BAA+BA,GAAa,eAC5C,iCAAkCA,GAAa,kBAC/C,iCAAkCA,GAAa,kBAC/C,qCAAsCA,GAAa,sBAGnD,kBAAmBC,GAAS,QAC5B,uBAAwBA,GAAS,aACjC,kBAAmBA,GAAS,QAC5B,eAAgBA,GAAS,KACzB,4BAA6BA,GAAS,kBACtC,wBAAyBA,GAAS,cAClC,iBAAkBA,GAAS,OAC3B,eAAgBA,GAAS,KAGzB,6BAA8BC,EAAa,cAC3C,8BAA+BA,EAAa,eAC5C,oBAAqBA,EAAa,KAClC,6BAA8BA,EAAa,cAC3C,0BAA2BA,EAAa,WACxC,gCAAiCA,EAAa,iBAC9C,+BAAgCA,EAAa,gBAC7C,kCAAmCA,EAAa,mBAChD,0BAA2BA,EAAa,WACxC,2BAA4BA,EAAa,YACzC,mCAAoCA,EAAa,oBACjD,2BAA4BA,EAAa,YACzC,oBAAqBA,EAAa,KAClC,oBAAqBA,EAAa,KAClC,sCAAuCA,EAAa,uBACpD,sCAAuCA,EAAa,uBACpD,wCAAyCA,EAAa,yBACtD,yCAA0CA,EAAa,0BACvD,mBAAoBA,EAAa,IAGjC,oBAAqBC,GAAU,SAC/B,eAAgBA,GAAU,IAC1B,gBAAiBA,GAAU,KAC3B,8BAA+BA,GAAU,mBACzC,wBAAyBA,GAAU,aACnC,yBAA0BA,GAAU,cAGpC,4BAA6BC,GAAc,YAC3C,kCAAmCA,GAAc,kBACjD,sCAAuCA,GAAc,sBACrD,gCAAiCA,GAAc,gBAC/C,mCAAoCA,GAAc,mBAClD,4BAA6BA,GAAc,YAC3C,2BAA4BA,GAAc,WAC1C,4BAA6BA,GAAc,YAC3C,4BAA6BA,GAAc,YAC3C,oBAAqBA,GAAc,IAGnC,uBAAwBC,EAAgB,KACxC,uBAAwBA,EAAgB,KACxC,wBAAyBA,EAAgB,MACzC,4BAA6BA,EAAgB,UAC7C,6BAA8BA,EAAgB,WAC9C,oCAAqCA,EAAgB,kBACrD,gCAAiCA,EAAgB,cACjD,qCAAsCA,EAAgB,mBACtD,gCAAiCA,EAAgB,cACjD,8BAA+BA,EAAgB,YAC/C,8BAA+BA,EAAgB,YAC/C,iCAAkCA,EAAgB,eAClD,qCAAsCA,EAAgB,mBACtD,4BAA6BA,EAAgB,UAC7C,8BAA+BA,EAAgB,YAC/C,4BAA6BA,EAAgB,UAC7C,6BAA8BA,EAAgB,WAC9C,iCAAkCA,EAAgB,eAClD,iCAAkCA,EAAgB,eAClD,8BAA+BA,EAAgB,YAC/C,4BAA6BA,EAAgB,UAC7C,8BAA+BA,EAAgB,YAC/C,4BAA6BA,EAAgB,UAC7C,mCAAoCA,EAAgB,iBACpD,mCAAoCA,EAAgB,iBACpD,iCAAkCA,EAAgB,eAClD,kCAAmCA,EAAgB,gBACnD,oCAAqCA,EAAgB,kBACrD,kCAAmCA,EAAgB,gBACnD,iCAAkCA,EAAgB,eAClD,yCAA0CA,EAAgB,uBAG1D,wBAAyBC,GAAiB,KAC1C,iCAAkCA,GAAiB,cAGnD,sBAAuBC,GAAe,KACtC,+BAAgCA,GAAe,cAC/C,kCAAmCA,GAAe,iBAGlD,2BAA4BC,EAAgB,SAC5C,yBAA0BA,EAAgB,OAC1C,gCAAiCA,EAAgB,cACjD,+BAAgCA,EAAgB,aAChD,iCAAkCA,EAAgB,eAClD,8BAA+BA,EAAgB,YAC/C,gCAAiCA,EAAgB,cAGjD,sBAAuBC,GAAe,KACtC,uBAAwBA,GAAe,MACvC,qBAAsBA,GAAe,IACrC,sBAAuBA,GAAe,KACtC,sBAAuBA,GAAe,KACtC,uBAAwBA,GAAe,MACvC,2BAA4BA,GAAe,UAC3C,2BAA4BA,GAAe,UAG3C,wBAAyBC,GAAiB,KAC1C,wBAAyBA,GAAiB,KAC1C,yBAA0BA,GAAiB,MAC3C,wBAAyBA,GAAiB,KAC1C,0BAA2BA,GAAiB,OAC5C,wBAAyBA,GAAiB,KAC1C,2BAA4BA,GAAiB,QAG7C,wBAAyBC,GAAa,cACtC,oBAAqBA,GAAa,KAClC,qBAAsBA,GAAa,MACnC,mBAAoBA,GAAa,IAGjC,yBAA0BC,GAAc,cACxC,sBAAuBA,GAAc,MACrC,oBAAqBA,GAAc,IAGnC,8BAA+BC,GAAiB,WAChD,0BAA2BA,GAAiB,OAC5C,2BAA4BA,GAAiB,QAC7C,wBAAyBA,GAAiB,KAG1C,qCAAsCC,GAAa,sBACnD,6BAA8BA,GAAa,cAC3C,sCAAuCA,GAAa,uBACpD,gCAAiCA,GAAa,iBAG9C,+BAAgCC,EAAgB,aAChD,kCAAmCA,EAAgB,gBACnD,4BAA6BA,EAAgB,UAC7C,6BAA8BA,EAAgB,WAC9C,gCAAiCA,EAAgB,cACjD,kCAAmCA,EAAgB,gBACnD,mCAAoCA,EAAgB,iBACpD,6BAA8BA,EAAgB,WAC9C,8BAA+BA,EAAgB,YAC/C,8BAA+BA,EAAgB,YAC/C,4BAA6BA,EAAgB,UAG7C,8BAA+BC,GAAmB,QAClD,0BAA2BA,GAAmB,IAC9C,iCAAkCA,GAAmB,WACrD,2BAA4BA,GAAmB,KAG/C,wBAAyBC,GAAc,QACvC,oBAAqBA,GAAc,IAGnC,mBAAoBC,EAAa,KACjC,sBAAuBA,EAAa,QACpC,qBAAsBA,EAAa,OACnC,qBAAsBA,EAAa,OACnC,uBAAwBA,EAAa,SACrC,qBAAsBA,EAAa,OACnC,qBAAsBA,EAAa,OACnC,wBAAyBA,EAAa,UACtC,uBAAwBA,EAAa,SACrC,mBAAoBA,EAAa,KACjC,qBAAsBA,EAAa,OAGnC,4BAAAC,GAGA,2BAA4BC,GAAoB,KAChD,2BAA4BA,GAAoB,KAChD,4BAA6BA,GAAoB,MAGjD,wBAAyBC,GAAe,OACxC,wBAAyBA,GAAe,OACxC,sBAAuBA,GAAe,KAGtC,qBAAsBC,GAAc,KACpC,sBAAuBA,GAAc,MAGrC,wBAAyBC,EAAe,OACxC,sBAAuBA,EAAe,KACtC,0BAA2BA,EAAe,SAC1C,wBAAyBA,EAAe,OACxC,wBAAyBA,EAAe,OACxC,yBAA0BA,EAAe,QACzC,4BAA6BA,EAAe,WAC5C,yBAA0BA,EAAe,QACzC,sBAAuBA,EAAe,KACtC,qCAAsCA,EAAe,oBACrD,8BAA+BA,EAAe,aAC9C,4BAA6BA,EAAe,WAG5C,2BAA4BC,GAAgB,SAC5C,gCAAiCA,GAAgB,cACjD,mCAAoCA,GAAgB,iBAGpD,gCAAiCC,GAAiB,aAClD,kCAAmCA,GAAiB,eACpD,4BAA6BA,GAAiB,SAC9C,wBAAyBA,GAAiB,KAG1C,yBAA0BC,GAAe,QACzC,yBAA0BA,GAAe,SACzC,yBAA0BA,GAAe,SACzC,yBAA0BA,GAAe,SACzC,yBAA0BA,GAAe,SACzC,sBAAuBA,GAAe,MACtC,uBAAwBA,GAAe,OACvC,uBAAwBA,GAAe,OACvC,uBAAwBA,GAAe,OACvC,sBAAuBA,GAAe,KAGtC,wBAAyBC,GAAiB,KAC1C,4BAA6BA,GAAiB,SAC9C,8BAA+BA,GAAiB,WAChD,wBAAyBA,GAAiB,KAG1C,6BAA8BC,GAAqB,KACnD,+BAAgCA,GAAqB,OACrD,8BAA+BA,GAAqB,MACpD,6BAA8BA,GAAqB,KAGnD,2BAA4BC,GAAiB,QAC7C,wBAAyBA,GAAiB,KAC1C,0BAA2BA,GAAiB,OAC5C,yBAA0BA,GAAiB,MAC3C,sBAAuBA,GAAiB,GACxC,wBAAyBA,GAAiB,KAG1C,sBAAuBC,GAAe,KACtC,uBAAwBA,GAAe,MACvC,yBAA0BA,GAAe,QAGzC,0BAA2BC,GAAgB,QAC3C,sBAAuBA,GAAgB,KACvC,sBAAuBA,GAAgB,KACvC,yBAA0BA,GAAgB,QAC1C,0BAA2BA,GAAgB,SAC3C,yBAA0BA,GAAgB,QAC1C,0BAA2BA,GAAgB,SAG3C,sBAAuBC,GAAU,WACjC,wBAAyBA,GAAU,aACnC,uBAAwBA,GAAU,YAClC,kBAAmBA,GAAU,OAC7B,iBAAkBA,GAAU,MAC5B,kBAAmBA,GAAU,OAC7B,kBAAmBA,GAAU,OAC7B,wBAAyBA,GAAU,aACnC,wBAAyBA,GAAU,aACnC,qBAAsBA,GAAU,UAChC,sBAAuBA,GAAU,WACjC,gBAAiBA,GAAU,KAG3B,sBAAuBC,EAAY,QACnC,sBAAuBA,EAAY,QACnC,sBAAuBA,EAAY,QACnC,sBAAuBA,EAAY,QACnC,sBAAuBA,EAAY,QACnC,mBAAoBA,EAAY,KAChC,oBAAqBA,EAAY,MACjC,oBAAqBA,EAAY,MACjC,oBAAqBA,EAAY,MACjC,mBAAoBA,EAAY,KAChC,mBAAoBA,EAAY,KAGhC,6BAAAC,GAGA,wBAAyBC,GAAgB,MACzC,uBAAwBA,GAAgB,KACxC,yBAA0BA,GAAgB,OAC1C,yBAA0BA,GAAgB,OAC1C,0BAA2BA,GAAgB,QAC3C,0BAA2BA,GAAgB,QAC3C,0BAA2BA,GAAgB,QAG3C,6BAA8BC,GAAoB,MAClD,2BAA4BA,GAAoB,IAGhD,kBAAAC,GACA,uBAAAC,GAGA,qBAAsBC,EAAW,YACjC,yBAA0BA,EAAW,gBACrC,eAAgBA,EAAW,MAC3B,mBAAoBA,EAAW,UAC/B,wBAAyBA,EAAW,eACpC,+BAAgCA,EAAW,sBAC3C,wBAAyBA,EAAW,eACpC,2BAA4BA,EAAW,kBACvC,2BAA4BA,EAAW,kBACvC,yBAA0BA,EAAW,gBACrC,0BAA2BA,EAAW,iBACtC,wBAAyBA,EAAW,eACpC,6BAA8BA,EAAW,oBACzC,uBAAwBA,EAAW,cAGnC,yBAA0BC,EAAW,YACrC,6BAA8BA,EAAW,gBACzC,mBAAoBA,EAAW,MAC/B,uBAAwBA,EAAW,UACnC,4BAA6BA,EAAW,eACxC,iCAAkCA,EAAW,oBAC7C,iCAAkCA,EAAW,oBAC7C,oCAAqCA,EAAW,uBAChD,8BAA+BA,EAAW,iBAC1C,gCAAiCA,EAAW,mBAC5C,2BAA4BA,EAAW,cACvC,iBAAkBA,EAAW,IAG7B,wCAAyCC,GAAsB,cAC/D,oCAAqCA,GAAsB,UAC3D,gCAAiCA,GAAsB,MACvD,kCAAmCA,GAAsB,QAGzD,wBAAyBC,GAAiB,KAC1C,6BAA8BA,GAAiB,UAC/C,6BAA8BA,GAAiB,UAC/C,6BAA8BA,GAAiB,UAC/C,8BAA+BA,GAAiB,WAChD,6BAA8BA,GAAiB,SACnD,ECv8BA,IAAIE,GAA4C,KAMzC,SAASC,GAAyBC,EAAiC,CACtEF,GAAmBE,CACvB,CA2CO,MAAMC,EAAe,CAArB,aAAA,CACH,KAAA,KAAe,EACf,KAAA,GAAa,CAAA,CAEb,aAAaC,EAAcC,EAAYC,EAA0B,CAC7D,YAAK,KAAOF,EAAG,SAASC,CAAE,EAAGA,IAC7B,KAAK,GAAKD,EAAG,SAASC,CAAE,EAAGA,IACpBA,CACX,CACJ,CAMO,MAAME,EAAU,CAAhB,aAAA,CACH,KAAA,IAAc,EACd,KAAA,KAAe,EACf,KAAA,OAAiB,EACjB,KAAA,MAAgB,CAAA,CAEhB,aAAaH,EAAcC,EAAYC,EAA0B,CAC7D,YAAK,IAAMF,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACzC,KAAK,KAAOD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC1C,KAAK,OAASD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC5C,KAAK,MAAQD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACpCA,CACX,CAEA,WAAWG,EAAuB,CAC9B,OAAQ,KAAK,OAAS,KAAK,MAAUA,EAAE,OAASA,EAAE,KAC1C,KAAK,MAAQ,KAAK,OAAWA,EAAE,MAAQA,EAAE,IACrD,CACJ,CAMO,MAAMC,EAAe,CAArB,aAAA,CACH,KAAA,SAAmB,EACnB,KAAA,MAAqB,CAAA,CAAC,CAEtB,aAAaL,EAAcC,EAAYK,EAAyB,CAC5D,KAAK,SAAWN,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC9C,KAAK,MAAQ,CAAA,EACb,QAAS,EAAI,EAAG,EAAI,KAAK,SAAU,IAAK,CACpC,MAAMM,EAAO,IAAIJ,GACjBF,EAAKM,EAAK,aAAaP,EAAIC,EAAIK,CAAE,EACjC,KAAK,MAAM,KAAKC,CAAI,CACxB,CACA,OAAON,CACX,CACJ,CAMO,MAAMO,EAAU,CAAhB,aAAA,CACH,KAAA,KAAe,EACf,KAAA,MAA+B,IAAA,CAE/B,aAAaR,EAAcC,EAAYK,EAAyB,CAC5D,YAAK,KAAON,EAAG,SAASC,CAAE,EAAGA,IACzB,KAAK,OAAS3B,GAAc,QAC5B,KAAK,MAAQ,IAAI+B,GACjBJ,EAAK,KAAK,MAAM,aAAaD,EAAIC,EAAIK,CAAE,GAEpCL,CACX,CACJ,CAMO,MAAMQ,EAAqB,CAA3B,aAAA,CACH,KAAA,GAAa,GACb,KAAA,KAAe,EACf,KAAA,MAAgB,EAChB,KAAA,MAAgB,EAChB,KAAA,OAAiB,CAAA,CAEjB,aAAaT,EAAcC,EAAYC,EAA0B,CAC7D,YAAK,GAAKF,EAAG,aAAaC,EAAI,EAAI,EAAGA,GAAM,EAC3C,KAAK,KAAOD,EAAG,SAASC,CAAE,EAAGA,IAC7B,KAAK,MAAQD,EAAG,SAASC,CAAE,EAAGA,IAC9B,KAAK,MAAQD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC3C,KAAK,OAASD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACrCA,CACX,CACJ,CAMO,MAAMS,EAAa,CAAnB,aAAA,CACH,KAAA,OAAiB,GACjB,KAAA,QAAkB,EAClB,KAAA,KAAiB,CAAA,CAAC,CAElB,aAAaV,EAAcC,EAAYC,EAA0B,CAC7D,KAAK,OAASF,EAAG,aAAaC,EAAI,EAAI,EAAGA,GAAM,EAC/C,KAAK,QAAUD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC7C,KAAK,KAAO,CAAA,EACZ,QAAS,EAAI,EAAG,EAAI,KAAK,QAAS,IAC9B,KAAK,KAAK,CAAC,EAAID,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAEjD,OAAOA,CACX,CACJ,CAMO,MAAMU,EAAY,CAAlB,aAAA,CACH,KAAA,OAAiB,EACjB,KAAA,MAAgB,EAChB,KAAA,EAAY,EACZ,KAAA,EAAY,EACZ,KAAA,OAAiB,EACjB,KAAA,UAAoB,GACpB,KAAA,QAA+B,KAC/B,KAAA,KAAoB,IAAI,YAAY,CAAC,CAAA,CAErC,aAAaX,EAAcC,EAAYK,EAAyB,CAM5D,GALA,KAAK,OAASN,EAAG,SAASC,CAAE,EAAGA,IAC/B,KAAK,MAAQD,EAAG,SAASC,CAAE,EAAGA,IAC9B,KAAK,EAAID,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACvC,KAAK,EAAID,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACvC,KAAK,OAASD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACxC,KAAK,MAAQxB,GAAiB,eAC9B,KAAK,UAAYuB,EAAG,aAAaC,EAAI,EAAI,EAAGA,GAAM,MAC/C,CACH,MAAMW,EAASZ,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACzCW,IAAW,EACX,KAAK,QAAU,MAEf,KAAK,QAAU,IAAIF,GACnB,KAAK,QAAQ,aAAaV,EAAIY,EAAQN,CAAE,EAEhD,CAGA,YAAK,KAAOA,EAAG,MAAML,CAAE,EACvBA,GAAM,KAAK,KAAK,WACTA,CACX,CACJ,CAMO,MAAMY,EAAW,CAAjB,aAAA,CACH,KAAA,EAAY,EACZ,KAAA,EAAY,CAAA,CAEZ,aAAab,EAAcC,EAAYC,EAA0B,CAC7D,YAAK,EAAIF,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACvC,KAAK,EAAID,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAChCA,CACX,CACJ,CAMO,MAAMa,EAAa,CAAnB,aAAA,CACH,KAAA,EAAY,EACZ,KAAA,EAAY,CAAA,CAEZ,aAAad,EAAcC,EAAYC,EAA0B,CAC7D,YAAK,EAAIF,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACvC,KAAK,EAAID,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAChCA,CACX,CACJ,CAMO,MAAMc,EAAW,CAAjB,aAAA,CACH,KAAA,WAAmC,IAAIN,GACvC,KAAA,MAA4B,KAC5B,KAAA,OAA6B,KAC7B,KAAA,UAA2B,KAC3B,KAAA,KAAwB,KACxB,KAAA,UAAkC,KAClC,KAAA,KAA6B,IAAA,CAE7B,aAAaT,EAAcC,EAAYK,EAAyB,CAiB5D,GAhBA,KAAK,WAAa,IAAIG,GACtBR,EAAK,KAAK,WAAW,aAAaD,EAAIC,EAAIK,CAAE,EAExC,KAAK,WAAW,OAAS/B,EAAe,SACxC0B,EAAK,KAAK,WAAWD,EAAIC,EAAIK,CAAE,GAG/B,KAAK,WAAW,OAAS/B,EAAe,SACxC,KAAK,OAAS,IAAIoC,GAClBV,EAAK,KAAK,OAAO,aAAaD,EAAIC,EAAIK,CAAE,GAGxC,KAAK,WAAW,OAAS/B,EAAe,UACxC,KAAK,UAAYyB,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,GAG/C,KAAK,WAAW,OAAS1B,EAAe,KAAM,CAC9C,MAAMyC,EAAehB,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACnD,MAAMgB,EAAcX,EAAG,MAAML,CAAE,EAC/B,KAAK,KAAO,CACR,UAAWe,EACX,KAAMC,CAAA,EAEVhB,GAAMgB,EAAY,UACtB,CAMA,GAJI,KAAK,WAAW,OAAS1C,EAAe,aACxC0B,EAAK,KAAK,eAAeD,EAAIC,EAAIK,CAAE,GAGnC,KAAK,WAAW,OAAS/B,EAAe,KAAM,CAC9C,GAAI,CAACqB,GACD,MAAM,IAAI,MAAM,gGAAgG,EAEpH,KAAK,KAAOA,GAAA,EACZK,EAAK,KAAK,KAAK,aAAaD,EAAIC,EAAIK,CAAE,CAC1C,CAEA,OAAOL,CACX,CAEQ,WAAWD,EAAcC,EAAYK,EAAyB,CAClE,MAAMY,EAASlB,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC7C,MAAMkB,EAAYlB,EAElB,IAAImB,EAAQ,GACZ,QAASC,EAAI,EAAGA,GAAK,EAAGA,IACpBD,GAAS,OAAO,aAAapB,EAAG,SAASC,EAAKoB,CAAC,CAAC,EAEpDpB,GAAM,EAGN,MAAMqB,EAAUtB,EAAG,UAAUC,CAAE,EAAGA,GAAM,EACxC,MAAMsB,EAAOvB,EAAG,UAAUC,CAAE,EAAGA,GAAM,EACrC,MAAMuB,EAAQxB,EAAG,UAAUC,CAAE,EAAGA,GAAM,EACtC,MAAMwB,EAASzB,EAAG,UAAUC,CAAE,EAAGA,GAAM,EACvC,MAAMyB,EAAS1B,EAAG,UAAUC,CAAE,EAAGA,GAAM,EACvC,MAAM0B,EAAU3B,EAAG,UAAUC,CAAE,EAAGA,GAAM,EAExC,MAAM2B,EAAa3B,EAAKkB,EAClBU,EAAOvB,EAAG,MAAML,EAAIiB,EAASjB,EAAK2B,CAAU,EAClD,OAAA3B,GAAM4B,EAAK,WAEX,KAAK,MAAQ,CACT,OAAAX,EACA,MAAAE,EACA,QAAAE,EACA,KAAAC,EACA,MAAAC,EACA,OAAAC,EACA,OAAAC,EACA,SAAUC,EACV,KAAAE,CAAA,EAGG5B,CACX,CAEQ,eAAeD,EAAcC,EAAYK,EAAyB,CACtE,MAAMwB,EAAQ9B,EAAG,SAASC,CAAE,EAAGA,GAAM,EACrC,MAAM8B,EAAW/B,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC/C,MAAM+B,EAAWhC,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC/C,MAAMgC,EAAW3B,EAAG,MAAML,EAAI8B,EAAW9B,CAAE,EAC3CA,GAAMgC,EAAS,WAGf,MAAMC,EAAcF,EAAWD,EACzBI,EAAiBlC,EAEvB,IAAImC,EAAa,GACjB,QAASf,EAAI,EAAGA,GAAK,EAAGA,IACpBe,GAAc,OAAO,aAAapC,EAAG,SAASC,EAAKoB,CAAC,CAAC,EAEzDpB,GAAM,EAGN,MAAMoC,EAAerC,EAAG,UAAUC,CAAE,EAAGA,GAAM,EAC7C,MAAMqC,EAAYtC,EAAG,UAAUC,CAAE,EAAGA,GAAM,EAC1C,MAAMsC,EAAavC,EAAG,UAAUC,CAAE,EAAGA,GAAM,EAC3C,MAAMuC,EAAcxC,EAAG,UAAUC,CAAE,EAAGA,GAAM,EAC5C,MAAMwC,EAAczC,EAAG,UAAUC,CAAE,EAAGA,GAAM,EAC5C,MAAMyC,EAAe1C,EAAG,UAAUC,CAAE,EAAGA,GAAM,EAE7C,MAAM0C,EAAkB1C,EAAKkC,EACvBS,EAAYtC,EAAG,MAAML,EAAIiC,EAAcjC,EAAK0C,CAAe,EACjE,OAAA1C,GAAM2C,EAAU,WAEhB,KAAK,UAAY,CACb,MAAAd,EACA,UAAWC,EACX,UAAWC,EACX,KAAMC,EACN,MAAO,CACH,OAAQC,EACR,MAAOE,EACP,QAASC,EACT,KAAMC,EACN,MAAOC,EACP,OAAQC,EACR,OAAQC,EACR,SAAUC,EACV,KAAME,CAAA,CACV,EAGG3C,CACX,CACJ,CAMO,MAAM4C,EAAW,CAAjB,aAAA,CACH,KAAA,MAAgB,EAChB,KAAA,IAAkB,IAAIhC,GACtB,KAAA,OAA4B,IAAA,CAE5B,aAAab,EAAcC,EAAYK,EAAyB,CAC5D,KAAK,MAAQN,EAAG,SAASC,CAAE,EAAGA,IAC9B,KAAK,IAAM,IAAIY,GACfZ,EAAK,KAAK,IAAI,aAAaD,EAAIC,EAAIK,CAAE,EACrC,MAAMM,EAASZ,EAAG,UAAUC,EAAI,EAAI,EACpC,OADuCA,GAAM,EACzCW,IAAW,GACX,KAAK,OAAS,KACPX,IAGX,KAAK,OAAS,IAAIc,GACX,KAAK,OAAO,aAAaf,EAAIY,EAAQN,CAAE,EAClD,CACJ,CAMO,MAAMwC,EAAa,CAAnB,aAAA,CACH,KAAA,IAAyB,KACzB,KAAA,IAAkB,IAAIjC,EAAW,CAEjC,aAAab,EAAcC,EAAYK,EAAyB,CAC5D,MAAMM,EAASZ,EAAG,UAAUC,EAAI,EAAI,EAAG,OAAAA,GAAM,EACzCW,IAAW,EACX,KAAK,IAAM,MAEX,KAAK,IAAM,IAAIG,GACf,KAAK,IAAI,aAAaf,EAAIY,EAAQN,CAAE,GAGxC,KAAK,IAAM,IAAIO,GACR,KAAK,IAAI,aAAab,EAAIC,EAAIK,CAAE,CAC3C,CACJ,CAMO,MAAMyC,EAAW,CAAjB,aAAA,CACH,KAAA,KAAe,EACf,KAAA,MAAgB,EAChB,KAAA,QAA+B,IAAA,CAE/B,aAAa/C,EAAcC,EAAYK,EAAyB,CAC5D,YAAK,KAAON,EAAG,SAASC,CAAE,EAAGA,IACzB,KAAK,OAASnB,GAAe,OAC7B,KAAK,MAAQkB,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,GACpC,KAAK,OAASnB,GAAe,UACpC,KAAK,QAAU,IAAIgE,GACnB7C,EAAK,KAAK,QAAQ,aAAaD,EAAIC,EAAIK,CAAE,GAEtCL,CACX,CACJ,CAMO,MAAM+C,EAAU,CAAhB,aAAA,CACH,KAAA,MAAoB,IAAID,GACxB,KAAA,cAAwB,EACxB,KAAA,KAAmB,IAAIF,EAAW,CAElC,aAAa7C,EAAcC,EAAYK,EAAyB,CAC5D,YAAK,MAAQ,IAAIyC,GACjB9C,EAAK,KAAK,MAAM,aAAaD,EAAIC,EAAIK,CAAE,EACvC,KAAK,cAAgBN,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACnD,KAAK,KAAO,IAAI4C,GACT,KAAK,KAAK,aAAa7C,EAAIC,EAAIK,CAAE,CAC5C,CACJ,CAMO,MAAM2C,EAAU,CAAhB,aAAA,CACH,KAAA,UAA+B,KAC/B,KAAA,QAAqB,IAAI9C,GACzB,KAAA,cAAwB,EACxB,KAAA,UAAoB,EACpB,KAAA,KAAmB,IAAI0C,EAAW,CAElC,aAAa7C,EAAcC,EAAYK,EAAyB,CAC5D,MAAMM,EAASZ,EAAG,UAAUC,EAAI,EAAI,EAAG,OAAAA,GAAM,EACzCW,IAAW,EACX,KAAK,UAAY,MAEjB,KAAK,UAAY,IAAIG,GACrB,KAAK,UAAU,aAAaf,EAAIY,EAAQN,CAAE,GAE9C,KAAK,QAAU,IAAIH,GACnBF,EAAK,KAAK,QAAQ,aAAaD,EAAIC,EAAIK,CAAE,EACzC,KAAK,cAAgBN,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACnD,KAAK,UAAYD,EAAG,SAASC,CAAE,EAAGA,IAClC,KAAK,KAAO,IAAI4C,GACT,KAAK,KAAK,aAAa7C,EAAIC,EAAIK,CAAE,CAC5C,CACJ,CAMO,MAAM4C,EAAkB,CAAxB,aAAA,CACH,KAAA,OAAiB,GACjB,KAAA,KAAe,EACf,KAAA,MAAgB,EAChB,KAAA,OAAiB,EACjB,KAAA,SAAmB,EACnB,KAAA,SAAmB,CAAA,CAEnB,aAAalD,EAAcC,EAAYC,EAA0B,CAC7D,YAAK,OAASF,EAAG,aAAaC,EAAI,EAAI,EAAGA,GAAM,EAC/C,KAAK,KAAOD,EAAG,SAASC,CAAE,EAAGA,IAC7B,KAAK,MAAQD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC3C,KAAK,OAASD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC5C,KAAK,SAAWD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC9C,KAAK,SAAWD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACvCA,CACX,CACJ,CAMO,MAAMkD,EAAY,CAAlB,aAAA,CACH,KAAA,MAAgB,EAChB,KAAA,OAAmC,KACnC,KAAA,KAAoB,IAAI,YAAY,CAAC,CAAA,CAErC,aAAanD,EAAcC,EAAYK,EAAyB,CAC5D,YAAK,MAAQN,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACvC,KAAK,MAAQtB,GAAiB,KAC9B,KAAK,OAAS,MAEd,KAAK,OAAS,IAAIuE,GAClBjD,EAAK,KAAK,OAAO,aAAaD,EAAIC,EAAIK,CAAE,EACxC,KAAK,KAAOA,EAAG,MAAML,CAAE,EACvBA,GAAM,KAAK,KAAK,YAEbA,CACX,CACJ,CAMO,MAAMmD,EAAa,CAAnB,aAAA,CACH,KAAA,UAAoB,EACpB,KAAA,MAAgB,EAChB,KAAA,OAAiB,EACjB,KAAA,OAAiB,EACjB,KAAA,MAAgB,CAAA,CAEhB,aAAapD,EAAcC,EAAYC,EAA0B,CAC7D,YAAK,UAAYF,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC/C,KAAK,MAAQD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC3C,KAAK,OAASD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC5C,KAAK,OAASD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC5C,KAAK,MAAQD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACpCA,CACX,CACJ,CC3hBO,MAAMoD,EAAwC,CAMjD,YAAYC,EAAiBrD,EAAa,CAL1C,KAAA,MAAgBxD,GAChB,KAAA,aAAuBC,GACvB,KAAA,aAAuBC,GACvB,KAAA,KAAe,EAGP2G,IAAM,QACN,KAAK,WAAWA,EAAGrD,CAAE,CAE7B,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,MAAQ,GACb,QAAS,EAAI,EAAG,EAAI,EAAG,IACnB,KAAK,OAAS,OAAO,aAAatD,EAAG,SAASC,EAAK,CAAC,CAAC,EAEzDA,GAAM,EAEN,KAAK,aAAeD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAClD,KAAK,aAAeD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAClD,KAAK,KAAOD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,CAC9C,CAEA,SAASqD,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,QAAS,EAAI,EAAG,EAAI,EAAG,IACnBtD,EAAG,SAASC,EAAK,EAAG,KAAK,MAAM,WAAW,CAAC,CAAC,EAEhDA,GAAM,EAEND,EAAG,UAAUC,EAAI,KAAK,aAAc,EAAI,EAAGA,GAAM,EACjDD,EAAG,UAAUC,EAAI,KAAK,aAAc,EAAI,EAAGA,GAAM,EACjDD,EAAG,UAAUC,EAAI,KAAK,KAAM,EAAI,EAAGA,GAAM,CAC7C,CAEA,YAAqB,CACjB,MAAO,GACX,CACJ,CAMO,MAAMsD,EAAsC,CAO/C,YAAYD,EAAiBrD,EAAa,CAN1C,KAAA,aAAuB,EACvB,KAAA,YAAsB,EACtB,KAAA,UAAoB,EACpB,KAAA,WAAuB,CAAA,EACvB,KAAA,YAAwB,CAAA,EAGhBqD,IAAM,QACN,KAAK,WAAWA,EAAGrD,CAAE,CAE7B,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMuD,EAASvD,EACTD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,aAAetD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAClD,KAAK,YAAcD,EAAG,SAASC,CAAE,EAAGA,IACpC,KAAK,UAAYD,EAAG,SAASC,CAAE,EAAGA,IAClC,MAAMwD,EAAgBzD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACpD,MAAMyD,EAAiB1D,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACrD,MAAM0D,EAAa3D,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAEjDA,EAAKuD,EAASG,EACd,KAAK,WAAa,CAAA,EAClB,QAAStC,EAAI,EAAGA,EAAIoC,EAAepC,IAC/B,KAAK,WAAW,QAAQrB,EAAG,UAAUC,EAAI,EAAI,CAAC,EAAGA,GAAM,EAG3D,KAAK,YAAc,CAAA,EACnB,QAASoB,EAAI,EAAGA,EAAIqC,EAAgBrC,IAChC,KAAK,YAAY,QAAQrB,EAAG,UAAUC,EAAI,EAAI,CAAC,EAAGA,GAAM,CAEhE,CAEA,SAASqD,EAAgBrD,EAAa,EAAS,CAC3C,MAAMuD,EAASvD,EACTD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,UAAUC,EAAI,KAAK,aAAc,EAAI,EAAGA,GAAM,EACjDD,EAAG,SAASC,EAAI,KAAK,WAAW,EAAGA,IACnCD,EAAG,SAASC,EAAI,KAAK,SAAS,EAAGA,IACjCD,EAAG,UAAUC,EAAI,KAAK,WAAW,OAAQ,EAAI,EAAGA,GAAM,EACtDD,EAAG,UAAUC,EAAI,KAAK,YAAY,OAAQ,EAAI,EAAGA,GAAM,EACvDD,EAAG,UAAUC,EAAKA,EAAKuD,EAAU,EAAG,EAAI,EAAGvD,GAAM,EAEjD,QAASoB,EAAI,EAAGA,EAAI,KAAK,WAAW,OAAQA,IACxCrB,EAAG,UAAUC,EAAI,KAAK,WAAWoB,CAAC,GAAK,EAAG,EAAI,EAAGpB,GAAM,EAG3D,QAASoB,EAAI,EAAGA,EAAI,KAAK,YAAY,OAAQA,IACzCrB,EAAG,UAAUC,EAAI,KAAK,YAAYoB,CAAC,GAAK,EAAG,EAAI,EAAGpB,GAAM,CAEhE,CAEA,YAAqB,CACjB,MAAO,IAAM,EAAI,KAAK,WAAW,OAAW,EAAI,KAAK,YAAY,MACrE,CACJ,CAMO,MAAM2D,EAAe,CAOxB,YAAYN,EAAiBrD,EAAa,CAN1C,KAAA,MAAgB,EAEhB,KAAA,UAAgC,KAChC,KAAA,WAAuB,CAAA,EACvB,KAAA,YAAwB,CAAA,EAGhBqD,IAAM,QACN,KAAK,WAAWA,EAAGrD,CAAE,CAE7B,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMuD,EAASvD,EACTD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,MAAQtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAI3C,KAAK,UAAYqD,EAAE,MAAMrD,EAAIA,EAAKlD,EAAyB,EAC3DkD,GAAMlD,GAEN,MAAM0G,EAAgBzD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACpD,MAAMyD,EAAiB1D,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACrD,MAAM0D,EAAa3D,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAEjDA,EAAKuD,EAASG,EACd,KAAK,WAAa,CAAA,EAClB,QAAStC,EAAI,EAAGA,EAAIoC,EAAepC,IAC/B,KAAK,WAAW,QAAQrB,EAAG,UAAUC,EAAI,EAAI,CAAC,EAAGA,GAAM,EAG3D,KAAK,YAAc,CAAA,EACnB,QAASoB,EAAI,EAAGA,EAAIqC,EAAgBrC,IAChC,KAAK,YAAY,QAAQrB,EAAG,UAAUC,EAAI,EAAI,CAAC,EAAGA,GAAM,CAEhE,CACJ,CAMO,MAAM4D,EAA4C,CAAlD,aAAA,CACH,KAAA,cAAwB,EACxB,KAAA,cAAiC,IAAA,CAEjC,SAASP,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,UAAUC,EAAI,KAAK,cAAe,EAAI,EAAGA,GAAM,EAClD,MAAM6D,EAAWhH,GAA+B,EAChD,QAASuE,EAAI,EAAGA,EAAIyC,EAAUzC,IACtB,KAAK,eAAiBA,EAAI,KAAK,cAAc,OAC7CrB,EAAG,SAASC,EAAI,KAAK,cAAcoB,CAAC,GAAK,CAAC,EAE1CrB,EAAG,SAASC,EAAI,CAAC,EAErBA,GAER,CAEA,YAAqB,CACjB,MAAO,GAAKnD,GAA+B,CAC/C,CACJ,CAMO,MAAMiH,EAAmB,CAG5B,YAAYT,EAAiBrD,EAAa,CAF1C,KAAA,SAAmB,EAGXqD,IAAM,QACN,KAAK,WAAWA,EAAGrD,CAAE,CAE7B,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,SAAWtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,CAClD,CAEA,YAAqB,CACjB,MAAO,EACX,CACJ,CAMO,MAAM+D,CAAsC,CAK/C,YAAYV,EAAiBrD,EAAa,CAJ1C,KAAA,KAAe,EACf,KAAA,KAAe,EACf,KAAA,KAAgC,OAGxBqD,IAAM,QACN,KAAK,WAAWA,EAAGrD,CAAE,CAE7B,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,KAAOtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC1C,KAAK,KAAOD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACtCqD,EAAE,WAAarD,IACf,KAAK,KAAOqD,EAAE,MAAMrD,CAAE,EAE9B,CAEA,SAASqD,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EAGzB,GAFAtD,EAAG,UAAUC,EAAI,KAAK,KAAM,EAAI,EAAGA,GAAM,EACzCD,EAAG,UAAUC,EAAI,KAAK,KAAO,KAAK,KAAK,WAAa,EAAG,EAAI,EAAGA,GAAM,EAChE,KAAK,MAAQ,KAAK,KAAK,WAAa,EAAG,CACvC,MAAMgE,EAAQ,IAAI,WAAW,KAAK,IAAI,EAChCC,EAAS,IAAI,WAAWZ,CAAC,EAC/B,QAASjC,EAAI,EAAGA,EAAI4C,EAAM,OAAQ5C,IAAKpB,IACnCiE,EAAOjE,CAAE,EAAIgE,EAAM5C,CAAC,GAAK,CAEjC,CACJ,CAEA,SAAS8C,EAAgBC,EAA2B,CAChD,KAAK,KAAOD,EACZ,KAAK,KAAOC,EAAM,WAAA,EAClB,KAAK,KAAO,IAAI,YAAY,KAAK,IAAI,EACrCA,EAAM,SAAS,KAAK,IAAI,CAC5B,CAEA,YAAqB,CACjB,OAAI,KAAK,KACE,EAAI,KAAK,KAAK,WAElB,CACX,CACJ,CAMO,MAAMC,EAAiB,CAI1B,YAAYf,EAAiBrD,EAAa,CAH1C,KAAA,cAAwB,EACxB,KAAA,SAA6B,CAAA,EAGrBqD,IAAM,QACN,KAAK,WAAWA,EAAGrD,CAAE,CAE7B,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,cAAgBtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACnD,KAAK,SAAW,CAAA,EAChB,QAAS,EAAI,EAAG,EAAI,KAAK,cAAe,IAAK,CACzC,MAAMqE,EAAO,IAAIvE,GACjBE,EAAKqE,EAAK,aAAatE,EAAIC,EAAIqD,CAAC,EAChC,KAAK,SAAS,KAAKgB,CAAI,CAC3B,CACJ,CACJ,CAMA,SAASC,GAAsBC,EAAyB,CACpD,MAAMC,EAAOD,EAAK,CAAC,EACnB,OAAIC,IAAS,OAAkB,IACtBA,GAAQjF,EAAW,oBAAuB,KAAO,CAC9D,CAMO,MAAMkF,EAA8C,CAIvD,YAAYnD,EAAciD,EAAgB,CACtC,KAAK,sBAAwBD,GAAsBC,CAAI,EACvD,KAAK,KAAOjD,CAChB,CAEA,SAAS+B,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACrB,KAAK,wBACLtD,EAAG,UAAUC,EAAI,EAAG,EAAI,EAAGA,GAAM,GAErCD,EAAG,UAAUC,EAAI,KAAK,KAAM,EAAI,EAAGA,GAAM,CAC7C,CAEA,YAAqB,CACjB,OAAO,KAAK,sBAAwB,EAAI,CAC5C,CACJ,CAMO,MAAM0E,EAAyB,CAKlC,YAAYC,EAAkCJ,EAAgB,CAC1D,KAAK,sBAAwBD,GAAsBC,CAAI,EACvD,MAAMxE,EAAK,IAAI,SAAS4E,EAAU,IAAI,EACtC,IAAI3E,EAAK,KAAK,sBAAwB,EAAI,EAC1C,KAAK,KAAOD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC1C,KAAK,QAAU2E,EAAU,KAAK,MAAM3E,CAAE,CAC1C,CAEA,SAAkB,CACd,OAAO,IAAI,YAAY,OAAO,EAAE,OAAO,KAAK,OAAO,CACvD,CACJ,CAMO,MAAM4E,EAAiD,CAI1D,YAAYtD,EAAciD,EAAgB,CACtC,KAAK,sBAAwBD,GAAsBC,CAAI,EACvD,KAAK,KAAOjD,CAChB,CAEA,SAAS+B,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACrB,KAAK,wBACLtD,EAAG,UAAUC,EAAI,EAAG,EAAI,EAAGA,GAAM,GAErCD,EAAG,UAAUC,EAAI,KAAK,KAAM,EAAI,EAAGA,GAAM,CAC7C,CAEA,YAAqB,CACjB,OAAO,KAAK,sBAAwB,EAAI,CAC5C,CACJ,CAMO,MAAM6E,EAA8C,CAKvD,YAAYvD,EAAcwD,EAAcP,EAAgB,CACpD,KAAK,sBAAwBD,GAAsBC,CAAI,EACvD,KAAK,KAAOjD,EACZ,KAAK,KAAOwD,CAChB,CAEA,SAASzB,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACrB,KAAK,wBACLtD,EAAG,UAAUC,EAAI,EAAG,EAAI,EAAGA,GAAM,GAErCD,EAAG,UAAUC,EAAI,KAAK,KAAM,EAAI,EAAGA,GAAM,EACzC,MAAM+E,EAAU,IAAI,YAAA,EAAc,OAAO,KAAK,IAAI,EAClD,IAAI,WAAW1B,EAAGrD,EAAI+E,EAAQ,UAAU,EAAE,IAAIA,CAAO,EAAG/E,GAAM+E,EAAQ,UAC1E,CAEA,YAAqB,CACjB,MAAMC,EAAgB,IAAI,YAAA,EAAc,OAAO,KAAK,IAAI,EAAE,WAC1D,OAAQ,KAAK,sBAAwB,EAAI,GAAKA,CAClD,CACJ,CAMO,MAAMC,EAAiB,CAU1B,YAAY5B,EAAgBrD,EAAa,CATzC,KAAA,UAAoB,EACpB,KAAA,oBAA8B,EAC9B,KAAA,oBAA8B,EAC9B,KAAA,iBAA2B,EAC3B,KAAA,eAAyB,EACzB,KAAA,YAAsB,EACtB,KAAA,eAAyB,EACzB,KAAA,QAAkB,EAGd,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,UAAYtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC/C,KAAK,oBAAsBD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACzD,KAAK,oBAAsBD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACzD,KAAK,iBAAmBD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACtD,KAAK,eAAiBD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACpD,KAAK,YAAcD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACjD,KAAK,eAAiBD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACpD,KAAK,QAAUD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,CACjD,CACJ,CAMO,MAAMkF,EAAsB,CAI/B,YAAY7B,EAAgBrD,EAAa,CAHzC,KAAA,eAAyB,EACzB,KAAA,YAAsB,EAGlB,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,eAAiBtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACpD,KAAK,YAAcD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,CACrD,CACJ,CAMO,MAAMmF,EAAsB,CAO/B,YAAY9B,EAAgBrD,EAAa,CANzC,KAAA,SAAmB,EACnB,KAAA,KAAe,EACf,KAAA,OAAiB,GACjB,KAAA,KAAe,EACf,KAAA,KAAgC,OAG5B,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,SAAWtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC9C,KAAK,KAAOD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC1C,KAAK,OAASD,EAAG,aAAaC,EAAI,EAAI,EAAGA,GAAM,EAC/C,KAAK,KAAOD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACtCqD,EAAE,WAAarD,IACf,KAAK,KAAOqD,EAAE,MAAMrD,CAAE,EAE9B,CACJ,CAMO,MAAMoF,EAAwB,CAGjC,YAAY/B,EAAgBrD,EAAa,CAFzC,KAAA,UAAoB,EAGhB,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,UAAYtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,CACnD,CACJ,CAMO,MAAMqF,EAAe,CAIxB,YAAYhC,EAAgBrD,EAAa,CAHzC,KAAA,WAAqB,EACrB,KAAA,OAAiB,EAGb,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,WAAatD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAChD,KAAK,OAASD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,CAChD,CACJ,CAMO,MAAMsF,EAAyC,CAGlD,YAAYC,EAA6B,CACrC,KAAK,WAAaA,EAAI,UAC1B,CAEA,SAASlC,EAAgBrD,EAAa,EAAS,CAChC,IAAI,SAASqD,CAAC,EACtB,UAAUrD,EAAI,KAAK,WAAY,EAAI,EAAGA,GAAM,CACnD,CAEA,YAAqB,CACjB,MAAO,EACX,CACJ,CAMO,MAAMwF,EAAsD,CAG/D,YAAYC,EAAc,CACtB,KAAK,KAAOA,CAChB,CAEA,SAASpC,EAAgBrD,EAAa,EAAS,CAChC,IAAI,SAASqD,CAAC,EACtB,UAAUrD,EAAI,KAAK,KAAM,EAAI,EAAGA,GAAM,CAC7C,CAEA,YAAqB,CACjB,MAAO,EACX,CACJ,CAMO,MAAM0F,EAAgD,CAGzD,YAAYC,EAAmB,CAC3B,KAAK,UAAYA,CACrB,CAEA,SAAStC,EAAgBrD,EAAa,EAAS,CAChC,IAAI,SAASqD,CAAC,EACtB,UAAUrD,EAAI,KAAK,UAAW,EAAI,EAAGA,GAAM,CAClD,CAEA,YAAqB,CACjB,MAAO,EACX,CACJ,CAMO,MAAM4F,EAA+C,CAOxD,YAAYtE,EAAcM,EAAoB,CAJ9C,KAAA,OAAiB,GAKb,KAAK,SAAWxC,GAChB,KAAK,KAAOkC,EACZ,KAAK,KAAOM,EAAK,WAAA,EACjB,KAAK,KAAOA,CAChB,CAEA,SAASyB,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,UAAUC,EAAI,KAAK,SAAU,EAAI,EAAGA,GAAM,EAC7CD,EAAG,UAAUC,EAAI,KAAK,KAAM,EAAI,EAAGA,GAAM,EACzCD,EAAG,aAAaC,EAAI,KAAK,OAAQ,EAAI,EAAGA,GAAM,EAC9CD,EAAG,UAAUC,EAAI,KAAK,KAAM,EAAI,EAAGA,GAAM,EACzC,KAAK,KAAK,SAASqD,EAAGrD,CAAE,CAC5B,CAEA,YAAqB,CACjB,MAAO,IAAgB,KAAK,KAAK,WAAA,CACrC,CACJ,CAMO,MAAM6F,EAAoD,CAI7D,YAAYC,EAAuCvB,EAAe,CAHlE,KAAA,QAAkB,EAClB,KAAA,KAAe,EAGP,OAAOuB,GAAoB,UAAYvB,IAAS,QAChD,KAAK,QAAUuB,EACf,KAAK,KAAOvB,GACLuB,aAA2B,aAClC,KAAK,WAAWA,CAAe,CAEvC,CAEA,SAASzC,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,UAAUC,EAAI,KAAK,QAAS,EAAI,EAAGA,GAAM,EAC5CD,EAAG,UAAUC,EAAI,KAAK,KAAM,EAAI,EAAGA,GAAM,CAC7C,CAEA,WAAWqD,EAAgBrD,EAAa,EAAW,CAC/C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,YAAK,QAAUtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC7C,KAAK,KAAOD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACnCA,CACX,CAEA,YAAqB,CACjB,MAAO,EACX,CACJ,CAMO,MAAM+F,EAA8C,CASvD,YAAYlE,EAAeN,EAAeC,EAAgBwE,EAAeC,EAAWC,EAAW,CAR/F,KAAA,OAAiB,EASb,KAAK,MAAQrE,EACb,KAAK,MAAQN,EACb,KAAK,OAASC,EACd,KAAK,MAAQwE,EACb,KAAK,EAAIC,EACT,KAAK,EAAIC,CACb,CAEA,SAAS7C,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,UAAUC,EAAI,KAAK,OAAQ,EAAI,EAAGA,GAAM,EAC3CD,EAAG,UAAUC,EAAI,KAAK,MAAO,EAAI,EAAGA,GAAM,EAC1CD,EAAG,UAAUC,EAAI,KAAK,OAAQ,EAAI,EAAGA,GAAM,EAC3CD,EAAG,UAAUC,EAAI,KAAK,MAAO,EAAI,EAAGA,GAAM,EAC1CD,EAAG,UAAUC,EAAI,KAAK,MAAO,EAAI,EAAGA,GAAM,EAC1CD,EAAG,UAAUC,EAAI,KAAK,EAAG,EAAI,EAAGA,GAAM,EACtCD,EAAG,UAAUC,EAAI,KAAK,EAAG,EAAI,EAAGA,GAAM,CAC1C,CAEA,YAAqB,CACjB,MAAO,GACX,CACJ,CAMO,MAAMmG,EAAqD,CAI9D,YAAYC,EAAkCC,EAAiB,CAH/D,KAAA,GAAa,EACb,KAAA,OAAiB,EAGT,OAAOD,GAAe,UAAYC,IAAW,QAC7C,KAAK,GAAKD,EACV,KAAK,OAASC,GACPD,aAAsB,aAC7B,KAAK,WAAWA,CAAU,CAElC,CAEA,SAAS/C,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,UAAUC,EAAI,KAAK,GAAI,EAAI,EAAGA,GAAM,EACvCD,EAAG,UAAUC,EAAI,KAAK,OAAQ,EAAI,EAAGA,GAAM,CAC/C,CAEA,WAAWqD,EAAgBrD,EAAa,EAAW,CAC/C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,YAAK,GAAKtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACxC,KAAK,OAASD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACrCA,CACX,CAEA,YAAqB,CACjB,MAAO,EACX,CACJ,CAMO,MAAMsG,EAAoD,CAI7D,YAAYC,EAAYC,EAAcC,EAAc,CAChD,KAAK,GAAKF,EACV,KAAK,OAAS;AAAA,OAA+BC,EAAO;AAAA,OAAYC,EAAO;AAAA,CAC3E,CAEA,SAASpD,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,UAAUC,EAAI,KAAK,GAAI,EAAI,EAAGA,GAAM,EACvC,QAAS,EAAI,EAAG,EAAI,KAAK,OAAO,OAAQ,IAAKA,IACzCD,EAAG,SAASC,EAAI,KAAK,OAAO,WAAW,CAAC,CAAC,CAEjD,CAEA,YAAqB,CACjB,MAAO,GAAI,KAAK,OAAO,OAAS,CACpC,CACJ,CAMO,MAAM0G,EAAmD,CAK5D,YAAYH,EAAYE,EAAc7E,EAAmB,CACrD,KAAK,GAAK2E,EACV,KAAK,KAAOE,EACZ,KAAK,KAAO7E,CAChB,CAEA,SAASyB,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EAGzB,GAFAtD,EAAG,UAAUC,EAAI,KAAK,GAAI,EAAI,EAAGA,GAAM,EACvCD,EAAG,aAAaC,EAAI,OAAO,KAAK,IAAI,EAAG,EAAI,EAAGA,GAAM,EAChD,KAAK,MAAQ,KAAK,KAAK,WAAa,EAAG,CACvC,MAAMgE,EAAQ,IAAI,WAAW,KAAK,IAAI,EAChCC,EAAS,IAAI,WAAWZ,CAAC,EAC/B,QAASjC,EAAI,EAAGA,EAAI4C,EAAM,OAAQ5C,IAAKpB,IACnCiE,EAAOjE,CAAE,EAAIgE,EAAM5C,CAAC,GAAK,CAEjC,CACJ,CAEA,YAAqB,CACjB,MAAO,IAAK,KAAK,IACrB,CACJ,CAMO,MAAMuF,EAAe,CAQxB,YAAYtD,EAAgBrD,EAAa,CAPzC,KAAA,UAAoB,GACpB,KAAA,SAAmB,EACnB,KAAA,WAAqB,EACrB,KAAA,KAAe,EACf,KAAA,WAAqB,EACrB,KAAA,QAAkB,GAGd,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,UAAYtD,EAAG,aAAaC,EAAI,EAAI,EAAGA,GAAM,EAClD,KAAK,SAAWD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC9C,KAAK,WAAaD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAChD,KAAK,KAAOD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC1C,KAAK,WAAaD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAChD,KAAK,QAAU,GACf,QAAS,EAAI,EAAG,EAAI,KAAK,WAAY,IAAK,CACtC,MAAM4G,EAAI7G,EAAG,SAASC,CAAE,EAAGA,IAC3B,KAAK,SAAW,OAAO,aAAa4G,CAAC,CACzC,CACJ,CACJ,CAMO,MAAMC,EAA6C,CAAnD,aAAA,CACH,KAAA,cAAwB,EACxB,KAAA,gBAA0B,EAC1B,KAAA,gBAA0B,GAAK,KAAO,KACtC,KAAA,wBAAkC,CAAA,CAElC,SAASxD,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,SAASC,EAAI,KAAK,aAAa,EAAGA,IACrCD,EAAG,aAAaC,EAAI,OAAO,KAAK,eAAe,EAAG,EAAI,EAAGA,GAAM,EAC/DD,EAAG,SAASC,EAAI,KAAK,eAAe,EAAGA,IACvCD,EAAG,UAAUC,EAAI,KAAK,wBAAyB,EAAI,EAAGA,GAAM,CAChE,CAEA,YAAqB,CACjB,MAAO,GACX,CACJ,CAMO,MAAM8G,EAAoB,CAA1B,aAAA,CACH,KAAA,UAAoB,EACpB,KAAA,IAAiB,IAAI5G,GACrB,KAAA,KAAkB,IAAIK,EAAU,CAEhC,aAAaR,EAAcC,EAAYK,EAAyB,CAC5D,YAAK,UAAYN,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC/C,KAAK,IAAM,IAAIE,GACfF,EAAK,KAAK,IAAI,aAAaD,EAAIC,EAAIK,CAAE,EACrC,KAAK,KAAO,IAAIE,GACT,KAAK,KAAK,aAAaR,EAAIC,EAAIK,CAAE,CAC5C,CACJ,CAMO,MAAM0G,EAAwB,CAIjC,YAAY1D,EAAgBrD,EAAa,CAHzC,KAAA,KAA4B,IAAI8G,GAChC,KAAA,KAAkB,IAAI9D,GAGlB,KAAK,WAAWK,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,KAAO,IAAIyD,GAChB9G,EAAK,KAAK,KAAK,aAAaD,EAAIC,EAAIqD,CAAC,EACrC,KAAK,KAAO,IAAIL,GAChB,KAAK,KAAK,aAAajD,EAAIC,EAAIqD,CAAC,CACpC,CACJ,CAMO,MAAM2D,EAAwB,CAIjC,YAAY3D,EAAgBrD,EAAa,CAHzC,KAAA,KAA4B,IAAI8G,GAChC,KAAA,KAAkB,IAAI/D,GAGlB,KAAK,WAAWM,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,KAAO,IAAIyD,GAChB9G,EAAK,KAAK,KAAK,aAAaD,EAAIC,EAAIqD,CAAC,EACrC,KAAK,KAAO,IAAIN,GAChB,KAAK,KAAK,aAAahD,EAAIC,EAAIqD,CAAC,CACpC,CACJ,CAMO,MAAM4D,EAAwB,CAIjC,YAAY5D,EAAgBrD,EAAa,CAHzC,KAAA,KAA4B,IAAI8G,GAChC,KAAA,OAAqB,IAAIlG,GAGrB,KAAK,WAAWyC,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,KAAO,IAAIyD,GAChB9G,EAAK,KAAK,KAAK,aAAaD,EAAIC,EAAIqD,CAAC,EACrC,KAAK,OAAS,IAAIzC,GAClB,KAAK,OAAO,aAAab,EAAIC,EAAIqD,CAAC,CACtC,CACJ,CAMO,MAAM6D,EAAsB,CAG/B,YAAY7D,EAAgBrD,EAAa,CAFzC,KAAA,QAAwB,IAAImD,GAGxB,KAAK,WAAWE,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,QAAU,IAAIF,GACnB,KAAK,QAAQ,aAAapD,EAAIC,EAAIqD,CAAC,CACvC,CACJ,CAMO,MAAM8D,EAAuB,CAGhC,YAAY9D,EAAgBrD,EAAa,CAFzC,KAAA,UAAoB,EAGhB,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,UAAYtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,CACnD,CACJ,CAMO,MAAMoH,EAAmB,CAG5B,YAAY/D,EAAgBrD,EAAa,CAFzC,KAAA,kBAA4B,EAGxB,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAW,CAC/C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,YAAK,kBAAoBtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAChDA,CACX,CACJ,CAMO,MAAMqH,EAA2B,CAGpC,YAAYhE,EAAgBrD,EAAa,CAFzC,KAAA,kBAA4B,EAGxB,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAW,CAC/C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,YAAK,kBAAoBtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAChDA,CACX,CACJ,CAMO,MAAMsH,EAAmB,CAO5B,YAAYjE,EAAgBrD,EAAa,CANzC,KAAA,SAAyB,IAAIa,GAC7B,KAAA,YAAsB,EACtB,KAAA,eAAyB,EACzB,KAAA,QAAkB,EAClB,KAAA,OAAsB,IAAIqC,GAGtB,KAAK,WAAWG,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,SAAW,IAAIxC,GACpBb,EAAK,KAAK,SAAS,aAAaD,EAAIC,EAAIqD,CAAC,EACzC,KAAK,YAActD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACjD,KAAK,eAAiBD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACpD,KAAK,QAAUD,EAAG,SAASC,CAAE,EAAGA,IAChC,KAAK,OAAS,IAAIkD,GAClB,KAAK,OAAO,aAAanD,EAAIC,EAAIqD,CAAC,CACtC,CACJ,CAMO,MAAMkE,EAAqB,CAI9B,YAAYlE,EAAgBrD,EAAa,CAHzC,KAAA,KAAe,EACf,KAAA,KAAgC,OAG5B,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAW,CAC/C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,YAAK,KAAOtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACtCqD,EAAE,WAAarD,IACf,KAAK,KAAOqD,EAAE,MAAMrD,CAAE,EACtBA,GAAM,KAAK,KAAK,YAEbA,CACX,CACJ,CAMO,MAAMwH,EAAqB,CAK9B,YAAYnE,EAAgBrD,EAAa,CAJzC,KAAA,KAAe,EACf,KAAA,KAAe,EACf,KAAA,KAAgC,OAG5B,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAW,CAC/C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,YAAK,KAAOtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC1C,KAAK,KAAOD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACtCqD,EAAE,WAAarD,IACf,KAAK,KAAOqD,EAAE,MAAMrD,CAAE,EACtBA,GAAM,KAAK,KAAK,YAEbA,CACX,CACJ,CAMO,MAAMyH,EAAsB,CAM/B,YAAYpE,EAAgBrD,EAAa,CALzC,KAAA,SAAmB,EACnB,KAAA,OAAiB,EACjB,KAAA,UAAoB,EACpB,KAAA,KAAe,EAGX,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAW,CAC/C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,YAAK,SAAWtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC9C,KAAK,OAASD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC5C,KAAK,UAAYD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC/C,KAAK,KAAOD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACnCA,CACX,CACJ,CAMO,MAAM0H,EAAkB,CAK3B,YAAYrE,EAAgBrD,EAAa,CAJzC,KAAA,SAAyB,IAAIa,GAC7B,KAAA,QAAkB,EAClB,KAAA,OAAsB,IAAIqC,GAGtB,KAAK,WAAWG,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,SAAW,IAAIxC,GACpBb,EAAK,KAAK,SAAS,aAAaD,EAAIC,EAAIqD,CAAC,EACzC,KAAK,QAAUtD,EAAG,SAASC,CAAE,EAAGA,IAChC,KAAK,OAAS,IAAIkD,GAClB,KAAK,OAAO,aAAanD,EAAIC,EAAIqD,CAAC,CACtC,CACJ,CAWO,MAAMsE,EAA+C,CAMxD,YAAY1B,EAAY,EAAGC,EAAY,EAAG0B,EAAuB,EAAGC,EAAoB,EAAG,CACvF,KAAK,EAAI5B,EACT,KAAK,EAAIC,EACT,KAAK,aAAe0B,EACpB,KAAK,UAAYC,CACrB,CAEA,SAASxE,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,UAAUC,EAAI,KAAK,EAAG,EAAI,EAAGA,GAAM,EACtCD,EAAG,UAAUC,EAAI,KAAK,EAAG,EAAI,EAAGA,GAAM,EACtCD,EAAG,UAAUC,EAAI,KAAK,aAAc,EAAI,EAAGA,GAAM,EACjDD,EAAG,SAASC,EAAI,KAAK,SAAS,EAAGA,GAAM,CAC3C,CAEA,YAAqB,CACjB,MAAO,GACX,CACJ,CAMO,MAAM8H,EAA6C,CAMtD,YAAY7B,EAAY,EAAGC,EAAY,EAAG0B,EAAuB,EAAGC,EAAoB,EAAG,CACvF,KAAK,EAAI5B,EACT,KAAK,EAAIC,EACT,KAAK,aAAe0B,EACpB,KAAK,UAAYC,CACrB,CAGA,SAASxE,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,UAAUC,EAAI,KAAK,EAAG,EAAI,EAAGA,GAAM,EACtCD,EAAG,UAAUC,EAAI,KAAK,EAAG,EAAI,EAAGA,GAAM,EACtCD,EAAG,UAAUC,EAAI,KAAK,aAAc,EAAI,EAAGA,GAAM,EACjDD,EAAG,SAASC,EAAI,KAAK,SAAS,EAAGA,GAAM,CAC3C,CAEA,YAAqB,CACjB,MAAO,GACX,CACJ,CAMO,MAAM+H,EAA4C,CAIrD,YAAYC,EAAiBpJ,GAAiB,KAAMgJ,EAAuBjJ,GAAqB,KAAM,CAClG,KAAK,OAASqJ,EACd,KAAK,aAAeJ,CACxB,CAEA,SAASvE,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,SAASC,EAAI,KAAK,MAAM,EAAGA,IAC9BD,EAAG,UAAUC,EAAI,KAAK,aAAc,EAAI,EAAGA,GAAM,CACrD,CAEA,YAAqB,CACjB,MAAO,EACX,CACJ,CAMO,MAAMiI,EAA8C,CAIvD,YAAYD,EAAiBpJ,GAAiB,KAAMgJ,EAAuB,EAAG,CAC1E,KAAK,OAASI,EACd,KAAK,aAAeJ,CACxB,CAGA,SAASvE,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,SAASC,EAAI,KAAK,MAAM,EAAGA,IAC9BD,EAAG,UAAUC,EAAI,KAAK,aAAc,EAAI,EAAGA,GAAM,CACrD,CAEA,YAAqB,CACjB,MAAO,EACX,CACJ,CAUO,MAAMkI,EAAyC,CAGlD,YAAYC,EAAe,EAAG,CAC1B,KAAK,KAAOA,CAChB,CAEA,SAAS9E,EAAgBrD,EAAa,EAAS,CAChC,IAAI,SAASqD,CAAC,EACtB,UAAUrD,EAAI,KAAK,KAAM,EAAI,EAAGA,GAAM,CAC7C,CAEA,YAAqB,CACjB,MAAO,EACX,CACJ,CAMO,MAAMoI,EAAuC,CAGhD,YAAYD,EAAe,EAAG,CAC1B,KAAK,KAAOA,CAChB,CAGA,SAAS9E,EAAgBrD,EAAa,EAAS,CAChC,IAAI,SAASqD,CAAC,EACtB,UAAUrD,EAAI,KAAK,KAAM,EAAI,EAAGA,GAAM,CAC7C,CAEA,YAAqB,CACjB,MAAO,EACX,CACJ,CAMO,MAAMqI,EAA4B,CAarC,YAAYhF,EAAgBrD,EAAa,CAZzC,KAAA,UAAoB,EACpB,KAAA,GAAa,EACb,KAAA,MAAgB,EAChB,KAAA,UAAoB,EACpB,KAAA,MAAgB,GAChB,KAAA,YAAsB,EACtB,KAAA,aAAuB,EACvB,KAAA,SAAmB,EACnB,KAAA,UAAoB,EACpB,KAAA,KAAkB,IAAIE,GACtB,KAAA,KAAkB,IAAIK,GAGlB,KAAK,WAAW8C,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,UAAYtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC/C,KAAK,GAAKD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACxC,KAAK,MAAQD,EAAG,SAASC,CAAE,EAAGA,GAAM,EACpC,KAAK,UAAYD,EAAG,SAASC,CAAE,EAAGA,GAAM,EACxC,KAAK,MAAQD,EAAG,aAAaC,EAAI,EAAI,EAAGA,GAAM,EAC9C,KAAK,YAAcD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACjD,KAAK,aAAeD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAClD,KAAK,SAAWD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC9C,KAAK,UAAYD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAE/C,KAAK,KAAO,IAAIE,GAChBF,EAAK,KAAK,KAAK,aAAaD,EAAIC,EAAIqD,CAAC,EACrC,KAAK,KAAO,IAAI9C,GAChB,KAAK,KAAK,aAAaR,EAAIC,EAAIqD,CAAC,CACpC,CACJ,CAMO,MAAMiF,EAAsB,CAA5B,aAAA,CACH,KAAA,GAAa,EACb,KAAA,eAAyB,CAAA,CAEzB,aAAavI,EAAcC,EAAYC,EAA0B,CAC7D,YAAK,GAAKF,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACxC,KAAK,eAAiBD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC7CA,CACX,CACJ,CAMO,MAAMuI,EAA0B,CAKnC,YAAYlF,EAAgBrD,EAAa,CAJzC,KAAA,KAA8B,IAAIsI,GAClC,KAAA,SAAmB,EACnB,KAAA,KAAmB,IAAI,WAAW,CAAC,EAG/B,KAAK,WAAWjF,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACnBmF,EAAK,IAAI,WAAWnF,CAAC,EAC3B,KAAK,KAAO,IAAIiF,GAChBtI,EAAK,KAAK,KAAK,aAAaD,EAAIC,EAAIqD,CAAC,EACrC,KAAK,SAAWtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC9C,KAAK,KAAOwI,EAAG,SAASxI,EAAIA,EAAK,KAAK,QAAQ,CAClD,CACJ,CAMO,MAAMyI,EAA+B,CAQxC,YAAYpF,EAAgBrD,EAAa,CAPzC,KAAA,KAA8B,IAAIsI,GAClC,KAAA,MAAgB,EAChB,KAAA,OAAiB,EACjB,KAAA,KAAkB,IAAIpI,GACtB,KAAA,SAAmB,EACnB,KAAA,KAAmB,IAAI,WAAW,CAAC,EAG/B,KAAK,WAAWmD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACnBmF,EAAK,IAAI,WAAWnF,CAAC,EAC3B,KAAK,KAAO,IAAIiF,GAChBtI,EAAK,KAAK,KAAK,aAAaD,EAAIC,EAAIqD,CAAC,EACrC,KAAK,MAAQtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC3C,KAAK,OAASD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC5C,KAAK,KAAO,IAAIE,GAChBF,EAAK,KAAK,KAAK,aAAaD,EAAIC,EAAIqD,CAAC,EACrC,KAAK,SAAWtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC9C,KAAK,KAAOwI,EAAG,SAASxI,EAAIA,EAAK,KAAK,QAAQ,CAClD,CACJ,CAMO,MAAM0I,EAA0B,CAInC,YAAYrF,EAAgBrD,EAAa,CAHzC,KAAA,GAAa,EACb,KAAA,KAAkB,IAAIO,GAGlB,KAAK,WAAW8C,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,GAAKtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACxC,KAAK,KAAO,IAAIO,GAChB,KAAK,KAAK,aAAaR,EAAIC,EAAIqD,CAAC,CACpC,CACJ,CAMO,MAAMsF,EAA6B,CAGtC,YAAYtF,EAAgBrD,EAAa,CAFzC,KAAA,GAAa,EAGT,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,GAAKtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,CAC5C,CACJ,CAMO,MAAM4I,EAAoC,CAM7C,YAAYvF,EAAgBrD,EAAa,CALzC,KAAA,SAAmB,EACnB,KAAA,SAAmB,EACnB,KAAA,cAAwB,EACxB,KAAA,UAAoB,EAGhB,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,SAAWtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC9C,KAAK,SAAWD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC9C,KAAK,cAAgBD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EACnD,KAAK,UAAYD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,CACnD,CACJ,CAMO,MAAM6I,EAAqD,CAW9D,YAAYC,EAAkBC,EAAkB,CARhD,KAAA,iBAA2B,EAC3B,KAAA,eAAyB,EACzB,KAAA,UAAoB,EACpB,KAAA,SAAmB,EACnB,KAAA,eAAyB,EAEzB,KAAA,WAAqB,GAGjB,KAAK,SAAWD,EAChB,KAAK,SAAWC,CACpB,CAEA,SAAS1F,EAAgBrD,EAAa,EAAS,CAC3C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBtD,EAAG,UAAUC,EAAI,KAAK,SAAU,EAAI,EAAGA,GAAM,EAC7CD,EAAG,UAAUC,EAAI,KAAK,SAAU,EAAI,EAAGA,GAAM,EAC7CD,EAAG,UAAUC,EAAI,KAAK,iBAAkB,EAAI,EAAGA,GAAM,EACrDD,EAAG,UAAUC,EAAI,KAAK,eAAgB,EAAI,EAAGA,GAAM,EACnDD,EAAG,UAAUC,EAAI,KAAK,UAAW,EAAI,EAAGA,GAAM,EAC9CD,EAAG,UAAUC,EAAI,KAAK,SAAU,EAAI,EAAGA,GAAM,EAC7CD,EAAG,UAAUC,EAAI,KAAK,eAAgB,EAAI,EAAGA,GAAM,EACnDD,EAAG,SAASC,EAAI,KAAK,WAAY,EAAI,EAAGA,GAAM,CAClD,CAEA,YAAqB,CACjB,MAAO,GAAI,CACf,CACJ,CAWO,MAAMgJ,EAAyB,CAIlC,YAAY3F,EAAgBrD,EAAa,CAHzC,KAAA,MAAgB,EAChB,KAAA,UAA6B,CAAA,EAGzB,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,KAAK,MAAQtD,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC3C,KAAK,UAAY,CAAA,EACjB,QAAS,EAAI,EAAG,EAAI,KAAK,MAAO,IAAK,CACjC,MAAMsB,EAAOvB,EAAG,SAASC,CAAE,EAAGA,IAC9B,MAAMuG,EAAKxG,EAAG,aAAaC,EAAI,EAAI,EAAGA,GAAM,EAC5C,KAAK,UAAU,KAAK,CAAE,KAAAsB,EAAM,GAAAiF,EAAI,CACpC,CACJ,CACJ,CAMO,MAAM0C,EAAiB,CAI1B,YAAY5F,EAAgBrD,EAAa,CAHzC,KAAA,OAAiB,EACjB,KAAA,KAAoB,IAAI,YAAY,CAAC,EAGjC,KAAK,WAAWqD,EAAGrD,CAAE,CACzB,CAEA,WAAWqD,EAAgBrD,EAAa,EAAS,CAC7C,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACnB6F,EAAWnJ,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC/C,MAAMW,EAASZ,EAAG,UAAUC,EAAI,EAAI,EAAGA,GAAM,EAC7C,KAAK,OAASD,EAAG,SAASC,CAAE,EAAGA,GAAM,EACrC,KAAK,KAAOqD,EAAE,MAAM1C,EAAQA,EAASuI,EAAW,CAAC,CACrD,CACJ,CCrgDO,MAAMC,EAAW,CAQpB,WAAkB,EAClB,MAAkB,EAClB,MAAkB,EAClB,MAAkB,EAClB,MAAkB,EAClB,MAAkB,EAClB,MAAkB,EAClB,MAAkB,EAClB,MAAkB,EAClB,MAAiB,GACjB,MAAiB,GACjB,UAAiB,GACjB,UAAiB,GACjB,cAAiB,GACjB,QAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,WAAiB,GACjB,WAAiB,GACjB,UAAiB,GACjB,UAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,cAAiB,GACjB,UAAiB,GACjB,UAAiB,GACjB,WAAiB,GACjB,WAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,MAAiB,GACjB,UAAiB,GACjB,WAAiB,GACjB,UAAiB,GAEjB,gBAAiB,GACjB,QAAiB,GACjB,UAAiB,GACjB,aAAiB,GACjB,OAAiB,GACjB,OAAiB,GACjB,OAAiB,GACjB,OAAiB,GACjB,OAAiB,GACjB,OAAiB,GACjB,OAAiB,GACjB,OAAiB,GACjB,OAAiB,GACjB,QAAiB,GACjB,YAAiB,GACjB,eAAiB,GACjB,SAAiB,GACjB,SAAiB,GACjB,SAAiB,GAEjB,SAAiB,GACjB,SAAiB,GACjB,SAAiB,GACjB,YAAiB,GACjB,SAAiB,GACjB,SAAiB,GACjB,SAAiB,GACjB,SAAiB,GACjB,eAAiB,GACjB,cAAiB,GAGjB,QAAiB,GACjB,QAAiB,EAIrB,EC9GaC,GAAmD,CAE5D,OAA6B,EAG7B,OAA6B,EAC7B,OAA6B,EAC7B,OAA6B,EAC7B,OAA6B,EAC7B,OAA6B,EAC7B,OAA6B,EAC7B,OAA6B,EAC7B,OAA6B,EAC7B,OAA6B,GAC7B,OAA6B,GAC7B,MAA6B,GAC7B,MAA6B,GAC7B,UAA6B,GAG7B,IAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,YAA6B,GAC7B,aAA6B,GAC7B,MAA6B,GAG7B,YAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,UAA6B,GAC7B,MAA6B,GAC7B,UAA6B,GAG7B,UAA6B,GAC7B,UAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,KAA6B,GAC7B,MAA6B,GAC7B,OAA6B,GAC7B,MAA6B,GAC7B,WAA6B,GAG7B,eAA6B,GAC7B,QAA6B,GAC7B,MAA6B,GAC7B,SAA6B,GAG7B,GAA6B,GAC7B,GAA6B,GAC7B,GAA6B,GAC7B,GAA6B,GAC7B,GAA6B,GAC7B,GAA6B,GAC7B,GAA6B,GAC7B,GAA6B,GAC7B,GAA6B,GAC7B,IAA6B,GAG7B,MAA6B,GAC7B,WAA6B,GAC7B,QAA6B,GAC7B,QAA6B,GAC7B,QAA6B,GAC7B,eAA6B,GAC7B,QAA6B,GAC7B,QAA6B,GAC7B,QAA6B,GAC7B,UAA6B,GAC7B,QAA6B,GAC7B,QAA6B,GAC7B,QAA6B,GAC7B,QAA6B,GAC7B,cAA6B,GAG7B,YAA6B,GAC7B,cAA6B,GAC7B,IAA6B,GAC7B,IAA6B,GAC7B,YAA6B,GAG7B,IAA6B,IAC7B,IAA6B,IAC7B,IAA6B,IAC7B,IAA6B,IAC7B,IAA6B,IAC7B,IAA6B,IAC7B,IAA6B,IAC7B,IAA6B,IAC7B,IAA6B,IAC7B,IAA6B,IAC7B,IAA6B,IAG7B,SAA6B,IAC7B,OAA6B,IAC7B,IAA6B,IAC7B,QAA6B,IAC7B,WAA6B,IAC7B,QAA6B,IAC7B,YAA6B,IAG7B,mBAA6B,KAC7B,eAA6B,KAC7B,YAA6B,KAC7B,aAA6B,KAC7B,gBAA6B,KAC7B,WAA6B,KAC7B,eAA6B,KAC7B,UAA6B,KAC7B,WAA6B,KAC7B,SAA6B,MAC7B,YAA6B,MAC7B,aAA6B,MAI7B,SAA6B,MAC7B,QAA6B,MAE7B,KAA6B,MAC7B,QAA6B,MAC7B,OAA6B,MAC7B,UAA6B,MAC7B,WAA6B,MAC7B,IAA6B,MAC7B,UAA6B,MAC7B,SAA6B,MAC7B,OAA6B,MAC7B,OAA6B,MAC7B,SAA6B,MAC7B,UAA6B,MAC7B,YAA6B,MAC7B,MAA6B,MAC7B,cAA6B,MAC7B,iBAA6B,MAC7B,eAA6B,MAC7B,YAA6B,MAC7B,eAA6B,MAC7B,YAA6B,MAC7B,WAA6B,MAC7B,WAA6B,MAC7B,YAA6B,KACjC,ECtKO,IAAIC,GAAQ,EAoDZ,MAAMC,GACT,6DAyHEC,GAAwC,CAEzC,GAAqBJ,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAG/B,IAAsBA,EAAS,eAC/B,IAAsBA,EAAS,SAC/B,IAAsBA,EAAS,SAC/B,IAAsBA,EAAS,SAC/B,IAAsBA,EAAS,SAC/B,IAAsBA,EAAS,SAC/B,IAAsBA,EAAS,SAC/B,IAAsBA,EAAS,YAC/B,GAAsBA,EAAS,SAC/B,GAAsBA,EAAS,SAC/B,GAAsBA,EAAS,SAC/B,GAAsBA,EAAS,SAC/B,IAAsBA,EAAS,UAC/B,IAAsBA,EAAS,eAG/B,IAAsBA,EAAS,UAC/B,IAAsBA,EAAS,WAC/B,IAAsBA,EAAS,UAC/B,IAAsBA,EAAS,WAC/B,IAAsBA,EAAS,UAC/B,IAAsBA,EAAS,UAC/B,IAAsBA,EAAS,WAC/B,IAAsBA,EAAS,WAG9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,MAC9B,GAAqBA,EAAS,UAG/B,GAAsBA,EAAS,UAC/B,GAAsBA,EAAS,WAC/B,EAAsBA,EAAS,cAC/B,EAAsBA,EAAS,QAC/B,GAAsBA,EAAS,WAC/B,GAAsBA,EAAS,UAC/B,GAAsBA,EAAS,QAC/B,GAAsBA,EAAS,aAC/B,GAAsBA,EAAS,cAC/B,IAAsBA,EAAS,YAG/B,IAAsBA,EAAS,OAC/B,IAAsBA,EAAS,OAC/B,IAAsBA,EAAS,OAC/B,IAAsBA,EAAS,OAC/B,IAAsBA,EAAS,OAC/B,IAAsBA,EAAS,OAC/B,IAAsBA,EAAS,OAC/B,IAAsBA,EAAS,OAC/B,IAAsBA,EAAS,OAC/B,IAAsBA,EAAS,QAC/B,IAAsBA,EAAS,QAC/B,IAAsBA,EAAS,QAM/B,GAAsB,GACtB,GAAsB,IAMtB,IAAsB,IAAQA,EAAS,WAAa,EACpD,IAAsB,IAAQA,EAAS,iBAAmB,EAC1D,GAAsB,IAAQA,EAAS,UAAY,EACnD,GAAsB,IAAQA,EAAS,UAAY,EACnD,GAAsB,IAAQA,EAAS,UAAY,EACnD,GAAsB,IAAQA,EAAS,UAAY,EACnD,GAAsB,IAAQA,EAAS,UAAY,EACnD,GAAsB,IAAQA,EAAS,UAAY,EACnD,GAAsB,IAAQA,EAAS,UAAY,EACnD,GAAsB,IAAQA,EAAS,UAAY,EACnD,GAAsB,IAAQA,EAAS,UAAY,EACnD,GAAsB,IAAQA,EAAS,gBAAkB,EACzD,GAAsB,MACtB,GAAsB,MACtB,GAAsB,KAC1B,EAGMK,GAAyC,CAC3C,IAAsBL,EAAS,UAC/B,GAAsBA,EAAS,UAC/B,GAAsBA,EAAS,aACnC,EAGMM,GAAqC,CACvC,IAAsBN,EAAS,UAC/B,IAAsBA,EAAS,UAC/B,IAAsBA,EAAS,aACnC,EAWO,SAASO,GAAYC,EAAiBxB,EAC7C,CACI,MAAMyB,EAAaR,GAAejB,CAAI,EACtC,GAAIyB,IAAe,OAEf,OAAOA,EAGX,MAAMC,EAAeN,GAAcI,CAAO,EAC1C,OAAIE,IAAiB,OAEVA,EAIP,OAAO,UAAc,KAAe,UAAU,UAAU,QAAQ,SAAS,IAAM,GAExEL,GAAeG,CAAO,EAItBF,GAAWE,CAAO,CAEjC,CAUO,SAASG,GAAmBH,EAAiBxB,EACpD,CACI,MAAM4B,EAAWL,GAAYC,EAASxB,CAAI,EAC1C,OAAI4B,IAAa,QAET,OAAO,MAAU,KAEjB,MAAM,cAAgBJ,CAAO,EAE1B,GAEJI,CACX,CAUO,SAASC,GAAiBL,EAAiBxB,EAClD,CACI,MAAM4B,EAAWL,GAAYC,EAASxB,CAAI,EAC1C,OAAI4B,IAAa,OAEN,EAGPA,EAAW,IAEJA,EAAW,IAIXA,EAAW,KAE1B,CASO,SAASE,GAAiBC,EACjC,CACI,MAAO,iBAAmBA,EAAE,aACrB,eAAiBA,EAAE,WACnB,UAAYA,EAAE,MACd,YAAcA,EAAE,QAChB,aAAeA,EAAE,SACjB,WAAaA,EAAE,OACf,UAAYA,EAAE,MACd,aAAeC,GAAcD,EAAE,QAAQ,EACvC,GACX,CA2BO,SAASC,GAAcC,EAC9B,CACI,GAAIA,EACJ,CACI,MAAMC,EAAMD,EAAG,OACf,IAAIE,EAAM,QAAUD,EACpB,OAAIA,EAAM,IAENC,GAAO,WAAaF,EAAG,MAAM,CAAC,EAAI,SAAWA,EAAG,IAAIC,EAAM,CAAC,GAE/DC,GAAO,IACAA,CACX,KAGI,OAAO,KAEf,CC5ZO,MAAMC,EAAgB,CAsBzB,YAAYC,EAAkBC,EAC9B,CAfA,KAAQ,OAAiB,EAGzB,KAAQ,KAAe,EAGvB,KAAQ,QAAyB,CAAA,EAGjC,KAAQ,eAA4C,OAOhD,KAAK,MAAQD,EACb,KAAK,SAAWC,EAEhB,KAAK,eAAiB,KAAK,UAAU,KAAK,IAAI,EAC9C,KAAK,MAAM,GAAG,WAAa,cAC3B,KAAK,MAAM,GAAG,iBAAiB,UAAW,KAAK,cAAc,CACjE,CAUA,QAAQC,EACR,CACI,KAAK,OAASA,CAClB,CAKA,WAAWC,EACX,CACI,KAAK,eAAiBA,CAC1B,CAKA,aACA,CACI,KAAK,eAAiB,MAC1B,CAMA,SACA,CACI,KAAK,MAAM,GAAG,oBAAoB,UAAW,KAAK,cAAc,EAChE,KAAK,QAAU,CAAA,EACf,KAAK,KAAO,EACZ,KAAK,OAAS,EACd,KAAK,eAAiB,MAC1B,CASQ,UAAUC,EAClB,CAKI,KAAK,QAAQA,EAAE,IAAI,CACvB,CASQ,QAAQvK,EAChB,CAEI,GAAI,KAAK,SAAW,EACpB,CACI,KAAK,QAAQ,KAAKA,CAAE,EACpB,KAAK,MAAQA,EAAG,WAChB,MACJ,CAsBA,IAlBI,KAAK,QAAQ,SAAW,GAAKA,EAAG,YAAc,KAAK,QAE/CA,EAAG,WAAa,KAAK,SAErB,KAAK,KAAOA,EAAG,WAAa,KAAK,OACjC,KAAK,QAAQ,KAAKA,EAAG,MAAM,KAAK,MAAM,CAAC,EACvCA,EAAKA,EAAG,MAAM,EAAG,KAAK,MAAM,GAEhC,KAAK,SAAS,KAAK,KAAK,MAAOA,EAC3B,KAAK,gBAAkB,MAAA,IAI3B,KAAK,QAAQ,KAAKA,CAAE,EACpB,KAAK,MAAQA,EAAG,YAIb,KAAK,MAAQ,KAAK,QAAU,KAAK,OAAS,GACjD,CACI,IAAIwK,EAAQ,EACZ,MAAMC,EAAQ,IAAI,YAAY,KAAK,MAAM,EACnCC,EAAO,IAAI,WAAWD,CAAK,EAEjC,KAAOD,EAAQC,EAAM,YAAc,KAAK,QAAQ,OAAS,GACzD,CACI,MAAME,EAAM,KAAK,QAAQ,MAAA,EACzB,GAAI,CAACA,EAED,OAEJ,MAAMC,EAAQ,IAAI,WAAWD,CAAG,EAC1BE,EAAOJ,EAAM,WAAaD,EAEhC,GAAII,EAAM,QAAUC,EAEhBH,EAAK,IAAIE,EAAOJ,CAAK,EACrBA,GAASI,EAAM,OACf,KAAK,MAAQA,EAAM,WAGvB,CACI,MAAME,EAAOF,EAAM,MAAM,EAAGC,CAAI,EAChCH,EAAK,IAAII,EAAMN,CAAK,EACpBA,GAASM,EAAK,OACd,KAAK,MAAQA,EAAK,OAElB,KAAK,QAAQ,QAAQF,EAAM,MAAMC,CAAI,EAAE,MAAM,CACjD,CACJ,CAEA,KAAK,SAAS,KAAK,KAAK,MAAOJ,EAC3B,KAAK,gBAAkB,MAAA,CAC/B,CACJ,CACJ,CCvMA,MAAMM,GAAgD,CAAC,GAAM,GAAM,IAAM,GAAI,EACvEC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAM,GAAI,EAE3DC,GAAgD,CAAC,GAAM,GAAM,IAAM,GAAI,EACvEC,GAAgD,CAAC,GAAM,GAAM,IAAM,GAAI,EAEvEC,GAAgD,CAAC,GAAM,IAAM,GAAI,EACjEC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAM,EAAI,EAE3DC,GAAgD,CAAC,GAAM,GAAM,IAAM,GAAI,EACvEC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAM,GAAI,EAE3DC,GAAgD,CAAC,GAAM,GAAM,IAAM,GAAI,EACvEC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,IAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,IAAM,GAAI,EAE3DC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAM,GAAI,EAC3DC,GAAgD,CAAC,GAAI,EAErDC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,GAAI,EAErDC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,GAAI,EAErDC,GAAgD,CAAC,GAAM,GAAM,IAAM,GAAI,EACvEC,GAAgD,CAAC,GAAI,EACrDC,GAAgD,CAAC,GAAI,EAM9CC,EAAgB,CACzB,kCAAqC,IAErC,eAAqC,KACrC,cAAqC,EAErC,qBAAqC,4BACrC,iBAAqC,IAErC,yBAAqC,GACrC,wBAAqC,GAErC,gBAAqC,0BACzC,EASA,SAASC,GAAmB3D,EAAatK,EAAcC,EACvD,CACI,MAAMiO,EAAI,IAAO5D,EACjB,OAAAtK,EAAG,SAASC,EAAIiO,CAAC,EACVjO,EAAK,CAChB,CAEA,SAASkO,EAAiB3H,EAAY4H,EAAapO,EAAcC,EACjE,CACI,OAAAA,EAAKoO,EAAe7H,EAAIxG,EAAIC,CAAE,EAC9BA,EAAKgO,GAAmB,EAAGjO,EAAIC,CAAE,EACjCD,EAAG,SAASC,EAAImO,CAAG,EACZnO,EAAK,CAChB,CAEA,SAASqO,GAAkB9H,EAAY4H,EAAapO,EAAcC,EAClE,CACI,OAAAA,EAAKoO,EAAe7H,EAAIxG,EAAIC,CAAE,EAC9BA,EAAKgO,GAAmB,EAAGjO,EAAIC,CAAE,EACjCD,EAAG,UAAUC,EAAImO,CAAG,EACbnO,EAAK,CAChB,CAEA,SAASsO,GAAkB/H,EAAY4H,EAAapO,EAAcC,EAClE,CACI,OAAAA,EAAKoO,EAAe7H,EAAIxG,EAAIC,CAAE,EAC9BA,EAAKgO,GAAmB,EAAGjO,EAAIC,CAAE,EACjCD,EAAG,UAAUC,EAAImO,CAAG,EACbnO,EAAK,CAChB,CAEA,SAASuO,GAAoBhI,EAAY4H,EAAapO,EAAcC,EACpE,CACI,OAAAA,EAAKoO,EAAe7H,EAAIxG,EAAIC,CAAE,EAC9BA,EAAKgO,GAAmB,EAAGjO,EAAIC,CAAE,EACjCD,EAAG,WAAWC,EAAImO,CAAG,EACdnO,EAAK,CAChB,CAEA,SAASwO,GAAoBnE,EAAatK,EAAcC,EACxD,CAGID,EAAG,SAASC,IAAM,CAAI,EACtBD,EAAG,SAASC,IAAM,CAAI,EACtBD,EAAG,SAASC,IAAM,CAAI,EACtBD,EAAG,SAASC,IAAM,CAAI,EACtB,MAAMmO,EAAM9D,EAAM,WAClB,QAASoE,EAAQ,GAAIA,GAAS,EAAGA,GAAS,EAEtC1O,EAAG,SAASC,IAAMmO,GAAOM,CAAK,EAElC,OAAOzO,CACX,CAEA,SAASoO,EAAeM,EAAa3O,EAAcC,EACnD,CACI,QAASoB,EAAI,EAAGA,EAAIsN,EAAI,OAAQtN,IAE5BrB,EAAG,SAASC,EAAKoB,EAAGsN,EAAItN,CAAC,CAAE,EAE/B,OAAOpB,EAAK0O,EAAI,MACpB,CAEA,SAASC,GAAgBC,EAAa7O,EAAcC,EACpD,CACI,QAASoB,EAAI,EAAGA,EAAIwN,EAAI,OAAQxN,IAE5BrB,EAAG,SAASC,EAAKoB,EAAGwN,EAAI,WAAWxN,CAAC,CAAC,EAEzC,OAAOpB,EAAK4O,EAAI,MACpB,CAEA,SAASC,GAActI,EAAY3E,EAAkC7B,EAAcC,EACnF,CACI,OAAAA,EAAKoO,EAAe7H,EAAIxG,EAAIC,CAAE,EAC1B4B,EAAK,OAAS,IAEd5B,EAAKgO,GAAmBpM,EAAK,OAAQ7B,EAAIC,CAAE,EAI3CA,EAAKwO,GAAoB5M,EAAK,OAAQ7B,EAAIC,CAAE,EAE5C,OAAO4B,GAAS,SAEhB5B,EAAK2O,GAAgB/M,EAAM7B,EAAIC,CAAE,EAIjCA,EAAKoO,EAAexM,EAAM7B,EAAIC,CAAE,EAE7BA,CACX,CAMA,MAAM8O,EACN,CADA,aAAA,CAEI,KAAiB,GAAa1D,GAC9B,KAAiB,QAAkB,EACnC,KAAiB,YAAsB,EACvC,KAAiB,YAAsB,EACvC,KAAiB,cAAwB,EACzC,KAAiB,QAAkB,OACnC,KAAiB,eAAyB,EAC1C,KAAiB,mBAA6B,CAAA,CAE9C,SAAS/H,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EAEzB,OAAArD,EAAKoO,EAAe,KAAK,GAAIrO,EAAIC,CAAE,EACnCA,EAAKwO,GAAoB,GAAMzO,EAAIC,CAAE,EACrCA,EAAKkO,EAAiB7C,GAAqB,KAAK,QAAStL,EAAIC,CAAE,EAC/DA,EAAKkO,EAAiB5C,GAA0B,KAAK,YAAavL,EAAIC,CAAE,EACxEA,EAAKkO,EAAiB3C,GAA2B,KAAK,YAAaxL,EAAIC,CAAE,EACzEA,EAAKkO,EAAiB1C,GAA6B,KAAK,cAAezL,EAAIC,CAAE,EAC7EA,EAAK6O,GAAcpD,GAAsB,KAAK,QAAS1L,EAAIC,CAAE,EAC7DA,EAAKkO,EAAiBxC,GAA8B,KAAK,eAAgB3L,EAAIC,CAAE,EAC/EA,EAAKkO,EAAiBvC,GAAmC,KAAK,mBAAoB5L,EAAIC,CAAE,EAEjFA,CACX,CAEA,YACA,CACI,MAAO,IAAW,KAAK,GAAG,MAC9B,CACJ,CAEA,MAAM+O,EACN,CADA,aAAA,CAEI,KAAiB,GAAanD,EAAA,CAE9B,SAASvI,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EAEzB,OAAArD,EAAKoO,EAAe,KAAK,GAAIrO,EAAIC,CAAE,EACnCD,EAAG,SAASC,IAAM,GAAI,EACfA,CACX,CAEA,YACA,CACI,OAAO,KAAK,GAAG,OAAS,CAC5B,CACJ,CAEA,MAAMgP,EACN,CADA,aAAA,CAEI,KAAiB,GAAanD,GAC9B,KAAiB,cAAwB,IACzC,KAAiB,UAAoB,QACrC,KAAiB,WAAqB,aAAA,CAEtC,SAASxI,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EAEzB,OAAArD,EAAKoO,EAAe,KAAK,GAAIrO,EAAIC,CAAE,EACnCA,EAAKwO,GAAoB,KAAK,aAAe,EAAI,KAAK,GAAG,OAAQzO,EAAIC,CAAE,EACvEA,EAAKqO,GAAkBvC,GAAqB,KAAK,cAAe/L,EAAIC,CAAE,EACtEA,EAAK6O,GAAc9C,GAAiB,KAAK,UAAWhM,EAAIC,CAAE,EAC1DA,EAAK6O,GAAc7C,GAAkB,KAAK,WAAYjM,EAAIC,CAAE,EACrDA,CACX,CAEA,YACA,CACI,OAAO,KAAK,GAAG,OAAS,EACf8L,GAAoB,OAAS,EAAI,EACjCC,GAAgB,OAAS,EAAI,KAAK,UAAU,OAC5CC,GAAiB,OAAS,EAAI,KAAK,WAAW,MAC3D,CACJ,CAEO,MAAMiD,EACb,CAKI,YAAYC,EACZ,CALA,KAAiB,GAAazB,GAE9B,KAAiB,SAAmBM,EAAc,cAI9C,KAAK,kBAAoBmB,CAC7B,CAEA,SAAS7L,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,OAAArD,EAAKoO,EAAe,KAAK,GAAIrO,EAAIC,CAAE,EACnCA,EAAKwO,GAAoB,KAAK,aAAe,EAAI,KAAK,GAAG,OAAQzO,EAAIC,CAAE,EACvEA,EAAKkO,EAAiBP,GAAe,KAAK,SAAU5N,EAAIC,CAAE,EAC1DA,EAAKuO,GAAoBb,GAAyB,KAAK,kBAAmB3N,EAAIC,CAAE,EACzEA,CACX,CAEA,YACA,CACI,OAAO,KAAK,GAAG,OAAS,EACpB0N,GAAwB,OAAS,EAAI,EACrCC,GAAc,OAAS,EAAI,CACnC,CACJ,CAEO,MAAMwB,EACb,CAMI,YAAY5N,EAAeC,EAC3B,CANA,KAAiB,GAAa6L,GAC9B,KAAiB,eAAyB,EAMtC,KAAK,MAAQ9L,EACb,KAAK,OAASC,CAClB,CAEA,SAAS6B,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,OAAArD,EAAKoO,EAAe,KAAK,GAAIrO,EAAIC,CAAE,EACnCA,EAAKwO,GAAoB,KAAK,aAAe,EAAI,KAAK,GAAG,OAAQzO,EAAIC,CAAE,EACvEA,EAAKkO,EAAiBZ,GAAsB,KAAK,eAAgBvN,EAAIC,CAAE,EACvEA,EAAKsO,GAAkBf,GAAkB,KAAK,MAAOxN,EAAIC,CAAE,EAC3DA,EAAKsO,GAAkBd,GAAmB,KAAK,OAAQzN,EAAIC,CAAE,EACtDA,CACX,CAEA,YACA,CACI,OAAO,KAAK,GAAG,OAAS,EACpBsN,GAAqB,OAAS,EAAI,EAClCC,GAAiB,OAAS,EAAI,EAC9BC,GAAkB,OAAS,EAAI,CACvC,CACJ,CAMA,MAAM4B,EACN,CAKI,YAAYC,EAAgBC,EAC5B,CALA,KAAiB,GAAapD,GAM1B,KAAK,OAASmD,EACd,KAAK,IAAMC,CACf,CAEA,SAASjM,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,OAAArD,EAAKoO,EAAe,KAAK,GAAIrO,EAAIC,CAAE,EACnCA,EAAKgO,GAAmB,KAAK,aAAe,EAAI,KAAK,GAAG,OAAQjO,EAAIC,CAAE,EAEtEA,EAAK6O,GAAc1C,GAAc,KAAK,OAAQpM,EAAIC,CAAE,EACpDA,EAAKsO,GAAkBlC,GAAoB,KAAK,IAAKrM,EAAIC,CAAE,EAEpDA,CACX,CAEA,YACA,CACI,OAAO,KAAK,GAAG,OAAS,EAChBmM,GAAa,OAAS,EAAI,KAAK,OAAO,OACtCC,GAAmB,OAAS,EAAI,CAC5C,CACJ,CAEA,MAAMmD,EACN,CAKI,YAAYC,EAAiBC,EAC7B,CALA,KAAiB,GAAaxD,GAM1B,KAAK,KAAO,IAAImD,GAASvD,GAA0B2D,CAAO,EAC1D,KAAK,MAAQ,IAAIJ,GAAS/C,GAAaoD,CAAQ,CACnD,CAEA,SAASpM,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,OAAArD,EAAKoO,EAAe,KAAK,GAAIrO,EAAIC,CAAE,EACnCA,EAAKwO,GAAoB,KAAK,aAAe,EAAI,KAAK,GAAG,OAAQzO,EAAIC,CAAE,EAEvEA,EAAK,KAAK,KAAK,SAASqD,EAAGrD,CAAE,EAC7BA,EAAK,KAAK,MAAM,SAASqD,EAAGrD,CAAE,EAEvBA,CACX,CAEA,YACA,CACI,OAAO,KAAK,GAAG,OAAS,EAChB,KAAK,KAAK,WAAA,EACV,KAAK,MAAM,WAAA,CACvB,CACJ,CAMO,MAAM0P,EACb,CA4BI,aACA,CA5BA,KAAiB,GAAapD,GAC9B,KAAiB,OAAiB,EAClC,KAAiB,IAAc,EAC/B,KAAiB,KAAe,EAChC,KAAiB,YAAsB,EACvC,KAAiB,YAAsB,EACvC,KAAiB,WAAqB,EACtC,KAAiB,WAAqB,EACtC,KAAiB,SAAmB,EACpC,KAAiB,mBAA6B,EAC9C,KAAiB,eAAyB,EAC1C,KAAiB,YAAsB,EACvC,KAAiB,WAAqB,IACtC,KAAiB,QAAkB,SAInC,KAAiB,aAAkC,CAC/C,GAAM,IAAM,IAAM,IAAM,GAAM,IAAM,GAAM,IAC1C,EACAyB,EAAc,cACd,EAAM,GACN,IAAM,IAAM,EAAM,EAClB,EAAM,EACN,CAAA,EAKA,KAAK,MAAQ,IAAIkB,GAAUlB,EAAc,cAAc,CAC3D,CAEA,SAAS1K,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,OAAArD,EAAKoO,EAAe,KAAK,GAAIrO,EAAIC,CAAE,EACnCA,EAAKwO,GAAoB,KAAK,aAAe,EAAI,KAAK,GAAG,OAAQzO,EAAIC,CAAE,EACvEA,EAAKkO,EAAiB3B,GAAmB,KAAK,OAAQxM,EAAIC,CAAE,EAC5DA,EAAKkO,EAAiB1B,GAAgB,KAAK,IAAKzM,EAAIC,CAAE,EACtDA,EAAKkO,EAAiBxB,GAAmB,KAAK,YAAa3M,EAAIC,CAAE,EACjEA,EAAKkO,EAAiBvB,GAAmB,KAAK,YAAa5M,EAAIC,CAAE,EACjEA,EAAKkO,EAAiBtB,GAAkB,KAAK,WAAY7M,EAAIC,CAAE,EAC/DA,EAAKkO,EAAiBrB,GAAkB,KAAK,WAAY9M,EAAIC,CAAE,EAC/DA,EAAK6O,GAAczB,GAAe,KAAK,QAASrN,EAAIC,CAAE,EACtDA,EAAKkO,EAAiBpB,GAAgB,KAAK,SAAU/M,EAAIC,CAAE,EAC3DA,EAAKkO,EAAiBnB,GAA4B,KAAK,mBAAoBhN,EAAIC,CAAE,EACjFA,EAAKkO,EAAiBlB,GAAuB,KAAK,eAAgBjN,EAAIC,CAAE,EACxEA,EAAKqO,GAAkBnB,GAAkB,KAAK,WAAYnN,EAAIC,CAAE,EAChEA,EAAKqO,GAAkBpB,GAAoB,KAAK,YAAalN,EAAIC,CAAE,EACnEA,EAAKkO,EAAiBzB,GAAiB,KAAK,KAAM1M,EAAIC,CAAE,EACxDA,EAAK6O,GAAc1B,GAAoB,KAAK,aAAcpN,EAAIC,CAAE,EAEhEA,EAAK,KAAK,MAAM,SAASqD,EAAGrD,CAAE,EACvBA,CACX,CAEA,YACA,CACI,OAAO,KAAK,GAAG,OAAS,EACpBuM,GAAkB,OAAS,EAAI,EAC/BC,GAAe,OAAS,EAAI,EAC5BC,GAAgB,OAAS,EAAI,EAC7BC,GAAkB,OAAS,EAAI,EAC/BC,GAAkB,OAAS,EAAI,EAC/BC,GAAiB,OAAS,EAAI,EAC9BC,GAAiB,OAAS,EAAI,EAC9BC,GAAe,OAAS,EAAI,EAC5BC,GAA2B,OAAS,EAAI,EACxCC,GAAsB,OAAS,EAAI,EACnCC,GAAmB,OAAS,EAAI,EAChCC,GAAiB,OAAS,EAAI,EAC9BE,GAAc,OAAS,KAAK,QAAQ,OAAS,EAC7CD,GAAmB,OAAS,EAAI,KAAK,aAAa,OAClD,KAAK,MAAM,WAAA,CACnB,CACJ,CAEO,MAAMwC,EACb,CA2BI,YAAYpO,EAAeC,EAC3B,CAjBA,KAAiB,GAAa8K,GAC9B,KAAiB,OAAiB,EAClC,KAAiB,IAAc,EAC/B,KAAiB,KAAe,EAChC,KAAiB,YAAsB,EACvC,KAAiB,YAAsB,EACvC,KAAiB,WAAqB,EACtC,KAAiB,WAAqB,EACtC,KAAiB,SAAmB,EACpC,KAAiB,mBAA6B,EAC9C,KAAiB,QAAkB,QACnC,KAAiB,eAAyB,EAC1C,KAAiB,YAAsB,EAMnC,KAAK,MAAQ,IAAI6C,GAAU5N,EAAOC,CAAM,CAC5C,CAEA,SAAS6B,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,OAAArD,EAAKoO,EAAe,KAAK,GAAIrO,EAAIC,CAAE,EACnCA,EAAKwO,GAAoB,KAAK,aAAe,EAAI,KAAK,GAAG,OAAQzO,EAAIC,CAAE,EACvEA,EAAKkO,EAAiB3B,GAAmB,KAAK,OAAQxM,EAAIC,CAAE,EAC5DA,EAAKkO,EAAiB1B,GAAgB,KAAK,IAAKzM,EAAIC,CAAE,EACtDA,EAAKkO,EAAiBxB,GAAmB,KAAK,YAAa3M,EAAIC,CAAE,EACjEA,EAAKkO,EAAiBvB,GAAmB,KAAK,YAAa5M,EAAIC,CAAE,EACjEA,EAAKkO,EAAiBtB,GAAkB,KAAK,WAAY7M,EAAIC,CAAE,EAC/DA,EAAKkO,EAAiBrB,GAAkB,KAAK,WAAY9M,EAAIC,CAAE,EAC/DA,EAAK6O,GAAczB,GAAe,KAAK,QAASrN,EAAIC,CAAE,EACtDA,EAAKkO,EAAiBpB,GAAgB,KAAK,SAAU/M,EAAIC,CAAE,EAC3DA,EAAKkO,EAAiBnB,GAA4B,KAAK,mBAAoBhN,EAAIC,CAAE,EACjFA,EAAKkO,EAAiBlB,GAAuB,KAAK,eAAgBjN,EAAIC,CAAE,EACxEA,EAAKqO,GAAkBpB,GAAoB,KAAK,YAAalN,EAAIC,CAAE,EACnEA,EAAKkO,EAAiBzB,GAAiB,KAAK,KAAM1M,EAAIC,CAAE,EACxDA,EAAK,KAAK,MAAM,SAASqD,EAAGrD,CAAE,EACvBA,CACX,CAEA,YACA,CACI,OAAO,KAAK,GAAG,OAAS,EACpBuM,GAAkB,OAAS,EAAI,EAC/BC,GAAe,OAAS,EAAI,EAC5BE,GAAkB,OAAS,EAAI,EAC/BC,GAAkB,OAAS,EAAI,EAC/BC,GAAiB,OAAS,EAAI,EAC9BC,GAAiB,OAAS,EAAI,EAC9BO,GAAc,OAAS,KAAK,QAAQ,OAAS,EAC7CN,GAAe,OAAS,EAAI,EAC5BC,GAA2B,OAAS,EAAI,EACxCC,GAAsB,OAAS,EAAI,EACnCC,GAAmB,OAAS,EAAI,EAChCR,GAAgB,OAAS,EAAI,EAC7B,KAAK,MAAM,WAAA,CACnB,CACJ,CAEO,MAAMmD,EACb,CAII,YAAYC,EACZ,CAJA,KAAiB,GAAaxD,GAK1B,KAAK,WAAawD,CACtB,CAEA,SAASxM,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,OAAArD,EAAKoO,EAAe,KAAK,GAAIrO,EAAIC,CAAE,EACnCA,EAAKwO,GAAoB,KAAK,aAAe,EAAI,KAAK,GAAG,OAAQzO,EAAIC,CAAE,EACvEA,EAAK,KAAK,WAAW,SAASqD,EAAGrD,CAAE,EAC5BA,CACX,CAEA,YACA,CACI,OAAO,KAAK,GAAG,OAAS,EACf,KAAK,WAAW,WAAA,CAC7B,CACJ,CAEO,MAAM8P,EACb,CAGI,YAAYC,EACZ,CACI,KAAK,SAAWA,CACpB,CAEA,SAAS1M,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzB,OAAArD,EAAKoO,EAAeR,GAAc7N,EAAIC,CAAE,EACxCD,EAAG,SAASC,IAAM,GAAI,EACtBA,EAAKqO,GAAkBR,GAAgB,KAAK,SAAU9N,EAAIC,CAAE,EACrDA,CACX,CAEA,YACA,CACI,OAAO4N,GAAa,OAAS,EACpBC,GAAe,OAAS,EAAI,CACzC,CACJ,CAEO,MAAMmC,EACb,CAKI,YAAYD,EAAkBnO,EAAmBqO,EACjD,CACI,KAAK,SAAWF,EAChB,KAAK,KAAOnO,EACZ,KAAK,SAAWqO,CACpB,CAEA,SAAS5M,EAAgBrD,EAAa,EACtC,CACI,MAAMD,EAAK,IAAI,SAASsD,CAAC,EACzBrD,EAAKoO,EAAeN,GAAmB/N,EAAIC,CAAE,EAC7CA,EAAKwO,GAAoB,KAAK,KAAK,WAAa,EAAGzO,EAAIC,CAAE,EACzDA,EAAKgO,GAAmB,EAAGjO,EAAIC,CAAE,EACjCD,EAAG,UAAUC,EAAI,KAAK,QAAQ,EAAGA,GAAM,EACvCD,EAAG,SAASC,EAAI,KAAK,SAAW+N,EAAc,kCAAoC,CAAC,EAAG/N,GAAM,EAG5F,MAAMkQ,EAAQ,IAAI,WAAW,KAAK,IAAI,EAEtC,OADc,IAAI,WAAW7M,EAAGrD,EAAI,KAAK,KAAK,UAAU,EAClD,IAAIkQ,CAAK,EACflQ,GAAM,KAAK,KAAK,WAETA,CACX,CAEA,YACA,CACI,OAAO8N,GAAkB,OAAS,EACzB,EAAI,EAAI,EACR,KAAK,KAAK,UACvB,CACJ,CAEO,MAAMqC,EACb,CAMI,aACA,CACI,KAAK,KAAO,IAAIrB,GAChB,KAAK,QAAU,IAAIC,GACnB,KAAK,SAAW,IAAIQ,GAAa,EAAG,CAAC,EAErC,KAAK,SAAS,KAAK,IAAM,KAAK,QAAQ,aAAe,KAAK,SAAS,WAAA,EAEnE,KAAK,KAAO,IAAIP,GAEhB,KAAK,SAAS,MAAM,IAAM,KAAK,SAAS,KAAK,IAAM,KAAK,KAAK,WAAA,CACjE,CAEA,SAAS3L,EAAgBrD,EAAa,EACtC,CACI,OAAAA,EAAK,KAAK,KAAK,SAASqD,EAAGrD,CAAE,EAC7BA,EAAK,KAAK,QAAQ,SAASqD,EAAGrD,CAAE,EAChCA,EAAK,KAAK,KAAK,SAASqD,EAAGrD,CAAE,EAEtBA,CACX,CAEA,YACA,CACI,OAAO,KAAK,KAAK,WAAA,EACV,KAAK,QAAQ,aACb,KAAK,KAAK,WAAA,CACrB,CACJ,CCzpBA,eAAeoQ,GAAWC,EAA2BC,EACrD,CACI,MAAMC,EAAM,MAAM,OAAO,OAAO,UAC5B,OACAF,EACA,CAAE,KAAM,WAAY,KAAM,OAAA,EAC1B,GACA,CAAC,SAAS,CAAA,EAMRG,EAAgB,IAAI,WAAWF,EAAS,OAAS,CAAC,EACxD,QAASlP,EAAI,EAAGA,EAAIkP,EAAS,OAAQlP,IAEjCoP,EAAcpP,CAAC,EAAIkP,EAAS,WAAWlP,CAAC,EAAI,IAEhDoP,EAAcF,EAAS,MAAM,EAAI,EAEjC,MAAMG,EAAY,MAAM,OAAO,OAAO,QAClC,CAAE,KAAM,UAAA,EACRF,EACAC,CAAA,EAIEhI,EAAK,IAAI,WAAWiI,CAAS,EAC7BpK,EAAmB,IAAI,MAAMmC,EAAG,MAAM,EAC5C,QAASpH,EAAI,EAAGA,EAAIoH,EAAG,OAAQpH,IAE3BiF,EAAOjF,CAAC,EAAIoH,EAAGpH,CAAC,EAEpB,OAAOiF,CACX,CCLO,MAAMqK,EAAkB,CAE3B,WAAY,aAEZ,MAAO,QAEP,KAAM,OAEN,OAAQ,SAER,MAAO,QAEP,QAAS,UAET,MAAO,OACX,EA+DO,MAAMC,EAA+B,CAiDxC,YAAYC,EACZ,CACI,GA5CJ,KAAA,MAA8BF,EAAgB,WAyB9C,KAAA,aAAuB,EAGvB,KAAA,UAAoB,EASpB,KAAQ,SAAoC,CAAA,EAOpC,CAACE,EAAQ,IAET,MAAM,IAAI,MAAM,wBAAwB,EAiD5C,GA9CA,KAAK,aAAeA,EAAQ,cAAgB,EAC5C,KAAK,KAAOA,EAAQ,MAAQ3S,EAAa,KACzC,KAAK,OAAS2S,EAAQ,QAAU,EAE5BA,EAAQ,SAAW,QAEnB,KAAK,OAASA,EAAQ,OACtB,KAAK,UAAYA,EAAQ,OAAO,UAChC,KAAK,SAAWA,EAAQ,OAAO,UAI/B,KAAK,SAAWA,EAAQ,UAAY,GAGpCA,EAAQ,WAAa,SAErB,KAAK,SAAWA,EAAQ,UAExBA,EAAQ,SAAW,SAEnB,KAAK,OAASA,EAAQ,QAEtBA,EAAQ,YAAc,SAEtB,KAAK,UAAYA,EAAQ,WAEzBA,EAAQ,WAAa,SAErB,KAAK,SAAWA,EAAQ,UAExBA,EAAQ,UAAY,SAEpB,KAAK,QAAUA,EAAQ,SAEvBA,EAAQ,YAAc,SAEtB,KAAK,UAAYA,EAAQ,WAEzBA,EAAQ,UAAY,SAEpB,KAAK,QAAUA,EAAQ,SAG3B,KAAK,GAAK,IAAI,UAAUA,EAAQ,IAAK,QAAQ,EAEzC,CAAC,KAAK,GAAG,WAET,MAAM,IAAI,MAAM,iEAAiE,EA0DrF,GAvDA,KAAK,WAAa,IAAIrG,GAAgB,KAAM,KAAK,eAAe,KAAK,IAAI,CAAC,EAE1E,KAAK,GAAG,iBAAiB,OAAQ,IACjC,CAII,KAAK,QAAA,EACL,KAAK,WAAW,QAAQ,IAAInH,GAAA,EAAkB,YAAY,EAC1D,KAAK,MAAQsN,EAAgB,KACjC,CAAC,EAED,KAAK,GAAG,iBAAiB,QAAU,GACnC,CACI,MAAMzM,EAAS,EAAE,OACbA,GAAU,QAASA,GAEnB,KAAK,OAAO,uDAAyDA,EAAO,GAAG,EAEnF,KAAK,YAAY,IAAI,MAAM,iBAAiB,CAAC,CACjD,CAAC,EAED,KAAK,GAAG,iBAAiB,QAAS,IAClC,CAII,GAAI,KAAK,QAAUyM,EAAgB,SAC/B,KAAK,QAAUA,EAAgB,OAC/B,KAAK,UAAY,OACrB,CACI,IAAIG,EACA,KAAK,QAAUH,EAAgB,WAE/BG,EAAM,IAAI,MAAM,qBAAqB,EAEhC,KAAK,QAAUH,EAAgB,OAC/B,KAAK,QAAUA,EAAgB,KAEpCG,EAAM,IAAI,MAAM,+BAA+B,EAE1C,KAAK,QAAUH,EAAgB,OAEpCG,EAAM,IAAI,MAAM,eAAe,EAI/BA,EAAM,IAAI,MAAM,0BAA4B,KAAK,KAAK,EAG1D,KAAK,QAAQA,CAAG,EAChB,KAAK,OAAOA,EAAI,UAAU,CAC9B,CACJ,CAAC,EAEG,KAAK,GAAG,aAAe,GAAK,KAAK,GAAG,aAAe,EAEnD,MAAM,IAAI,MAAM,wBAA0BD,EAAQ,GAAG,EAGzD,KAAK,QAAU,WAAW,IAAM,KAAK,cAAA,EAAiBjU,EAAqB,CAC/E,CAMQ,SACR,CACI,MAAMmU,EAAM,IAAI1N,GACV2N,EAAM,IAAIzN,GAWhB,GATAyN,EAAI,aAAe,KAAK,aACxBA,EAAI,YAAc,KAAK,KACvBA,EAAI,UAAY,KAAK,OAErBA,EAAI,WAAW,KACV,GAAKnU,GAAe,wBACpB,GAAKA,GAAe,WAAA,EAGrBmU,EAAI,cAAgB9S,EAAa,SACrC,CACI,IAAIsG,EAAO,EACP,OAAO,YAAgB,KACvB,YAAY,gBAAgBwJ,EAAc,oBAAoB,IAE9DxJ,GAAS,GAAK3G,GAAiB,MAEnCmT,EAAI,YAAY,KAAKxM,CAAI,CAC7B,SACSwM,EAAI,cAAgB9S,EAAa,KAEtC8S,EAAI,YAAY,KACX,GAAKlT,GAAa,sBAAA,UAGlBkT,EAAI,cAAgB9S,EAAa,QAC1C,CACI,IAAIsG,EAAQ,GAAKzG,EAAgB,aACrB,GAAKA,EAAgB,cACrB,GAAKA,EAAgB,YACrB,GAAKA,EAAgB,YAC7B,OAAO,YAAgB,KACvB,YAAY,gBAAgBiQ,EAAc,eAAe,IAEzDxJ,GAAS,GAAKzG,EAAgB,WAElCiT,EAAI,YAAY,KAAKxM,CAAI,CAC7B,CAEAuM,EAAI,KAAOC,EAAI,WAAA,EAEf,MAAM1Q,EAAK,IAAI,YAAYyQ,EAAI,aAAeC,EAAI,YAAY,EAC9DD,EAAI,SAASzQ,CAAE,EACf0Q,EAAI,SAAS1Q,EAAIyQ,EAAI,WAAA,CAAY,EAIjC,KAAK,GAAG,KAAKzQ,CAAE,CACnB,CAMQ,WAAW2Q,EACnB,CACI,MAAMF,EAAM,IAAIlN,GAChBkN,EAAI,cAAgBlU,GAAe,WACnCkU,EAAI,cAAgBE,EACpB,MAAM3Q,EAAK,IAAI,YAAYyQ,EAAI,YAAY,EAE3CA,EAAI,SAASzQ,CAAE,EAGf,KAAK,GAAG,KAAKA,CAAE,CACnB,CAMA,QAAQ0Q,EACR,CACI,MAAM1Q,EAAK,IAAI,YAAY0Q,EAAI,YAAY,EAC3CA,EAAI,SAAS1Q,CAAE,EACf,KAAK,eAGL,KAAK,GAAG,KAAKA,CAAE,CACnB,CAMQ,eAAeA,EAAiB4Q,EACxC,CAGI,GAAI,KAAK,QAAUP,EAAgB,MAE/B,GAAIO,IAAgB,OACpB,CACI,MAAMF,EAAM,IAAIhN,EAAc1D,CAAE,EAE5B0Q,EAAI,KAAO,IAWXA,EAAI,OAAS,GAEb,KAAK,eAAeA,CAAG,EACvB,KAAK,WAAW,QAAQ,IAAIhN,EAAA,EAAgB,YAAY,IAIxD,KAAK,WAAW,QAAQgN,EAAI,IAAI,EAChC,KAAK,WAAW,WAAWA,CAAG,EAEtC,MAGIE,EAAY,KAAO5Q,EACnB,KAAK,eAAe4Q,CAAW,EAC/B,KAAK,WAAW,QAAQ,IAAIlN,EAAA,EAAgB,YAAY,EACxD,KAAK,WAAW,YAAA,UAGf,KAAK,QAAU2M,EAAgB,MAGpC,GADA,KAAK,SAAW,IAAItN,GAAgB/C,CAAE,EAClC,KAAK,SAAS,QAAU7D,GAC5B,CACI,KAAK,MAAQkU,EAAgB,MAC7B,MAAM9F,EAAI,IAAI,MAAM,0BAA4B,KAAK,SAAS,KAAK,EACnE,KAAK,YAAYA,CAAC,CACtB,MAII,KAAK,WAAW,QAAQ,KAAK,SAAS,IAAI,EAC1C,KAAK,MAAQ8F,EAAgB,aAG5B,KAAK,QAAUA,EAAgB,KAIpC,GAFA,KAAK,UAAY,IAAI/M,GAAetD,CAAE,EAElC,KAAK,UAAU,MACnB,CACI,KAAK,MAAQqQ,EAAgB,MAC7B,MAAM9F,EAAI,IAAI,MAAM,2BAA6B,KAAK,UAAU,KAAK,EACrE,KAAK,YAAYA,CAAC,CACtB,KAEA,CACI,GAAI,CAAC,KAAK,UAAU,UACpB,CACI,KAAK,MAAQ8F,EAAgB,MAC7B,KAAK,YAAY,IAAI,MAAM,sCAAsC,CAAC,EAClE,MACJ,CAIAN,GAAW,KAAK,UAAU,UAAW,KAAK,QAAQ,EAC7C,KAAMK,GACP,CACI,KAAK,WAAWA,CAAS,EACzB,KAAK,MAAQC,EAAgB,OAC7B,KAAK,WAAW,QAAQ,IAAI5M,GAAA,EAAqB,YAAY,CACjE,CAAC,EACA,MAAO+M,GACR,CACI,KAAK,MAAQH,EAAgB,MAC7B,MAAMK,EAAMF,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,EAC3D,KAAK,YAAY,IAAI,MAAM,0BAA4BE,CAAG,CAAC,CAC/D,CAAC,CACT,SAEK,KAAK,QAAUL,EAAgB,OAGpC,GADA,KAAK,UAAY,IAAI5M,GAAmBzD,CAAE,EACtC,KAAK,UAAU,WAAatD,GAAa,GAC7C,CAGI,GAAI,KAAK,OAASkB,EAAa,QAC/B,CAEI,MAAMiT,EAAQ,IAAIrK,GACZsK,EAAQ,IAAIpN,EAClBoN,EAAM,SAAS9T,GAAiB,KAAM6T,CAAK,EAE3C,KAAK,QAAQC,CAAK,CACtB,CACA,KAAK,MAAQT,EAAgB,MAC7B,KAAK,WAAW,QAAQ,IAAI3M,EAAA,EAAgB,YAAY,EACpD,KAAK,UAAY,SAEjB,aAAa,KAAK,OAAO,EACzB,KAAK,QAAU,OAEvB,MAGI,KAAK,MAAQ2M,EAAgB,MACzB,KAAK,UAAU,WAAa3T,GAAa,kBAEzC,KAAK,YAAY,IAAI,MAAM,oBAAoB,CAAC,EAIhD,KAAK,YAAY,IAAI,MAAM,yBAA2B,KAAK,UAAU,QAAQ,CAAC,CAI9F,CAMQ,sBAAsBgU,EAC9B,CACI,GAAIA,EAAI,OAAS/T,GAAS,QAC1B,CACI,GAAI,CAAC+T,EAAI,KAEL,YAAK,QAAQ,8BAA8B,EACpC,GAEX,MAAMxL,EAAM,IAAIF,GAAe0L,EAAI,IAAI,EAEvC,KAAK,UAAYxL,EAAI,OAErB,KAAK,aAAe,KAAK,UACzB,MAAM6L,EAAS,IAAI9L,GAAiBC,CAAG,EACjC4L,EAAQ,IAAIpN,EAClB,OAAAoN,EAAM,SAASjU,GAAU,SAAUkU,CAAM,EACzC,KAAK,QAAQD,CAAK,EACX,EACX,CAEA,GAAIJ,EAAI,OAAS/T,GAAS,KAC1B,CAEI,MAAMqU,EAAO,IAAItN,EACjB,OAAAsN,EAAK,KAAOnU,GAAU,KAClB6T,EAAI,OAEJM,EAAK,KAAON,EAAI,KAAK,MAAM,EAAG,EAAE,GAEpCM,EAAK,KAAOA,EAAK,WAAA,EACjB,KAAK,QAAQA,CAAI,EACV,EACX,CAEA,GAAIN,EAAI,OAAS/T,GAAS,OAC1B,CACI,GAAI,CAAC+T,EAAI,KAEL,YAAK,QAAQ,6BAA6B,EACnC,GAGX,MAAMO,EAAS,IAAI3K,GAAeoK,EAAI,IAAI,EAC1C,OAAIO,EAAO,WAAanT,GAAoB,MAExC,KAAK,OAAOmT,EAAO,OAAO,EAErBA,EAAO,WAAanT,GAAoB,KAE7C,KAAK,QAAQmT,EAAO,OAAO,EAI3B,KAAK,QAAQA,EAAO,OAAO,EAExB,EACX,CAEA,MAAO,EACX,CAMQ,eAAeP,EACvB,CACI,MAAMQ,EAAQ,KAAK,IAAA,EAEnB,IAAIC,EAAK,KAAK,sBAAsBT,CAAG,EAUvC,GATKS,IAEDA,EAAK,KAAK,sBAAsBT,CAAG,EAC9BS,GAED,KAAK,QAAQ,KAAK,YAAA,EAAgB,0BAA4BT,EAAI,KAAO,GAAG,GAIhF,KAAK,eAAiB,QAAa,KAAK,YAExC,KAAK,eACD,KAAK,cAAgB,GACzB,CACI,KAAK,aAAe,KAAK,UACzB,MAAMxL,EAAM,IAAIxB,EAChBwB,EAAI,KAAOrI,GAAU,IACrB,KAAK,QAAQqI,CAAG,CAEpB,CAGJ,MAAMkM,EAAQ,KAAK,IAAA,EAAQF,EAC3B,OAAiBE,EAAQ1D,EAAc,yBAEnC,QAAQ,IAAI,SAAW,KAAK,YAAA,EAAgB,IAAMgD,EAAI,KAAO,IAAMU,CAAK,EAErED,CACX,CAaU,sBAAsBT,EAChC,CACI,YAAK,OAAO,KAAK,YAAA,EAAgB,mDAAqDA,EAAI,IAAI,EACvF,EACX,CAMA,aACA,CACI,OAAQ,KAAK,KAAA,CAET,KAAK9S,EAAa,KAAW,MAAO,OACpC,KAAKA,EAAa,QAAW,MAAO,UACpC,KAAKA,EAAa,OAAW,MAAO,SACpC,KAAKA,EAAa,OAAW,MAAO,SACpC,KAAKA,EAAa,SAAW,MAAO,WACpC,KAAKA,EAAa,OAAW,MAAO,SACpC,KAAKA,EAAa,OAAW,MAAO,SACpC,KAAKA,EAAa,UAAW,MAAO,YACpC,KAAKA,EAAa,SAAW,MAAO,WACpC,KAAKA,EAAa,KAAW,MAAO,OACpC,KAAKA,EAAa,OAAW,MAAO,SACpC,QAA6B,MAAO,WAAa,KAAK,IAAA,CAE9D,CAMA,WAAWyT,EACX,CACI,MAAMX,EAAMW,EAAK,KAAK,GAAG,EAEzB,GADA,QAAQ,IAAIX,CAAG,EACX,KAAK,WAAa,OAAO,SAAa,IAC1C,CACI,MAAMY,EAAY,SAAS,eAAe,KAAK,SAAS,EACxD,GAAIA,EACJ,CACI,MAAMC,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,YAAY,SAAS,eAAeb,CAAG,CAAC,EAC1Ca,EAAE,WAAa,qBACfD,EAAU,YAAYC,CAAC,CAC3B,CACJ,CACJ,CAEA,WAAWF,EACX,CACI,MAAMX,EAAMW,EAAK,KAAK,GAAG,EAEzB,GADA,QAAQ,IAAI,YAAcX,CAAG,EACzB,KAAK,WAAa,OAAO,SAAa,IAC1C,CACI,MAAMY,EAAY,SAAS,eAAe,KAAK,SAAS,EACxD,GAAIA,EACJ,CACI,MAAMC,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,YAAY,SAAS,eAAeb,CAAG,CAAC,EAC1Ca,EAAE,WAAa,wBACfD,EAAU,YAAYC,CAAC,CAC3B,CACJ,CACJ,CAEA,UAAUF,EACV,CACI,MAAMX,EAAMW,EAAK,KAAK,GAAG,EAEzB,GADA,QAAQ,IAAI,UAAYX,CAAG,EACvB,KAAK,WAAa,OAAO,SAAa,IAC1C,CACI,MAAMY,EAAY,SAAS,eAAe,KAAK,SAAS,EACxD,GAAIA,EACJ,CACI,MAAMC,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,YAAY,SAAS,eAAeb,CAAG,CAAC,EAC1Ca,EAAE,WAAa,sBACfD,EAAU,YAAYC,CAAC,CAC3B,CACJ,CACJ,CAMA,mBAAmBtQ,EAAcyP,EACjC,CACI,GAAI,CAAC,KAAK,SAASzP,CAAI,GAAK+H,GAAQ,EACpC,CACI,IAAIuF,EAAM,GAGNA,EAAM,kCAEV,KAAK,QAAQ,0BAA4BtN,EAAO,IAAMyP,EAAM,IAAMnC,CAAG,EACrE,KAAK,SAAStN,CAAI,EAAI,EAC1B,CACJ,CAMA,YAAYsJ,EACZ,CAEI,GADA,KAAK,OAAOA,EAAE,UAAU,EACpB,KAAK,UAAY,OAEjB,KAAK,QAAQA,CAAC,MAId,OAAMA,CAEd,CAEA,cAAcV,EACd,CACQ,KAAK,YAAc,QAEnB,KAAK,UAAUA,CAAC,CAExB,CAUA,SACA,CACQ,KAAK,UAAY,SAEjB,aAAa,KAAK,OAAO,EACzB,KAAK,QAAU,QAEf,KAAK,YAEL,KAAK,WAAW,QAAA,EAEhB,KAAK,KAEL,KAAK,MAAQwG,EAAgB,QAC7B,KAAK,GAAG,MAAA,EAEhB,CAMQ,eACR,CACI,MAAM9F,EAAI,IAAI,MAAM,uBAAuB,EAC3C,KAAK,YAAYA,CAAC,CACtB,CACJ,CC7uBO,MAAMiH,GAAgB,CACzB,QAAS,UACT,aAAc,eACd,UAAW,YACX,OAAQ,SACR,UAAW,WACf,EAsFMC,OAAuB,IAQtB,SAASC,GAAuBzQ,EAAc0Q,EACrD,CACIF,GAAiB,IAAIxQ,EAAM0Q,CAAI,CACnC,CAcO,MAAMC,WAAsBtB,EAAU,CAmCzC,YAAYC,EACZ,CACI,GAAI,OAAO,UAAc,IAErB,MAAM,IAAI,MAAM,8DAA8D,EAGlF,MAAMA,CAAO,EAvCjB,KAAA,UAAoB,EACpB,KAAA,UAAoB,EACpB,KAAA,OAAiB,EAGjB,KAAA,SAAuB,CACnB,QAAS,OACT,OAAQ,OACR,OAAQ,OACR,SAAU,OACV,MAAO,CAAA,EACP,MAAO,CAAA,CAAC,EAIZ,KAAA,eAA0B,GAC1B,KAAA,YAAsB,EACtB,KAAA,cAAiC,CAAA,EACjC,KAAA,UAAsB,CAAC,CAAC,EAGxB,KAAA,cAA8C,CAAA,EAC9C,KAAA,eAAyB,EACzB,KAAA,kBAAoC,CAAA,CAiBpC,CAMmB,sBAAsBG,EACzC,CACI,GAAIA,EAAI,OAAS9T,EAAa,cAE1B,YAAK,mBAAmB8T,EAAI,KAAM,oBAAoB,EAC/C,GAGX,GAAIA,EAAI,OAAS9T,EAAa,eAE1B,YAAK,mBAAmB8T,EAAI,KAAM,qBAAqB,EAChD,GAGX,GAAIA,EAAI,OAAS9T,EAAa,KAE1B,OAAO,KAAK,WAAW8T,CAAG,EAG9B,GAAIA,EAAI,OAAS9T,EAAa,WAE1B,OAAO,KAAK,mBAAmB8T,CAAG,EAGtC,GAAIA,EAAI,OAAS9T,EAAa,iBAE1B,YAAK,mBAAmB8T,EAAI,KAAM,uBAAuB,EAClD,GAGX,GAAIA,EAAI,OAAS9T,EAAa,cAE1B,OAAO,KAAK,mBAAmB8T,CAAG,EAGtC,GAAIA,EAAI,OAAS9T,EAAa,gBAE1B,YAAK,aAAA,EACE,GAGX,GAAI8T,EAAI,OAAS9T,EAAa,uBAC9B,CACI,GAAI8T,EAAI,KACR,CACI,MAAMmB,EAAkB,IAAI9M,GAAwB2L,EAAI,IAAI,EAC5D,KAAK,YAAcmB,EAAgB,SACvC,CACA,YAAK,aAAA,EACE,EACX,CAEA,OAAInB,EAAI,OAAS9T,EAAa,YAEnB,KAAK,iBAAiB8T,CAAG,EAGhCA,EAAI,OAAS9T,EAAa,oBAE1B,KAAK,eAAiB,GACf,IAGP8T,EAAI,OAAS9T,EAAa,WAEnB,KAAK,gBAAgB8T,CAAG,EAG/BA,EAAI,OAAS9T,EAAa,qBAE1B,KAAK,mBAAmB8T,EAAI,KAAM,0BAA0B,EACrD,IAGPA,EAAI,OAAS9T,EAAa,aAE1B,KAAK,mBAAmB8T,EAAI,KAAM,kBAAkB,EAC7C,IAGPA,EAAI,OAAS9T,EAAa,MAE1B,KAAK,mBAAmB8T,EAAI,KAAM,WAAW,EACtC,IAGPA,EAAI,OAAS9T,EAAa,MAE1B,KAAK,mBAAmB8T,EAAI,KAAM,WAAW,EACtC,IAGPA,EAAI,OAAS9T,EAAa,wBAE1B,KAAK,mBAAmB8T,EAAI,KAAM,6BAA6B,EACxD,IAGPA,EAAI,OAAS9T,EAAa,0BAE1B,KAAK,mBAAmB8T,EAAI,KAAM,+BAA+B,EAC1D,IAGPA,EAAI,OAAS9T,EAAa,2BAE1B,KAAK,mBAAmB8T,EAAI,KAAM,gCAAgC,EAC3D,IAGJ,EACX,CAMQ,WAAWA,EACnB,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,QAAQ,2BAA2B,EACjC,GAGX,KAAK,QAAQ,gBAAkB,KAAK,GAAG,GAAG,EAC1C,KAAK,cAAc,WAAW,EAE9B,KAAK,SAAW,IAAI9L,GAAiB8L,EAAI,IAAI,EAC7C,KAAK,aAAe,KAAK,SAAS,UAClC,KAAK,YAAc,KAAK,SAAS,YAgBjC,KAAK,UAAY,KAAK,IAAA,EACtB,KAAK,OAAS,KAAK,SAAS,eAE5B,KAAK,gBACD,KAAK,SAAS,iBACd,KAAK,SAAS,mBAAA,EAGd,KAAK,SAAS,gBAEd,KAAK,aAAA,EAIT,MAAMoB,EAAS,IAAIpO,EACnB,OAAAoO,EAAO,KAAOhV,GAAc,gBAC5BgV,EAAO,KAAOA,EAAO,WAAA,EACrB,KAAK,QAAQA,CAAM,EAEZ,EACX,CAMQ,mBAAmBpB,EAC3B,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,QAAQ,oCAAoC,EAC1C,GAIX,MAAMqB,EAAQ,IAAIhO,GAAiB2M,EAAI,IAAI,EAE3C,QAAS3P,EAAI,EAAGA,EAAIgR,EAAM,SAAS,OAAQhR,IAC3C,CACI,MAAMiR,EAAWD,EAAM,SAAShR,CAAC,EAC3BkR,EAA6B,CAC/B,IAAK,KAAK,GAAG,IACb,OAAQ,KACR,aAAc,KAAK,aACnB,KAAMD,EAAS,KACf,OAAQA,EAAS,EAAA,EAGrB,GAAIA,EAAS,OAASpU,EAAa,QAE3BoU,EAAS,KAAO,EAEhB,KAAK,SAAS,QAAU,KAAK,cACzBpU,EAAa,QACbqU,CAAA,EAKJ,KAAK,QACD,wDAAA,UAIHD,EAAS,OAASpU,EAAa,OACxC,CACI,MAAMsU,EAAa,KAAK,cACpBtU,EAAa,OACbqU,CAAA,EAEAC,GAAc,cAAeA,GAE7B,KAAK,SAAS,OAASA,EACvB,KAAK,SAAS,OAAO,UAAY,KAAK,WAEjCA,IAGL,KAAK,SAAS,OAASA,EAE/B,SACSF,EAAS,OAASpU,EAAa,OAEpC,KAAK,SAAS,OAAS,KAAK,cACxBA,EAAa,OACbqU,CAAA,UAGCD,EAAS,OAASpU,EAAa,SAEpC,KAAK,SAAS,SAAW,KAAK,cAC1BA,EAAa,SACbqU,CAAA,UAGCD,EAAS,OAASpU,EAAa,KACxC,CACI,MAAMuU,EAAO,KAAK,cACdvU,EAAa,KACbqU,CAAA,EAEAE,GAEA,KAAK,SAAS,MAAM,KAAKA,CAAI,CAErC,KAEA,CAEI,MAAMrO,EAAQ,IAAIwM,GAAU2B,CAAQ,EACpC,KAAK,SAAS,MAAM,KAAKnO,CAAK,EAC9B,KAAK,OAAO,gBAAkBA,EAAM,YAAA,EAAgB,kBAAkB,CAC1E,CACJ,CAEA,MAAO,EACX,CAMQ,cACJ7C,EACAsP,EAEJ,CACI,MAAM/Q,EAAUiS,GAAiB,IAAIxQ,CAAI,EACzC,OAAIzB,EAEO,IAAIA,EAAQ+Q,CAAO,GAI9B,KAAK,QACD,0CAA4CtP,EAC5C,8BAAA,EAEG,IAAIqP,GAAUC,CAAO,EAChC,CAMQ,mBAAmBG,EAC3B,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,QAAQ,iCAAiC,EACvC,GAGX,MAAMtL,EAAO,IAAIP,GAAsB6L,EAAI,IAAI,EAK/C,YAAK,gBAAgBtL,EAAK,YAAaA,EAAK,cAAc,EACnD,EACX,CAKQ,gBAAgBgN,EAAiBC,EACzC,CAGI,GAFA,KAAK,UAAYD,EAEbA,IAAYrU,GAAe,QAC1BsU,EAAYtU,GAAe,OAChC,CACI,MAAMuU,EAAc,IAAInN,GACpBpH,GAAe,MAAA,EAEbwU,EAAK,IAAI7O,EACf6O,EAAG,SAASzV,GAAc,mBAAoBwV,CAAW,EACzD,KAAK,QAAQC,CAAE,CACnB,CAEI,KAAK,SAAS,SAEd,KAAK,SAAS,OAAO,UAAYH,EAEzC,CAUA,cACA,CACI,KAAK,eAAiB,GAEtB,MAAMI,EAAa,IAAInN,GAAwB,KAAO,CAAC,EACjDkN,EAAK,IAAI7O,EACf6O,EAAG,SAASzV,GAAc,YAAa0V,CAAU,EACjD,KAAK,QAAQD,CAAE,EAEf,KAAK,0BAA0B,CAAC,EAE5B,KAAK,UAAY,QAEjB,KAAK,QAAA,CAEb,CAKA,0BAA0BE,EAC1B,CACI,MAAMvO,EAAO,IAAIsB,GACbiN,EACC,GAAKvT,EAAW,YAChB,GAAKA,EAAW,gBAChB,GAAKA,EAAW,MAChB,GAAKA,EAAW,oBAChB,GAAKA,EAAW,mBAAA,EAErB,KAAK,iBAAiBD,EAAW,sBAAuBiF,CAAI,CAChE,CAUA,sBAAsBwO,EACtB,CACI,GAAK,KAAK,eAUV,IALIA,GAEA,KAAK,cAAc,KAAKA,CAAO,EAG5B,KAAK,YAAc,GAAK,KAAK,cAAc,OAAS,GAC3D,CACI,MAAMH,EAAK,KAAK,cAAc,MAAA,EAC1BA,IAEA,KAAK,QAAQA,CAAE,EACf,KAAK,cAEb,CACJ,CAMA,iBAAiBtR,EAAcyR,EAC/B,CACI,MAAMpO,EAAY,IAAIiB,GAAuBtE,EAAMyR,CAAO,EACpDC,EAAU3T,GACZ,IAAI0E,EAAA,EAAgB,WAAA,EAClBnC,EAAO,IAAI,YAAY+C,EAAU,YAAY,EACnDA,EAAU,SAAS/C,CAAI,EAEvB,IAAIqR,EAAK,EACT,KAAOA,EAAKtO,EAAU,cACtB,CACI,MAAMuO,EAAK,KAAK,IAAID,EAAKD,EAASrO,EAAU,YAAY,EAClDiO,EAAK,IAAI7O,EACf6O,EAAG,KAAOzV,GAAc,WACxByV,EAAG,KAAOM,EAAKD,EACfL,EAAG,KAAOhR,EAAK,MAAMqR,EAAIC,CAAE,EAC3B,KAAK,sBAAsBN,CAAE,EAC7BK,EAAKC,CACT,CACJ,CAMQ,iBAAiBnC,EACzB,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,QAAQ,kCAAkC,EACxC,GAGX,MAAMoC,EAAS,IAAI/N,GAAwB2L,EAAI,IAAI,EACnD,KAAK,aAAeoC,EAAO,UAC3B,KAAK,sBAAA,EAGL,IAAIC,EAAkB,KAAK,YAC3B,KAAOA,EAAkB,GAAK,KAAK,kBAAkB,OAAS,GAC9D,CACI,MAAMC,EAAW,KAAK,kBAAkB,MAAA,EACpCA,IAEA,KAAK,aAAaA,EAAUA,EAAS,SAAS,EAC9CD,IAER,CAEA,MAAO,EACX,CAUQ,gBAAgBrC,EACxB,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,QAAQ,iCAAiC,EACvC,GAGX,MAAMpM,EAAY,IAAIQ,GAAsB4L,EAAI,IAAI,EAEpD,GAAIpM,EAAU,OAASrF,EAAW,sBAClC,CACI,GAAIqF,EAAU,KACd,CACI,MAAM2O,EAAe,IAAIzN,GACrBlB,EAAU,IAAA,EAEd,KAAK,UAAY,CAAC2O,EAAa,IAAI,EAC/BA,EAAa,SAEb,KAAK,0BAA0B,CAAC,CAExC,CACA,MAAO,EACX,CAEA,OAAI3O,EAAU,OAASrF,EAAW,kBAE1BqF,EAAU,MAEV,KAAK,qBACD,IAAIwB,GAA6BxB,EAAU,IAAI,CAAA,EAGhD,IAGPA,EAAU,OAASrF,EAAW,gBAE9B,KAAK,oBAAA,EACE,IAGPqF,EAAU,OAASrF,EAAW,WAE9B,KAAK,uBAAuBqF,CAAS,EAC9B,IAGPA,EAAU,OAASrF,EAAW,mBAE9B,KAAK,oBAAA,EACE,IAGPqF,EAAU,OAASrF,EAAW,iBAQtC,CAUA,cAAciU,EACd,CACI,MAAMC,EAAS,KAAK,iBACdC,EAAqB,CACvB,GAAID,EACJ,KAAAD,EACA,MAAO1B,GAAc,QACrB,UAAW,GACX,UAAW,CAAA,EAEf,KAAK,cAAc2B,CAAM,EAAIC,EAE7B,MAAMC,EAAY,IAAIpN,GAClBkN,EACAD,EAAK,KACLA,EAAK,IAAA,EAET,KAAK,iBAAiBjU,EAAW,gBAAiBoU,CAAS,CAC/D,CAMQ,qBACJC,EAEJ,CACI,MAAMN,EAAW,KAAK,cAAcM,EAAe,EAAE,EACrD,GAAI,CAACN,EAED,OAGJ,IAAIO,EAEJ,OAAQD,EAAe,OAAA,CAEnB,KAAKnU,GAAsB,cACvB6T,EAAS,MAAQxB,GAAc,aAC/B,KAAK,aAAawB,CAAQ,EAC1B,OACJ,KAAK7T,GAAsB,UACvBoU,EAAY,uCACZP,EAAS,MAAQxB,GAAc,UAC/B,MACJ,KAAKrS,GAAsB,MACvBoU,EAAY,0CACZP,EAAS,MAAQxB,GAAc,OAC/B,MACJ,KAAKrS,GAAsB,QACvB6T,EAAS,MAAQxB,GAAc,UAC/B,MACJ,QACI+B,EAAY,0BAA4BD,EAAe,OACvDN,EAAS,MAAQxB,GAAc,OAC/B,KAAA,CAGR,KAAK,kBAAkBwB,EAAUO,CAAS,CAC9C,CAMQ,aAAaC,EAA4BC,EACjD,CACI,MAAMC,EAAuB,GAAK1U,GAElC,GAAI,CAACwU,GACD,CAAC,KAAK,cAAcA,EAAa,EAAE,GAClCC,IAAc,QAAaA,EAAY,GACvCA,IAAcD,EAAa,KAAK,KAEjC,OAGJ,GAAIA,EAAa,UACjB,CACI,MAAMG,EAAa,IAAI7N,GACnB0N,EAAa,GACbrU,GAAsB,SAAA,EAE1B,KAAK,iBACDF,EAAW,iBACX0U,CAAA,EAEJH,EAAa,MAAQhC,GAAc,UACnC,OAAO,KAAK,cAAcgC,EAAa,EAAE,EACzC,MACJ,CAEA,MAAMZ,EAAKa,GAAa,EAClBZ,EAAK,KAAK,IACZD,EAAKc,EACLF,EAAa,KAAK,IAAA,EAGtB,GAAI,CAAC,KAAK,YACV,CACIA,EAAa,UAAYZ,EACzB,KAAK,kBAAkB,KAAKY,CAAY,EACxC,MACJ,CAEA,MAAMI,EAAS,IAAI,WACnBA,EAAO,OAAUrJ,GACjB,OACI,MAAMvE,GAAS6N,EAAAtJ,EAAE,SAAF,YAAAsJ,EAAU,OACzB,GAAI,EAAE7N,aAAkB,aAEpB,OAGJ,MAAM8N,EAAW,IAAIzN,GACjBmN,EAAa,GACbxN,EAAO,WACPA,CAAA,EAEJ,KAAK,iBACD/G,EAAW,eACX6U,CAAA,EAEJ,KAAK,aAAaN,EAAcX,CAAE,EAG9B,KAAK,oBAEL,KAAK,mBACDW,EAAa,GACbX,EACAW,EAAa,KAAK,KAClBA,EAAa,KAAK,IAAA,CAG9B,EAEA,MAAMO,EAAQP,EAAa,KAAK,MAAMZ,EAAIC,CAAE,EAC5Ce,EAAO,kBAAkBG,CAAK,CAClC,CAMQ,kBACJP,EACAQ,EAEJ,CACQA,GAEA,KAAK,OAAOA,CAAK,EACjBR,EAAa,MAAQhC,GAAc,SAInC,KAAK,QACD,gBAAkBgC,EAAa,KAAK,KACpC,kBAAA,EAEJA,EAAa,MAAQhC,GAAc,WAInC,KAAK,oBAEL,KAAK,mBACDgC,EAAa,GACbA,EAAa,KAAK,KAClBQ,CAAA,EAIR,OAAO,KAAK,cAAcR,EAAa,EAAE,CAC7C,CAMA,eAAeL,EACf,CACI,MAAMC,EAAO,KAAK,cAAcD,CAAM,EAClCC,IAEAA,EAAK,UAAY,GACjBA,EAAK,MAAQ5B,GAAc,UAEnC,CAUQ,qBACR,CAGI,MAAMyC,EAAgB7U,GAAiB,UACjC8U,EAAmB,IAAI3P,GACzB0P,EACA,KAAK,SAAA,EAET,KAAK,iBACDhV,EAAW,kBACXiV,CAAA,CAER,CAMQ,uBACJ5P,EAEJ,CAGI,GAAI,CAACA,EAAU,KAEX,OAGJ,MAAM6P,EAAoB,IAAI9P,GAC1B,CAAE,KAAMC,EAAU,IAAA,EAClB,KAAK,SAAA,EAGT,GAAI6P,EAAkB,OAAS/U,GAAiB,UAChD,CACI,MAAMqF,EAAO0P,EAAkB,QAAA,EAG3B,KAAK,aAEL,KAAK,YAAY1P,CAAI,EAIrB,OAAO,UAAc,KACrB,UAAU,WACV,UAAU,UAAU,WAEpB,UAAU,UAAU,UAAUA,CAAI,EAAE,MAC/B+L,GACD,CACI,QAAQ,KACJ,0CACAA,CAAA,CAER,CAAA,CAGZ,MAGI,QAAQ,IACJ,8BACA2D,EAAkB,IAAA,CAG9B,CAMQ,qBACR,CAGQ,OAAO,UAAc,KACrB,UAAU,WACV,UAAU,UAAU,UAEpB,UAAU,UAAU,WAAW,KAC1B1P,GACD,CACI,MAAMwP,EAAgB7U,GAAiB,UACjCgV,EAAe,IAAI5P,GACrByP,EACAxP,EACA,KAAK,SAAA,EAET,KAAK,iBACDxF,EAAW,UACXmV,CAAA,CAER,CAAA,EACF,MACG5D,GACD,CACI,QAAQ,IAAI,4BAA6BA,CAAG,CAChD,CAAA,CAGZ,CAMA,mBACA,CAKI,MAAMyD,EAAgB7U,GAAiB,UACjCiV,EAAc,IAAIjQ,GACpB6P,EACA,KAAK,SAAA,EAET,KAAK,iBACDhV,EAAW,eACXoV,CAAA,CAER,CASA,aACI7S,EACAN,EACAC,EACAwE,EACAC,EACAC,EAEJ,CACI,MAAMyO,EAAiB,IAAI5O,GACvBlE,EACAN,EACAC,EACAwE,EACAC,EACAC,CAAA,EAEJ,KAAK,iBAAiB5G,EAAW,gBAAiBqV,CAAc,CACpE,CAUA,aACA,CACI,OAAQ,KAAK,IAAA,EAAQ,KAAK,UAAa,KAAK,MAChD,CASA,MACA,CACI,KAAK,MAAQjE,EAAgB,QAEzB,KAAK,SAAS,SAEd,KAAK,SAAS,OAAO,QAAA,EACrB,KAAK,SAAS,OAAS,QAGvB,KAAK,SAAS,SAEd,KAAK,SAAS,OAAO,QAAA,EACrB,KAAK,SAAS,OAAS,QAGvB,KAAK,SAAS,UAEd,KAAK,SAAS,QAAQ,QAAA,EACtB,KAAK,SAAS,QAAU,QAGxB,KAAK,SAAS,WAEd,KAAK,SAAS,SAAS,QAAA,EACvB,KAAK,SAAS,SAAW,QAG7B,UAAW8B,KAAQ,KAAK,SAAS,MAE7BA,EAAK,QAAA,EAET,KAAK,SAAS,MAAQ,CAAA,EAEtB,KAAK,QAAA,EAEL,UAAWrO,KAAS,KAAK,SAAS,MAE9BA,EAAM,QAAA,EAEV,KAAK,SAAS,MAAQ,CAAA,CAC1B,CACJ,CCvoCA,MAAMyQ,GAAe,kBAad,MAAMC,EACb,CAgBI,YAAYtO,EAAYgN,EACxB,CATA,KAAA,UAAY,GAGZ,KAAQ,qBAAmD,OAG3D,KAAQ,YAA+C,OAInD,KAAK,GAAKhN,EACV,KAAK,KAAOgN,CAChB,CAWA,kBAAkBuB,EAAqBF,GACvC,CACI,GAAI,OAAO,SAAa,IAEpB,OAGJ,MAAMG,EAAW,SAAS,eAAeD,CAAU,EACnD,GAAI,CAACC,EAED,OAGJ,MAAMC,EAAS,SAAS,cAAc,OAAO,EAC7C,KAAK,qBAAuB,SAAS,cAAc,KAAK,EACxD,KAAK,YAAc,SAAS,cAAc,UAAU,EAEpDA,EAAO,KAAO,SACdA,EAAO,MAAQ,SACfA,EAAO,MAAM,SAAW,QACxBA,EAAO,QAAU,IACjB,CACI,KAAK,UAAY,GACjB,KAAK,kBAAA,CACT,EAEA,KAAK,YAAY,aAAa,MAAO,OAAO,KAAK,KAAK,IAAI,CAAC,EAC3D,KAAK,YAAY,aAAa,QAAS,GAAG,EAC1C,KAAK,YAAY,MAAM,MAAQ,OAC/B,KAAK,YAAY,MAAM,OAAS,WAChC,KAAK,YAAY,MAAM,QAAU,eAEjC,KAAK,qBAAqB,MAAM,MAAQ,MACxC,KAAK,qBAAqB,MAAM,OAAS,OACzC,KAAK,qBAAqB,MAAM,QAAU,MAC1C,KAAK,qBAAqB,YAAc,KAAK,KAAK,KAElD,KAAK,qBAAqB,YAAYA,CAAM,EAC5C,KAAK,qBAAqB,YAAY,KAAK,WAAW,EAEtDD,EAAS,YAAY,KAAK,oBAAoB,CAClD,CAOA,kBAAkBE,EAClB,CACQ,KAAK,aAEL,KAAK,YAAY,aAAa,QAAS,OAAOA,CAAK,CAAC,CAE5D,CAKA,mBACA,CACQ,KAAK,sBAAwB,KAAK,qBAAqB,YAEvD,KAAK,qBAAqB,WAAW,YAAY,KAAK,oBAAoB,EAE9E,KAAK,qBAAuB,OAC5B,KAAK,YAAc,MACvB,CACJ,CAmBO,SAASC,GAAmBtK,EACnC,CACIA,EAAE,gBAAA,EACFA,EAAE,eAAA,EACEA,EAAE,eAEFA,EAAE,aAAa,WAAa,OAEpC,CASO,SAASuK,GAAevK,EAAcwK,EAC7C,CAII,GAHAxK,EAAE,gBAAA,EACFA,EAAE,eAAA,EAEE,CAACA,EAAE,aAEH,OAGJ,MAAMyK,EAAQzK,EAAE,aAAa,MAC7B,QAASxJ,EAAIiU,EAAM,OAAS,EAAGjU,GAAK,EAAGA,IACvC,CACI,MAAMmS,EAAO8B,EAAMjU,CAAC,EAChBmS,GAAQA,EAAK,MAEb6B,EAAW,cAAc7B,CAAI,CAErC,CACJ,CCnJA,MAAM+B,GAAqB,IAGrBC,GAAsB,EAGtBC,GAAgB,GAef,SAASC,GAAaL,EAC7B,CAMI,GALI,OAAO,SAAa,KAAe,OAAO,OAAW,KAKrD,CAACA,EAAW,SAEZ,OAGJ,MAAMM,EAAW,SAAS,eAAeN,EAAW,QAAQ,EAC5D,GAAI,CAACM,EAED,OAGJ,IAAIC,EAAID,EAAS,YACb/K,EAAI,OAAO,YAAc6K,GAG7B,GAAIJ,EAAW,UACf,CACI,MAAMlL,EAAI,SAAS,eAAekL,EAAW,SAAS,EACtD,GAAIlL,IAAM,KAEN,GAAI,OAAO,iBAAiBA,CAAC,EAAE,iBAAiB,SAAS,IAAM,OAC/D,CAEI,MAAM0L,EAAK,SACP,OAAO,iBAAiB1L,CAAC,EAAE,iBAAiB,QAAQ,EACpD,EAAA,EAEC,MAAM0L,CAAE,IAETjL,EAAIA,EAAIiL,EAEhB,MAIIjL,EAAIA,EAAIT,EAAE,aAAeA,EAAE,YAGvC,CAGIS,EAAI4K,GAAsB,IAE1B5K,GAAMA,EAAI4K,IAGVI,EAAIJ,GAAsB,IAE1BI,GAAMA,EAAIJ,IAGdH,EAAW,aAAa,EAAGO,EAAGhL,EAAG,GAAI,EAAG,CAAC,CAC7C,CAaO,MAAMkL,EACb,CASI,YAAYT,EAAiCU,EAAqBR,GAClE,CARA,KAAQ,YAAyD,OAiBjE,KAAA,aAAe,IACf,CACQ,KAAK,cAAgB,SAErB,aAAa,KAAK,WAAW,EAC7B,KAAK,YAAc,QAGvB,KAAK,YAAc,WAAW,IAC9B,CACIG,GAAa,KAAK,UAAU,EAC5B,KAAK,YAAc,MACvB,EAAG,KAAK,UAAU,CACtB,EArBI,KAAK,WAAaL,EAClB,KAAK,WAAaU,CACtB,CAwBA,SACA,CACQ,KAAK,cAAgB,SAErB,aAAa,KAAK,WAAW,EAC7B,KAAK,YAAc,OAE3B,CACJ,CAiBO,SAASC,GACZpE,EACAyD,EACAU,EAAqBR,GAEzB,CACI,GAAI,OAAO,eAAmB,IAE1B,OAGJ,MAAMU,EAAU,IAAIH,GAAmBT,EAAYU,CAAU,EAEvDG,EAAW,IAAI,eAAe,IACpC,CACID,EAAQ,aAAA,CACZ,CAAC,EAED,OAAAC,EAAS,QAAQtE,CAAS,EAEnB,IACP,CACIsE,EAAS,WAAA,EACTD,EAAQ,QAAA,CACZ,CACJ,CC5FA,SAASE,GAASC,EAClB,CAEI,IAAIC,EAAM,GADKD,EAAK,QAAU,IACX,MAAMA,EAAK,IAAI,IAAIA,EAAK,IAAI,GAC/C,OAAIA,EAAK,OAELC,GAAOD,EAAK,KAAK,WAAW,GAAG,EAAIA,EAAK,KAAO,IAAIA,EAAK,IAAI,IAEzDC,CACX,CAEA,SAASC,GAAeC,EACxB,CACI,GAAI,OAAO,SAAa,IAAa,OACrC,MAAMC,MAAW,KACjBA,EAAK,QAAQA,EAAK,QAAA,EAAY,GAAK,GAAK,GAAK,GAAI,EACjD,SAAS,OAAS,SAASD,CAAK,aAAaC,EAAK,aAAa,UACnE,CAoBO,MAAMC,GAAeC,EAAAA,WACxB,SAAsBC,EAAOC,EAC7B,CACI,KAAM,CACF,WAAYC,EACZ,QAASC,EACT,SAAAC,EACA,MAAOC,EACP,UAAAC,EACA,MAAAC,EACA,UAAAC,EACA,aAAAC,EACA,QAAAC,EACA,SAAAC,EACA,YAAAC,EACA,uBAAAC,EACA,uBAAAC,EACA,WAAAC,CAAA,EACAf,EAGEgB,EAAeC,EAAAA,OAAuB,IAAI,EAC1CC,EAAYD,EAAAA,OAAuB,IAAI,EACvCE,EAAUF,EAAAA,OAA6B,IAAI,EAC3CG,GAAaH,EAAAA,OAA4B,IAAI,EAG7CI,GAAeJ,EAAAA,OAAO,CACxB,UAAAT,EACA,aAAAC,EACA,QAAAC,EACA,SAAAC,EACA,YAAAC,EACA,uBAAAC,EACA,uBAAAC,EACA,WAAAC,CAAA,CACH,EACDM,GAAa,QAAU,CACnB,UAAAb,EACA,aAAAC,EACA,QAAAC,EACA,SAAAC,EACA,YAAAC,EACA,uBAAAC,EACA,uBAAAC,EACA,WAAAC,CAAA,EAIJ,MAAMO,IAAiBlB,GAAA,YAAAA,EAAU,iBAAkB,GAC7CmB,IAAcnB,GAAA,YAAAA,EAAU,cAAe,GACvCoB,GAAkBpB,GAAA,YAAAA,EAAU,kBAAmB,GAC/CqB,GAAqBrB,GAAA,YAAAA,EAAU,qBAAsB,GACrDsB,GAAevB,GAAA,YAAAA,EAAc,eAAgB,GAG7C,CAACwB,CAAQ,EAAIC,EAAAA,SAAS,IAAM,gBAAgB,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,EAAG,CAAC,CAAC,EAAE,EAMpFC,GAAaC,EAAAA,YAAY,IAC/B,SACQV,GAAW,UAEXA,GAAW,QAAA,EACXA,GAAW,QAAU,MAErBD,EAAQ,UAERA,EAAQ,QAAQ,KAAA,EAChBA,EAAQ,QAAU,OAEtBY,GAAAvE,EAAA6D,GAAa,SAAQ,eAArB,MAAAU,EAAA,KAAAvE,EACJ,EAAG,CAAA,CAAE,EAECwE,EAAUF,EAAAA,YAAY,IAC5B,OAEI,GAAI,OAAO,SAAa,IAAa,OAGrCD,GAAA,EAGI3B,EAAU,OAEVP,GAAeO,EAAU,KAAK,EAGlC,MAAMR,EAAMF,GAASU,CAAS,EACxB+B,EAAMZ,GAAa,QAEnBnH,GAA4B,CAC9B,IAAAwF,EACA,SAAAiC,EACA,SAAUzB,EAAU,UAAY,GAChC,QAAUhM,GACV,UACI6N,GAAAvE,EAAA6D,GAAa,SAAQ,UAArB,MAAAU,EAAA,KAAAvE,EAA+BtJ,EACnC,EACA,UAAW,IACX,UACI6N,GAAAvE,EAAA6D,GAAa,SAAQ,YAArB,MAAAU,EAAA,KAAAvE,EACJ,EACA,QAAS,IACT,CACI,MAAM0E,EAAKf,EAAQ,QACnB,GAAI,CAACe,EAAI,OAGLb,GAAa,QAAQ,cAErBa,EAAG,YAAe9T,GAAA,SACd,OAAA2T,GAAAvE,EAAA6D,GAAa,SAAQ,cAArB,YAAAU,EAAA,KAAAvE,EAAmCpP,KAE3C8T,EAAG,mBAAqB,CAACpF,EAAQqF,EAAOC,EAAOC,IAAA,WAC3C,OAAAN,IAAAvE,GAAA6D,GAAa,SAAQ,yBAArB,YAAAU,GAAA,KAAAvE,GAA8CV,EAAQqF,EAAOC,EAAOC,IACxEH,EAAG,mBAAqB,CAACpF,EAAQuF,EAAU1E,IAAA,UACvC,OAAAoE,IAAAvE,EAAA6D,GAAa,SAAQ,yBAArB,YAAAU,GAAA,KAAAvE,EAA8CV,EAAQuF,EAAU1E,IAGpE,MAAM2E,EAAUJ,EAAG,SAAS,QAa5B,GAZII,IAEAA,EAAQ,UAAY,CAACC,EAAW1X,EAAOC,EAAQ0X,IAC/C,WACQA,KAEAT,IAAAvE,GAAA6D,GAAa,SAAQ,WAArB,MAAAU,GAAA,KAAAvE,GAAgC3S,EAAOC,GAE/C,GAIA4W,GAAgBV,EAAa,QACjC,CACIjC,GAAamD,CAAE,EACf,MAAMO,EAAkBpD,GACpB2B,EAAa,QACbkB,CAAA,EAEJ,GAAIO,EACJ,CACI,MAAMC,EAActB,GAAW,QAC/BA,GAAW,QAAU,IACrB,CACIqB,EAAA,EACAC,GAAA,MAAAA,GACJ,CACJ,CACJ,CAGA,GAAIjB,GAAsBT,EAAa,QACvC,CACI,MAAM/F,EAAY+F,EAAa,QACzB2B,EAAezO,IACjBsK,GAAmBtK,EAAc,EAC/B0O,EAAe1O,IACjBuK,GAAevK,GAAgBgO,CAAE,EACrCjH,EAAU,iBAAiB,WAAY0H,EAAa,EAAK,EACzD1H,EAAU,iBAAiB,OAAQ2H,EAAa,EAAK,EAErD,MAAMF,EAActB,GAAW,QAC/BA,GAAW,QAAU,IACrB,CACInG,EAAU,oBAAoB,WAAY0H,EAAa,EAAK,EAC5D1H,EAAU,oBAAoB,OAAQ2H,EAAa,EAAK,EACxDF,GAAA,MAAAA,GACJ,CACJ,CAGA,GAAIrB,GAAa,QAAQ,WAErB,UAAWvF,KAAQoG,EAAG,SAAS,MAC/B,CACI,MAAMW,EAAW/G,EACjB+G,EAAS,WAAa,CAAC/S,EAAM5E,IAAA,WACzB,OAAA6W,IAAAvE,GAAA6D,GAAa,SAAQ,aAArB,YAAAU,GAAA,KAAAvE,GAAkC1N,EAAM5E,GAChD,CAER,CAAA,EAGJ,GACA,CACIiW,EAAQ,QAAU,IAAI5F,GAAcrB,EAAO,CAC/C,OACOhG,EACP,CACI,MAAMiG,EAAMjG,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,GACxDsJ,EAAAyE,EAAI,UAAJ,MAAAzE,EAAA,KAAAyE,EAAc9H,EAClB,CACJ,EAAG,CAAC+F,EAAU,KAAMA,EAAU,KAAMA,EAAU,SAAUA,EAAU,MAC9DA,EAAU,OAAQA,EAAU,KAAMyB,EAAUE,GAC5CJ,EAAoBC,EAAcF,CAAA,CAAgB,EAEtDsB,OAAAA,EAAAA,oBAAoB7C,EAAK,KAAO,CAC5B,eAAgB,IAChB,CACI,MAAMiC,EAAKf,EAAQ,QACnB,GAAI,CAACe,EAAI,OACT,MAAMa,EAASb,EAAG,SAAS,OAC3Ba,GAAA,MAAAA,EAAQ,gBACZ,EACA,WAAAlB,GACA,UAAWG,EACX,cAAe,IAAMb,EAAQ,OAAA,GAC7B,CAACU,GAAYG,CAAO,CAAC,EAMzBgB,EAAAA,UAAU,IACV,CACI,MAAMhE,EAAWkC,EAAU,QAC3B,GAAI,CAAClC,EAAU,OAEf,MAAMiE,EAAY,IAClB,CACI,MAAMf,EAAKf,EAAQ,QACnB,GAAKe,EACL,OAAOA,EAAG,SAAS,MACvB,EAEMgB,GAA2C,CAAA,EAEjD,GAAI5B,GACJ,CACI,MAAM6B,EAAajP,GACnB,CACI,MAAM6O,EAASE,EAAA,EACfF,GAAA,MAAAA,EAAQ,cAAc7O,EAC1B,EACMkP,EAAWlP,GACjB,CACI,MAAM6O,EAASE,EAAA,EACfF,GAAA,MAAAA,EAAQ,YAAY7O,EACxB,EACAgP,GAAS,KAAK,CAAC,UAAWC,CAAS,EAAG,CAAC,QAASC,CAAO,CAAC,CAC5D,CAEA,GAAI7B,GACJ,CACI,MAAM8B,EAAenP,GACrB,CACI,MAAM6O,EAASE,EAAA,EACfF,GAAA,MAAAA,EAAQ,gBAAgB7O,EAC5B,EACMoP,EAAepP,GACrB,CACI,MAAM6O,EAASE,EAAA,EACfF,GAAA,MAAAA,EAAQ,gBAAgB7O,EAC5B,EACMqP,EAAarP,GACnB,CACI,MAAM6O,EAASE,EAAA,EACfF,GAAA,MAAAA,EAAQ,cAAc7O,EAC1B,EACMsP,EAAWtP,GACjB,CACI,MAAM6O,EAASE,EAAA,EACfF,GAAA,MAAAA,EAAQ,iBAAiB7O,EAC7B,EACMuP,EAAiBvP,GACvB,CACI,MAAM6O,EAASE,EAAA,EACfF,GAAA,MAAAA,EAAQ,kBAAkB7O,EAC9B,EACAgP,GAAS,KACL,CAAC,YAAaG,CAAW,EACzB,CAAC,YAAaC,CAAW,EACzB,CAAC,UAAWC,CAAS,EACrB,CAAC,QAASC,CAAO,EACjB,CAAC,cAAeC,CAAa,CAAA,CAErC,CAEA,SAAW,CAACC,EAAOpE,CAAO,IAAK4D,GAE3BlE,EAAS,iBAAiB0E,EAAOpE,CAAO,EAG5C,MAAO,IACP,CACI,SAAW,CAACoE,EAAOpE,CAAO,IAAK4D,GAE3BlE,EAAS,oBAAoB0E,EAAOpE,CAAO,CAEnD,CACJ,EAAG,CAACgC,GAAgBC,EAAW,CAAC,EAMhCyB,EAAAA,UAAU,KAENhB,EAAA,EACO,IACP,CACIH,GAAA,CACJ,GACD,CAACG,EAASH,EAAU,CAAC,EAOpB8B,GAAAA,IAAC,MAAA,CACG,IAAK3C,EACL,UAAAV,EACA,MAAO,CACH,SAAU,WACV,SAAU,SACV,GAAGC,CAAA,EAGP,SAAAoD,GAAAA,IAAC,MAAA,CACG,IAAKzC,EACL,GAAIS,EACJ,SAAU,EACV,MAAO,CACH,QAAS,OACT,MAAO,OACP,OAAQ,MAAA,CACZ,CAAA,CACJ,CAAA,CAGZ,CACJ,EAEA7B,GAAa,YAAc,eCzX3B,MAAM8D,GAAM,OAAO,SAAa,IAwBzB,SAASC,GAAS3J,EACzB,CACI,KAAM,CAAC4J,EAAQC,CAAS,EAAInC,EAAAA,SAAsB,cAAc,EAC1D,CAACjE,EAAOqG,CAAQ,EAAIpC,EAAAA,SAAuB,IAAI,EAC/C,CAACqC,EAAYC,CAAa,EAAItC,EAAAA,SAAiC,IAAI,EACnE,CAACuC,EAAUC,CAAW,EAAIxC,EAAAA,SAAS,CAAC,EAEpCT,EAAUF,EAAAA,OAA6B,IAAI,EAG3CI,EAAeJ,EAAAA,OAAO/G,GAAA,YAAAA,EAAS,SAAS,EAC9CmH,EAAa,QAAUnH,GAAA,YAAAA,EAAS,UAEhC,MAAMmK,EAAYnK,GAAA,YAAAA,EAAS,UAMrB2H,EAAaC,EAAAA,YAAY,IAC/B,SACQX,EAAQ,UAERA,EAAQ,QAAQ,KAAA,EAChBA,EAAQ,QAAU,MAEtB4C,EAAU,cAAc,EACxBG,EAAc,IAAI,EAClBE,EAAY,CAAC,GACbrC,GAAAvE,EAAA6D,EAAa,UAAb,YAAA7D,EAAsB,eAAtB,MAAAuE,EAAA,KAAAvE,EACJ,EAAG,CAAA,CAAE,EAEC8G,EAAYxC,cAAayC,GAC/B,UACI,GAAIX,GAAK,OAGT/B,EAAA,EAEAkC,EAAU,YAAY,EACtBC,EAAS,IAAI,EAGb,IAAIrC,EAAW4C,EAAO,SAClB,CAAC5C,IAAY0C,GAAA,MAAAA,EAAW,WAGnBA,EAAU,QAAQ,KAEnBA,EAAU,QAAQ,GAAK,gBAAgB,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,EAAG,CAAC,CAAC,IAEjF1C,EAAW0C,EAAU,QAAQ,IAGjC,MAAMG,EAA8B,CAChC,IAAKD,EAAO,IACZ,SAAA5C,EACA,OAAQ4C,EAAO,OACf,UAAWA,EAAO,UAClB,SAAUA,EAAO,UAAY,GAC7B,QAAUrQ,GACV,SACI6P,EAAU,OAAO,EACjBC,EAAS9P,CAAC,GACV6N,GAAAvE,EAAA6D,EAAa,UAAb,YAAA7D,EAAsB,UAAtB,MAAAuE,EAAA,KAAAvE,EAAgCtJ,EACpC,EACA,UAAW,IACX,SACI6P,EAAU,WAAW,GACrBhC,GAAAvE,EAAA6D,EAAa,UAAb,YAAA7D,EAAsB,YAAtB,MAAAuE,EAAA,KAAAvE,EACJ,EACA,QAAS,IACT,OACI,MAAM0E,EAAKf,EAAQ,QACnB,GAAI,CAACe,EAAI,QAGL1E,EAAA6D,EAAa,UAAb,MAAA7D,EAAsB,cAEtB0E,EAAG,YAAe9T,IAAA,SACd,OAAA2T,GAAAvE,EAAA6D,EAAa,UAAb,YAAA7D,EAAsB,cAAtB,YAAAuE,EAAA,KAAAvE,EAAoCpP,MAI5C8T,EAAG,mBAAqB,CAACpF,GAAQqF,EAAOC,EAAOC,IAAA,SAC3C,OAAAN,GAAAvE,EAAA6D,EAAa,UAAb,YAAA7D,EAAsB,yBAAtB,YAAAuE,EAAA,KAAAvE,EAA+CV,GAAQqF,EAAOC,EAAOC,IACzEH,EAAG,mBAAqB,CAACpF,GAAQuF,EAAUlI,IAAA,SACvC,OAAA4H,GAAAvE,EAAA6D,EAAa,UAAb,YAAA7D,EAAsB,yBAAtB,YAAAuE,EAAA,KAAAvE,EAA+CV,GAAQuF,EAAUlI,IAGrE,MAAMmI,EAAUJ,EAAG,SAAS,QACxBI,IAEAA,EAAQ,UAAY,CAACmC,GAAY5Z,EAAOC,EAAQ0X,IAChD,SAEI,MAAMkC,EAAe,OAAO,KAAKpC,EAAQ,QAAQ,EAAE,OAGnD,GAFA8B,EAAYM,CAAY,EAEpBlC,EACJ,CAEI,MAAMmC,EAAUrC,EAAQ,kBAAA,EACpBqC,GAEAT,EAAc,CAAE,MAAOS,EAAQ,MAAO,OAAQA,EAAQ,OAAQ,GAElE5C,GAAAvE,EAAA6D,EAAa,UAAb,YAAA7D,EAAsB,WAAtB,MAAAuE,EAAA,KAAAvE,EAAiC3S,EAAOC,EAC5C,KAEA,CAEI,MAAM6Z,EAAUrC,EAAQ,kBAAA,EAGpB4B,EAFAS,EAEc,CAAE,MAAOA,EAAQ,MAAO,OAAQA,EAAQ,QAIxC,IAJgD,CAMtE,CACJ,EAER,CAAA,EAGJ,GACA,CACIxD,EAAQ,QAAU,IAAI5F,GAAciJ,CAAS,CACjD,OACOtQ,EACP,CACI,MAAMiG,EAAMjG,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,EACxD6P,EAAU,OAAO,EACjBC,EAAS7J,CAAG,GACZ4H,IAAAvE,EAAA6D,EAAa,UAAb,YAAA7D,EAAsB,UAAtB,MAAAuE,GAAA,KAAAvE,EAAgCrD,EACpC,CACJ,EAAG,CAAC0H,EAAYwC,CAAS,CAAC,EAMpBpB,EAAYnB,EAAAA,YAAY,IAC9B,CACI,MAAMI,EAAKf,EAAQ,QACnB,GAAKe,EACL,OAAOA,EAAG,SAAS,MACvB,EAAG,CAAA,CAAE,EAEC0C,EAAc9C,cAAazO,GACjC,CACI,MAAM0P,EAASE,EAAA,EACf,GAAI,CAACF,EAAQ,OACb,MAAM1I,EAAM,IAAIhN,EACVgB,EAAU,IAAImD,GAAiB6B,CAAQ,EAC7CgH,EAAI,SAASxT,EAAgB,SAAUwH,CAAO,EAC9C0U,EAAO,QAAQ1I,CAAG,CACtB,EAAG,CAAC4I,CAAS,CAAC,EAER4B,EAAY/C,cAAazO,GAC/B,CACI,MAAM0P,EAASE,EAAA,EACf,GAAI,CAACF,EAAQ,OACb,MAAM1I,EAAM,IAAIhN,EACVgB,EAAU,IAAIqD,GAAe2B,CAAQ,EAC3CgH,EAAI,SAASxT,EAAgB,OAAQwH,CAAO,EAC5C0U,EAAO,QAAQ1I,CAAG,CACtB,EAAG,CAAC4I,CAAS,CAAC,EAER6B,EAAgBhD,EAAAA,YAAY,CAACvS,EAAWC,IAC9C,CACI,MAAMuT,EAASE,EAAA,EACf,GAAI,CAACF,EAAQ,OACb,MAAM1I,EAAM,IAAIhN,EACVgB,GAAU,IAAI4C,GAAuB1B,EAAGC,EAAGuT,EAAO,YAAa,CAAC,EACtE1I,EAAI,SAASxT,EAAgB,eAAgBwH,EAAO,EACpD0U,EAAO,QAAQ1I,CAAG,CACtB,EAAG,CAAC4I,CAAS,CAAC,EAER8B,EAAkBjD,EAAAA,YAAY,CAACxQ,EAAgB0T,IACrD,CACI,MAAMjC,EAASE,EAAA,EACf,GAAI,CAACF,EAAQ,OACb,MAAM1I,EAAM,IAAIhN,EAChB,GAAI2X,EACJ,CACI,MAAM3W,GAAU,IAAIgD,GAAoBC,EAAQyR,EAAO,WAAW,EAClE1I,EAAI,SAASxT,EAAgB,YAAawH,EAAO,CACrD,KAEA,CACI,MAAMA,GAAU,IAAIkD,GAAsBD,EAAQyR,EAAO,WAAW,EACpE1I,EAAI,SAASxT,EAAgB,cAAewH,EAAO,CACvD,CACA0U,EAAO,QAAQ1I,CAAG,CACtB,EAAG,CAAC4I,CAAS,CAAC,EAERgC,EAAgBnD,cAAaoD,GACnC,CACI,MAAMhD,EAAKf,EAAQ,QACde,GAELA,EAAG,kBAAA,CACP,EAAG,CAAA,CAAE,EAECiD,GAAmBrD,EAAAA,YAAY,CAACjX,EAAeC,IACrD,CACI,MAAMoX,EAAKf,EAAQ,QACde,GACLA,EAAG,aAAa,EAAGrX,EAAOC,EAAQ,GAAI,EAAG,CAAC,CAC9C,EAAG,CAAA,CAAE,EAECsa,GAAiBtD,EAAAA,YAAY,IACnC,CACI,MAAMiB,EAASE,EAAA,EACfF,GAAA,MAAAA,EAAQ,gBACZ,EAAG,CAACE,CAAS,CAAC,EAERoC,GAAgBvD,EAAAA,YAAY,IAAMX,EAAQ,QAAS,CAAA,CAAE,EAM3D6B,OAAAA,EAAAA,UAAU,IAEC,IACP,CACQ7B,EAAQ,UAERA,EAAQ,QAAQ,KAAA,EAChBA,EAAQ,QAAU,KAE1B,EACD,CAAA,CAAE,EAmBE,CACH,OAAA2C,EACA,MAAAnG,EACA,WAAAsG,EACA,SAAAE,EACA,SAlB4B,CAC5B,QAASG,EACT,WAAAzC,EACA,YAAA+C,EACA,UAAAC,EACA,cAAAC,EACA,gBAAAC,EACA,cAAAE,EACA,cAAeE,GACf,eAAAC,GACA,cAAAC,EAAA,CAQA,CAER,CC/YO,MAAMC,EAAgB,CACzB,QAAS,EACT,KAAM,EACN,MAAO,EACP,MAAO,EACP,MAAO,EACP,KAAM,CACV,EAQMC,GAAU,EACVC,GAAY,EACZC,GAAa,KACbC,GAAa,GACbC,GAAeJ,GACfK,GAAiBJ,GACjBK,GAAkBJ,GAMlBK,EAAkB,EAClBC,GAAgB,EAChBC,GAAgB,EAChBC,GAAgB,EAChBC,EAAmB,EAezB,SAASC,IAA2B,CAChC,MAAO,CACH,aAAc,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,CAAC,EACrC,WAAY,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,CAAC,EACnC,gBAAiB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,CAAC,EACxC,eAAgB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,CAAC,EACvC,QAAS,CAAA,EACT,QAAS,CAAA,CAAC,CAElB,CAEA,MAAMC,GAA0BD,GAAA,EAC1BE,EAA0BF,GAAA,EAM1BG,GAAoB,CACtB,EACA,EAAY,EAAY,EAAY,GACpC,GAAY,GAAY,IAAY,IACpC,IAAY,KAAY,KAAY,KACpC,KAAY,MAAY,MAAY,MACpC,OAAY,OAAY,OAAY,QACpC,QAAY,QAAY,QAAY,SACpC,SAAY,SAAY,UAAY,UACpC,UAAY,WAAY,WAAY,UACxC,EAEMC,GAAoB,CAAA,EAEpBC,GAA0B,CAC5B,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EACtD,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EACtD,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,CAC1D,EAEMC,GAAc,CAChB,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAC/D,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,EACpC,EAEMC,GAAoB,CACtB,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACxE,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACxE,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACxE,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACxE,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACxE,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACxE,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACxE,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACxE,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACxE,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACxE,EAAG,EAAG,EAAG,EAAG,EAAG,CACnB,EAEMC,GAA0B,CAC5B,SAAY,UAAY,UAAY,WAAY,WAAY,UAC5D,WAAY,UAAY,WAAY,UAAY,WAAY,WAC5D,UAAY,WAAY,WAAY,UAAY,WAAY,WAC5D,UAAY,WAAY,WAAY,WAAY,WAAY,UAC5D,WAAY,WAAY,UAAY,SAAY,WAAY,UAC5D,WAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,UAAY,UAAY,WAAY,WAAY,WAC5D,WAAY,WAAY,WAAY,UAAY,WAAY,WAC5D,WAAY,WAAY,WAAY,WAAY,UAAY,WAC5D,WAAY,WAAY,WAAY,WAAY,UAAY,WAC5D,WAAY,UAAY,WAAY,WAAY,WAAY,WAC5D,SAAY,WAAY,WAAY,WAAY,WAAY,UAC5D,UAAY,WAAY,SAAY,WAAY,SAAY,WAC5D,WAAY,UAAY,WAAY,SAAY,UAAY,WAC5D,WAAY,WAAY,SAAY,UAAY,WAAY,WAC5D,SAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,WAAY,WAAY,WAAY,UAAY,WAC5D,UAAY,WAAY,UAAY,UAAY,WAAY,SAC5D,WAAY,UAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,UAAY,WAAY,WAAY,WAAY,WAC5D,UAAY,WAAY,WAAY,UAAY,UAAY,UAC5D,UAAY,WAAY,UAAY,WAAY,WAAY,WAC5D,UAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,WAAY,WAAY,WAAY,WAAY,UAC5D,WAAY,WAAY,WAAY,WAAY,UAAY,WAC5D,WAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,SAAY,UAAY,UAAY,WAAY,UAAY,WAC5D,WAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,UAAY,UAAY,WAAY,WAAY,WAC5D,UAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,UAAY,WAAY,UAAY,UAAY,WAC5D,SAAY,WAAY,WAAY,WAAY,WAAY,UAC5D,WAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,UAAY,WAAY,WAAY,WAAY,UAC5D,WAAY,WAAY,WAAY,WAAY,WAAY,UAC5D,WAAY,WAAY,WAAY,UAAY,WAAY,UAC5D,SAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,WAAY,WAAY,UAAY,WAAY,WAC5D,WAAY,WAAY,WAAY,WAAY,WAAY,WAC5D,WAAY,UAAY,WAAY,UACxC,EAMA,SAASC,GAASnP,EAAqB,CACnC,GAAIA,IAAQ,EACR,MAAO,GAGX,IAAI9H,EAAS,EAEb,IADA8H,GAAO,EACCA,EAAMA,IAAQ,GAClB9H,IAGJ,OAAOA,CACX,CAEA,SAASkX,GAAWC,EAAoBC,EAAaC,EAAqB,CACtE,QAASC,EAAI,EAAGA,EAAIF,EAAKE,IAAK,CAC1B,IAAIC,EAAeF,EAAQD,EAC3B,MAAMI,EAAab,GAAQS,EAAME,CAAC,EAC9BC,EAAeC,IACfD,EAAeC,GAGnB,MAAMC,EAAed,GAAQS,CAAG,EAAK,GAAKG,GAAgBD,GAC1DH,EAAO,aAAaG,CAAC,EAAKC,GAAgBD,EAC1CH,EAAO,WAAWG,CAAC,EAAIC,EAAeN,GAASQ,CAAY,EAC3DN,EAAO,gBAAgBG,CAAC,EAAKX,GAAQ,GAAKY,CAAY,IAAQ,EAC9DJ,EAAO,eAAeG,CAAC,EAAIL,GAASQ,CAAY,CACpD,CAGA,MAAMC,EAAef,GAAQS,CAAG,EAC1BO,EAAkBD,IAAiB,EACzC,QAASE,EAAI,EAAGA,GAAKF,EAAcE,IAC3BA,GAAKD,EACLR,EAAO,QAAQS,CAAC,EAAIA,GAAK,EAEzBT,EAAO,QAAQS,CAAC,GAAMF,EAAeE,GAAM,GAAK,EAKxD,QAASA,EAAI,EAAGA,GAAKF,EAAcE,IAC3BA,EAAI,EACJT,EAAO,QAAQS,CAAC,EAAIF,GAAgBE,IAAM,GAE1CT,EAAO,QAAQS,CAAC,EAAKA,IAAM,CAGvC,CAEA,SAASC,GAAa5c,EAAsB,CACxC,OAAQA,EAAA,CACJ,KAAK0a,EAAc,KACf,MAAO,GACX,KAAKA,EAAc,MACf,MAAO,GACX,KAAKA,EAAc,MACf,MAAO,GACX,KAAKA,EAAc,MACf,MAAO,GACX,KAAKA,EAAc,KACf,MAAO,GACX,KAAKA,EAAc,QACnB,QACI,eAAQ,IAAI;AAAA,CAAwB,EAC7B,CAAA,CAEnB,CAEA,SAASmC,GAAWC,EAAsB,CACtC,OAAIA,EAAO,WACAhB,GAAQgB,IAAS,EAAE,EACnBA,EAAO,WACP,EAAIhB,GAASgB,IAAS,GAAM,GAAU,EACtCA,EAAO,WACP,GAAKhB,GAASgB,IAAS,EAAK,GAAU,EAEtC,GAAKhB,GAAQgB,EAAO,GAAU,CAE7C,CAOA,SAASC,GAAmBV,EAAWS,EAA4B,CAC/D,IAAI5M,EACA8M,EAEJ,GAAIF,EAAO,GAAKA,EAAOrB,EAAY,gBAAgBY,CAAC,EAAI,CACpD,MAAMY,EAAaJ,GAAWC,CAAI,EAClCE,EAAQC,EAAa,EAAIZ,EACzBnM,EAAM+M,GAAcZ,EAAMS,GAAS,GAAKE,EAAUtB,GAAQW,CAAC,CAC/D,MACIW,EAAQvB,EAAY,WAAWY,CAAC,EAChCnM,EAAKuL,EAAY,aAAaY,CAAC,GAAOS,GAAS,GAAKE,EAAUtB,GAAQD,EAAY,eAAeY,CAAC,CAAE,GAExG,MAAO,CAAE,YAAaW,EAAO,GAAA9M,CAAA,CACjC,CAEA,SAASgN,GAAkB9T,EAAWiT,EAAmB,CACrD,OAAIjT,EAAIqS,EAAY,aAAaY,CAAC,GACtBjT,IAAMiT,GAAK,EAAIA,EAEhBZ,EAAY,WAAWY,CAAC,CAEvC,CAMA,MAAMc,EAAU,CASZ,YAAYhB,EAAa,CAPzB,KAAA,SAAmB,EACnB,KAAA,aAAuB,EACvB,KAAA,SAAmB,EACnB,KAAA,UAAoB,EACpB,KAAA,QAAkB,EAClB,KAAA,QAAkB,EAGd,IAAIiB,EAAO,EAIX,OAFA,KAAK,OAAS,GAAOjB,EAEbpB,GAAA,CACJ,IAAK,GACD,KAAK,SAAW,EAChB,KAAK,UAAY,EACjB,KAAK,QAAU,EACf,KAAK,QAAU,EACf,MACJ,IAAK,GACD,KAAK,SAAW,EAChB,KAAK,UAAY,EACjB,KAAK,QAAU,EACf,KAAK,QAAU,EACf,MACJ,IAAK,GACD,KAAK,SAAW,EAChB,KAAK,UAAY,EACjB,KAAK,QAAU,EACf,KAAK,QAAU,EACf,MACJ,IAAK,GACL,IAAK,GACL,IAAK,GACD,QAAQ,IAAI;AAAA,CAAmD,EAC/D,MACJ,QACI,QAAQ,IAAI;AAAA,CAAiD,CAAA,CAGrE,IAAIsC,EAAU,KAAK,SAAW,EAC1BC,EAAQ,KAAK,UAEjB,EAAG,CACC,IAAIC,EACA,KAAK,SACLA,EAASH,EAAO,EAEhBG,EAAS,EAGR,EAAEF,IACHA,EAAU,KAAK,QACfC,GAAS,KAAK,SAGlBF,EAAOG,EAASD,EAAQ,EACpBF,EAAOE,GAAS,KAAK,SACrBF,EAAO,KAAK,OAAS,GAGpB,KAAK,eACN,KAAK,aAAe,KAAK,QAG7B,KAAK,UACT,OAASA,EAAO,KAAK,OAAS,EAClC,CACJ,CAMA,MAAMI,EAAW,CAAjB,aAAA,CACI,KAAA,SAAmB,EACnB,KAAA,SAAqB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,CAAC,CAAA,CAE5C,MAAMC,EAAmB,CACrB,KAAK,SAAWA,EAChB,KAAK,SAAW,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,CAAC,CAC3C,CAEA,gBAAgBC,EAAoBC,EAAgBF,EAAmB,CACnE,IAAIG,EAAWH,EAAM,EACjBI,EAAe,KAAK,SAASD,CAAQ,GACpC,KAAK,SAASA,CAAQ,GAAK,GAAKV,GAAkBS,EAAQC,CAAQ,EAEvE,QAAS9d,EAAI2d,EAAM,EAAG3d,GAAK,EAAGA,IAAK,CAC/B,MAAMge,EAAc,KAAK,SAAShe,CAAC,GAC9B,KAAK,SAASA,CAAC,GAAK,GAAKod,GAAkBS,EAAQ7d,CAAC,EAErDge,EAAaD,IACbD,EAAW9d,EACX+d,EAAcC,EAEtB,CAIA,GAFA,KAAK,SAAWF,EAEZC,EAAcH,EAAM,UACpB,QAAS5d,EAAI,EAAGA,EAAI2d,EAAK3d,IACrB,KAAK,SAASA,CAAC,GAAK,KAAK,SAASA,CAAC,GAAK,KAAO,CAG3D,CACJ,CAMA,MAAMie,EAAe,CAArB,aAAA,CACI,KAAA,YAA4B,CAAA,EAC5B,KAAA,WAA2B,CAAA,CAAC,CAE5B,oBAAoBC,EAA2B,CAC3C,IAAIZ,EAAO,EACPa,EAAU,EAEVZ,EAAUW,EAAM,SAAW,EAC3BV,EAAQU,EAAM,UAElB,EAAG,CACC,IAAIT,EACAU,EACAV,EAASH,EAAO,EAEhBG,EAAS,EAGR,EAAEF,IACHA,EAAUW,EAAM,QAChBV,GAASU,EAAM,SAGnBZ,EAAOG,EAASD,EAAQ,EACpBF,EAAOE,GAASU,EAAM,SACtBZ,EAAOY,EAAM,OAAS,GAG1B,MAAME,EAAS,IAAIV,GACnB,KAAK,WAAWS,CAAO,EAAIC,EAE3B,QAASpe,EAAIyd,EAAQzd,GAAKsd,EAAMtd,IAC5B,KAAK,YAAYA,CAAC,EAAIoe,EAG1BD,GACJ,OAASb,EAAOY,EAAM,OAAS,GAC/B,MAAO,EACX,CACJ,CAeA,MAAMG,EAAY,CASd,YAAYC,EAAsBC,EAAsB,CAFxD,KAAA,YAA4B,CAAA,EAGxB,KAAK,MAAQ,IAAIC,GACjB,KAAK,eAAiB,IAAIP,GAC1B,KAAK,eAAiB,IAAIA,GAC1B,KAAK,aAAe,CAAE,KAAM,EAAG,IAAK,CAAA,CAAC,EACrC,KAAK,UAAYK,EACjB,KAAK,UAAYC,EAEjB,KAAK,eAAe,oBAAoB,KAAK,SAAS,EACtD,KAAK,eAAe,oBAAoB,KAAK,SAAS,CAC1D,CAEA,MAAMlC,EAAsB,CAGxB,GAFA,KAAK,aAAe,CAAE,KAAM,EAAG,IAAK,CAAA,CAAC,EAEjCA,IAAQ,EAAG,CACX,QAASoC,EAAI,EAAGA,EAAI,KAAK,UAAU,SAAUA,IACzC,KAAK,eAAe,WAAWA,CAAC,EAAG,MAAM,CAAC,EAE9C,KAAK,YAAc,KAAK,eAAe,WAC3C,SAAWpC,IAAQ,EAAG,CAClB,QAASoC,EAAI,EAAGA,EAAI,KAAK,UAAU,SAAUA,IACzC,KAAK,eAAe,WAAWA,CAAC,EAAG,MAAM,CAAC,EAE9C,KAAK,YAAc,KAAK,eAAe,WAC3C,KACI,gBAAQ,IAAI,iBAAmBpC,EAAM;AAAA,CAAI,EAClC,GAGX,YAAK,MAAM,MAAA,EACJ,EACX,CACJ,CAMA,MAAMmC,EAAY,CAAlB,aAAA,CACI,KAAA,QAAkB,EAClB,KAAA,YAAsB,IACtB,KAAA,UAAoB,EACpB,KAAA,MAAgB,EAChB,KAAA,QAAkBrD,GAClB,KAAA,UAAoB,EACpB,KAAA,QAAkB,EAClB,KAAA,UAAoB,CAAA,CAEpB,cAAqB,CACjB,IAAIuD,EAAK,KAAK,MACVA,EAAK,KACLA,EAAK,IAGT,KAAK,UAAY5C,GAAY,KAAK,MAAMb,GAAO,CAAC,CAAC,EAAGyD,CAAE,CAC1D,CAEA,OAAc,CACV,KAAK,QAAU,EACf,KAAK,YAAc,IACnB,KAAK,MAAQ,EACb,KAAK,QAAUvD,GAEf,KAAK,aAAA,EAEL,KAAK,UAAY,EACjB,KAAK,QAAUY,GAAE,CAAC,EAClB,KAAK,UAAY,GAAK,KAAK,OAC/B,CAEA,SAAkB,CACd,YAAK,cACEE,GAAc,KAAK,YAAc,GAAK,CACjD,CACJ,CAMA,MAAM0C,EAAY,CAiBd,aAAc,CAhBd,KAAA,KAAe,EACf,KAAA,MAAgB,EAChB,KAAA,OAAiB,EACjB,KAAA,MAAgB,EAChB,KAAA,gBAA0B,EAC1B,KAAA,OAAiB,EACjB,KAAA,WAAqB,EACrB,KAAA,MAAoB,IAAI,WAAW,CAAC,EACpC,KAAA,MAAgB,EAChB,KAAA,cAAwB,EAExB,KAAA,SAAwB,IAAIH,GAMxB,KAAK,UAAY,IAAInB,GAAU,CAAC,EAChC,KAAK,UAAY,IAAIA,GAAU,CAAC,EAChC,KAAK,SAAW,CAAA,EAEhB,QAASrd,EAAI,EAAGA,EAAI,EAAGA,IACnB,KAAK,SAAS,KAAK,IAAIqe,GAAY,KAAK,UAAW,KAAK,SAAS,CAAC,CAE1E,CAEA,MAAMO,EAA4B,CAC9B,YAAK,SAAS,MAAA,EAEd,KAAK,MAAQA,EACb,KAAK,MAAQ,KAAK,MAAM,OACxB,KAAK,MAAQ,EACb,KAAK,cAAgB,EACd,EACX,CAEA,YAAmB,CACf,GAAI,KAAK,OAAS,KAAK,MACnB,MAAM,IAAI,MAAM,mBAAmB,EAEvC,KAAK,WACA,KAAK,MAAM,KAAK,OAAO,EACvB,KAAK,MAAM,KAAK,OAAO,GAAM,EAC7B,KAAK,MAAM,KAAK,OAAO,GAAM,GAC7B,KAAK,MAAM,KAAK,OAAO,GAAM,EACtC,CAEA,cAAc3V,EAAmB,CAC7B,KAAK,OAAS,KAAK,QAAUA,EAE7B,MAAMoH,EAAQ,KAAK,gBAAkBpH,EACrC,GAAIoH,GAAS,EACT,KAAK,gBAAkBA,EACvB,KAAK,QAAU,KAAK,aAAe,KAAK,oBACrC,CACH,MAAMwO,EAAW,GAAKxO,EACtB,KAAK,QAAU,KAAK,YAAcwO,EAClC,KAAK,WAAA,EACL,KAAK,gBAAkB,GAAKA,EAC5B,KAAK,QAAU,KAAK,aAAe,KAAK,eAC5C,CACJ,CAEA,iBAAwB,CACpB,KAAK,cAAc,EAAE,EACrB,KAAK,cAAc,EAAE,CACzB,CAEA,cAAcxC,EAAsB,CAChC,QAASrc,EAAI,EAAGA,EAAI,EAAGA,IACnB,GAAI,CAAC,KAAK,SAASA,CAAC,EAAG,MAAMqc,CAAG,EAC5B,MAAO,GAGf,MAAO,EACX,CAEA,gBAAgBuC,EAA4B,CACxC,GAAI,CAAC,KAAK,MAAMA,CAAK,EACjB,MAAO,GAGX,KAAK,MAAQ,EACb,KAAK,WACA,KAAK,MAAM,KAAK,OAAO,EACvB,KAAK,MAAM,KAAK,OAAO,GAAM,EAC7B,KAAK,MAAM,KAAK,OAAO,GAAM,GAC7B,KAAK,MAAM,KAAK,OAAO,GAAM,GAClC,KAAK,OAAS,KAAK,WACnB,KAAK,gBAAkB,EAEvB,MAAM7e,EAAQ,KAAK,OAEnB,GADA,KAAK,gBAAA,EACDA,IAAU,WACV,eAAQ,IAAI,mBAAqBA,EAAM,SAAS,EAAE,CAAC,EAC5C,GAGX,MAAME,EAAU,KAAK,OAErB,GADA,KAAK,gBAAA,EACDA,IAAc,EACd,eAAQ,IAAI,qBAAuBA,EAAQ,SAAS,EAAE,CAAC,EAChD,GAGX,KAAK,KAAO,KAAK,OACjB,KAAK,gBAAA,EAEL,KAAK,MAAQ,KAAK,OAClB,KAAK,gBAAA,EAEL,KAAK,OAAS,KAAK,OACnB,KAAK,gBAAA,EAEL,MAAMoc,EAAMS,GAAa,KAAK,IAAI,EAElC,MAAK,OAAK,cAAcT,CAAG,CAK/B,CAMA,2BACIrc,EAAW8e,EAAoBC,EAC/BC,EAAkB3C,EAAa4C,EAC3B,CAEJ,IAAIC,EACA1Z,EACAvD,EAEJ,GAAKjC,EA6BDkf,EAAUlf,EAAI,KAAK,SAAS,YA7BxB,CACJ8e,EAAO1D,CAAe,EAAI,EAC1B5V,EAAI,EACJ,GACIvD,EAAIgb,GACA,KAAK,SAASzX,CAAC,EAAG,YAAY,KAAK,SAASA,CAAC,EAAG,aAAa,IAAI,EAAG,SACpE,KAAK,MAAA,EAET,KAAK,SAASA,CAAC,EAAG,aAAa,IAAI,CAAC,EAAIvD,EAAE,GAC1C6c,EAAO,EAAItZ,CAAC,EAAKmW,EAAY,QAAQ1Z,EAAE,EAAE,EAAK,IAC9C,KAAK,cAAcA,EAAE,WAAW,QAC3B,EAAEuD,EAAI,GAEf,GAAI,KAAK,SAAS,QACd,EAAE,KAAK,SAAS,YACb,CACH,KAAK,SAAS,QAAW,KAAK,SAAS,UAAYwZ,EACnDxZ,EAAI,EACJ,GACI,KAAK,SAASA,CAAC,EAAG,YAAY,KAAK,SAASA,CAAC,EAAG,aAAa,IAAI,EAC5D,gBACG,KAAK,SACL,KAAK,SAASA,CAAC,EAAG,aAAa,IAAI,CAAC,EACpC6W,CAAA,QAEH,EAAE7W,EAAI,EACnB,CACA0Z,EAAU,EAAElf,EAAI,KAAK,SAAS,OAClC,CAIA,KAAOkf,EAAUH,GAAK,CAClB,KAAO/e,GAAKkf,EAASlf,IAAK,CACtB8e,EAAQ9e,EAAIwb,EAAoBJ,CAAe,EAAI,EACnD5V,EAAI,EACJ,GACIvD,EAAIgb,GACA,KAAK,SAASzX,CAAC,EAAG,YAAY,KAAK,SAASA,CAAC,EAAG,aAAa,IAAIxF,EAAI,CAAC,CAAE,EAAG,SAC3E,KAAK,MAAA,EAET,KAAK,SAASwF,CAAC,EAAG,aAAa,IAAIxF,CAAC,EAAIiC,EAAE,GAC1C6c,EAAQ9e,EAAIwb,GAAqB,EAAIhW,EAAE,EAClCmW,EAAY,QAAQ1Z,EAAE,EAAE,EAAK6c,GAAS9e,EAAI,GAAKwb,GAAqB,EAAIhW,EAAE,EAAMyZ,EACrF,KAAK,cAAchd,EAAE,WAAW,QAC3B,EAAEuD,EAAI,EACnB,CACAA,EAAI,EACJ,GACI,KAAK,SAASA,CAAC,EAAG,YAAY,KAAK,SAASA,CAAC,EAAG,aAAa,IAAI0Z,EAAU,CAAC,CAAE,EACzE,gBACG,KAAK,SACL,KAAK,SAAS1Z,CAAC,EAAG,aAAa,IAAI0Z,CAAO,EAC1C7C,CAAA,QAEH,EAAE7W,EAAI,GACf0Z,EAAUlf,GAAK,KAAK,SAAS,QAAA,EAAYgf,EAC7C,CAEA,KAAOhf,EAAI+e,EAAK/e,IAAK,CACjB8e,EAAQ9e,EAAIwb,EAAoBJ,CAAe,EAAI,EACnD5V,EAAI,EACJ,GACIvD,EAAIgb,GACA,KAAK,SAASzX,CAAC,EAAG,YAAY,KAAK,SAASA,CAAC,EAAG,aAAa,IAAIxF,EAAI,CAAC,CAAE,EAAG,SAC3E,KAAK,MAAA,EAET,KAAK,SAASwF,CAAC,EAAG,aAAa,IAAIxF,CAAC,EAAIiC,EAAE,GAC1C6c,EAAQ9e,EAAIwb,GAAqB,EAAIhW,EAAE,EAClCmW,EAAY,QAAQ1Z,EAAE,EAAE,EAAK6c,GAAS9e,EAAI,GAAKwb,GAAqB,EAAIhW,EAAE,EAAMyZ,EACrF,KAAK,cAAchd,EAAE,WAAW,QAC3B,EAAEuD,EAAI,EACnB,CACA,KAAK,SAAS,QAAU0Z,EAAUH,CACtC,CAMA,wBAAwBD,EAA0B,CAG9C,IAAI5Q,EAAM,EACN/N,EAAQ,KAAK,MAEjB,KAAQ+a,GAAS,KAAK,SAAS,OAAW,KAAK,SAAS,SAAW/a,GAC3D,KAAK,SAAS,UACd,KAAK,2BACD+N,EAAK4Q,EACL5Q,EAAM,KAAK,SAAS,QACpB0N,GAAQ,KAAK,SAAS,KAAK,EAC3B,EAAK,GAAA,EAET1N,GAAO,KAAK,SAAS,QACrB/N,GAAS,KAAK,SAAS,SAG3B,KAAK,SAAS,QACd,KAAK,SAAS,aAAA,EACd,KAAK,SAAS,QAAUgb,GAGxBhb,IACA,KAAK,2BACD+N,EAAK4Q,EAAQ5Q,EAAM/N,EACnByb,GAAQ,KAAK,SAAS,KAAK,EAAI,EAAK,GAAA,EAEpCV,GAAS,KAAK,SAAS,QACvB,KAAK,SAAS,SAAW/a,GAGrC,CAMA,0BACIgf,EAAqBL,EAAoB9e,EAAW+e,EACpD1C,EAAa4C,EACT,CAEJ,MAAMD,EAAWpD,GAAQ,KAAK,SAAS,KAAK,EAE5C,IAAI,EACAwD,EAAW,EACXC,EAAS,EACTH,EAAU,EACV1Z,EAEJ,GAAKxF,EA+BDkf,EAAUlf,EAAI,KAAK,SAAS,YA/BxB,CACJ8e,EAAO1D,CAAe,EAAI,EAE1B5V,EAAI,EACJ,GACI,EAAIyX,GACA,KAAK,SAASzX,CAAC,EAAG,YAAY,KAAK,SAASA,CAAC,EAAG,aAAa,IAAI,EAAG,SACpE,KAAK,MAAA,EAET,KAAK,SAASA,CAAC,EAAG,aAAa,IAAI,CAAC,EAAI,EAAE,GAC1CsZ,EAAO,EAAItZ,CAAC,EACPmW,EAAY,QAAQ,KAAK,SAASnW,CAAC,EAAG,aAAa,IAAI,CAAC,CAAE,EAAK2Z,EAAQ,EAAI3Z,CAAC,EAAMyZ,EACvF,KAAK,cAAc,EAAE,WAAW,QAC3B,EAAEzZ,EAAI,GAEf,GAAI,KAAK,SAAS,QACd,EAAE,KAAK,SAAS,YACb,CACH,KAAK,SAAS,QAAW,KAAK,SAAS,UAAYwZ,EACnDxZ,EAAI,EACJ,GACI,KAAK,SAASA,CAAC,EAAG,YAAY,KAAK,SAASA,CAAC,EAAG,aAAa,IAAI,EAC5D,gBACG,KAAK,SACL,KAAK,SAASA,CAAC,EAAG,aAAa,IAAI,CAAC,EACpC6W,CAAA,QAEH,EAAE7W,EAAI,EACnB,CACA0Z,EAAU,EAAElf,EAAI,KAAK,SAAS,OAClC,CAIA,OAAS,CACL,IAAIoQ,EAAK,EACT,KAAO8O,EAAUH,GAAO,CAAC3O,GAAI,CACzB,KAAOpQ,GAAKkf,GAAW,CAAC9O,EAAIpQ,IAAK,CAC7B,MAAMsf,EAAQtf,EAAIwb,EACZ+D,GAAWvf,EAAI,GAAKwb,EACpBgE,GAAWxf,EAAI,GAAKwb,EAE1B,GAAI2D,EAAQI,EAAUlE,EAAa,IAAO8D,EAAQG,EAAQjE,EAAa,GACnE8D,EAAQI,EAAUjE,EAAa,IAAO6D,EAAQG,EAAQhE,EAAa,GACnE6D,EAAQI,EAAUhE,EAAa,IAAO4D,EAAQG,EAAQ/D,EAAa,GAC/D6D,IAAapf,GAAKA,EAAI,GACrB8e,EAAOS,EAAUlE,EAAa,IAAOyD,EAAOU,EAAUnE,EAAa,GACnEyD,EAAOS,EAAUjE,EAAa,IAAOwD,EAAOU,EAAUlE,EAAa,GACnEwD,EAAOS,EAAUhE,EAAa,IAAOuD,EAAOU,EAAUjE,EAAa,EAAK,CAMzE,IAJA,KAAK,SAAS,QAAU2D,EAAUlf,EAClCof,EAAWpf,EACXqf,EAASrf,EAAI,KAAK,UAAU,KAAK,QAAQ,EAElCA,EAAIqf,EAAQrf,IAAK,CACpB,MAAMyf,EAAKzf,EAAIwb,EACTkE,GAAQ1f,EAAI,GAAKwb,EACvBsD,EAAOW,EAAKrE,CAAe,EAAI,EAC/B0D,EAAOW,EAAKpE,EAAa,EAAIyD,EAAOY,EAAOrE,EAAa,EACxDyD,EAAOW,EAAKnE,EAAa,EAAIwD,EAAOY,EAAOpE,EAAa,EACxDwD,EAAOW,EAAKlE,EAAa,EAAIuD,EAAOY,EAAOnE,EAAa,CAC5D,CAEA,GAAIvb,IAAM+e,EACN,OAEAG,EAAUlf,EAAI,KAAK,SAAS,QAC5BoQ,EAAK,EACL,KAER,CAGJ5K,EAAI,EACJsZ,EAAOQ,EAAQlE,CAAe,EAAI,EAClC,EAAG,CACC,MAAMuE,EAAK,KAAK,SAASna,CAAC,EACpBoa,EAAKD,EAAG,aAEd,EAAI1C,GAAmB0C,EAAG,YAAYC,EAAG,IAAI5f,EAAI,CAAC,CAAE,EAAG,SAAU,KAAK,MAAM,EAC5E4f,EAAG,IAAI5f,CAAC,EAAI,EAAE,GACd8e,EAAOQ,GAAS,EAAI9Z,EAAE,EACjBmW,EAAY,QAAQ,EAAE,EAAE,GACtBmD,EAAOS,GAAW,EAAI/Z,EAAE,EAAK2Z,EAAQG,GAAS,EAAI9Z,EAAE,GAAO,GAAMyZ,EACxE,KAAK,cAAc,EAAE,WAAW,CACpC,OAAS,EAAEzZ,EAAI,EACnB,CACA,GAAI4K,EACA,MAGJ5K,EAAI,EACJ,GACI,KAAK,SAASA,CAAC,EAAG,YAAY,KAAK,SAASA,CAAC,EAAG,aAAa,IAAI0Z,EAAU,CAAC,CAAE,EACzE,gBACG,KAAK,SACL,KAAK,SAAS1Z,CAAC,EAAG,aAAa,IAAI0Z,CAAO,EAC1C7C,CAAA,QAEH,EAAE7W,EAAI,GAEf0Z,EAAUlf,GAAK,KAAK,SAAS,QAAA,EAAYgf,EAC7C,CAEA,KAAOhf,EAAI+e,GAAO,CAAC3O,EAAIpQ,IAAK,CACxB,MAAMsf,EAAQtf,EAAIwb,EACZ+D,GAAWvf,EAAI,GAAKwb,EACpBgE,GAAWxf,EAAI,GAAKwb,EAE1B,GAAI2D,EAAQI,EAAUlE,EAAa,IAAO8D,EAAQG,EAAQjE,EAAa,GACnE8D,EAAQI,EAAUjE,EAAa,IAAO6D,EAAQG,EAAQhE,EAAa,GACnE6D,EAAQI,EAAUhE,EAAa,IAAO4D,EAAQG,EAAQ/D,EAAa,GAC/D6D,IAAapf,GAAKA,EAAI,GACrB8e,EAAOS,EAAUlE,EAAa,IAAOyD,EAAOU,EAAUnE,EAAa,GACnEyD,EAAOS,EAAUjE,EAAa,IAAOwD,EAAOU,EAAUlE,EAAa,GACnEwD,EAAOS,EAAUhE,EAAa,IAAOuD,EAAOU,EAAUjE,EAAa,EAAK,CAMzE,IAJA,KAAK,SAAS,QAAU2D,EAAUlf,EAClCof,EAAWpf,EACXqf,EAASrf,EAAI,KAAK,UAAU,KAAK,QAAQ,EAElCA,EAAIqf,EAAQrf,IAAK,CACpB,MAAMyf,EAAKzf,EAAIwb,EACTkE,GAAQ1f,EAAI,GAAKwb,EACvBsD,EAAOW,EAAKrE,CAAe,EAAI,EAC/B0D,EAAOW,EAAKpE,EAAa,EAAIyD,EAAOY,EAAOrE,EAAa,EACxDyD,EAAOW,EAAKnE,EAAa,EAAIwD,EAAOY,EAAOpE,EAAa,EACxDwD,EAAOW,EAAKlE,EAAa,EAAIuD,EAAOY,EAAOnE,EAAa,CAC5D,CAEA,GAAIvb,IAAM+e,EACN,OAEAG,EAAUlf,EAAI,KAAK,SAAS,QAC5BoQ,EAAK,EACL,KAER,CAGJ0O,EAAOQ,EAAQlE,CAAe,EAAI,EAClC5V,EAAI,EACJ,GACI,EAAIyX,GACA,KAAK,SAASzX,CAAC,EAAG,YAAY,KAAK,SAASA,CAAC,EAAG,aAAa,IAAIxF,EAAI,CAAC,CAAE,EAAG,SAC3E,KAAK,MAAA,EAET,KAAK,SAASwF,CAAC,EAAG,aAAa,IAAIxF,CAAC,EAAI,EAAE,GAC1C8e,EAAOQ,GAAS,EAAI9Z,EAAE,EACjBmW,EAAY,QAAQ,EAAE,EAAE,GACtBmD,EAAOS,GAAW,EAAI/Z,EAAE,EAAK2Z,EAAQG,GAAS,EAAI9Z,EAAE,GAAO,GAAMyZ,EACxE,KAAK,cAAc,EAAE,WAAW,QAC3B,EAAEzZ,EAAI,EACnB,CAEA,GAAI,CAAC4K,EAAI,CACL,KAAK,SAAS,QAAU8O,EAAUH,EAClC,MACJ,CACJ,CACJ,CAMA,UAAUnB,EAA4B,CAClC,IAAIiC,EAAS,EAEb,EAAG,CACC,MAAMhb,EAAK,EAAE,KAAK,SAAW,MAAQ,EAAK,IACpCkF,EAAO8R,GAAQhX,CAAC,EAEtB,QAASib,EAAO,EAAGA,GAAQ/V,EAAM+V,IAC7BD,GAAUjC,EAAM,UAEZA,EAAM,UAAY,KAClBA,EAAM,QAAU7B,GAAE,EAAE6B,EAAM,SAAS,EACnCA,EAAM,UAAa,GAAKA,EAAM,SAGtC,GAAI7T,IAAS,EAAG,CACZ,KAAK,cAAcA,EAAO,CAAC,EAC3B,KACJ,CACA,KAAK,cAAc,CAAC,CACxB,OAAS,IAET,OAAI6T,EAAM,UACNiC,GAAU,KAAK,SAAY,GAAKjC,EAAM,QACtC,KAAK,cAAcA,EAAM,OAAO,GAGhCA,EAAM,YACNA,EAAM,QAAU7B,GAAE,EAAE6B,EAAM,SAAS,EACnCA,EAAM,UAAa,GAAKA,EAAM,SAG3BiC,CACX,CAMA,uBAAuBV,EAAqBL,EAA0B,CAGlE,IAAI5Q,EAAM,EACN/N,EAAQ,KAAK,MAEjB,KAAQ+a,GAAS,KAAK,SAAS,OAAW,KAAK,SAAS,SAAW/a,GAC3D,KAAK,SAAS,UACd,KAAK,0BACDgf,EAASL,EAAQ5Q,EACjBA,EAAM,KAAK,SAAS,QAAS,EAAK,GAAA,EAEtCA,GAAO,KAAK,SAAS,QACrB/N,GAAS,KAAK,SAAS,SAG3B,KAAK,SAAS,QACd,KAAK,SAAS,aAAA,EACd,KAAK,SAAS,QAAUgb,GAGxBhb,IACA,KAAK,0BACDgf,EAASL,EAAQ5Q,EACjBA,EAAM/N,EAAO,EAAK,GAAA,EAElB+a,GAAS,KAAK,SAAS,QACvB,KAAK,SAAS,SAAW/a,GAGrC,CAMA,0BACI4f,EAAsB/f,EACtBggB,EAA4BlB,EAAoBC,EAChDC,EAAkB3C,EAAa4C,EAC3B,CACJ,IAAIC,EACAjd,EAuBJ,IArBIjC,IAAM,GACNiC,EAAIgb,GACA8C,EAAQ,YAAYC,EAAa,IAAI,EAAG,SACxC,KAAK,MAAA,EAETA,EAAa,IAAI,CAAC,EAAI/d,EAAE,GACxB6c,EAAO1D,CAAe,EAAIO,EAAY,QAAQ1Z,EAAE,EAAE,EAClD,KAAK,cAAcA,EAAE,WAAW,EAE5B8d,EAAQ,MAAM,QACd,EAAEA,EAAQ,MAAM,SAEhBA,EAAQ,MAAM,QAAWA,EAAQ,MAAM,UAAYf,EACnDe,EAAQ,YAAYC,EAAa,IAAI,EAChC,gBAAgBD,EAAQ,MAAOC,EAAa,IAAI,CAAC,EAAI3D,CAAG,GAEjE6C,EAAU,EAAElf,EAAI+f,EAAQ,MAAM,SAE9Bb,EAAUlf,EAAI+f,EAAQ,MAAM,QAGzBb,EAAUH,GAAK,CAClB,IAAIkB,EAEJ,KAAOjgB,GAAKkf,EAASlf,IACjBigB,EAAUF,EAAQ,YAAYC,EAAa,IAAIhgB,EAAI,CAAC,CAAE,EAEtDiC,EAAIgb,GAAmBgD,EAAS,SAAU,KAAK,MAAM,EACrDD,EAAa,IAAIhgB,CAAC,EAAIiC,EAAE,GACxB6c,EAAQ9e,EAAIwb,EAAoBJ,CAAe,EAC1CO,EAAY,QAAQ1Z,EAAE,EAAE,EAAK6c,GAAS9e,EAAI,GAAKwb,EAAoBJ,CAAe,EAAM6D,EAC7F,KAAK,cAAchd,EAAE,WAAW,EAGpCge,EAAS,gBAAgBF,EAAQ,MAAOC,EAAa,IAAId,CAAO,EAAI7C,CAAG,EAEvE6C,EAAUlf,GAAK+f,EAAQ,MAAM,QAAA,EAAYf,EAC7C,CAEA,KAAOhf,EAAI+e,EAAK/e,IACZiC,EAAIgb,GACA8C,EAAQ,YAAYC,EAAa,IAAIhgB,EAAI,CAAC,CAAE,EAAG,SAC/C,KAAK,MAAA,EAGTggB,EAAa,IAAIhgB,CAAC,EAAIiC,EAAE,GACxB6c,EAAQ9e,EAAIwb,EAAoBJ,CAAe,EAC1CO,EAAY,QAAQ1Z,EAAE,EAAE,EAAK6c,GAAS9e,EAAI,GAAKwb,EAAoBJ,CAAe,EAAM6D,EAC7F,KAAK,cAAchd,EAAE,WAAW,EAEpC8d,EAAQ,MAAM,QAAUb,EAAUH,CACtC,CAMA,uBAAuBgB,EAAsBjB,EAA0B,CAGnE,MAAMkB,EAAeD,EAAQ,aAC7B,IAAI7R,EAAM,EACN/N,EAAQ,KAAK,MAEjB,KAAQ+a,GAAS6E,EAAQ,MAAM,OAAWA,EAAQ,MAAM,SAAW5f,GAC3D4f,EAAQ,MAAM,UACd,KAAK,0BACDA,EAAS7R,EAAK8R,EAAclB,EAC5B5Q,EAAM6R,EAAQ,MAAM,QAASnE,GAAQmE,EAAQ,MAAM,KAAK,EACxD,EAAK,GAAA,EAET7R,GAAO6R,EAAQ,MAAM,QACrB5f,GAAS4f,EAAQ,MAAM,SAG3BA,EAAQ,MAAM,QACdA,EAAQ,MAAM,aAAA,EACdA,EAAQ,MAAM,QAAU5E,GAGxBhb,IACA,KAAK,0BACD4f,EAAS7R,EAAK8R,EAAclB,EAAQ5Q,EAAM/N,EAC1Cyb,GAAQmE,EAAQ,MAAM,KAAK,EAAI,EAAK,GAAA,EAEpC7E,GAAS6E,EAAQ,MAAM,QACvBA,EAAQ,MAAM,SAAW5f,GAGrC,CAMA,yBACI4f,EACAC,EAA4Bb,EAAqBL,EACjD9e,EAAW+e,EAAa1C,EAAa4C,EACjC,CACJ,MAAMD,EAAWpD,GAAQmE,EAAQ,MAAM,KAAK,EAC5C,IAAIb,EAEAE,EAAW,EACXC,EAEApd,EAyBJ,IAvBIjC,IAAM,GACNiC,EAAIgb,GACA8C,EAAQ,YAAYC,EAAa,IAAI,EAAG,SACxC,KAAK,MAAA,EAGTA,EAAa,IAAI,CAAC,EAAI/d,EAAE,GACxB6c,EAAO1D,CAAe,EACjBO,EAAY,QAAQ1Z,EAAE,EAAE,EAAKkd,EAAQ/D,CAAe,EAAM6D,EAC/D,KAAK,cAAchd,EAAE,WAAW,EAE5B8d,EAAQ,MAAM,QACd,EAAEA,EAAQ,MAAM,SAEhBA,EAAQ,MAAM,QAAWA,EAAQ,MAAM,UAAYf,EACnDe,EAAQ,YAAYC,EAAa,IAAI,EAChC,gBAAgBD,EAAQ,MAAOC,EAAa,IAAI,CAAC,EAAI3D,CAAG,GAEjE6C,EAAU,EAAElf,EAAI+f,EAAQ,MAAM,SAE9Bb,EAAUlf,EAAI+f,EAAQ,MAAM,UAGvB,CACL,IAAI3P,EAAK,EACT,KAAO8O,EAAUH,GAAO,CAAC3O,GAAI,CACzB,IAAI6P,EACJ,KAAOjgB,GAAKkf,GAAW,CAAC9O,EAAIpQ,IAAK,CAC7B,MAAMsf,EAAQtf,EAAIwb,EACZ+D,GAAWvf,EAAI,GAAKwb,EACpBgE,GAAWxf,EAAI,GAAKwb,EAE1B,GAAI2D,EAAQI,EAAUnE,CAAe,IAAO+D,EAAQG,EAAQlE,CAAe,GACnEgE,IAAapf,GAAKA,EAAI,GACtB8e,EAAOS,EAAUnE,CAAe,IAAO0D,EAAOU,EAAUpE,CAAe,EAAI,CAO3E,IALA2E,EAAQ,MAAM,QAAUb,EAAUlf,EAClCof,EAAWpf,EAEXqf,EAASrf,EAAI,KAAK,UAAU+f,EAAQ,KAAK,EAElC/f,EAAIqf,EAAQrf,IAAK,CACpB,MAAMyf,EAAKzf,EAAIwb,EACTkE,IAAQ1f,EAAI,GAAKwb,EACvBsD,EAAOW,EAAKrE,CAAe,EAAI0D,EAAOY,GAAOtE,CAAe,CAChE,CAEA,GAAIpb,IAAM+e,EACN,OAEAG,EAAUlf,EAAI+f,EAAQ,MAAM,QAC5B3P,EAAK,EACL,KAER,CAGJ6P,EAAUF,EAAQ,YAAYC,EAAa,IAAIhgB,EAAI,CAAC,CAAE,EACtDiC,EAAIgb,GAAmBgD,EAAS,SAAU,KAAK,MAAM,EACrDD,EAAa,IAAIhgB,CAAC,EAAIiC,EAAE,GACxB6c,EAAOQ,EAAQlE,CAAe,EACzBO,EAAY,QAAQ1Z,EAAE,EAAE,GACtB6c,EAAOS,EAAUnE,CAAe,EAAK+D,EAAQG,EAAQlE,CAAe,GAAO,GAAM6D,EACxF,KAAK,cAAchd,EAAE,WAAW,CACpC,CACA,GAAImO,EACA,MAGJ6P,EAAS,gBAAgBF,EAAQ,MAAOC,EAAa,IAAId,CAAO,EAAI7C,CAAG,EAEvE6C,EAAUlf,GAAK+f,EAAQ,MAAM,QAAA,EAAYf,EAC7C,CAEA,KAAOhf,EAAI+e,GAAO,CAAC3O,EAAIpQ,IAAK,CACxB,MAAMsf,EAAQtf,EAAIwb,EACZ+D,GAAWvf,EAAI,GAAKwb,EACpBgE,GAAWxf,EAAI,GAAKwb,EAC1B,GAAI2D,EAAQI,EAAUnE,CAAe,IAAO+D,EAAQG,EAAQlE,CAAe,GACnEgE,IAAapf,GAAKA,EAAI,GACtB8e,EAAOS,EAAUnE,CAAe,IAAO0D,EAAOU,EAAUpE,CAAe,EAAI,CAO3E,IALA2E,EAAQ,MAAM,QAAUb,EAAUlf,EAClCof,EAAWpf,EAEXqf,EAASrf,EAAI,KAAK,UAAU+f,EAAQ,KAAK,EAElC/f,EAAIqf,EAAQrf,IAAK,CACpB,MAAMyf,EAAKzf,EAAIwb,EACTkE,GAAQ1f,EAAI,GAAKwb,EACvBsD,EAAOW,EAAKrE,CAAe,EAAI0D,EAAOY,EAAOtE,CAAe,CAChE,CAEA,GAAIpb,IAAM+e,EACN,OAEAG,EAAUlf,EAAI+f,EAAQ,MAAM,QAC5B3P,EAAK,EACL,KAER,CAGJnO,EAAIgb,GACA8C,EAAQ,YAAYC,EAAa,IAAIhgB,EAAI,CAAC,CAAE,EAAG,SAC/C,KAAK,MAAA,EAETggB,EAAa,IAAIhgB,CAAC,EAAIiC,EAAE,GACxB6c,EAAOQ,EAAQlE,CAAe,EACzBO,EAAY,QAAQ1Z,EAAE,EAAE,GACtB6c,EAAOS,EAAUnE,CAAe,EAAK+D,EAAQG,EAAQlE,CAAe,GAAO,GAAM6D,EACxF,KAAK,cAAchd,EAAE,WAAW,CACpC,CAEA,GAAI,CAACmO,EAAI,CACL2P,EAAQ,MAAM,QAAUb,EAAUH,EAClC,MACJ,CACJ,CACJ,CAMA,sBACIgB,EAAsBZ,EAAqBL,EACvC,CAGJ,MAAMkB,EAAeD,EAAQ,aAC7B,IAAI7R,EAAM,EACN/N,EAAQ,KAAK,MAEjB,KAAQ+a,GAAS6E,EAAQ,MAAM,OAAWA,EAAQ,MAAM,SAAW5f,GAC3D4f,EAAQ,MAAM,UACd,KAAK,yBACDA,EAASC,EAAcb,EAASL,EAAQ5Q,EACxCA,EAAM6R,EAAQ,MAAM,QAAS,EAAK,GAAA,EAEtC7R,GAAO6R,EAAQ,MAAM,QACrB5f,GAAS4f,EAAQ,MAAM,SAG3BA,EAAQ,MAAM,QACdA,EAAQ,MAAM,aAAA,EACdA,EAAQ,MAAM,QAAU5E,GAGxBhb,IACA,KAAK,yBACD4f,EAASC,EAAcb,EAASL,EAAQ5Q,EACxCA,EAAM/N,EAAO,EAAK,GAAA,EAElB+a,GAAS6E,EAAQ,MAAM,QACvBA,EAAQ,MAAM,SAAW5f,GAGrC,CAMA,WAAWyJ,EAAiBvJ,EAAyB,CACjD,OAAQ,KAAK,KAAA,CACT,KAAKua,EAAc,MACnB,KAAKA,EAAc,MACf,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,EACtC,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,EACtC,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,EACtC,KAAK,wBAAwBhR,CAAG,EAEhC,KAAK,gBACL,QAASsW,EAAM,EAAGA,EAAM,KAAK,OAAQA,IAAO,CACxC,MAAMC,EAAOvW,EACbA,EAAMuW,EAAK,SAAS9f,CAAM,EAC1B,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,KAAK,SAAS,CAAC,EAAG,aAAa,IAAI,CAAC,EAC1E,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,KAAK,SAAS,CAAC,EAAG,aAAa,IAAI,CAAC,EAC1E,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,KAAK,SAAS,CAAC,EAAG,aAAa,IAAI,CAAC,EAC1E,KAAK,uBAAuB8f,EAAMvW,CAAG,EACrC,KAAK,eACT,CACA,MAEJ,KAAKgR,EAAc,MACf,eAAQ,IAAI;AAAA,CAAmC,EACxC,GAEX,KAAKA,EAAc,KACf,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,EACtC,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,EACtC,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,EACtC,KAAK,wBAAwBhR,CAAG,EAEhC,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,EACtC,KAAK,uBAAuB,KAAK,SAAS,CAAC,EAAIA,CAAG,EAElD,KAAK,gBACL,QAASsW,EAAM,EAAGA,EAAM,KAAK,OAAQA,IAAO,CACxC,MAAMC,EAAOvW,EACbA,EAAMuW,EAAK,SAAS9f,CAAM,EAE1B,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,KAAK,SAAS,CAAC,EAAG,aAAa,IAAI,CAAC,EAC1E,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,KAAK,SAAS,CAAC,EAAG,aAAa,IAAI,CAAC,EAC1E,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,KAAK,SAAS,CAAC,EAAG,aAAa,IAAI,CAAC,EAC1E,KAAK,uBAAuB8f,EAAMvW,CAAG,EAErC,KAAK,SAAS,CAAC,EAAG,aAAa,KAAO,KAAK,SAAS,CAAC,EAAG,aAAa,IAAI,CAAC,EAC1E,KAAK,sBAAsB,KAAK,SAAS,CAAC,EAAIuW,EAAMvW,CAAG,EACvD,KAAK,eACT,CACA,MAEJ,KAAKgR,EAAc,KACf,eAAQ,IAAI;AAAA,CAAmC,EACxC,GAEX,KAAKA,EAAc,QACnB,QACI,eAAQ,IAAI;AAAA,CAAwB,EAC7B,EAAA,CAEf,MAAO,EACX,CAMA,iBAAiBhR,EAAoC,CAKjD,GAHI,CAAC,KAAK,gBAAgBA,CAAG,GAGzB,KAAK,OAASgR,EAAc,OAC5B,KAAK,OAASA,EAAc,OAC5B,KAAK,OAASA,EAAc,KAC5B,OAAO,KAEX,MAAMwF,EAAM,IAAI,WAAW,KAAK,MAAQ,KAAK,OAAS,CAAC,EAEvD,OADAA,EAAI,CAAC,EAAI,GACL,KAAK,WAAWA,EAAK,KAAK,MAAQ,CAAM,EACjCA,EAEJ,IACX,CACJ,CAMA,IAAIC,GAA8B,KAElC,SAASC,IAA0B,CAC/B,OAAKD,KACDA,GAAU,IAAI1B,IAEX0B,EACX,CAMO,MAAME,EAAmC,CAAzC,aAAA,CACH,KAAA,UAAoB,EACpB,KAAA,OAA4B,KAC5B,KAAA,KAAe,EACf,KAAA,MAAgB,EAChB,KAAA,OAAiB,CAAA,CAEjB,aAAa5hB,EAAcC,EAAYK,EAAyB,CAC5D,MAAMuhB,EAAMF,GAAA,EACZ,KAAK,UAAY3hB,EAAG,UAAUC,EAAI,EAAI,EACtCA,GAAM,EACN,MAAMgL,EAAM,IAAI,WAAW3K,EAAG,MAAML,CAAE,CAAC,EACjCqG,EAASub,EAAI,iBAAiB5W,CAAG,EACvC,YAAK,OAAS3E,EACVA,IACA,KAAK,KAAOub,EAAI,KAChB,KAAK,MAAQA,EAAI,MACjB,KAAK,OAASA,EAAI,QAEtB5hB,GAAMgL,EAAI,OACHhL,CACX,CACJ,CAMO,SAAS6hB,GACZC,EACAC,EACqB,CACrB,GAAI,CAACA,EAAU,OACX,OAEJ,MAAMzX,EAAMwX,EAAQ,gBAAgBC,EAAU,MAAOA,EAAU,MAAM,EAC/DC,EAAc1X,EAAI,MAAQA,EAAI,OAAS,EAC7C,QAAS,EAAI,EAAG,EAAI0X,EAAa,GAAK,EAClC1X,EAAI,KAAK,EAAI,CAAC,EAAIyX,EAAU,OAAO,EAAI,CAAC,EACxCzX,EAAI,KAAK,EAAI,CAAC,EAAIyX,EAAU,OAAO,EAAI,CAAC,EACxCzX,EAAI,KAAK,EAAI,CAAC,EAAIyX,EAAU,OAAO,EAAI,CAAC,EACpCA,EAAU,OAAS/F,EAAc,KACjC1R,EAAI,KAAK,EAAI,CAAC,EAAI,IAElBA,EAAI,KAAK,EAAI,CAAC,EAAI,IAAMyX,EAAU,OAAO,EAAI,CAAC,EAGtD,OAAOzX,CACX,CAMAiT,GAAWR,EAAa,EAAGX,EAAU,EACrCmB,GAAWT,GAAa,EAAGV,EAAU,EAGrC,CACI,IAAIyD,EAAI,EACJoC,EAAI,EACJtE,EAAI,EACR,QAASvc,EAAI,EAAGA,EAAI,IAAK,EAAEA,EACvB6b,GAAQ7b,CAAC,EAAIuc,EACb,EAAEsE,EACEA,IAAM,IACNA,EAAIpC,EACJ,EAAElC,EACFkC,GAAK,EAGjB,CAGA4B,GAAU,IAAI1B,GCn8Cd,SAASmC,GACLC,EACAniB,EACAoiB,EACA9gB,EACA+gB,EACM,CACN,IAAIZ,EAAUzhB,EACVsiB,EAAK,EAET,QACQC,EAAOJ,EAAMV,GAAS,EACzBa,EAAK,EAAKF,EAAO,OAClBG,EAAOJ,EAAMV,GAAS,EACxB,CACE,IAAI9K,EAAM2L,EACNjY,EAAMkY,GAAQ,EAEdC,GADcD,EAAO,KAAO,EAGhC,GAAIA,GAAQ,GAAI,CAEZ,IAAIpa,EAGJ,GAFAkC,IAEIA,IAAQ,EACR,GACIlC,EAAOga,EAAMV,GAAS,EACtBpX,GAAOlC,QACFA,IAAS,KAoBtB,GAlBAA,EAAOga,EAAMV,GAAS,EACtBe,GAAOra,EAEHA,IAAS,KACJqa,EAAMra,IAAW,OAClBqa,EAAML,EAAMV,GAAS,GAAM,EAC3Be,GAAOL,EAAMV,GAAS,EACtBe,GAAO,MAGfnY,GAAO,EACH/I,IAAStC,EAAY,OACrBqL,GAAO,GAGXmY,GAAO,EAEP7L,GAAO6L,EACH7L,IAAS2L,EAAK,EAAI,CAElB,MAAMrU,EAAI0I,EACV,KAAOtM,EAAK,EAAEA,EAAK,CACf,GAAI/I,IAAStC,EAAY,KACrBojB,EAAQE,EAAK,EAAK,CAAC,EAAIF,EAAQnU,EAAI,EAAK,CAAC,MAEzC,SAAS7M,EAAI,EAAGA,EAAI,EAAGA,IACnBghB,EAAQE,EAAK,EAAKlhB,CAAC,EAAIghB,EAAQnU,EAAI,EAAK7M,CAAC,EAGjDkhB,GACJ,CACJ,KAEI,MAAOjY,EAAK,EAAEA,EAAK,CACf,GAAI/I,IAAStC,EAAY,KACrBojB,EAAQE,EAAK,EAAK,CAAC,EAAIF,EAAQzL,EAAM,EAAK,CAAC,MAE3C,SAASvV,EAAI,EAAGA,EAAI,EAAGA,IACnBghB,EAAQE,EAAK,EAAKlhB,CAAC,EAAIghB,EAAQzL,EAAM,EAAKvV,CAAC,EAGnDkhB,IACA3L,GACJ,CAER,KAkBI,KAhBA4L,IAEIjhB,IAAStC,EAAY,KACrBojB,EAAQE,EAAK,EAAK,CAAC,EAAIH,EAAMV,GAAS,GAGtCW,EAAQE,EAAK,EAAK,CAAC,EAAIH,EAAMV,EAAU,CAAC,EACxCW,EAAQE,EAAK,EAAK,CAAC,EAAIH,EAAMV,EAAU,CAAC,EACxCW,EAAQE,EAAK,EAAK,CAAC,EAAIH,EAAMV,EAAU,CAAC,EACpCY,IACAD,EAAQE,EAAK,EAAK,CAAC,EAAI,KAE3Bb,GAAW,GAEfa,IAEK,EAAEC,EAAMA,EAAMA,IACXjhB,IAAStC,EAAY,KACrBojB,EAAQE,EAAK,EAAK,CAAC,EAAIH,EAAMV,GAAS,GAGtCW,EAAQE,EAAK,EAAK,CAAC,EAAIH,EAAMV,EAAU,CAAC,EACxCW,EAAQE,EAAK,EAAK,CAAC,EAAIH,EAAMV,EAAU,CAAC,EACxCW,EAAQE,EAAK,EAAK,CAAC,EAAIH,EAAMV,EAAU,CAAC,EACpCY,IACAD,EAAQE,EAAK,EAAK,CAAC,EAAI,KAE3Bb,GAAW,GAEfa,GAGZ,CACA,OAAOb,EAAU,CACrB,CAUA,SAASgB,GAAcC,EAAsB,CACzC,MAAMC,EAAKD,EAAI,MAAQ,EACjB/X,EAAI+X,EAAI,OACd,IAAIE,EAAQjY,EACZ,MAAMkY,EAAO,IAAI,WAAWH,EAAI,MAAQA,EAAI,OAAS,CAAC,EACtD,KAAOE,KACHC,EAAK,IAAIH,EAAI,KAAK,SAASE,EAAQD,GAAKC,EAAQ,GAAKD,CAAE,GAAIhY,EAAIiY,EAAQ,GAAKD,CAAE,EAElFD,EAAI,KAAK,IAAIG,CAAI,CACrB,CAsBO,SAASC,GACZhB,EACAiB,EACqB,CACrB,GACIA,EAAQ,OAAS/jB,EAAY,OAC7B+jB,EAAQ,OAAS/jB,EAAY,KAC/B,CACE,MAAMwJ,EAAK,IAAI,WAAWua,EAAQ,IAAI,EAChCzY,EAAMwX,EAAQ,gBAAgBiB,EAAQ,MAAOA,EAAQ,MAAM,EAI3D/iB,EAAKkiB,GACP1Z,EACA,EACA8B,EAAI,KACJtL,EAAY,MACZ+jB,EAAQ,OAAS/jB,EAAY,IAAA,EAGjC,OAAK+jB,EAAQ,UACTN,GAAcnY,CAAG,EAGjByY,EAAQ,OAAS/jB,EAAY,MAE7BkjB,GAAkB1Z,EAAIxI,EAAIsK,EAAI,KAAMtL,EAAY,KAAM,EAAK,EAGxDsL,CACX,SAAWyY,EAAQ,OAAS/jB,EAAY,KAAM,CAC1C,MAAMwJ,EAAK,IAAI,WAAWua,EAAQ,IAAI,EAChCzY,EAAMwX,EAAQ,gBAAgBiB,EAAQ,MAAOA,EAAQ,MAAM,EACjE,OAAAb,GAAkB1Z,EAAI,EAAG8B,EAAI,KAAMtL,EAAY,KAAM,EAAK,EACnDsL,CACX,CAGJ,CClMO,SAAS0Y,GACZlB,EACAmB,EACqB,CAErB,GACIA,EAAY,SAAWxkB,GAAe,QACtCwkB,EAAY,SAAWxkB,GAAe,KAEtC,OAGJ,MAAM+J,EAAK,IAAI,WAAWya,EAAY,IAAI,EACpC1hB,EAAQ0hB,EAAY,EACpBzhB,EAASyhB,EAAY,EACrBxhB,EAASwhB,EAAY,OAM3B,IAAIC,EAAY,EACZC,EAAS,EACPF,EAAY,MAAQzkB,GAAiB,WACvC0kB,GAAa1hB,EAAS,GAAKC,EAC3B0hB,EAAS,EAAI1hB,GAGjB,MAAM6I,EAAMwX,EAAQ,gBAAgBvgB,EAAOC,CAAM,EAC3C4hB,EAAM9Y,EAAI,KAQhB,QAAS3J,EAAS,EAAGA,EAASa,EAASC,EAAQyhB,GAAaC,EACxD,QAASld,EAAI,EAAGA,EAAI1E,EAAO0E,IAAKtF,GAAU,EAAGuiB,GAAa,EAEtDE,EAAIziB,EAAS,CAAC,EAAI6H,EAAG0a,EAAY,CAAC,EAClCE,EAAIziB,EAAS,CAAC,EAAI6H,EAAG0a,EAAY,CAAC,EAClCE,EAAIziB,EAAS,CAAC,EAAI6H,EAAG0a,EAAY,CAAC,EAI9BD,EAAY,SAAWxkB,GAAe,OACtC2kB,EAAIziB,EAAS,CAAC,EAAI,IAKlByiB,EAAIziB,EAAS,CAAC,EAAI6H,EAAG0a,CAAS,EAK1C,OAAO5Y,CACX,CCyHO,MAAM+Y,WAAyB1S,EAAU,CAiB5C,YAAYC,EACZ,CACI,MAAMA,CAAO,EAjBjB,KAAA,SAAyC,CAAA,EAIzC,KAAA,MAAoB,CAAA,EAGpB,KAAA,QAAuC,CAAA,CAWvC,CAMmB,sBAAsBG,EACzC,CACI,GAAIA,EAAI,OAAS3T,EAAgB,KAE7B,YAAK,mBAAmB2T,EAAI,KAAM,cAAc,EACzC,GAGX,GAAIA,EAAI,OAAS3T,EAAgB,KAE7B,YAAK,mBAAmB2T,EAAI,KAAM,cAAc,EACzC,GAGX,GAAIA,EAAI,OAAS3T,EAAgB,MACjC,CAEI,MAAMkmB,EAAU,KAAK,SAAS,KAAK,cAAe,EAClD,OAAIA,GAEAA,EAAQ,OAAO,QAAQ,QAAA,EAEpB,EACX,CAGA,OAAIvS,EAAI,OAAS3T,EAAgB,UAEtB,KAAK,eAAe2T,CAAG,EAG9BA,EAAI,OAAS3T,EAAgB,UAEtB,KAAK,eAAe2T,CAAG,EAG9BA,EAAI,OAAS3T,EAAgB,aAE7B,KAAK,mBAAmB2T,EAAI,KAAM,qBAAqB,EAChD,IAGPA,EAAI,OAAS3T,EAAgB,YAE7B,KAAK,mBAAmB2T,EAAI,KAAM,oBAAoB,EAC/C,IAGPA,EAAI,OAAS3T,EAAgB,gBAE7B,KAAK,mBAAmB2T,EAAI,KAAM,wBAAwB,EACnD,IAGPA,EAAI,OAAS3T,EAAgB,gBAE7B,KAAK,mBAAmB2T,EAAI,KAAM,wBAAwB,EACnD,IAGPA,EAAI,OAAS3T,EAAgB,aAE7B,KAAK,mBAAmB2T,EAAI,KAAM,qBAAqB,EAChD,IAGPA,EAAI,OAAS3T,EAAgB,WAE7B,KAAK,mBAAmB2T,EAAI,KAAM,mBAAmB,EAC9C,IAGPA,EAAI,OAAS3T,EAAgB,aAE7B,KAAK,mBAAmB2T,EAAI,KAAM,qBAAqB,EAChD,IAGPA,EAAI,OAAS3T,EAAgB,kBAE7B,KAAK,mBAAmB2T,EAAI,KAAM,0BAA0B,EACrD,IAGPA,EAAI,OAAS3T,EAAgB,kBAE7B,KAAK,mBAAmB2T,EAAI,KAAM,0BAA0B,EACrD,IAGPA,EAAI,OAAS3T,EAAgB,gBAE7B,KAAK,mBAAmB2T,EAAI,KAAM,wBAAwB,EACnD,IAIPA,EAAI,OAAS3T,EAAgB,UAEtB,KAAK,eAAe2T,CAAG,EAI9BA,EAAI,OAAS3T,EAAgB,eAEtB,KAAK,oBAAoB2T,CAAG,EAGnCA,EAAI,OAAS3T,EAAgB,gBAEtB,KAAK,qBAAqB2T,CAAG,EAIpCA,EAAI,OAAS3T,EAAgB,cAEtB,KAAK,mBAAmB2T,CAAG,EAGlCA,EAAI,OAAS3T,EAAgB,aAC7B2T,EAAI,OAAS3T,EAAgB,kBAEtB,KAAK,iBAAiB2T,CAAG,EAGhCA,EAAI,OAAS3T,EAAgB,uBAEtB,KAAK,2BAA2B2T,CAAG,EAG1CA,EAAI,OAAS3T,EAAgB,YAEtB,KAAK,iBAAiB2T,CAAG,EAGhCA,EAAI,OAAS3T,EAAgB,eAEtB,KAAK,oBAAoB2T,CAAG,EAGnCA,EAAI,OAAS3T,EAAgB,oBAE7B,KAAK,mBAAmB2T,EAAI,KAAM,4BAA4B,EACvD,IAIPA,EAAI,OAAS3T,EAAgB,WAEtB,KAAK,gBAAgB2T,CAAG,EAG/BA,EAAI,OAAS3T,EAAgB,mBAE7B,KAAK,mBAAmB2T,EAAI,KAAM,2BAA2B,EACtD,IAGPA,EAAI,OAAS3T,EAAgB,eAE7B,KAAK,mBAAmB2T,EAAI,KAAM,uBAAuB,EAClD,IAGPA,EAAI,OAAS3T,EAAgB,oBAE7B,KAAK,mBAAmB2T,EAAI,KAAM,oBAAoB,EAC/C,IAIPA,EAAI,OAAS3T,EAAgB,iBAE7B,KAAK,mBAAmB2T,EAAI,KAAM,yBAAyB,EACpD,IAGJ,EACX,CAWQ,eAAeA,EACvB,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,OAAO,uBAAuB,EAC5B,GAGX,MAAMwS,EAAW,IAAIxc,GAAwBgK,EAAI,IAAI,EAyBrD,GArBKwS,EAAS,KAAK,IAAI,WAAWA,EAAS,KAAK,OAAO,GAEnD,KAAK,QAAQ,wFAAwF,EAErGA,EAAS,KAAK,KAAK,OAASllB,GAAc,MAE1C,KAAK,QAAQ,8CAA8C,EAE3DklB,EAAS,KAAK,gBAAkBxkB,GAAU,QAE1C,KAAK,QAAQ,8CAAgDwkB,EAAS,KAAK,aAAa,EAExFA,EAAS,KAAK,KAAK,OAEnB,KAAK,QAAQ,8CAAgDA,EAAS,KAAK,KAAK,KAAK,EAErFA,EAAS,KAAK,KAAK,QAEnB,KAAK,QAAQ,sCAAsC,EAGnDA,EAAS,MAAQA,EAAS,KAAK,UACnC,CACI,MAAMC,EAAYD,EAAS,KAAK,UAC1BE,EAAaD,EAAU,WAW7B,GATIC,EAAW,OACXA,EAAW,QAAUllB,GAAgB,UACrCklB,EAAW,QAAUllB,GAAgB,gBAErC,KAAK,QAAQ,0CAA4CklB,EAAW,KAAK,EAC3D,KAAK,QAAQ,WAAYF,CAAQ,GAI/CE,EAAW,OAASnlB,EAAe,KACvC,CACI,MAAMglB,EAAU,KAAK,SAASC,EAAS,KAAK,SAAS,EACrD,GAAI,CAACD,EAED,YAAK,QAAQ,6BAA+BC,EAAS,KAAK,SAAS,EAC5D,GAEX,GAAI,CAACC,EAAU,KAEX,YAAK,QAAQ,kDAAkD,EACxD,GAEX,MAAME,EAAY7B,GAAsByB,EAAQ,OAAO,QAASE,EAAU,IAAI,EAC9E,OAAKE,EAME,KAAK,eAAe,CACvB,KAAMH,EAAS,KACf,QAASA,EAAS,KAAK,QACvB,UAAWG,EACX,IAAK,YAAcF,EAAU,KAAK,KAClC,SAAUA,EAAU,KAAK,OAASxH,EAAc,KAChD,WAAAyH,CAAA,CACH,GAXG,KAAK,QAAQ,4CAA4C,EAClD,GAWf,CAGA,GAAIA,EAAW,OAASnlB,EAAe,YACnCmlB,EAAW,OAASnlB,EAAe,oBACvC,CACI,MAAMqlB,EAAc,KAAK,MAAM,OAAOF,EAAW,EAAE,CAAC,EACpD,OAAKE,EAME,KAAK,eAAe,CACvB,KAAMJ,EAAS,KACf,QAASA,EAAS,KAAK,QACvB,UAAWI,EACX,IAAK,aAAeF,EAAW,GAC/B,SAAU,GACV,WAAAA,CAAA,CACH,GAXG,KAAK,QAAQ,yCAA2CA,EAAW,GAAK,YAAY,EAC7E,GAYf,CAGA,GAAIA,EAAW,OAASnlB,EAAe,QACvC,CACI,GAAIklB,EAAU,YAAc,KAExB,YAAK,QAAQ,6CAA6C,EACnD,GAEX,MAAMI,EAAgB,KAAK,SAASJ,EAAU,SAAS,EACvD,GAAI,CAACI,EAED,YAAK,QAAQ,oCAAsCJ,EAAU,UAAY,YAAY,EAC9E,GAGX,MAAMK,EAAgBD,EAAc,OAAO,QACrCE,EAAUP,EAAS,KAAK,QAExBG,EAAYG,EAAc,aAC5BC,EAAQ,KAAMA,EAAQ,IACtBA,EAAQ,MAAQA,EAAQ,KACxBA,EAAQ,OAASA,EAAQ,GAAA,EAGvBC,EAAkB,IAAI7jB,GAC5B,OAAA6jB,EAAgB,IAAM,EACtBA,EAAgB,KAAO,EACvBA,EAAgB,MAAQL,EAAU,MAClCK,EAAgB,OAASL,EAAU,OAE5B,KAAK,eAAe,CACvB,KAAMH,EAAS,KACf,QAASQ,EACT,UAAWL,EACX,IAAK,YAAcF,EAAU,UAC7B,SAAUI,EAAc,SAAW9kB,GAAgB,SACnD,WAAA2kB,CAAA,CACH,CACL,CAGA,GAAIA,EAAW,OAASnlB,EAAe,KAEnC,OAAKklB,EAAU,MAMf,KAAK,eACDD,EAAS,KACTE,EACAD,EAAU,KAAK,KACf,KACAD,EAAS,KAAK,SAAA,EAEX,KAXH,KAAK,QAAQ,kDAAkD,EACxD,IAcf,GAAIE,EAAW,OAASnlB,EAAe,WACvC,CACI,GAAI,CAACklB,EAAU,UAEX,YAAK,QAAQ,wDAAwD,EAC9D,GAIX,IAAIQ,EACJ,MAAMV,EAAU,KAAK,SAASC,EAAS,KAAK,SAAS,EACrD,OAAID,GAAWA,EAAQ,SAAWxkB,GAAgB,WAE9CklB,EAAWlB,GAAoBQ,EAAQ,OAAO,QAASE,EAAU,UAAU,KAAK,GAAK,QAGzF,KAAK,eACDD,EAAS,KACTE,EACAD,EAAU,UAAU,KACpBQ,GAAY,KACZT,EAAS,KAAK,SAAA,EAEX,EACX,CAGA,GAAIE,EAAW,OAASnlB,EAAe,OACvC,CACI,MAAMglB,EAAU,KAAK,SAASC,EAAS,KAAK,SAAS,EACrD,GAAI,CAACD,EAED,YAAK,QAAQ,+BAAiCC,EAAS,KAAK,SAAS,EAC9D,GAEX,GAAI,CAACC,EAAU,OAEX,YAAK,OAAO,aAAa,EAClB,GAGX,MAAME,EAAYV,GAAwBM,EAAQ,OAAO,QAASE,EAAU,MAAM,EAClF,OAAKE,EAOE,KAAK,eAAe,CACvB,KAAMH,EAAS,KACf,QAASA,EAAS,KAAK,QACvB,UAAWG,EACX,IAAK,UAAYF,EAAU,OAAO,OAClC,SAAUA,EAAU,OAAO,SAAW/kB,GAAe,OACrD,WAAAglB,CAAA,CACH,GAZG,KAAK,QAAQ,gDACTD,EAAU,OAAO,MAAM,EACpB,GAWf,CAGA,GAAIC,EAAW,OAASnlB,EAAe,OACvC,CACI,MAAMglB,EAAU,KAAK,SAASC,EAAS,KAAK,SAAS,EACrD,GAAI,CAACD,EAED,YAAK,QAAQ,+BAAiCC,EAAS,KAAK,SAAS,EAC9D,GAEX,GAAI,CAACC,EAAU,MAEX,YAAK,OAAO,aAAa,EAClB,GAGX,MAAME,EAAYZ,GAAoBQ,EAAQ,OAAO,QAASE,EAAU,KAAK,EAC7E,OAAKE,EAOE,KAAK,eAAe,CACvB,KAAMH,EAAS,KACf,QAASA,EAAS,KAAK,QACvB,UAAWG,EACX,IAAK,UAAYF,EAAU,MAAM,KACjC,SAAUA,EAAU,MAAM,OAASxkB,EAAY,KAC/C,WAAAykB,CAAA,CACH,GAZG,KAAK,QAAQ,8CACTD,EAAU,MAAM,IAAI,EACjB,GAWf,CAGA,YAAK,QAAQ,yCAA2CC,EAAW,IAAI,EACvE,KAAK,QAAQ,WAAYF,CAAQ,EAC1B,EACX,CAEA,YAAK,QAAQ,gCAAgC,EACtC,EACX,CAUQ,eAAexS,EACvB,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,OAAO,uBAAuB,EAC5B,GAGX,MAAMkT,EAAW,IAAIjd,GAAwB+J,EAAI,IAAI,EAiBrD,GAbIkT,EAAS,KAAK,gBAAkBllB,GAAU,QAE1C,KAAK,QAAQ,8CAAgDklB,EAAS,KAAK,aAAa,EAExFA,EAAS,KAAK,KAAK,OAEnB,KAAK,QAAQ,8CAAgDA,EAAS,KAAK,KAAK,KAAK,EAErFA,EAAS,KAAK,KAAK,QAEnB,KAAK,QAAQ,sCAAsC,EAGnDA,EAAS,KAAK,MAAM,OAASplB,GAAe,MAChD,CAEI,MAAMqlB,EAAQD,EAAS,KAAK,MAAM,MAAQ,SACpCE,EAAW,QAAUD,GAAS,IAAM,MAASA,GAAS,EAAK,KAAQ,MAAQA,EAAQ,KAAQ,IAE3FZ,EAAU,KAAK,SAASW,EAAS,KAAK,SAAS,EACrD,GAAI,CAACX,EAED,YAAK,QAAQ,wBAA0BW,EAAS,KAAK,SAAS,EACvD,GAGXX,EAAQ,OAAO,QAAQ,UAAYa,EACnCb,EAAQ,OAAO,QAAQ,SACnBW,EAAS,KAAK,IAAI,KAAMA,EAAS,KAAK,IAAI,IAC1CA,EAAS,KAAK,IAAI,MAAQA,EAAS,KAAK,IAAI,KAC5CA,EAAS,KAAK,IAAI,OAASA,EAAS,KAAK,IAAI,GAAA,EA0BjDX,EAAQ,WACZ,MAGI,KAAK,QAAQ,4CAA8CW,EAAS,KAAK,MAAM,IAAI,EAGvF,MAAO,EACX,CAUQ,eAAelT,EACvB,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,OAAO,uBAAuB,EAC5B,GAGX,MAAMqT,EAAW,IAAInd,GAAwB8J,EAAI,IAAI,EAI/CuS,EAAU,KAAK,SAASc,EAAS,KAAK,SAAS,EACrD,GAAI,CAACd,EAED,YAAK,QAAQ,wBAA0Bc,EAAS,KAAK,SAAS,EACvD,GAGX,MAAMP,EAAgBP,EAAQ,OAAO,QAErC,IAAI/hB,EAAQ+hB,EAAQ,OAAO,OAAO,MAAQc,EAAS,OAAO,EACtD5iB,EAAS8hB,EAAQ,OAAO,OAAO,OAASc,EAAS,OAAO,EACxD7iB,EAAS6iB,EAAS,KAAK,IAAI,MAAQA,EAAS,KAAK,IAAI,OAErD7iB,EAAQ6iB,EAAS,KAAK,IAAI,MAAQA,EAAS,KAAK,IAAI,MAEpD5iB,EAAU4iB,EAAS,KAAK,IAAI,OAASA,EAAS,KAAK,IAAI,MAEvD5iB,EAAS4iB,EAAS,KAAK,IAAI,OAASA,EAAS,KAAK,IAAI,KAG1D,MAAMV,EAAYG,EAAc,aAC5BO,EAAS,OAAO,EAAGA,EAAS,OAAO,EAAG7iB,EAAOC,CAAA,EAEjD,OAAA6iB,GAAsBR,EAAeH,EACjCU,EAAS,KAAK,IAAI,KAAMA,EAAS,KAAK,IAAI,GAAA,EAoB9Cd,EAAQ,YACD,EACX,CAaQ,eAAegB,EACvB,CACI,MAAMhB,EAAU,KAAK,SAASgB,EAAE,KAAK,SAAS,EAC9C,GAAI,CAAChB,EAED,YAAK,QAAQ,8BAAgCgB,EAAE,KAAK,SAAS,EACtD,GAGX,MAAMC,EAASjB,EAAQ,OAEvB,OAAIgB,EAAE,SAIEhB,EAAQ,SAAWxkB,GAAgB,UAEnC0lB,GAAWF,EAAE,SAAS,EACtBC,EAAO,QAAQ,aAAaD,EAAE,UAAWA,EAAE,KAAK,IAAI,KAAMA,EAAE,KAAK,IAAI,GAAG,GAIxED,GAAsBE,EAAO,QAASD,EAAE,UACpCA,EAAE,KAAK,IAAI,KAAMA,EAAE,KAAK,IAAI,GAAA,EAKpCC,EAAO,QAAQ,aAAaD,EAAE,UAAWA,EAAE,KAAK,IAAI,KAAMA,EAAE,KAAK,IAAI,GAAG,GAGxEA,EAAE,QAAQ,KAAO,GAAKA,EAAE,QAAQ,IAAM,IAEtC,KAAK,QAAQ,sDAAsD,EAGnEA,EAAE,YAAeA,EAAE,WAAW,MAAQ/lB,GAAgB,WAEtD,KAAK,MAAM,OAAO+lB,EAAE,WAAW,EAAE,CAAC,EAAIA,EAAE,WAuB5ChB,EAAQ,YACD,EACX,CAkBQ,eACJmB,EACAhB,EACAzhB,EACAgiB,EACA/K,EAEJ,CACI,GAAI,OAAO,SAAa,IACxB,CACI,KAAK,QAAQ,6CAA6C,EAC1D,MACJ,CAGA,IAAIyL,EAAS,mBACb,MAAMC,EAAM,IAAI,WAAW3iB,CAAQ,EACnC,QAASZ,EAAI,EAAGA,EAAIujB,EAAI,OAAQvjB,IAE5BsjB,GAAU,IACNC,EAAIvjB,CAAC,EAAK,KAEVsjB,GAAU,KAEdA,GAAUC,EAAIvjB,CAAC,EAAG,SAAS,EAAE,EAGjC,MAAMshB,EAAM,IAAI,MAGhBA,EAAI,OAAS,IACb,CACI,IAAIZ,EACA8C,EAAgB,GAEpB,MAAMtB,EAAU,KAAK,SAASrK,CAAS,EACvC,GAAKqK,EAkBDxB,EAAUwB,EAAQ,OAAO,YAjB7B,CAII,MAAMuB,EAAa,SAAS,cAAc,QAAQ,EAClDA,EAAW,aAAa,QAAS,OAAOJ,EAAK,IAAI,KAAK,CAAC,EACvDI,EAAW,aAAa,SAAU,OAAOJ,EAAK,IAAI,MAAM,CAAC,EACzD,MAAMK,EAAUD,EAAW,WAAW,IAAI,EAC1C,GAAI,CAACC,EAED,OAEJhD,EAAUgD,EACVF,EAAgB,EACpB,CAMA,GAAIZ,EACJ,CAEI,MAAMpd,EAAI,SAAS,cAAc,QAAQ,EACnCme,EAAIne,EAAE,WAAW,IAAI,EAC3B,GAAI,CAACme,EAED,OAEJne,EAAE,aAAa,QAAS,OAAOod,EAAS,KAAK,CAAC,EAC9Cpd,EAAE,aAAa,SAAU,OAAOod,EAAS,MAAM,CAAC,EAChDe,EAAE,aAAaf,EAAU,EAAG,CAAC,EAC7Be,EAAE,yBAA2B,YAC7BA,EAAE,UAAUrC,EAAK,EAAG,CAAC,EAErBZ,EAAQ,UAAUlb,EAAG6d,EAAK,IAAI,KAAMA,EAAK,IAAI,GAAG,EAE5ChB,EAAW,MAAQllB,GAAgB,WAEnC,KAAK,MAAM,OAAOklB,EAAW,EAAE,CAAC,EAC5BsB,EAAE,aAAa,EAAG,EAAGf,EAAS,MAAOA,EAAS,MAAM,EAEhE,MAIIlC,EAAQ,UAAUY,EAAK+B,EAAK,IAAI,KAAMA,EAAK,IAAI,GAAG,EAGlD/B,EAAI,OAAS,KACbA,EAAI,IAAMpZ,GAENma,EAAW,MAAQllB,GAAgB,WAEnC,KAAK,MAAM,OAAOklB,EAAW,EAAE,CAAC,EAC5B3B,EAAQ,aAAa2C,EAAK,IAAI,KAAMA,EAAK,IAAI,IACzCA,EAAK,IAAI,MAAQA,EAAK,IAAI,KAC1BA,EAAK,IAAI,OAASA,EAAK,IAAI,GAAA,GAIvC,CAACG,GAAiBtB,GAoBlBA,EAAQ,WAEhB,EAEAZ,EAAI,IAAMgC,CACd,CAaQ,QAAQM,EAAgBC,EAChC,CACI,MAAM3B,EAAU,KAAK,SAAS2B,EAAK,KAAK,SAAS,EACjD,GAAI,CAAC3B,EAED,OAGJ,IAAI1U,EAAMoW,EAAS,IAAMC,EAAK,KAAK,UAAY,IAAM3B,EAAQ,UAAY,KACzE1U,GAAO,YAAcqW,EAAK,KAAK,IAAI,KAAO,KAAOA,EAAK,KAAK,IAAI,IAAM,OAC7DA,EAAK,KAAK,IAAI,MAAQ,KAAOA,EAAK,KAAK,IAAI,OACnDrW,GAAO,eAAiBqW,EAAK,KAAK,KAAK,KAEvC,MAAMrjB,EAAOqjB,EAAK,KAClB,GAAIrjB,EACJ,CACI,GAAI,YAAaA,EACjB,CACI,MAAMkiB,EAAUliB,EAAK,QACrBgN,GAAO,cAAgBkV,EAAQ,KAAO,KAAOA,EAAQ,IAAM,OACrDA,EAAQ,MAAQ,KAAOA,EAAQ,MACzC,CAEA,GAAI,cAAeliB,GAAQA,EAAK,UAChC,CACI,MAAMsjB,EAAStjB,EAAK,UACpBgN,GAAO,oBAAsBsW,EAAO,WAAW,GAC/CtW,GAAO,sBAAwBsW,EAAO,WAAW,MAAQ,YAAcA,EAAO,WAAW,OACzFtW,GAAO,qBAAuBsW,EAAO,WAAW,KAAO,WAAaA,EAAO,WAAW,MAClFA,EAAO,YAAc,OAErBtW,GAAO,2BAA6BsW,EAAO,WAE3CA,EAAO,SAEPtW,GAAO,mBAAqBsW,EAAO,OAAO,OACtC,WAAaA,EAAO,OAAO,MAC3B,OAASA,EAAO,OAAO,EACvB,OAASA,EAAO,OAAO,EACvB,YAAcA,EAAO,OAAO,QAEhCA,EAAO,OAEPtW,GAAO,eAAiBsW,EAAO,KAAK,KAChC,WAAaA,EAAO,KAAK,MACzB,YAAcA,EAAO,KAAK,QAE9BA,EAAO,QAEPtW,GAAO,mBAAqBsW,EAAO,MAAM,OACrC,WAAaA,EAAO,MAAM,MAC1B,eAAiBA,EAAO,MAAM,QAAQ,SAAS,EAAE,EACjD,UAAYA,EAAO,MAAM,KACzB,WAAaA,EAAO,MAAM,MAC1B,YAAcA,EAAO,MAAM,OAC3B,YAAcA,EAAO,MAAM,OAC3B,cAAgBA,EAAO,MAAM,SAEzC,KACS,cAAetjB,IAEpBgN,GAAO,wBAGX,GAAI,UAAWhN,EACf,CACI,MAAMujB,EAAQvjB,EAAK,MACfujB,EAAM,OAAStmB,GAAe,QAE9B+P,GAAO,mBAAqBuW,EAAM,MAAM,SAAS,EAAE,GAEnDA,EAAM,OAAStmB,GAAe,SAAWsmB,EAAM,UAE/CvW,GAAO,eACHuW,EAAM,QAAQ,MAAQ,KAEtBvW,GAAO,eAIPA,GAAO,SAEXA,GAAO,OAASuW,EAAM,QAAQ,IAAI,EAAI,KAAOA,EAAM,QAAQ,IAAI,EAEvE,CAUA,GARI,kBAAmBvjB,IAEnBgN,GAAO,oBAAuBhN,EAAmC,eAEjE,cAAeA,IAEfgN,GAAO,gBAAmBhN,EAA+B,WAEzD,SAAUA,EACd,CACI,MAAMwjB,EAAOxjB,EAAK,KAClBgN,GAAO,gBAAkBwW,EAAK,MAC9BxW,GAAO,cAAgBwW,EAAK,IAAI,EAAI,KAAOA,EAAK,IAAI,EAChDA,EAAK,SAAW,MAEhBxW,GAAO,uBAAyBwW,EAAK,OAAO,WAAW,MAAQ,YAAcA,EAAK,OAAO,WAAW,OACpGxW,GAAO,sBAAwBwW,EAAK,OAAO,WAAW,KAAO,WAAaA,EAAK,OAAO,WAAW,OAIjGxW,GAAO,uBAEf,CACJ,CAEA,QAAQ,IAAIA,CAAG,CACnB,CAYQ,mBAAmBmC,EAC3B,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,OAAO,2BAA2B,EAChC,GAGX,MAAM7G,EAAI,IAAI7B,GAA4B0I,EAAI,IAAI,EAW9C,KAAK,QAAQ7G,EAAE,EAAE,GAEjB,QAAQ,IAAI,UAAYA,EAAE,GAAK,iBAAiB,EAIpD,MAAM2F,EAAqB,CACvB,GAAI3F,EAAE,GACN,UAAWA,EAAE,UACb,UAAWA,EAAE,UACb,YAAaA,EAAE,YACf,aAAcA,EAAE,aAChB,KAAM,CAAE,KAAMA,EAAE,KAAK,KAAM,IAAKA,EAAE,KAAK,IAAK,MAAOA,EAAE,KAAK,MAAO,OAAQA,EAAE,KAAK,MAAA,EAChF,KAAM,OACN,cAAe,EACf,MAAO,OACP,MAAO,OACP,aAAc,OACd,MAAO,CAAA,EACP,UAAW,EACX,YAAa,EACb,WAAY,GACZ,aAAc,OACd,OAAQ,OACR,cAAe,EACf,UAAW,CAAA,EAKf,GAFA,KAAK,QAAQA,EAAE,EAAE,EAAI2F,EAEjB3F,EAAE,YAAc/K,GAAoB,IACxC,CACI,GAAI,OAAO,YAAgB,KAAe,OAAO,SAAa,IAE1D,YAAK,QAAQ,yDAAyD,EAC/D,GAGX,MAAMkmB,EAAQ,IAAI,YACZC,EAAI,SAAS,cAAc,OAAO,EACxCA,EAAE,IAAM,IAAI,gBAAgBD,CAAK,EAEjCC,EAAE,aAAa,QAAS,MAAM,EAC9BA,EAAE,aAAa,WAAY,MAAM,EACjCA,EAAE,aAAa,QAAS,OAAOpb,EAAE,WAAW,CAAC,EAC7Cob,EAAE,aAAa,SAAU,OAAOpb,EAAE,YAAY,CAAC,EAE/C,IAAIqb,EAAOrb,EAAE,KAAK,KACdsb,EAAMtb,EAAE,KAAK,IACjB,MAAMoZ,EAAU,KAAK,SAASpZ,EAAE,SAAS,EAOzC,GANIoZ,IAEAiC,GAAQjC,EAAQ,OAAO,OAAO,WAC9BkC,GAAOlC,EAAQ,OAAO,OAAO,WAG7B,KAAK,QAAU,KAAK,OAAO,SAC/B,CACI,MAAM5N,EAAW,SAAS,eAAe,KAAK,OAAO,QAAQ,EACzDA,GAEAA,EAAS,YAAY4P,CAAC,CAE9B,CACAA,EAAE,aAAa,QACX,gDAAkDE,EAAM,YAAcD,EAAO,KAAA,EAEjF1V,EAAM,MAAQyV,EACdzV,EAAM,MAAQwV,EAGdA,EAAM,iBAAiB,aAAc,IACrC,CACI,KAAK,sBAAsBxV,CAAK,CACpC,EAAG,EAAK,EACRwV,EAAM,iBAAiB,cAAe,IACtC,CACI,KAAK,OAAO,kCAAkC,CAClD,EAAG,EAAK,EACRA,EAAM,iBAAiB,eAAgB,IACvC,CACI,KAAK,OAAO,mCAAmC,CACnD,EAAG,EAAK,CACZ,MACSnb,EAAE,YAAc/K,GAAoB,MAEzC0Q,EAAM,cAAgB,EAItB,QAAQ,IAAI,2BAA6B3F,EAAE,SAAS,EAGxD,MAAO,EACX,CAUQ,iBAAiB6G,EACzB,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,OAAO,yBAAyB,EAC9B,GAIX,MAAM7G,EADW6G,EAAI,OAAS3T,EAAgB,kBAExC,IAAIqL,GAA+BsI,EAAI,IAAI,EAC3C,IAAIxI,GAA0BwI,EAAI,IAAI,EAEtC0U,EAAS,KAAK,QAAQvb,EAAE,KAAK,EAAE,EACrC,GAAI,CAACub,EAED,eAAQ,IAAI,oBAAoB,EACzB,GAGX,MAAMC,EAAW,KAAK,OAChBC,EAAcD,GAAY,OAAOA,EAAS,aAAgB,WAC1DA,EAAS,cACT,EACAE,EAAe1b,EAAE,KAAK,eAAiByb,EAE7C,OAAIF,EAAO,YAActmB,GAAoB,OAEzC,KAAK,uBAAuBsmB,EAAQvb,EAAG0b,CAAY,EAGnDH,EAAO,YAActmB,GAAoB,KAEzC,KAAK,uBAAuBsmB,EAAQvb,CAAC,EAGlC,EACX,CAUQ,2BAA2B6G,EACnC,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,OAAO,mCAAmC,EACxC,GAGX,MAAM7G,EAAI,IAAItB,GAAoCmI,EAAI,IAAI,EAEpD8U,EAAS,IAAIhd,GAA6BqB,EAAE,SAAUA,EAAE,QAAQ,EAChEub,EAAS,KAAK,QAAQvb,EAAE,QAAQ,EACtC,OAAIub,IAEAA,EAAO,OAASI,EAChBJ,EAAO,cAAgBvb,EAAE,cACzBub,EAAO,UAAYvb,EAAE,WAGlB,EACX,CAUQ,iBAAiB6G,EACzB,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,OAAO,yBAAyB,EAC9B,GAGX,MAAM7G,EAAI,IAAIxB,GAA0BqI,EAAI,IAAI,EAG1C0U,EAAS,KAAK,QAAQvb,EAAE,EAAE,EAChC,OAAIub,IAEAA,EAAO,KAAOvb,EAAE,MAEb,EACX,CAWQ,oBAAoB6G,EAC5B,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,OAAO,4BAA4B,EACjC,GAGX,MAAM7G,EAAI,IAAIvB,GAA6BoI,EAAI,IAAI,EAG7C0U,EAAS,KAAK,QAAQvb,EAAE,EAAE,EAChC,GAAIub,EACJ,CACI,GAAIA,EAAO,YAActmB,GAAoB,KAAOsmB,EAAO,MAC3D,CACI,GAAI,OAAO,SAAa,KAAe,KAAK,QAAU,KAAK,OAAO,SAClE,CACI,MAAM/P,EAAW,SAAS,eAAe,KAAK,OAAO,QAAQ,EACzDA,GAAY+P,EAAO,MAAM,aAAe/P,GAExCA,EAAS,YAAY+P,EAAO,KAAK,CAEzC,CACAA,EAAO,aAAe,OACtBA,EAAO,MAAQ,OACfA,EAAO,MAAQ,MACnB,CACA,OAAO,KAAK,QAAQvb,EAAE,EAAE,CAC5B,CAEA,MAAO,EACX,CAWQ,sBAAsBub,EAC9B,CACI,GAAIA,EAAO,aAEP,OAGJ,GAAI,CAACA,EAAO,MACZ,CACI,KAAK,OAAO,mDAAqDA,EAAO,EAAE,EAC1E,MACJ,CAEA,IAAIxS,EACJ,GACA,CACIA,EAAKwS,EAAO,MAAM,gBAAgB1X,EAAc,eAAe,CACnE,MAEA,CACI,KAAK,OAAO,SAAWA,EAAc,gBAAkB,iBAAiB,EACxE,MACJ,CAEA0X,EAAO,aAAexS,EAGtB,KAAK,qBAAqBwS,CAAM,EAGhC,MAAM9a,EAAI,IAAIwF,GACR2V,EAAK,IAAInW,GAAoB8V,EAAO,YAAaA,EAAO,YAAY,EACpEV,EAAI,IAAInV,GAAWkW,CAAE,EAErBzlB,EAAK,IAAI,YAAYsK,EAAE,aAAeoa,EAAE,YAAY,EAC1D,IAAIpkB,EAASgK,EAAE,SAAStK,CAAE,EAC1B0kB,EAAE,SAAS1kB,EAAIM,CAAM,EAErBsS,EAAG,iBAAiB,QAAS,IAC7B,CACI,KAAK,OAAO,qBAAqB,CACrC,EAAG,EAAK,EAERA,EAAG,iBAAiB,YAAa,IACjC,CACI,KAAK,4BAA4BwS,CAAM,CAC3C,EAAG,EAAK,EAER,KAAK,kBAAkBA,EAAQplB,CAAE,CACrC,CAUQ,kBAAkBolB,EAAqBplB,EAC/C,CACI,GAAKolB,EAAO,aAIZ,GACA,CACIA,EAAO,WAAa,GACpBA,EAAO,aAAa,aAAaplB,CAAE,CACvC,OACOuK,EACP,CACI,MAAMmI,EAAUnI,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EACzD,KAAK,OAAO,gCAAkCmI,CAAO,CACzD,CACJ,CAWQ,4BAA4B0S,EACpC,CAEI,GAAIA,EAAO,cAAgBA,EAAO,OAClC,CACI,MAAMC,EAAW,KAAK,OAChBC,EAAcD,GAAY,OAAOA,EAAS,aAAgB,WAC1DA,EAAS,cACT,EACN,KAAK,wBACDD,EAAQA,EAAO,aAAa,UAC5BA,EAAO,aAAa,UAAYE,CAAA,CAExC,CAGA,GAAIF,EAAO,MAAM,OAAS,EAC1B,CACI,MAAMM,EAAON,EAAO,MAAM,MAAA,EAC1BA,EAAO,aAAe,CAAE,UAAWM,EAAK,SAAA,EACpCA,EAAK,IAEL,KAAK,kBAAkBN,EAAQM,EAAK,EAAE,CAE9C,MAGIN,EAAO,WAAa,GAGxB,GAAKA,EAAO,MAQZ,IAAIA,EAAO,MAAM,SAAS,OAAS,EACnC,CACI,MAAMO,EAAYP,EAAO,MAAM,SAAS,MAAMA,EAAO,MAAM,SAAS,OAAS,CAAC,EAC1EA,EAAO,MAAM,YAAcO,IAE3B,QAAQ,IAAI,qDAAuDA,CAAS,EAC5EP,EAAO,MAAM,YAAcO,EAEnC,CAGIP,EAAO,MAAM,QAAUA,EAAO,MAAM,YAAc,GAElDA,EAAO,MAAM,KAAA,EAAO,MAAM,IAAM,CAAkC,CAAC,EAM3E,CAUQ,YACJA,EACAQ,EACA5lB,EAEJ,CACQolB,EAAO,YAEPA,EAAO,aAAe,CAAE,UAAAQ,CAAA,EACxB,KAAK,kBAAkBR,EAAQplB,CAAE,GAIjColB,EAAO,MAAM,KAAK,CAAE,UAAAQ,EAAW,GAAA5lB,EAAI,CAE3C,CASQ,iBACJolB,EACA1U,EACAd,EAEJ,CACI,MAAMiW,EAAS,IAAIlW,GACfe,EAAI,KAAK,eAAiB0U,EAAO,YACjC1U,EAAI,KAAK,MAAA,EAAQ,OACjBd,CAAA,EAEE5P,EAAK,IAAI,YAAY6lB,EAAO,YAAY,EAC9CA,EAAO,SAAS7lB,CAAE,EAElB,KAAK,YAAYolB,EAAQ1U,EAAI,KAAK,eAAgB1Q,CAAE,CACxD,CAUQ,gBACJolB,EACA1U,EAEJ,CACI0U,EAAO,YAAc1U,EAAI,KAAK,eAC9B,MAAMnK,EAAI,IAAIkJ,GAAY2V,EAAO,YAAcA,EAAO,SAAS,EAEzDplB,EAAK,IAAI,YAAYuG,EAAE,YAAY,EACzCA,EAAE,SAASvG,CAAE,EAEb,KAAK,YAAYolB,EAAQ1U,EAAI,KAAK,eAAgB1Q,CAAE,EAEpD,KAAK,iBAAiBolB,EAAQ1U,EAAK,EAAI,CAC3C,CAWQ,uBACJ0U,EACA1U,EAEJ,CACQ0U,EAAO,YAAc,GAErBA,EAAO,UAAY1U,EAAI,KAAK,eAC5B,KAAK,gBAAgB0U,EAAQ1U,CAAG,GAE3BA,EAAI,KAAK,eAAiB0U,EAAO,aAAe1X,EAAc,iBAEnE,KAAK,gBAAgB0X,EAAQ1U,CAAG,EAIhC,KAAK,iBAAiB0U,EAAQ1U,EAAK,EAAK,CAEhD,CAcQ,uBACJ0U,EACAvb,EACA0b,EAEJ,CAEI,GAAIA,EAAe,GAAKH,EAAO,cAAgB,EAC/C,CACQA,EAAO,QAEPA,EAAO,OAAO,WAElB,MACJ,CAEA,GAAI,OAAO,SAAa,IAEpB,OAIJ,IAAIf,EAAS,mBACb,QAAStjB,EAAI,EAAGA,EAAI8I,EAAE,KAAK,OAAQ9I,IAE/BsjB,GAAU,IACNxa,EAAE,KAAK9I,CAAC,EAAK,KAEbsjB,GAAU,KAEdA,GAAUxa,EAAE,KAAK9I,CAAC,EAAG,SAAS,EAAE,EAIpC,MAAM+kB,EAAW,IAAIrf,GACrBqf,EAAS,UAAYV,EAAO,UAE5B,MAAMW,EAAQ,SAAUlc,GAAKA,aAAazB,GACpCyB,EAAE,KACFub,EAAO,KACbU,EAAS,IAAM,IAAIjmB,GACnBimB,EAAS,IAAI,KAAOC,EAAK,KACzBD,EAAS,IAAI,IAAMC,EAAK,IACxBD,EAAS,IAAI,MAAQC,EAAK,MAC1BD,EAAS,IAAI,OAASC,EAAK,OAG3B,MAAM1D,EAAM,IAAI,MACV5Z,EAAW2c,EAAO,GAClBQ,EAAY/b,EAAE,KAAK,eAEzBwY,EAAI,OAAS,IACb,CACI,MAAM2D,EAAe,KAAK,QAAQvd,CAAQ,EACtCud,GAEAA,EAAa,gBAGjB,IAAIvE,EACA8C,EAAgB,GAEpB,MAAMtB,EAAU,KAAK,SAAS6C,EAAS,SAAS,EAChD,GAAK7C,EAgBDxB,EAAUwB,EAAQ,OAAO,YAf7B,CAEI,MAAMuB,EAAa,SAAS,cAAc,QAAQ,EAClDA,EAAW,aAAa,QAAS,OAAOsB,EAAS,IAAI,KAAK,CAAC,EAC3DtB,EAAW,aAAa,SAAU,OAAOsB,EAAS,IAAI,MAAM,CAAC,EAC7D,MAAMrB,EAAUD,EAAW,WAAW,IAAI,EAC1C,GAAI,CAACC,EAED,OAEJhD,EAAUgD,EACVF,EAAgB,EACpB,CAqCA,GA9BA9C,EAAQ,UAAUY,EAAKyD,EAAS,IAAI,KAAMA,EAAS,IAAI,GAAG,EAG1DzD,EAAI,OAAS,KACbA,EAAI,IAAMpZ,GAEN,CAACsb,GAAiBtB,GAoBlBA,EAAQ,YAIR+C,GAAgBA,EAAa,OACjC,CACI,MAAMX,EAAW,KAAK,OAChBY,EAASZ,GAAY,OAAOA,EAAS,aAAgB,WACrDA,EAAS,cACT,EACN,KAAK,wBAAwBW,EAAcJ,EAAWA,EAAYK,CAAM,CAC5E,CACJ,EACA5D,EAAI,IAAMgC,EAEVe,EAAO,eACX,CAUQ,wBACJA,EACAQ,EACAL,EAEJ,CACI,GAAKH,EAAO,SAKZA,EAAO,OAAO,YACVA,EAAO,OAAO,mBAAqB,IAEnCA,EAAO,OAAO,iBAAmBQ,GAGjCR,EAAO,OAAO,UAAYA,EAAO,eAChCQ,EAAYR,EAAO,OAAO,iBAAoBA,EAAO,WAC1D,CACIA,EAAO,OAAO,eAAiBQ,EAC/BR,EAAO,OAAO,eAAiBG,EAE/B,MAAM7U,EAAM,IAAIhN,EAChBgN,EAAI,SAAS1T,GAAiB,cAAeooB,EAAO,MAAM,EAC1D,KAAK,QAAQ1U,CAAG,EAEhB0U,EAAO,OAAO,iBAAmB,EACjCA,EAAO,OAAO,UAAY,EAC1BA,EAAO,OAAO,SAAW,CAC7B,CACJ,CAUQ,qBAAqBA,EAC7B,CACI,GAAI,CAACA,EAAO,MAER,OAGJ,MAAMc,EAAQd,EAAO,MAEfe,EAAgB5b,GACtB,CACQ6a,EAAO,OAEiBA,EAAO,MAAM,SAAS,OAAS,GAEnD,QAAQ,IAAIA,EAAO,MAAM,YAAc,OAASA,EAAO,GACnD,UAAY7a,EAAE,KAAOX,GAAiBwb,EAAO,KAAK,CAAC,EAcvCA,EAAO,MAAM,OAAS,GAE1C,QAAQ,IAAI,eAAiBA,EAAO,MAAM,OAAS,kBAAoBA,EAAO,UAAU,CAEhG,EAEqB,CAAC,QAAS,OAAO,EASzB,QAASjf,GAAS+f,EAAM,iBAAiB/f,EAAMggB,CAAY,CAAC,CAS7E,CAMQ,oBAAoBzV,EAC5B,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,OAAO,4BAA4B,EACjC,GAGX,MAAM7G,EAAI,IAAIhD,GAAsB6J,EAAI,IAAI,EAS5C,GAAI7G,EAAE,QAAQ,SAAWpL,GAAgB,UACrCoL,EAAE,QAAQ,SAAWpL,GAAgB,SAErC,YAAK,QAAQ,uCAAyCoL,EAAE,QAAQ,OAAS,OAAO,EACzE,GAIX,GAAI,OAAO,SAAa,IAEpB,YAAK,QAAQ,kDAAkD,EACxD,GAGX,MAAMuc,EAAW,SAAS,cAAc,QAAQ,EAChDA,EAAS,aAAa,QAAS,OAAOvc,EAAE,QAAQ,KAAK,CAAC,EACtDuc,EAAS,aAAa,SAAU,OAAOvc,EAAE,QAAQ,MAAM,CAAC,EACxDuc,EAAS,aAAa,KAAM,iBAAmBvc,EAAE,QAAQ,SAAS,EAClEuc,EAAS,aAAa,WAAY,OAAOvc,EAAE,QAAQ,SAAS,CAAC,EAE7D,MAAMwc,EAAMD,EAAS,WAAW,IAAI,EACpC,GAAI,CAACC,EAED,YAAK,OAAO,wCAA0Cxc,EAAE,QAAQ,SAAS,EAClE,GAaX,MAAMyc,EAA2B,CAC7B,OAAQF,EACR,QAASC,CAAA,EAGP7W,EAAsB,CACxB,UAAW3F,EAAE,QAAQ,UACrB,MAAOA,EAAE,QAAQ,MACjB,OAAQA,EAAE,QAAQ,OAClB,OAAQA,EAAE,QAAQ,OAClB,MAAOA,EAAE,QAAQ,MACjB,OAAQyc,EACR,UAAW,CAAA,EAMf,GAHA,KAAK,SAASzc,EAAE,QAAQ,SAAS,EAAI2F,EAGjC3F,EAAE,QAAQ,MAAQhM,GACtB,CAMI,GALA,KAAK,eAAiBgM,EAAE,QAAQ,UAGhCwc,EAAI,KAAA,EAEA,KAAK,QAAU,KAAK,OAAO,SAC/B,CACI,MAAMhR,EAAW,SAAS,eAAe,KAAK,OAAO,QAAQ,EACzDA,IAEAA,EAAS,YAAY+Q,CAAQ,EAE7B/Q,EAAS,MAAM,OAASxL,EAAE,QAAQ,OAAS,KAEnD,CAEA,KAAK,WAAA,CACT,CAGA,OAAI,KAAK,WAEL,KAAK,UAAUA,EAAE,QAAQ,UAAWA,EAAE,QAAQ,MAAOA,EAAE,QAAQ,OAAQ,EAAI,EAGxE,EACX,CAMQ,qBAAqB6G,EAC7B,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,OAAO,6BAA6B,EAClC,GAGX,MAAM7G,EAAI,IAAI/C,GAAuB4J,EAAI,IAAI,EAG7C,YAAK,cAAc7G,EAAE,SAAS,EACvB,EACX,CAWA,cAAc+O,EACd,CACI,MAAMqK,EAAU,KAAK,SAASrK,CAAS,EACvC,GAAKqK,EAKL,IAAI,OAAO,SAAa,IACxB,CACI,MAAMmD,EAAWnD,EAAQ,OAAO,OAWhC,GAAI,KAAK,iBAAmBrK,IAExB,KAAK,aAAA,EACL,KAAK,eAAiB,OAElB,KAAK,QAAU,KAAK,OAAO,UAC/B,CACI,MAAMvD,EAAW,SAAS,eAAe,KAAK,OAAO,QAAQ,EACzDA,GAAY+Q,EAAS,aAAe/Q,GAEpCA,EAAS,YAAY+Q,CAAQ,CAErC,CAER,CAGI,KAAK,WAEL,KAAK,UAAUxN,EAAWqK,EAAQ,MAAOA,EAAQ,OAAQ,EAAK,EAGlE,OAAO,KAAK,SAASrK,CAAS,EAClC,CASA,iBACA,CACI,MAAM2N,EAAM,OAAO,KAAK,KAAK,QAAQ,EAAE,IAAI,MAAM,EACjD,UAAWrgB,KAAMqgB,EAEb,KAAK,cAAcrgB,CAAE,CAE7B,CAMQ,gBAAgBwK,EACxB,CACI,GAAI,CAACA,EAAI,KAEL,YAAK,OAAO,wBAAwB,EAC7B,GAGX,MAAM7G,EAAI,IAAIlB,GAAyB+H,EAAI,IAAI,EAG/C,QAAS3P,EAAI,EAAGA,EAAI8I,EAAE,MAAO9I,IAC7B,CACI,MAAMylB,EAAW3c,EAAE,UAAU9I,CAAC,EAC9B,GAAIylB,EACJ,CACI,MAAMtW,EAAM,OAAOsW,EAAS,EAAE,EAC1B,KAAK,MAAMtW,CAAG,IAAM,QAEpB,OAAO,KAAK,MAAMA,CAAG,CAE7B,CACJ,CACA,MAAO,EACX,CAYA,WAAWhK,EAAYugB,EACvB,CACI,KAAK,MAAM,OAAOvgB,CAAE,CAAC,EAAIugB,CAC7B,CAQA,eAAevgB,EACf,CACI,OAAO,KAAK,MAAM,OAAOA,CAAE,CAAC,CAChC,CAQA,gBAAgBA,EAChB,CACI,OAAO,KAAK,MAAM,OAAOA,CAAE,CAAC,IAAM,MACtC,CAYA,WAAW0S,EACX,CACI,OAAO,KAAK,SAASA,CAAS,CAClC,CAOA,mBACA,CACI,GAAI,KAAK,iBAAmB,OAI5B,OAAO,KAAK,SAAS,KAAK,cAAc,CAC5C,CAcA,YACA,CACI,GAAI,KAAK,iBAAmB,OAExB,OAGJ,MAAMqK,EAAU,KAAK,SAAS,KAAK,cAAc,EACjD,GAAI,CAACA,EAED,OAGJ,MAAMmD,EAAWnD,EAAQ,OAAO,OAGhC,GAAI,KAAK,OACT,CACI,MAAMoC,EAAW,KAAK,OAClB,OAAOA,EAAS,mBAAsB,aAEtC,KAAK,cAAgB,IAAMA,EAAS,kBAAA,EAGpC,KAAK,cAAA,EAELe,EAAS,iBAAiB,QAAS,KAAK,aAAa,EAE7D,CAEAA,EAAS,MAAA,CACb,CAKA,cACA,CACI,GAAI,KAAK,iBAAmB,OAExB,OAGJ,MAAMnD,EAAU,KAAK,SAAS,KAAK,cAAc,EACjD,GAAI,CAACA,EAED,OAGJ,MAAMmD,EAAWnD,EAAQ,OAAO,OAE5B,KAAK,gBAELmD,EAAS,oBAAoB,QAAS,KAAK,aAAa,EACxD,KAAK,cAAgB,OAE7B,CAMS,SACT,CACI,KAAK,gBAAA,EACL,KAAK,MAAQ,CAAA,EACb,KAAK,QAAU,CAAA,EACf,MAAM,QAAA,CACV,CACJ,CAiBA,SAASpC,GACLvC,EACAiF,EACA9gB,EACAC,EAEJ,CACI,GAAI,OAAO,SAAa,IAEpB,OAEJ,MAAMU,EAAI,SAAS,cAAc,QAAQ,EACnCme,EAAIne,EAAE,WAAW,IAAI,EACtBme,IAILne,EAAE,aAAa,QAAS,OAAOmgB,EAAE,KAAK,CAAC,EACvCngB,EAAE,aAAa,SAAU,OAAOmgB,EAAE,MAAM,CAAC,EACzChC,EAAE,aAAagC,EAAG,EAAG,CAAC,EACtBjF,EAAQ,UAAUlb,EAAGX,EAAGC,EAAG6gB,EAAE,MAAOA,EAAE,MAAM,EAChD,CASA,SAASvC,GAAWuC,EACpB,CACI,QAAS3lB,EAAI,EAAGA,EAAK2lB,EAAE,MAAQA,EAAE,OAAS,EAAI3lB,GAAK,EAE/C2lB,EAAE,KAAK3lB,EAAI,CAAC,EAAI,GAExB,CAwBA2Q,GAAuB9T,EAAa,QAASolB,EAAgB,EC3zE7D,SAAS2D,GAAc1lB,EAAcyD,EACrC,CACI,MAAMgM,EAAM,IAAIhN,EAChB,OAAAgN,EAAI,SAASzP,EAAMyD,CAAO,EACnBgM,CACX,CAeA,SAASkW,GAAiBC,EAC1B,CACI,OAAQA,EAAA,CAEJ,IAAK,GAAG,OAAOtoB,GAAiB,KAChC,IAAK,GAAG,OAAOA,GAAiB,OAChC,IAAK,GAAG,OAAOA,GAAiB,MAChC,QAAS,OAAOA,GAAiB,OAAA,CAEzC,CAWA,SAASuoB,GAAiBC,EAC1B,CACI,IAAIhC,EAAO,EACX,OAAIgC,EAAa,IAAKhC,GAAQzmB,GAAqB,MAC/CyoB,EAAa,IAAKhC,GAAQzmB,GAAqB,QAC/CyoB,EAAa,IAAKhC,GAAQzmB,GAAqB,OAC5CymB,CACX,CAkBA,MAAMiC,GAAgB,MAMf,MAAMC,WAAwB3W,EAAU,CAqB3C,YAAYC,EACZ,CACI,MAAMA,CAAO,EArBjB,KAAA,OAA6B,OAC7B,KAAA,OAA6B,OAC7B,KAAA,YAAsB,EACtB,KAAA,cAAwB,EAGxB,KAAA,UAAoB,EAIpB,KAAA,kBAA4B,EAE5B,KAAQ,UAA2B,CAC/B,MAAO,GACP,KAAM,GACN,IAAK,GACL,KAAM,EAAA,CAMV,CAMmB,sBAAsBG,EACzC,CACI,GAAIA,EAAI,OAASzT,GAAe,KAChC,CACI,GAAI,CAACyT,EAAI,KAAQ,MAAO,GACxB,MAAMwW,EAAO,IAAIngB,GAAmB2J,EAAI,IAAI,EAC5C,YAAK,kBAAoBwW,EAAK,kBAGvB,EACX,CAEA,GAAIxW,EAAI,OAASzT,GAAe,cAChC,CACI,GAAI,CAACyT,EAAI,KAAQ,MAAO,GACxB,MAAMR,EAAM,IAAIlJ,GAA2B0J,EAAI,IAAI,EACnD,YAAK,kBAAoBR,EAAI,kBAGtB,EACX,CAEA,OAAIQ,EAAI,OAASzT,GAAe,kBAG5B,KAAK,eAAiB2B,GACf,IAGJ,EACX,CAkBA,cAAc2L,EACd,CACI,MAAMb,EAAWD,GAAmBc,EAAE,QAASA,EAAE,IAAI,EACrD,GAAIb,IAAa,EAEb,OAGJ,KAAK,wBAAwBa,EAAGb,CAAQ,EAExC,MAAMwG,EAAM,IAAIrI,GAAiB6B,CAAQ,EACnCyd,EAASR,GAAczpB,EAAgB,SAAUgT,CAAG,EACtD,KAAK,QAAU,SAEf,KAAK,QAAQiX,CAAM,EAGvB5c,EAAE,eAAA,CACN,CAQA,YAAYA,EACZ,CACI,MAAMb,EAAWC,GAAiBY,EAAE,QAASA,EAAE,IAAI,EACnD,GAAIb,IAAa,EAEb,OAGJ,KAAK,wBAAwBa,EAAGb,CAAQ,EAExC,MAAMwG,EAAM,IAAInI,GAAe2B,CAAQ,EACjCyd,EAASR,GAAczpB,EAAgB,OAAQgT,CAAG,EACpD,KAAK,QAAU,SAEf,KAAK,QAAQiX,CAAM,EAGvB5c,EAAE,eAAA,CACN,CAYA,gBACA,CACI,GAAI,KAAK,QAAU,QAEf,OAGJ,KAAK,eAAe,GAAMzB,EAAS,SAAS,EAC5C,KAAK,eAAe,GAAMA,EAAS,OAAO,EAE1C,MAAMse,EAAate,EAAS,eACtBue,EAAU,IAAIxf,GAAiBuf,CAAU,EACzCE,EAAUX,GAAczpB,EAAgB,SAAUmqB,CAAO,EAC/D,KAAK,QAAQC,CAAO,EAGpB,MAAMC,EAAQ,IAAIxf,GAAeqf,EAAa,GAAI,EAC5CI,EAAQb,GAAczpB,EAAgB,OAAQqqB,CAAK,EACzD,KAAK,QAAQC,CAAK,EAEd,KAAK,UAAU,OAAS,GAExB,KAAK,eAAe,GAAO1e,EAAS,SAAS,EAE7C,KAAK,UAAU,MAAQ,GAEvB,KAAK,eAAe,GAAOA,EAAS,OAAO,CAEnD,CAYQ,eAAe6V,EAAgB7W,EACvC,CACI,MAAM4I,EAAMiO,EACNgI,GAAczpB,EAAgB,SAAU,IAAI2K,GAAiBC,CAAI,CAAC,EAClE6e,GAAczpB,EAAgB,OAAQ,IAAI6K,GAAeD,EAAO,GAAI,CAAC,EAE3E,KAAK,QAAQ4I,CAAG,CACpB,CAWQ,wBAAwBnG,EAAkBzC,EAClD,CAEQ,KAAK,UAAU,QAAU,KAEzB,KAAK,UAAU,MAAQyC,EAAE,SAAW,EAAI,EACxC,KAAK,UAAU,KAAOA,EAAE,QAAU,EAAI,EACtC,KAAK,UAAU,IAAMA,EAAE,OAAS,EAAI,EACpC,KAAK,UAAU,KAAOA,EAAE,QAAU,EAAI,GAItCzC,IAASgB,EAAS,WAElB,KAAK,UAAU,MAAQ,EAElBhB,IAASgB,EAAS,QAEvB,KAAK,UAAU,IAAM,EAEhBhB,IAASgB,EAAS,UAEvB,KAAK,UAAU,KAAO,EAEjBhB,IAASkf,GAEd,KAAK,UAAU,KAAO,EAEjBlf,KAAU,IAAOgB,EAAS,YAE/B,KAAK,UAAU,MAAQ,EAElBhB,KAAU,IAAOgB,EAAS,SAE/B,KAAK,UAAU,IAAM,EAEhBhB,KAAU,IAAOgB,EAAS,WAE/B,KAAK,UAAU,KAAO,EAEjBhB,KAAU,MAASkf,MAExB,KAAK,UAAU,KAAO,GAItB,KAAK,QAAU,UAKf,KAAK,UAAU,SAAWzc,EAAE,SAAW,EAAI,KAE3C,QAAQ,IAAI,yBAAyB,EACrC,KAAK,eAAeA,EAAE,SAAUzB,EAAS,UAAU,EACnD,KAAK,UAAU,MAAQyB,EAAE,SAAW,EAAI,GAExC,KAAK,UAAU,OAASA,EAAE,OAAS,EAAI,KAEvC,QAAQ,IAAI,uBAAuB,EACnC,KAAK,eAAeA,EAAE,OAAQzB,EAAS,OAAO,EAC9C,KAAK,UAAU,IAAMyB,EAAE,OAAS,EAAI,GAEpC,KAAK,UAAU,QAAUA,EAAE,QAAU,EAAI,KAEzC,QAAQ,IAAI,wBAAwB,EACpC,KAAK,eAAeA,EAAE,QAASzB,EAAS,SAAS,EACjD,KAAK,UAAU,KAAOyB,EAAE,QAAU,EAAI,GAEtC,KAAK,UAAU,QAAUA,EAAE,QAAU,EAAI,KAEzC,QAAQ,IAAI,wBAAwB,EACpC,KAAK,eAAeA,EAAE,QAASyc,EAAa,EAC5C,KAAK,UAAU,KAAOzc,EAAE,QAAU,EAAI,GAE9C,CAmBA,gBAAgBA,EAAe/C,EAAoB,EACnD,CACI,GAAI,KAAK,QAAU,SAMf,OAAK,eAAiB,EAAI5I,IAM9B,IAAI,KAAK,YAAcb,GAAe,OACtC,CACI,MAAM0pB,EAAO,IAAIngB,GACbiD,EAAE,QAASA,EAAE,QAAS,KAAK,YAAa/C,CAAA,EAEtCkJ,EAAMiW,GAAczpB,EAAgB,eAAgBuqB,CAAI,EAC9D,KAAK,QAAQ/W,CAAG,CACpB,KAEA,CACI,MAAM+W,EAAO,IAAIhgB,GACb8C,EAAE,UAAWA,EAAE,UAAW,KAAK,YAAa/C,CAAA,EAE1CkJ,EAAMiW,GAAczpB,EAAgB,aAAcuqB,CAAI,EAC5D,KAAK,QAAQ/W,CAAG,CACpB,CAEA,KAAK,gBACT,CAUA,gBAAgBnG,EAChB,CACI,GAAI,KAAK,QAAU,QAEf,OAGJ,MAAM5C,EAASif,GAAiBrc,EAAE,MAAM,EACxC,KAAK,YAAcuc,GAAiBvc,EAAE,OAAO,EAE7C,MAAMmd,EAAQ,IAAIhgB,GAAoBC,EAAQ,KAAK,WAAW,EACxD+I,EAAMiW,GAAczpB,EAAgB,YAAawqB,CAAK,EAC5D,KAAK,QAAQhX,CAAG,EAEhBnG,EAAE,eAAA,CACN,CAOA,cAAcA,EACd,CACI,GAAI,KAAK,QAAU,QAEf,OAGJ,MAAM5C,EAASif,GAAiBrc,EAAE,MAAM,EACxC,KAAK,YAAcuc,GAAiBvc,EAAE,OAAO,EAE7C,MAAMod,EAAU,IAAI/f,GAAsBD,EAAQ,KAAK,WAAW,EAC5D+I,EAAMiW,GAAczpB,EAAgB,cAAeyqB,CAAO,EAChE,KAAK,QAAQjX,CAAG,EAEhBnG,EAAE,eAAA,CACN,CASA,iBAAiBA,EACjB,CACI,GAAI,KAAK,QAAU,QAEf,OAGJ,MAAM5C,EAAS4C,EAAE,OAAS,EACpBhM,GAAiB,GACjBA,GAAiB,KAEjBmpB,EAAQ,IAAIhgB,GAAoBC,EAAQ,CAAC,EACzCigB,EAAWjB,GAAczpB,EAAgB,YAAawqB,CAAK,EACjE,KAAK,QAAQE,CAAQ,EAErB,MAAMD,EAAU,IAAI/f,GAAsBD,EAAQ,CAAC,EAC7CkgB,EAAalB,GAAczpB,EAAgB,cAAeyqB,CAAO,EACvE,KAAK,QAAQE,CAAU,EAEvBtd,EAAE,eAAA,CACN,CAQA,kBAAkBA,EAClB,CACIA,EAAE,eAAA,CACN,CACJ,CAMAmH,GAAuB9T,EAAa,OAAQqpB,EAAe,EC/e3D,SAASa,GAAc5mB,EAAeC,EAAgBqX,EACtD,CACI,GAAI,OAAO,SAAa,IAEpB,MAAM,IAAI,MAAM,qDAAqD,EAGzE,MAAMrQ,EAAK,IAAI,WAAWqQ,CAAK,EACzBuP,EAAU,IAAI,kBAAkB5f,EAAG,OAAQA,EAAG,WAAYA,EAAG,UAAU,EACvEse,EAAY,IAAI,UAAUsB,EAAS7mB,EAAOC,CAAM,EAEhD+iB,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,MAAQhjB,EACfgjB,EAAO,OAAS/iB,EAChB,MAAMklB,EAAMnC,EAAO,WAAW,IAAI,EAClC,GAAI,CAACmC,EAED,MAAM,IAAI,MAAM,sCAAsC,EAE1D,OAAAA,EAAI,aAAaI,EAAW,EAAG,CAAC,EACzBvC,EAAO,UAAU,WAAW,CACvC,CC3BA,eAAe8D,GAAKC,EACpB,CACI,MAAM1mB,EAAO,IAAI,cAAc,OAAO0mB,CAAK,EACrCC,EAAa,MAAM,OAAO,OAAO,OAAO,QAAS3mB,CAAI,EACrDiX,EAAQ,IAAI,WAAW0P,CAAU,EACvC,OAAO,MAAM,KAAK1P,EAAQ5K,GAAMA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAC5E,CAuBA,SAASua,GAAkB9F,EAAuB+F,EAClD,CACI,MAAMC,EAAKhG,EACX,OAAAgG,EAAG,YAAcD,EACjBC,EAAG,UAAY,EACfA,EAAG,UAAY,EACRA,CACX,CAOA,MAAMC,GAAsC,CAAA,EAGtCC,GAAyC,CAAA,EAE/C,IAAIC,GAAS,GAQb,SAASC,GAAUC,EAAc9T,EACjC,CACI0T,GAAYI,CAAI,EAAI9T,CACxB,CAMA,SAAS+T,GAAcD,EAAcE,EACrC,CACSJ,KAEDA,GAAS,GACL,OAAO,OAAW,KAAe,OAAO,OAAO,OAAU,YAEzD,OAAO,MACH;AAAA;AAAA,uMAAA,GAUPD,GAAeG,CAAI,IAEpBH,GAAeG,CAAI,EAAIE,EACvB,QAAQ,IACJ,oJAAA,EAGJ,QAAQ,IACJ,kCAAoCF,EAAO,+BAAA,EAGvD,CAQA,SAASG,GAAoBte,EAAe3G,EAC5C,CACI,MAAMklB,EAAM,IAAI,WAAWve,EAAE,KAAM,CAC/B,QAAS,GACT,WAAY,GACZ,KAAMA,EAAE,KACR,OAAQA,EAAE,OACV,QAASA,EAAE,QACX,QAASA,EAAE,QACX,QAASA,EAAE,QACX,QAASA,EAAE,QACX,QAASA,EAAE,QACX,OAAQA,EAAE,OACV,SAAUA,EAAE,SACZ,QAASA,EAAE,QACX,OAAQA,EAAE,OACV,cAAeA,EAAE,aAAA,CACpB,EACD,OAAO3G,EAAO,cAAcklB,CAAG,CACnC,CAyBA,eAAeC,GACX5e,EACA6e,EACAZ,EACAQ,EAEJ,CACI,GAAI,OAAO,SAAa,IACpB,OAEJ,MAAMK,EAAY,MAAMjB,GACpBY,EAAU,IAAMI,EAAO,OAAO,SAAW,IAAMA,EAAO,OAAO,QAAA,EAI3DE,EAASZ,GAAYW,CAAS,EACpC,GAAIC,IAAW,OACf,CACI,MAAMC,EAAS,OAASD,EAAS,aACjCd,EAAO,MAAM,OAASe,CAC1B,CAEA,GAAI,OAAO,OAAW,KAAe,OAAO,iBAAiBf,EAAQ,IAAI,EAAE,SAAW,OACtF,CAKI,GAJAO,GAAcM,EAAWL,CAAO,EAEhCR,EAAO,MAAM,OAAS,OAElB,CAACje,EAAM,gBACX,CACI,MAAMkY,EAAM8F,GAAkB,SAAS,cAAc,KAAK,EAAGC,CAAM,EAEnE/F,EAAI,MAAM,SAAW,WACrBA,EAAI,MAAM,QAAU,OACpBA,EAAI,MAAM,SAAW,SAErBA,EAAI,YAAc+F,EAElB,MAAMzS,EAAWpL,GACjB,CACIse,GAAoBte,EAAG6d,CAAM,CACjC,EACA/F,EAAI,iBAAiB,YAAa1M,CAAO,EACzCxL,EAAM,uBAAyBwL,EAE/ByS,EAAO,YAAY/F,CAAG,EACtBlY,EAAM,gBAAkBkY,CAC5B,CAEAlY,EAAM,gBAAgB,IAAMye,EAE5Bze,EAAM,gBAAgB,UAAY6e,EAAO,OAAO,SAChD7e,EAAM,gBAAgB,UAAY6e,EAAO,OAAO,SAEhD7e,EAAM,gBAAgB,MAAM,cAAgB,MAChD,MAGQA,EAAM,kBAENA,EAAM,gBAAgB,YAAY,YAAYA,EAAM,eAAe,EACnEA,EAAM,gBAAkB,OAGpC,CAKA,SAASif,GAAuBjf,EAChC,CACQA,EAAM,kBAEFA,EAAM,yBAENA,EAAM,gBAAgB,oBAAoB,YAAaA,EAAM,sBAAsB,EACnFA,EAAM,uBAAyB,QAE/BA,EAAM,gBAAgB,YAEtBA,EAAM,gBAAgB,WAAW,YAAYA,EAAM,eAAe,EAEtEA,EAAM,gBAAkB,OAEhC,CAEO,MAAMkf,GAAsB,CAC/B,UAAAZ,GACA,eAAAM,GACA,uBAAAK,EACJ,ECxMO,MAAME,WAAwBhZ,EACrC,CAOI,YAAYC,EACZ,CACI,MAAMA,CAAO,EAPjB,KAAA,gBAAkD,OAGlD,KAAA,uBAAgE,MAKhE,CAMmB,sBAAsBG,EACzC,CACI,GAAI,CAACA,EAAI,KAEL,MAAO,GAGX,GAAIA,EAAI,OAASvT,GAAe,KAChC,CACI,MAAMosB,EAAa,IAAItiB,GAAmByJ,EAAI,IAAI,EAG5Ca,EAAI,KAAK,OACf,OAAIA,GAAKA,EAAE,QACPA,EAAE,OAAO,YAAcxT,GAAe,SAMtCwT,EAAE,OAAO,OAASgY,EAAW,SAAS,EACtChY,EAAE,OAAO,OAASgY,EAAW,SAAS,GAGnC,EACX,CAEA,GAAI7Y,EAAI,OAASvT,GAAe,IAChC,CACI,MAAMqsB,EAAY,IAAIniB,GAAkBqJ,EAAI,IAAI,EAGhD,GAAI8Y,EAAU,OAAO,MAAQnrB,GAAiB,KAC9C,CACI,MAAM+pB,EAAS,KAAK,UAAA,EACpB,OAAIA,IAEAA,EAAO,MAAM,OAAS,QAEnB,EACX,CAOA,OALIoB,EAAU,OAAO,MAAQ,GAEzB,KAAK,QAAQ,sCAAwCA,EAAU,OAAO,KAAK,EAG3EA,EAAU,OAAO,QACjBA,EAAU,OAAO,OAAO,OAAS3qB,GAAgB,OAEjD,KAAK,QACD,qCAAuC2qB,EAAU,OAAO,OAAO,IAAA,EAE5D,KAGPA,EAAU,OAAO,QAEjB,KAAK,UAAU,CACX,OAAQA,EAAU,OAAO,OACzB,KAAMA,EAAU,OAAO,IAAA,CAC1B,EAGE,GACX,CAEA,GAAI9Y,EAAI,OAASvT,GAAe,KAE5B,YAAK,mBAAmBuT,EAAI,KAAM,aAAa,EACxC,GAGX,GAAIA,EAAI,OAASvT,GAAe,KAChC,CAEI,MAAMirB,EAAS,KAAK,UAAA,EACpB,OAAIA,IAEAA,EAAO,MAAM,OAAS,QAEnB,EACX,CAEA,GAAI1X,EAAI,OAASvT,GAAe,MAE5B,YAAK,mBAAmBuT,EAAI,KAAM,cAAc,EACzC,GAGX,GAAIA,EAAI,OAASvT,GAAe,MAChC,CAEI,MAAMirB,EAAS,KAAK,UAAA,EACpB,OAAIA,IAEAA,EAAO,MAAM,OAAS,QAEnB,EACX,CAEA,OAAI1X,EAAI,OAASvT,GAAe,WAE5B,KAAK,mBAAmBuT,EAAI,KAAM,kBAAkB,EAC7C,IAGPA,EAAI,OAASvT,GAAe,SAQpC,CAMQ,UAAU6rB,EAClB,CACI,MAAMJ,EAAUd,GACZkB,EAAO,OAAO,MACdA,EAAO,OAAO,OACdA,EAAO,IAAA,EAGLG,EACF,OAASP,EAAU,KACnBI,EAAO,OAAO,SAAW,IAAMA,EAAO,OAAO,SAC7C,YAEEZ,EAAS,KAAK,UAAA,EACfA,IAKLA,EAAO,MAAM,OAAS,OACtBA,EAAO,MAAM,OAASe,EAElB,OAAO,OAAW,KAClB,OAAO,iBAAiBf,EAAQ,IAAI,EAAE,SAAW,QAEjDiB,GAAoB,eAChB,KACAL,EACAZ,EACAQ,CAAA,EAGZ,CAMQ,WACR,CACI,GAAI,OAAO,SAAa,IAEpB,OAAO,KAEX,MAAMrX,EAAI,KAAK,OACTyG,EAAWzG,EAAIA,EAAE,SAAW,KAAK,SACvC,OAAKyG,EAIE,SAAS,eAAeA,CAAQ,EAF5B,IAGf,CAMS,SACT,CACIqR,GAAoB,uBAAuB,IAAI,EAC/C,MAAM,QAAA,CACV,CACJ,CAMA3X,GAAuB9T,EAAa,OAAQ0rB,EAAe,ECrN3D,SAASG,GAAcC,EACvB,CACI,GAAIA,EAAM,SAAW,EAEjB,OAAOA,EAAM,MAAA,EAGjB,IAAI1f,EAAM,EACV,QAASjJ,EAAI,EAAGA,EAAI2oB,EAAM,OAAQ3oB,IAE9BiJ,GAAO0f,EAAM3oB,CAAC,EAAG,WAGrB,MAAMf,EAAK,IAAI,YAAYgK,CAAG,EACxB2f,EAAM,IAAI,WAAW3pB,CAAE,EAC7B,IAAIM,EAAS,EACb,QAASS,EAAI,EAAGA,EAAI2oB,EAAM,OAAQ3oB,IAE9B4oB,EAAI,IAAI,IAAI,WAAWD,EAAM3oB,CAAC,CAAE,EAAGT,CAAM,EACzCA,GAAUopB,EAAM3oB,CAAC,EAAG,WAExB,OAAA2oB,EAAM,OAAS,EACR1pB,CACX,CAMO,MAAM4pB,WAA0BtZ,EACvC,CAoCI,YAAYC,EACZ,CACI,MAAMA,CAAO,EApCjB,KAAQ,MAAuB,CAAA,EAG/B,KAAQ,WAAa,GAGrB,KAAQ,UAAY,EAGpB,KAAQ,YAAc,EAGtB,KAAQ,aAAe,EAGvB,KAAQ,aAAe,EAGvB,KAAQ,YAAuC,OAG/C,KAAQ,aAAyC,OAGjD,KAAQ,aAA6C,OAIrD,KAAiB,aAAe,IAAY,CAAE,KAAK,iBAAA,CAAoB,EACvE,KAAiB,cAAgB,IAAY,CAAE,KAAK,kBAAA,CAAqB,EACzE,KAAiB,eAAiB,IAAY,CAAE,KAAK,mBAAA,CAAsB,EAC3E,KAAiB,oBAAuB,GAAmB,CAAE,KAAK,wBAAwB,CAAC,CAAG,EAC9F,KAAiB,mBAAqB,IAAY,CAAE,KAAK,uBAAA,CAA0B,CAKnF,CAMmB,sBAAsBG,EACzC,CACI,GAAI,CAACA,EAAI,KAEL,MAAO,GAGX,GAAI,OAAO,YAAgB,IAEvB,YAAK,OAAO,kCAAkC,EACvC,GAGX,GAAIA,EAAI,OAAStT,GAAiB,MAClC,CACI,MAAM8T,EAAQ,IAAI9J,GAAsBsJ,EAAI,IAAI,EAMhD,GAAIQ,EAAM,YAAcxD,EAAc,eAElC,YAAK,OAAO,uCAAyCwD,EAAM,SAAS,EAC7D,GAGX,GAAIA,EAAM,WAAaxD,EAAc,cAEjC,YAAK,OAAO,6BAA+BwD,EAAM,SAAW,WAAW,EAChE,GAGX,GAAIA,EAAM,SAAWvT,GAAc,IAE/B,YAAK,OAAO,oCAAsCuT,EAAM,MAAM,EACvD,GAGX,GAAI,CAAC,KAAK,aACV,CACI,KAAK,YAAc,IAAI,YAEvB,KAAK,aAAe,SAAS,cAAc,OAAO,EAClD,KAAK,aAAa,aAAa,WAAY,MAAM,EACjD,KAAK,aAAa,IAAM,IAAI,gBAAgB,KAAK,WAAW,EAE5D,MAAM8G,EAAW,KAAK,OAAS,KAAK,OAAO,SAAW,KAAK,SAC3D,GAAIA,EACJ,CACI,MAAMoQ,EAAS,SAAS,eAAepQ,CAAQ,EAC3CoQ,GAEAA,EAAO,YAAY,KAAK,YAAY,CAE5C,CAEA,YAAK,YAAY,iBAAiB,aAAc,KAAK,aAAc,EAAK,EACxE,KAAK,YAAY,iBAAiB,cAAe,KAAK,cAAe,EAAK,EAC1E,KAAK,YAAY,iBAAiB,eAAgB,KAAK,eAAgB,EAAK,EAE5E,KAAK,aAAe,EAEb,EACX,CACJ,CAEA,GAAI1X,EAAI,OAAStT,GAAiB,KAClC,CACI,MAAMmE,EAAO,IAAI2F,GAAqBwJ,EAAI,IAAI,EAE9C,GAAI,CAAC,KAAK,aAEN,MAAO,GAIX,GAAI,KAAK,cACL,KAAK,aAAa,YAAc,GAChC,KAAK,aAAa,SAAS,OAAS,GACpC,KAAK,aAAa,cAAgB,KAAK,aAAa,SAAS,IAAI,CAAC,GAClE,KAAK,aAAa,YAAc,KAAK,aAAa,SAAS,MACvD,KAAK,aAAa,SAAS,OAAS,CAAA,EAE5C,CACI,MAAMmZ,EAAU,KAAK,aAAa,SAAS,MACvC,KAAK,aAAa,SAAS,OAAS,CAAA,EAExC,QAAQ,IACJ,iEAAmEA,CAAA,EAEvE,KAAK,aAAa,YAAcA,CACpC,CAeA,OAAI,KAAK,YAAc,GACnBtoB,EAAK,OAAU,KAAK,aAAemM,EAAc,0BAE7C,KAAK,IAAInM,EAAK,MAAQmM,EAAc,yBAA2B,KAAK,aAAa,EACjFA,EAAc,mBAMdnM,EAAK,KAAO,KAAK,aAAemM,EAAc,0BAWtD,KAAK,aAAenM,EAAK,KAOrB,KAAK,YAAc,EAEnB,KAAK,cAAcA,CAAI,EAElBA,EAAK,KAAO,KAAK,aAAemM,EAAc,iBAEnD,KAAK,WAAWnM,CAAI,EAIpB,KAAK,YAAYA,EAAM,EAAK,EAGzB,EACX,CAEA,GAAImP,EAAI,OAAStT,GAAiB,KAClC,CACI,MAAMgI,EAAO,IAAI+B,GAAqBuJ,EAAI,IAAI,EAC9C,OAAItL,EAAK,OAAS1H,GAAmB,OAEjC,KAAK,OAAO,kCAAoC0H,EAAK,IAAI,EACzD,KAAK,aAAe,QAEjB,EACX,CAEA,OAAIsL,EAAI,OAAStT,GAAiB,MAG1B,KAAK,cAEL,KAAK,aAAA,EACE,IAIXsT,EAAI,OAAStT,GAAiB,QAE9B,KAAK,mBAAmBsT,EAAI,KAAM,iBAAiB,EAC5C,IAGPA,EAAI,OAAStT,GAAiB,MAE9B,KAAK,mBAAmBsT,EAAI,KAAM,eAAe,EAC1C,IAGPA,EAAI,OAAStT,GAAiB,SAE9B,KAAK,mBAAmBsT,EAAI,KAAM,kBAAkB,EAC7C,IAGJ,EACX,CAOQ,cAAcnP,EACtB,CACI,GAAI,CAAC,KAAK,aAEN,OAGJ,KAAK,UAAYA,EAAK,KAEtB,MAAM+I,EAAI,IAAIwF,GACR2V,EAAK,IAAIpW,GACTqV,EAAI,IAAInV,GAAWkW,CAAE,EAErBzlB,EAAK,IAAI,YAAYsK,EAAE,aAAeoa,EAAE,YAAY,EAE1D,KAAK,aAAepa,EAAE,SAAStK,EAAI,CAAC,EACpC,KAAK,aAAe0kB,EAAE,SAAS1kB,EAAI,KAAK,YAAY,EAEpD,KAAK,aAAa,iBAAiB,QAAS,KAAK,oBAAqB,EAAK,EAC3E,KAAK,aAAa,iBAAiB,YAAa,KAAK,mBAAoB,EAAK,EAC9E,KAAK,aAAaA,CAAE,EAEpB,KAAK,WAAWuB,CAAI,CACxB,CAGQ,WAAWA,EACnB,CACI,KAAK,YAAcA,EAAK,KAExB,MAAMgF,EAAI,IAAIkJ,GAAYlO,EAAK,KAAO,KAAK,SAAS,EAE9CvB,EAAK,IAAI,YAAYuG,EAAE,YAAY,EACzC,KAAK,cAAgBA,EAAE,SAASvG,EAAI,CAAC,EAEjC,KAAK,WAEL,KAAK,aAAaA,CAAE,EAIpB,KAAK,MAAM,KAAKA,CAAE,EAGtB,KAAK,YAAYuB,EAAM,EAAI,CAC/B,CAGQ,YAAYA,EAA4BqO,EAChD,CACI,GAAI,CAACrO,EAAK,KAEN,OAGJ,MAAMqR,EAAK,IAAIjD,GACXpO,EAAK,KAAO,KAAK,YACjBA,EAAK,KAAK,MAAM,CAAC,EACjBqO,CAAA,EAEE5P,EAAK,IAAI,YAAY4S,EAAG,YAAY,EAE1C,KAAK,cAAgBA,EAAG,SAAS5S,EAAI,CAAC,EAElC,KAAK,WAEL,KAAK,aAAaA,CAAE,EAIpB,KAAK,MAAM,KAAKA,CAAE,CAE1B,CAOQ,aAAa2K,EACrB,CACI,GAAK,KAAK,aAKV,GACA,CACI,KAAK,aAAa,aAAaA,CAAG,EAClC,KAAK,WAAa,EACtB,OACO,EACP,CACI,MAAM+F,EAAM,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,EACrD,KAAK,OAAO,gCAAkCA,CAAG,CACrD,CACJ,CAGQ,cACR,CACI,GAAI,KAAK,aACT,CACI,MAAMsH,EAAW,KAAK,OAAS,KAAK,OAAO,SAAW,KAAK,SAC3D,GAAIA,GAAY,OAAO,SAAa,IACpC,CACI,MAAMoQ,EAAS,SAAS,eAAepQ,CAAQ,EAC3CoQ,GAAU,KAAK,aAAa,aAAeA,GAE3CA,EAAO,YAAY,KAAK,YAAY,CAE5C,CACA,IAAI,gBAAgB,KAAK,aAAa,GAAG,CAC7C,CAEA,KAAK,2BAAA,EAED,KAAK,eAEL,KAAK,aAAa,oBAAoB,QAAS,KAAK,oBAAqB,EAAK,EAC9E,KAAK,aAAa,oBAAoB,YAAa,KAAK,mBAAoB,EAAK,GAGrF,KAAK,aAAe,OACpB,KAAK,YAAc,OACnB,KAAK,aAAe,OAEpB,KAAK,WAAa,GAClB,KAAK,MAAQ,CAAA,EACb,KAAK,UAAY,CACrB,CAMQ,kBACR,CACI,GAAI,GAAC,KAAK,aAAe,KAAK,cAS9B,IAJA,KAAK,aAAe,KAAK,YAAY,gBACjC1a,EAAc,oBAAA,EAGd,CAAC,KAAK,aACV,CACI,KAAK,OAAO,SAAWA,EAAc,qBAAuB,iBAAiB,EAC7E,MACJ,CAEA,KAAK,qBAAA,EAEL,KAAK,aAAa,KAAO,WAO7B,CAEQ,mBACR,CACI,KAAK,OAAO,kCAAkC,CAClD,CAEQ,oBACR,CACI,KAAK,OAAO,mCAAmC,CACnD,CAEQ,wBAAwBnD,EAChC,CACI,KAAK,OAAO,wBAA0BA,aAAa,WAAaA,EAAE,QAAU,UAAU,CAC1F,CAEQ,wBACR,CAGI,GAFA,KAAK,sBAAsB,WAAW,EAElC,KAAK,MAAM,OAAS,EACxB,CACI,MAAMvK,EAAKypB,GAAc,KAAK,KAAK,EACnC,KAAK,aAAazpB,CAAE,CACxB,MAGI,KAAK,WAAa,EAE1B,CAMQ,sBAAsB8pB,EAC9B,CAmB+B,KAAK,MAAM,OAAS,GAE3C,QAAQ,IACJ,eAAiB,KAAK,MAAM,OAC5B,kBAAoB,KAAK,UAAA,CAGrC,CAGQ,sBACR,CACI,GAAI,CAAC,KAAK,aAEN,OAGJ,MAAMC,EAAQ,KAAK,aAGbC,EAAe,CAAC,QAAS,OAAO,EAahC7D,EAAgB5b,GACtB,CACI,KAAK,sBAAsBA,EAAE,IAAI,CACrC,EAEA,UAAWpE,KAAQ6jB,EAEfD,EAAM,iBAAiB5jB,EAAMggB,CAAY,CAkBjD,CAMQ,4BACR,CACQ,KAAK,cAEL,KAAK,YAAY,oBAAoB,aAAc,KAAK,aAAc,EAAK,EAC3E,KAAK,YAAY,oBAAoB,cAAe,KAAK,cAAe,EAAK,EAC7E,KAAK,YAAY,oBAAoB,eAAgB,KAAK,eAAgB,EAAK,EAEvF,CAMS,SACT,CACQ,KAAK,cAEL,KAAK,aAAA,EAET,MAAM,QAAA,CACV,CACJ,CAMAzU,GAAuB9T,EAAa,SAAUgsB,EAAiB,ECzkBxD,MAAMK,WAAsB3Z,EAAU,CASzC,YAAYC,EACZ,CACI,MAAMA,CAAO,EATjB,KAAA,SAA0B,KAC1B,KAAA,WAAsB,GAUlB,MAAM2Z,EAAW3Z,EACjB,KAAK,WAAa2Z,EAAS,WAC3B,KAAK,YAAcA,EAAS,YAC5B,KAAK,WAAaA,EAAS,UAC/B,CAEmB,sBAAsBxZ,EACzC,CACI,GAAIA,EAAI,OAASrT,GAAa,KAC9B,CACI,GAAI,KAAK,WAAa,KACtB,CACI,GAAI,CAACqT,EAAI,KAEL,YAAK,QAAQ,uCAAuC,EAC7C,GAEX,MAAM7G,EAAI,IAAIjB,GAAiB8H,EAAI,IAAI,EACvC,YAAK,SAAW,IAAI,YAAA,EAAc,OAAO7G,EAAE,IAAI,EAC/C,KAAK,WAAaA,EAAE,SAAW,EAG3B,KAAK,YAEL,KAAK,WAAW,KAAK,SAAU,KAAK,UAAU,EAE3C,EACX,CAGA,MAAO,EACX,CAEA,OAAI6G,EAAI,OAASrT,GAAa,MAErBqT,EAAI,MAQL,KAAK,aAAe,KAAK,WAAa,MAEtC,KAAK,YAAY,KAAK,SAAU,IAAI,WAAWA,EAAI,IAAI,CAAC,EAErD,KAVH,KAAK,QAAQ,wCAAwC,EAC9C,IAYXA,EAAI,OAASrT,GAAa,cAErBqT,EAAI,MAQL,KAAK,YAAc,KAAK,WAAa,MAErC,KAAK,WAAW,KAAK,SAAUA,EAAI,IAAI,EAEpC,KAVH,KAAK,QAAQ,uCAAuC,EAC7C,IAaR,EACX,CAKA,aAAanP,EACb,CACI,MAAMmP,EAAM,IAAIhN,EACVgB,EAAU,CACZ,SAAS1B,EAAgBrD,EAAa,EACtC,CACI,IAAI,WAAWqD,EAAGrD,CAAE,EAAE,IAAI,IAAI,WAAW4B,CAAI,CAAC,CAClD,EACA,YACA,CACI,OAAOA,EAAK,UAChB,CAAA,EAEJmP,EAAI,SAASpT,GAAc,cAAeoH,CAAO,EACjD,KAAK,QAAQgM,CAAG,CACpB,CAKA,cAAcyZ,EACd,CACI,MAAMzZ,EAAM,IAAIhN,EACVgB,EAAU,CACZ,SAAS1B,EAAgBrD,EAAa,EACtC,CACI,IAAI,WAAWqD,EAAGrD,CAAE,EAAE,IAAI,IAAI,WAAWwqB,CAAS,CAAC,CACvD,EACA,YACA,CACI,OAAOA,EAAU,UACrB,CAAA,EAEJzZ,EAAI,SAASpT,GAAc,MAAOoH,CAAO,EACzC,KAAK,QAAQgM,CAAG,CACpB,CAES,SACT,CACI,MAAM,QAAA,EACN,KAAK,WAAa,OAClB,KAAK,YAAc,OACnB,KAAK,WAAa,MACtB,CACJ,CAGAgB,GAAuB9T,EAAa,KAAMqsB,EAAa,EChKvD,SAASG,GAAiBC,EAAqBnZ,EAAgB4O,EAA2B,CACtF,IAAI,EAAI5O,GAAS,EACb3G,EAAIuV,GAAOuK,EAAO,WAEtB,OAAI9f,EAAI,IACJA,EAAI8f,EAAO,WAAa9f,GAExB,EAAI,IACJ,EAAI8f,EAAO,WAAa,GAExB,EAAI,IACJ,EAAI,GAEJ9f,EAAI,IACJA,EAAI,GAEJA,EAAI8f,EAAO,aACX9f,EAAI8f,EAAO,YAEX,EAAI9f,IACJ,EAAIA,GAGD8f,EAAO,MAAM,EAAG9f,CAAC,CAC5B,CAQA,SAAS+f,MAAsBC,EAAqC,CAChE,IAAIC,EAAc,EAClB,UAAW7f,KAAO4f,EACdC,GAAe7f,EAAI,WAGvB,MAAM3E,EAAS,IAAI,YAAYwkB,CAAW,EACpCrJ,EAAM,IAAI,WAAWnb,CAAM,EACjC,IAAI1F,EAAS,EAEb,UAAWqK,KAAO4f,EACdpJ,EAAI,IAAI,IAAI,WAAWxW,CAAG,EAAGrK,CAAM,EACnCA,GAAUqK,EAAI,WAGlB,OAAO3E,CACX,CAQA,SAASykB,GAA0BlpB,EAA+B,CAC9D,MAAM8oB,EAAS,IAAI,YAAY9oB,EAAK,UAAU,EAC9C,WAAI,WAAW8oB,CAAM,EAAE,IAAI9oB,CAAI,EACxB8oB,CACX,CASA,SAASK,GAAkB1nB,EAAgB4K,EAAyB,CAChE,GAAI5K,EAAE,aAAe4K,EAAE,WACnB,MAAO,GAEX,MAAM+c,EAAQ,IAAI,WAAW3nB,CAAC,EACxB4nB,EAAQ,IAAI,WAAWhd,CAAC,EAC9B,QAAS,EAAI,EAAG,EAAI+c,EAAM,WAAY,IAClC,GAAIA,EAAM,CAAC,IAAMC,EAAM,CAAC,EACpB,MAAO,GAGf,MAAO,EACX,CCzEA,MAAMC,EAAc,CAahB,YAAYR,EAAyBS,EAAqBC,EAAqB,CACvED,IAAe,QAAaC,IAAe,QAC3C,KAAK,GAAK,IAAI,SAASV,EAAQS,EAAYC,CAAU,EACrD,KAAK,GAAK,IAAI,WAAWV,EAAQS,EAAYC,CAAU,GAChDD,IAAe,QACtB,KAAK,GAAK,IAAI,SAAST,EAAQS,CAAU,EACzC,KAAK,GAAK,IAAI,WAAWT,EAAQS,CAAU,IAE3C,KAAK,GAAK,IAAI,SAAST,CAAM,EAC7B,KAAK,GAAK,IAAI,WAAWA,CAAM,EAEvC,CAGA,IAAI,QAA0B,CAC1B,OAAO,KAAK,GAAG,MACnB,CAGA,IAAI,YAAqB,CACrB,OAAO,KAAK,GAAG,UACnB,CAGA,IAAI,YAAqB,CACrB,OAAO,KAAK,GAAG,UACnB,CAMA,SAASS,EAA4B,CACjC,OAAO,KAAK,GAAG,SAASA,CAAU,CACtC,CAEA,QAAQA,EAA4B,CAChC,OAAO,KAAK,GAAG,QAAQA,CAAU,CACrC,CAEA,UAAUA,EAAoBE,EAAgC,CAC1D,OAAO,KAAK,GAAG,UAAUF,EAAYE,CAAY,CACrD,CAEA,SAASF,EAAoBE,EAAgC,CACzD,OAAO,KAAK,GAAG,SAASF,EAAYE,CAAY,CACpD,CAEA,UAAUF,EAAoBE,EAAgC,CAC1D,OAAO,KAAK,GAAG,UAAUF,EAAYE,CAAY,CACrD,CAEA,SAASF,EAAoBE,EAAgC,CACzD,OAAO,KAAK,GAAG,SAASF,EAAYE,CAAY,CACpD,CAEA,WAAWF,EAAoBE,EAAgC,CAC3D,OAAO,KAAK,GAAG,WAAWF,EAAYE,CAAY,CACtD,CAEA,WAAWF,EAAoBE,EAAgC,CAC3D,OAAO,KAAK,GAAG,WAAWF,EAAYE,CAAY,CACtD,CAQA,aAAaF,EAAoBE,EAAgC,CAC7D,OAAO,KAAK,GAAG,aAAaF,EAAYE,CAAY,CACxD,CAKA,YAAYF,EAAoBE,EAAgC,CAC5D,OAAO,KAAK,GAAG,YAAYF,EAAYE,CAAY,CACvD,CAMA,SAASF,EAAoBlW,EAAqB,CAC9C,KAAK,GAAG,SAASkW,EAAYlW,CAAK,CACtC,CAEA,QAAQkW,EAAoBlW,EAAqB,CAC7C,KAAK,GAAG,QAAQkW,EAAYlW,CAAK,CACrC,CAEA,UAAUkW,EAAoBlW,EAAeoW,EAA8B,CACvE,KAAK,GAAG,UAAUF,EAAYlW,EAAOoW,CAAY,CACrD,CAEA,SAASF,EAAoBlW,EAAeoW,EAA8B,CACtE,KAAK,GAAG,SAASF,EAAYlW,EAAOoW,CAAY,CACpD,CAEA,UAAUF,EAAoBlW,EAAeoW,EAA8B,CACvE,KAAK,GAAG,UAAUF,EAAYlW,EAAOoW,CAAY,CACrD,CAEA,SAASF,EAAoBlW,EAAeoW,EAA8B,CACtE,KAAK,GAAG,SAASF,EAAYlW,EAAOoW,CAAY,CACpD,CAEA,WAAWF,EAAoBlW,EAAeoW,EAA8B,CACxE,KAAK,GAAG,WAAWF,EAAYlW,EAAOoW,CAAY,CACtD,CAEA,WAAWF,EAAoBlW,EAAeoW,EAA8B,CACxE,KAAK,GAAG,WAAWF,EAAYlW,EAAOoW,CAAY,CACtD,CAQA,aAAaF,EAAoBlW,EAAeoW,EAA8B,CAC1E,KAAK,GAAG,aAAaF,EAAYlW,EAAOoW,CAAY,CACxD,CAKA,YAAYF,EAAoBlW,EAAeoW,EAA8B,CACzE,KAAK,GAAG,YAAYF,EAAYlW,EAAOoW,CAAY,CACvD,CAeA,QAAQF,EAAoBC,EAAoC,CAC5D,MAAME,EAAY,KAAK,GAAG,WAAaH,EACvC,OAAO,IAAID,GAAc,KAAK,GAAG,OAAQI,EAAWF,CAAU,CAClE,CAWA,UAAUG,EAA+B,CACrC,OAAO,KAAK,GAAG,WAAaA,CAChC,CASA,SAASJ,EAAoBC,EAAiC,CAC1D,MAAM/gB,EAAM+gB,GAAe,KAAK,GAAG,WAAaD,EAChD,OAAO,IAAI,WAAW,KAAK,GAAG,OAAO,MACjC,KAAK,GAAG,WAAaA,EACrB,KAAK,GAAG,WAAaA,EAAa9gB,CAAA,CACrC,CACL,CAQA,SAAS8gB,EAAoBvpB,EAAwB,CACjD,KAAK,GAAG,IAAIA,EAAMupB,CAAU,CAChC,CACJ,CAUA,SAASK,GACLd,EACAS,EACAC,EACa,CACb,OAAO,IAAIF,GAAcR,EAAQS,EAAYC,CAAU,CAC3D,CAcA,SAASK,GACLf,EACAS,EACAC,EACQ,CACR,OAAID,IAAe,QAAaC,IAAe,OACpC,IAAI,SAASV,EAAQS,EAAYC,CAAU,EAC3CD,IAAe,OACf,IAAI,SAAST,EAAQS,CAAU,EAEnC,IAAI,SAAST,CAAM,CAC9B,CCvQO,MAAMgB,GAAU"}