{"version":3,"file":"conflict-resolver.mjs","sources":["../../../../src/lib/data/sync/conflict-resolver.ts"],"sourcesContent":["/**\n * @file Conflict Resolver\n * @description Advanced conflict resolution strategies for data synchronization\n * including three-way merge, field-level resolution, and vector clocks.\n *\n * Features:\n * - Multiple resolution strategies\n * - Three-way merge support\n * - Field-level conflict resolution\n * - Vector clock implementation\n * - Custom merge functions\n * - Conflict history tracking\n *\n * @example\n * ```typescript\n * import { createConflictResolver, threeWayMerge } from '@/lib/data/sync';\n *\n * const resolver = createConflictResolver({\n *   strategy: 'three-way-merge',\n *   fieldStrategies: {\n *     updatedAt: 'latest',\n *     version: 'increment',\n *   },\n * });\n *\n * const resolved = resolver.resolve(local, remote, base);\n * ```\n */\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * Conflict resolution strategy\n */\nexport type ConflictStrategy =\n  | 'server-wins'\n  | 'client-wins'\n  | 'latest-wins'\n  | 'three-way-merge'\n  | 'field-level'\n  | 'manual';\n\n/**\n * Field-level resolution strategy\n */\nexport type FieldStrategy =\n  | 'server'\n  | 'client'\n  | 'latest'\n  | 'merge'\n  | 'concat'\n  | 'sum'\n  | 'max'\n  | 'min'\n  | 'increment'\n  | 'custom';\n\n/**\n * Conflict information\n */\nexport interface Conflict {\n  /** Field path where conflict occurred */\n  path: string[];\n  /** Local value */\n  localValue: unknown;\n  /** Remote value */\n  remoteValue: unknown;\n  /** Base value (if available) */\n  baseValue?: unknown;\n  /** Local modified timestamp */\n  localModifiedAt?: number;\n  /** Remote modified timestamp */\n  remoteModifiedAt?: number;\n  /** Resolved value */\n  resolvedValue?: unknown;\n  /** How it was resolved */\n  resolution?: string;\n}\n\n/**\n * Conflict resolution result\n */\nexport interface ConflictResolutionResult<T> {\n  /** Merged data */\n  data: T;\n  /** Whether conflicts were detected */\n  hasConflicts: boolean;\n  /** List of conflicts */\n  conflicts: Conflict[];\n  /** Resolution metadata */\n  metadata: {\n    strategy: ConflictStrategy;\n    resolvedAt: number;\n    localVersion?: string;\n    remoteVersion?: string;\n  };\n}\n\n/**\n * Conflict resolver configuration\n */\nexport interface ConflictResolverConfig {\n  /** Default resolution strategy */\n  strategy: ConflictStrategy;\n  /** Field-level strategies */\n  fieldStrategies?: Record<\n    string,\n    FieldStrategy | ((local: unknown, remote: unknown, base?: unknown) => unknown)\n  >;\n  /** Fields to ignore in merge */\n  ignoreFields?: string[];\n  /** Fields that should always use server value */\n  serverFields?: string[];\n  /** Fields that should always use client value */\n  clientFields?: string[];\n  /** Timestamp field for latest-wins */\n  timestampField?: string;\n  /** Custom merge function */\n  customMerge?: <T>(local: T, remote: T, base?: T) => T;\n  /** Track conflict history */\n  trackHistory?: boolean;\n}\n\n/**\n * Vector clock for distributed systems\n */\nexport interface VectorClock {\n  [nodeId: string]: number;\n}\n\n/**\n * Conflict resolver instance\n */\nexport interface ConflictResolver<T = unknown> {\n  /** Resolve conflict between local and remote */\n  resolve: (local: T, remote: T, base?: T) => ConflictResolutionResult<T>;\n  /** Get conflicts without resolving */\n  detectConflicts: (local: T, remote: T, base?: T) => Conflict[];\n  /** Compare vector clocks */\n  compareVersions: (\n    localClock: VectorClock,\n    remoteClock: VectorClock\n  ) => 'equal' | 'local-newer' | 'remote-newer' | 'concurrent';\n  /** Merge vector clocks */\n  mergeClocks: (localClock: VectorClock, remoteClock: VectorClock) => VectorClock;\n  /** Get conflict history */\n  getHistory: () => ConflictResolutionResult<T>[];\n  /** Clear history */\n  clearHistory: () => void;\n}\n\n// =============================================================================\n// UTILITIES\n// =============================================================================\n\n/**\n * Deep equality check\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n  if (a === b) return true;\n  if (a === null || b === null) return a === b;\n  if (typeof a !== typeof b) return false;\n\n  if (typeof a === 'object') {\n    if (Array.isArray(a) && Array.isArray(b)) {\n      if (a.length !== b.length) return false;\n      return a.every((item, index) => deepEqual(item, b[index]));\n    }\n\n    if (Array.isArray(a) || Array.isArray(b)) return false;\n\n    const aObj = a as Record<string, unknown>;\n    const bObj = b as Record<string, unknown>;\n    const aKeys = Object.keys(aObj);\n    const bKeys = Object.keys(bObj);\n\n    if (aKeys.length !== bKeys.length) return false;\n\n    return aKeys.every((key) => deepEqual(aObj[key], bObj[key]));\n  }\n\n  return false;\n}\n\n/**\n * Deep clone\n */\nfunction deepClone<T>(obj: T): T {\n  if (obj === null || typeof obj !== 'object') {\n    return obj;\n  }\n\n  if (obj instanceof Date) {\n    return new Date(obj.getTime()) as unknown as T;\n  }\n\n  if (Array.isArray(obj)) {\n    return obj.map((item: unknown) => deepClone(item)) as unknown as T;\n  }\n\n  const cloned: Record<string, unknown> = {};\n  for (const key of Object.keys(obj)) {\n    cloned[key] = deepClone((obj as Record<string, unknown>)[key]);\n  }\n  return cloned as T;\n}\n\n/**\n * Get value at path\n */\nfunction getAtPath(obj: unknown, path: string[]): unknown {\n  let current = obj;\n  for (const key of path) {\n    if (current === null || current === undefined) return undefined;\n    current = (current as Record<string, unknown>)[key];\n  }\n  return current;\n}\n\n/**\n * Set value at path\n */\nfunction setAtPath<T>(obj: T, path: string[], value: unknown): T {\n  if (path.length === 0) return value as T;\n\n  const cloned = deepClone(obj);\n  let current = cloned as Record<string, unknown>;\n\n  for (let i = 0; i < path.length - 1; i++) {\n    const key = path[i] as string;\n    current[key] ??= {};\n    current = current[key] as Record<string, unknown>;\n  }\n\n  current[path[path.length - 1] as string] = value;\n  return cloned;\n}\n\n/**\n * Get all paths in an object\n */\nfunction getAllPaths(obj: unknown, prefix: string[] = []): string[][] {\n  const paths: string[][] = [];\n\n  if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) {\n    if (prefix.length > 0) {\n      paths.push(prefix);\n    }\n    return paths;\n  }\n\n  const objRecord = obj as Record<string, unknown>;\n\n  for (const key of Object.keys(objRecord)) {\n    const newPrefix = [...prefix, key];\n    const value = objRecord[key];\n\n    if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n      paths.push(...getAllPaths(value, newPrefix));\n    } else {\n      paths.push(newPrefix);\n    }\n  }\n\n  return paths;\n}\n\n// =============================================================================\n// THREE-WAY MERGE\n// =============================================================================\n\n/**\n * Three-way merge algorithm\n */\nexport function threeWayMerge<T extends Record<string, unknown>>(\n  local: T,\n  remote: T,\n  base: T,\n  config: {\n    fieldStrategies?: Record<string, FieldStrategy>;\n    ignoreFields?: string[];\n  } = {}\n): ConflictResolutionResult<T> {\n  const { fieldStrategies = {}, ignoreFields = [] } = config;\n  const conflicts: Conflict[] = [];\n  const result = deepClone(base) as Record<string, unknown>;\n\n  // Get all unique paths\n  const allPaths = new Set<string>();\n  getAllPaths(local).forEach((p) => allPaths.add(p.join('.')));\n  getAllPaths(remote).forEach((p) => allPaths.add(p.join('.')));\n  getAllPaths(base).forEach((p) => allPaths.add(p.join('.')));\n\n  for (const pathStr of allPaths) {\n    const path = pathStr.split('.');\n\n    // Skip ignored fields\n    if (ignoreFields.some((f) => pathStr.startsWith(f))) {\n      continue;\n    }\n\n    const localValue = getAtPath(local, path);\n    const remoteValue = getAtPath(remote, path);\n    const baseValue = getAtPath(base, path);\n\n    const localChanged = !deepEqual(localValue, baseValue);\n    const remoteChanged = !deepEqual(remoteValue, baseValue);\n\n    if (!localChanged && !remoteChanged) {\n      // No changes\n      setAtPath(result as T, path, baseValue);\n    } else if (localChanged && !remoteChanged) {\n      // Only local changed\n      setAtPath(result as T, path, localValue);\n    } else if (!localChanged && remoteChanged) {\n      // Only remote changed\n      setAtPath(result as T, path, remoteValue);\n    } else if (deepEqual(localValue, remoteValue)) {\n      // Both changed to same value\n      setAtPath(result as T, path, localValue);\n    } else {\n      // Conflict - both changed to different values\n      const fieldStrategy =\n        fieldStrategies[pathStr] ?? fieldStrategies[path[0] as string] ?? 'server';\n\n      let resolvedValue: unknown;\n      let resolution: string;\n\n      switch (fieldStrategy) {\n        case 'client':\n          resolvedValue = localValue;\n          resolution = 'client-wins';\n          break;\n        case 'server':\n          resolvedValue = remoteValue;\n          resolution = 'server-wins';\n          break;\n        case 'merge':\n          if (typeof localValue === 'object' && typeof remoteValue === 'object') {\n            resolvedValue = { ...(remoteValue as object), ...(localValue as object) };\n            resolution = 'merged';\n          } else {\n            resolvedValue = remoteValue;\n            resolution = 'server-wins';\n          }\n          break;\n        case 'concat':\n          if (Array.isArray(localValue) && Array.isArray(remoteValue)) {\n            resolvedValue = [\n              ...new Set([...(remoteValue as unknown[]), ...(localValue as unknown[])]),\n            ];\n            resolution = 'concatenated';\n          } else {\n            resolvedValue = remoteValue;\n            resolution = 'server-wins';\n          }\n          break;\n        case 'sum':\n          if (\n            typeof localValue === 'number' &&\n            typeof remoteValue === 'number' &&\n            typeof baseValue === 'number'\n          ) {\n            resolvedValue = baseValue + (localValue - baseValue) + (remoteValue - baseValue);\n            resolution = 'summed';\n          } else {\n            resolvedValue = remoteValue;\n            resolution = 'server-wins';\n          }\n          break;\n        case 'max':\n          resolvedValue = Math.max(Number(localValue), Number(remoteValue));\n          resolution = 'max';\n          break;\n        case 'min':\n          resolvedValue = Math.min(Number(localValue), Number(remoteValue));\n          resolution = 'min';\n          break;\n        case 'increment':\n          resolvedValue = Math.max(Number(localValue), Number(remoteValue)) + 1;\n          resolution = 'incremented';\n          break;\n        default:\n          resolvedValue = remoteValue;\n          resolution = 'server-wins';\n      }\n\n      conflicts.push({\n        path,\n        localValue,\n        remoteValue,\n        baseValue,\n        resolvedValue,\n        resolution,\n      });\n\n      setAtPath(result as T, path, resolvedValue);\n    }\n  }\n\n  return {\n    data: result as T,\n    hasConflicts: conflicts.length > 0,\n    conflicts,\n    metadata: {\n      strategy: 'three-way-merge',\n      resolvedAt: Date.now(),\n    },\n  };\n}\n\n// =============================================================================\n// VECTOR CLOCK\n// =============================================================================\n\n/**\n * Compare two vector clocks\n */\nexport function compareVectorClocks(\n  a: VectorClock,\n  b: VectorClock\n): 'equal' | 'a-newer' | 'b-newer' | 'concurrent' {\n  let aGreater = false;\n  let bGreater = false;\n\n  const allKeys = new Set([...Object.keys(a), ...Object.keys(b)]);\n\n  for (const key of allKeys) {\n    const aVal = a[key] !== undefined && a[key] !== 0 ? a[key] : 0;\n    const bVal = b[key] !== undefined && b[key] !== 0 ? b[key] : 0;\n\n    if (aVal > bVal) aGreater = true;\n    if (bVal > aVal) bGreater = true;\n  }\n\n  if (!aGreater && !bGreater) return 'equal';\n  if (aGreater && !bGreater) return 'a-newer';\n  if (!aGreater && bGreater) return 'b-newer';\n  return 'concurrent';\n}\n\n/**\n * Merge two vector clocks\n */\nexport function mergeVectorClocks(a: VectorClock, b: VectorClock): VectorClock {\n  const result: VectorClock = {};\n  const allKeys = new Set([...Object.keys(a), ...Object.keys(b)]);\n\n  for (const key of allKeys) {\n    result[key] = Math.max(\n      a[key] !== undefined && a[key] !== 0 ? a[key] : 0,\n      b[key] !== undefined && b[key] !== 0 ? b[key] : 0\n    );\n  }\n\n  return result;\n}\n\n/**\n * Increment vector clock for a node\n */\nexport function incrementVectorClock(clock: VectorClock, nodeId: string): VectorClock {\n  return {\n    ...clock,\n    [nodeId]: (clock[nodeId] !== undefined && clock[nodeId] !== 0 ? clock[nodeId] : 0) + 1,\n  };\n}\n\n/**\n * Create initial vector clock\n */\nexport function createVectorClock(nodeId: string): VectorClock {\n  return { [nodeId]: 1 };\n}\n\n// =============================================================================\n// CONFLICT RESOLVER FACTORY\n// =============================================================================\n\n/**\n * Create a conflict resolver\n */\nexport function createConflictResolver<T extends Record<string, unknown>>(\n  config: ConflictResolverConfig\n): ConflictResolver<T> {\n  const {\n    strategy,\n    fieldStrategies = {},\n    ignoreFields = [],\n    serverFields = [],\n    clientFields = [],\n    timestampField = 'updatedAt',\n    customMerge,\n    trackHistory = false,\n  } = config;\n\n  const history: ConflictResolutionResult<T>[] = [];\n\n  // Build effective field strategies\n  const effectiveFieldStrategies: Record<\n    string,\n    FieldStrategy | ((local: unknown, remote: unknown, base?: unknown) => unknown)\n  > = { ...fieldStrategies };\n  for (const field of serverFields) {\n    effectiveFieldStrategies[field] = 'server';\n  }\n  for (const field of clientFields) {\n    effectiveFieldStrategies[field] = 'client';\n  }\n\n  function resolve(local: T, remote: T, base?: T): ConflictResolutionResult<T> {\n    let result: ConflictResolutionResult<T>;\n\n    switch (strategy) {\n      case 'server-wins':\n        result = {\n          data: deepClone(remote),\n          hasConflicts: false,\n          conflicts: [],\n          metadata: {\n            strategy: 'server-wins',\n            resolvedAt: Date.now(),\n          },\n        };\n        break;\n\n      case 'client-wins':\n        result = {\n          data: deepClone(local),\n          hasConflicts: false,\n          conflicts: [],\n          metadata: {\n            strategy: 'client-wins',\n            resolvedAt: Date.now(),\n          },\n        };\n        break;\n\n      case 'latest-wins': {\n        const localTs = (getAtPath(local, [timestampField]) as number) || 0;\n        const remoteTs = (getAtPath(remote, [timestampField]) as number) || 0;\n        result = {\n          data: deepClone(localTs > remoteTs ? local : remote),\n          hasConflicts: false,\n          conflicts: [],\n          metadata: {\n            strategy: 'latest-wins',\n            resolvedAt: Date.now(),\n          },\n        };\n        break;\n      }\n\n      case 'three-way-merge':\n        if (base) {\n          result = threeWayMerge(local, remote, base, {\n            fieldStrategies: effectiveFieldStrategies as Record<string, FieldStrategy>,\n            ignoreFields,\n          });\n        } else {\n          // Fall back to field-level without base\n          result = resolveFieldLevel(local, remote);\n        }\n        break;\n\n      case 'field-level':\n        result = resolveFieldLevel(local, remote);\n        break;\n\n      case 'manual':\n        if (customMerge) {\n          result = {\n            data: customMerge(local, remote, base),\n            hasConflicts: false,\n            conflicts: [],\n            metadata: {\n              strategy: 'manual',\n              resolvedAt: Date.now(),\n            },\n          };\n        } else {\n          // Fall back to server-wins\n          result = {\n            data: deepClone(remote),\n            hasConflicts: false,\n            conflicts: [],\n            metadata: {\n              strategy: 'server-wins',\n              resolvedAt: Date.now(),\n            },\n          };\n        }\n        break;\n\n      default:\n        result = {\n          data: deepClone(remote),\n          hasConflicts: false,\n          conflicts: [],\n          metadata: {\n            strategy: 'server-wins',\n            resolvedAt: Date.now(),\n          },\n        };\n    }\n\n    if (trackHistory) {\n      history.push(result);\n    }\n\n    return result;\n  }\n\n  function resolveFieldLevel(local: T, remote: T): ConflictResolutionResult<T> {\n    const conflicts: Conflict[] = [];\n    const result = deepClone(remote) as Record<string, unknown>;\n\n    const allPaths = new Set<string>();\n    getAllPaths(local).forEach((p) => allPaths.add(p.join('.')));\n    getAllPaths(remote).forEach((p) => allPaths.add(p.join('.')));\n\n    for (const pathStr of allPaths) {\n      const path = pathStr.split('.');\n\n      if (ignoreFields.some((f) => pathStr.startsWith(f))) {\n        continue;\n      }\n\n      const localValue = getAtPath(local, path);\n      const remoteValue = getAtPath(remote, path);\n\n      if (deepEqual(localValue, remoteValue)) {\n        continue;\n      }\n\n      const fieldStrategy =\n        effectiveFieldStrategies[pathStr] ??\n        effectiveFieldStrategies[path[0] as string] ??\n        'server';\n\n      let resolvedValue: unknown;\n      let resolution: string;\n\n      if (typeof fieldStrategy === 'function') {\n        resolvedValue = fieldStrategy(localValue, remoteValue);\n        resolution = 'custom';\n      } else {\n        switch (fieldStrategy) {\n          case 'client':\n            resolvedValue = localValue;\n            resolution = 'client-wins';\n            break;\n          case 'latest': {\n            const localTs = (getAtPath(local, [timestampField]) as number) || 0;\n            const remoteTs = (getAtPath(remote, [timestampField]) as number) || 0;\n            resolvedValue = localTs > remoteTs ? localValue : remoteValue;\n            resolution = localTs > remoteTs ? 'local-latest' : 'remote-latest';\n            break;\n          }\n          default:\n            resolvedValue = remoteValue;\n            resolution = 'server-wins';\n        }\n      }\n\n      conflicts.push({\n        path,\n        localValue,\n        remoteValue,\n        resolvedValue,\n        resolution,\n      });\n\n      setAtPath(result as T, path, resolvedValue);\n    }\n\n    return {\n      data: result as T,\n      hasConflicts: conflicts.length > 0,\n      conflicts,\n      metadata: {\n        strategy: 'field-level',\n        resolvedAt: Date.now(),\n      },\n    };\n  }\n\n  function detectConflicts(local: T, remote: T, base?: T): Conflict[] {\n    const conflicts: Conflict[] = [];\n\n    const allPaths = new Set<string>();\n    getAllPaths(local).forEach((p) => allPaths.add(p.join('.')));\n    getAllPaths(remote).forEach((p) => allPaths.add(p.join('.')));\n\n    for (const pathStr of allPaths) {\n      const path = pathStr.split('.');\n\n      if (ignoreFields.some((f) => pathStr.startsWith(f))) {\n        continue;\n      }\n\n      const localValue = getAtPath(local, path);\n      const remoteValue = getAtPath(remote, path);\n      const baseValue = base ? getAtPath(base, path) : undefined;\n\n      if (deepEqual(localValue, remoteValue)) {\n        continue;\n      }\n\n      if (base) {\n        const localChanged = !deepEqual(localValue, baseValue);\n        const remoteChanged = !deepEqual(remoteValue, baseValue);\n\n        if (localChanged && remoteChanged) {\n          conflicts.push({\n            path,\n            localValue,\n            remoteValue,\n            baseValue,\n          });\n        }\n      } else {\n        conflicts.push({\n          path,\n          localValue,\n          remoteValue,\n        });\n      }\n    }\n\n    return conflicts;\n  }\n\n  return {\n    resolve,\n    detectConflicts,\n\n    compareVersions: (localClock, remoteClock) => {\n      const result = compareVectorClocks(localClock, remoteClock);\n      if (result === 'a-newer') return 'local-newer';\n      if (result === 'b-newer') return 'remote-newer';\n      return result;\n    },\n\n    mergeClocks: mergeVectorClocks,\n\n    getHistory: () => [...history],\n    clearHistory: () => {\n      history.length = 0;\n    },\n  };\n}\n\n// =============================================================================\n// PRESET RESOLVERS\n// =============================================================================\n\n/**\n * Server-wins resolver\n */\nexport const serverWinsResolver = <T extends Record<string, unknown>>(): ConflictResolver<T> =>\n  createConflictResolver<T>({ strategy: 'server-wins' });\n\n/**\n * Client-wins resolver\n */\nexport const clientWinsResolver = <T extends Record<string, unknown>>(): ConflictResolver<T> =>\n  createConflictResolver<T>({ strategy: 'client-wins' });\n\n/**\n * Latest-wins resolver\n */\nexport const latestWinsResolver = <T extends Record<string, unknown>>(\n  timestampField = 'updatedAt'\n): ConflictResolver<T> => createConflictResolver<T>({ strategy: 'latest-wins', timestampField });\n\n/**\n * Three-way merge resolver\n */\nexport const threeWayMergeResolver = <T extends Record<string, unknown>>(\n  options?: Partial<ConflictResolverConfig>\n): ConflictResolver<T> =>\n  createConflictResolver<T>({\n    strategy: 'three-way-merge',\n    ...options,\n  });\n"],"names":["deepEqual","a","b","item","index","aObj","bObj","aKeys","bKeys","key","deepClone","obj","cloned","getAtPath","path","current","setAtPath","value","i","getAllPaths","prefix","paths","objRecord","newPrefix","threeWayMerge","local","remote","base","config","fieldStrategies","ignoreFields","conflicts","result","allPaths","p","pathStr","f","localValue","remoteValue","baseValue","localChanged","remoteChanged","fieldStrategy","resolvedValue","resolution","compareVectorClocks","aGreater","bGreater","allKeys","aVal","bVal","mergeVectorClocks","incrementVectorClock","clock","nodeId","createVectorClock","createConflictResolver","strategy","serverFields","clientFields","timestampField","customMerge","trackHistory","history","effectiveFieldStrategies","field","resolve","localTs","remoteTs","resolveFieldLevel","detectConflicts","localClock","remoteClock","serverWinsResolver","clientWinsResolver","latestWinsResolver","threeWayMergeResolver","options"],"mappings":"AAgKA,SAASA,EAAUC,GAAYC,GAAqB;AAClD,MAAID,MAAMC,EAAG,QAAO;AACpB,MAAID,MAAM,QAAQC,MAAM,aAAaD,MAAMC;AAC3C,MAAI,OAAOD,KAAM,OAAOC,EAAG,QAAO;AAElC,MAAI,OAAOD,KAAM,UAAU;AACzB,QAAI,MAAM,QAAQA,CAAC,KAAK,MAAM,QAAQC,CAAC;AACrC,aAAID,EAAE,WAAWC,EAAE,SAAe,KAC3BD,EAAE,MAAM,CAACE,GAAMC,MAAUJ,EAAUG,GAAMD,EAAEE,CAAK,CAAC,CAAC;AAG3D,QAAI,MAAM,QAAQH,CAAC,KAAK,MAAM,QAAQC,CAAC,EAAG,QAAO;AAEjD,UAAMG,IAAOJ,GACPK,IAAOJ,GACPK,IAAQ,OAAO,KAAKF,CAAI,GACxBG,IAAQ,OAAO,KAAKF,CAAI;AAE9B,WAAIC,EAAM,WAAWC,EAAM,SAAe,KAEnCD,EAAM,MAAM,CAACE,MAAQT,EAAUK,EAAKI,CAAG,GAAGH,EAAKG,CAAG,CAAC,CAAC;AAAA,EAC7D;AAEA,SAAO;AACT;AAKA,SAASC,EAAaC,GAAW;AAC/B,MAAIA,MAAQ,QAAQ,OAAOA,KAAQ;AACjC,WAAOA;AAGT,MAAIA,aAAe;AACjB,WAAO,IAAI,KAAKA,EAAI,SAAS;AAG/B,MAAI,MAAM,QAAQA,CAAG;AACnB,WAAOA,EAAI,IAAI,CAACR,MAAkBO,EAAUP,CAAI,CAAC;AAGnD,QAAMS,IAAkC,CAAA;AACxC,aAAWH,KAAO,OAAO,KAAKE,CAAG;AAC/B,IAAAC,EAAOH,CAAG,IAAIC,EAAWC,EAAgCF,CAAG,CAAC;AAE/D,SAAOG;AACT;AAKA,SAASC,EAAUF,GAAcG,GAAyB;AACxD,MAAIC,IAAUJ;AACd,aAAWF,KAAOK,GAAM;AACtB,QAAIC,KAAY,KAA+B;AAC/C,IAAAA,IAAWA,EAAoCN,CAAG;AAAA,EACpD;AACA,SAAOM;AACT;AAKA,SAASC,EAAaL,GAAQG,GAAgBG,GAAmB;AAC/D,MAAIH,EAAK,WAAW,EAAG,QAAOG;AAE9B,QAAML,IAASF,EAAUC,CAAG;AAC5B,MAAII,IAAUH;AAEd,WAASM,IAAI,GAAGA,IAAIJ,EAAK,SAAS,GAAGI,KAAK;AACxC,UAAMT,IAAMK,EAAKI,CAAC;AAClB,IAAAH,EAAQN,CAAG,MAAM,CAAA,GACjBM,IAAUA,EAAQN,CAAG;AAAA,EACvB;AAEA,SAAAM,EAAQD,EAAKA,EAAK,SAAS,CAAC,CAAW,IAAIG,GACpCL;AACT;AAKA,SAASO,EAAYR,GAAcS,IAAmB,IAAgB;AACpE,QAAMC,IAAoB,CAAA;AAE1B,MAAIV,MAAQ,QAAQ,OAAOA,KAAQ,YAAY,MAAM,QAAQA,CAAG;AAC9D,WAAIS,EAAO,SAAS,KAClBC,EAAM,KAAKD,CAAM,GAEZC;AAGT,QAAMC,IAAYX;AAElB,aAAWF,KAAO,OAAO,KAAKa,CAAS,GAAG;AACxC,UAAMC,IAAY,CAAC,GAAGH,GAAQX,CAAG,GAC3BQ,IAAQK,EAAUb,CAAG;AAE3B,IAAIQ,MAAU,QAAQ,OAAOA,KAAU,YAAY,CAAC,MAAM,QAAQA,CAAK,IACrEI,EAAM,KAAK,GAAGF,EAAYF,GAAOM,CAAS,CAAC,IAE3CF,EAAM,KAAKE,CAAS;AAAA,EAExB;AAEA,SAAOF;AACT;AASO,SAASG,EACdC,GACAC,GACAC,GACAC,IAGI,CAAA,GACyB;AAC7B,QAAM,EAAE,iBAAAC,IAAkB,CAAA,GAAI,cAAAC,IAAe,CAAA,MAAOF,GAC9CG,IAAwB,CAAA,GACxBC,IAAStB,EAAUiB,CAAI,GAGvBM,wBAAe,IAAA;AACrB,EAAAd,EAAYM,CAAK,EAAE,QAAQ,CAACS,MAAMD,EAAS,IAAIC,EAAE,KAAK,GAAG,CAAC,CAAC,GAC3Df,EAAYO,CAAM,EAAE,QAAQ,CAACQ,MAAMD,EAAS,IAAIC,EAAE,KAAK,GAAG,CAAC,CAAC,GAC5Df,EAAYQ,CAAI,EAAE,QAAQ,CAACO,MAAMD,EAAS,IAAIC,EAAE,KAAK,GAAG,CAAC,CAAC;AAE1D,aAAWC,KAAWF,GAAU;AAC9B,UAAMnB,IAAOqB,EAAQ,MAAM,GAAG;AAG9B,QAAIL,EAAa,KAAK,CAACM,MAAMD,EAAQ,WAAWC,CAAC,CAAC;AAChD;AAGF,UAAMC,IAAaxB,EAAUY,GAAOX,CAAI,GAClCwB,IAAczB,EAAUa,GAAQZ,CAAI,GACpCyB,IAAY1B,EAAUc,GAAMb,CAAI,GAEhC0B,IAAe,CAACxC,EAAUqC,GAAYE,CAAS,GAC/CE,IAAgB,CAACzC,EAAUsC,GAAaC,CAAS;AAEvD,QAAI,CAACC,KAAgB,CAACC;AAEpB,MAAAzB,EAAUgB,GAAalB,GAAMyB,CAAS;AAAA,aAC7BC,KAAgB,CAACC;AAE1B,MAAAzB,EAAUgB,GAAalB,GAAMuB,CAAU;AAAA,aAC9B,CAACG,KAAgBC;AAE1B,MAAAzB,EAAUgB,GAAalB,GAAMwB,CAAW;AAAA,aAC/BtC,EAAUqC,GAAYC,CAAW;AAE1C,MAAAtB,EAAUgB,GAAalB,GAAMuB,CAAU;AAAA,SAClC;AAEL,YAAMK,IACJb,EAAgBM,CAAO,KAAKN,EAAgBf,EAAK,CAAC,CAAW,KAAK;AAEpE,UAAI6B,GACAC;AAEJ,cAAQF,GAAA;AAAA,QACN,KAAK;AACH,UAAAC,IAAgBN,GAChBO,IAAa;AACb;AAAA,QACF,KAAK;AACH,UAAAD,IAAgBL,GAChBM,IAAa;AACb;AAAA,QACF,KAAK;AACH,UAAI,OAAOP,KAAe,YAAY,OAAOC,KAAgB,YAC3DK,IAAgB,EAAE,GAAIL,GAAwB,GAAID,EAAA,GAClDO,IAAa,aAEbD,IAAgBL,GAChBM,IAAa;AAEf;AAAA,QACF,KAAK;AACH,UAAI,MAAM,QAAQP,CAAU,KAAK,MAAM,QAAQC,CAAW,KACxDK,IAAgB;AAAA,YACd,uBAAO,IAAI,CAAC,GAAIL,GAA2B,GAAID,CAAwB,CAAC;AAAA,UAAA,GAE1EO,IAAa,mBAEbD,IAAgBL,GAChBM,IAAa;AAEf;AAAA,QACF,KAAK;AACH,UACE,OAAOP,KAAe,YACtB,OAAOC,KAAgB,YACvB,OAAOC,KAAc,YAErBI,IAAgBJ,KAAaF,IAAaE,MAAcD,IAAcC,IACtEK,IAAa,aAEbD,IAAgBL,GAChBM,IAAa;AAEf;AAAA,QACF,KAAK;AACH,UAAAD,IAAgB,KAAK,IAAI,OAAON,CAAU,GAAG,OAAOC,CAAW,CAAC,GAChEM,IAAa;AACb;AAAA,QACF,KAAK;AACH,UAAAD,IAAgB,KAAK,IAAI,OAAON,CAAU,GAAG,OAAOC,CAAW,CAAC,GAChEM,IAAa;AACb;AAAA,QACF,KAAK;AACH,UAAAD,IAAgB,KAAK,IAAI,OAAON,CAAU,GAAG,OAAOC,CAAW,CAAC,IAAI,GACpEM,IAAa;AACb;AAAA,QACF;AACE,UAAAD,IAAgBL,GAChBM,IAAa;AAAA,MAAA;AAGjB,MAAAb,EAAU,KAAK;AAAA,QACb,MAAAjB;AAAA,QACA,YAAAuB;AAAA,QACA,aAAAC;AAAA,QACA,WAAAC;AAAA,QACA,eAAAI;AAAA,QACA,YAAAC;AAAA,MAAA,CACD,GAED5B,EAAUgB,GAAalB,GAAM6B,CAAa;AAAA,IAC5C;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAMX;AAAA,IACN,cAAcD,EAAU,SAAS;AAAA,IACjC,WAAAA;AAAA,IACA,UAAU;AAAA,MACR,UAAU;AAAA,MACV,YAAY,KAAK,IAAA;AAAA,IAAI;AAAA,EACvB;AAEJ;AASO,SAASc,EACd5C,GACAC,GACgD;AAChD,MAAI4C,IAAW,IACXC,IAAW;AAEf,QAAMC,IAAU,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK/C,CAAC,GAAG,GAAG,OAAO,KAAKC,CAAC,CAAC,CAAC;AAE9D,aAAWO,KAAOuC,GAAS;AACzB,UAAMC,IAAOhD,EAAEQ,CAAG,MAAM,UAAaR,EAAEQ,CAAG,MAAM,IAAIR,EAAEQ,CAAG,IAAI,GACvDyC,IAAOhD,EAAEO,CAAG,MAAM,UAAaP,EAAEO,CAAG,MAAM,IAAIP,EAAEO,CAAG,IAAI;AAE7D,IAAIwC,IAAOC,MAAMJ,IAAW,KACxBI,IAAOD,MAAMF,IAAW;AAAA,EAC9B;AAEA,SAAI,CAACD,KAAY,CAACC,IAAiB,UAC/BD,KAAY,CAACC,IAAiB,YAC9B,CAACD,KAAYC,IAAiB,YAC3B;AACT;AAKO,SAASI,EAAkBlD,GAAgBC,GAA6B;AAC7E,QAAM8B,IAAsB,CAAA,GACtBgB,IAAU,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK/C,CAAC,GAAG,GAAG,OAAO,KAAKC,CAAC,CAAC,CAAC;AAE9D,aAAWO,KAAOuC;AAChB,IAAAhB,EAAOvB,CAAG,IAAI,KAAK;AAAA,MACjBR,EAAEQ,CAAG,MAAM,UAAaR,EAAEQ,CAAG,MAAM,IAAIR,EAAEQ,CAAG,IAAI;AAAA,MAChDP,EAAEO,CAAG,MAAM,UAAaP,EAAEO,CAAG,MAAM,IAAIP,EAAEO,CAAG,IAAI;AAAA,IAAA;AAIpD,SAAOuB;AACT;AAKO,SAASoB,EAAqBC,GAAoBC,GAA6B;AACpF,SAAO;AAAA,IACL,GAAGD;AAAA,IACH,CAACC,CAAM,IAAID,EAAMC,CAAM,MAAM,UAAaD,EAAMC,CAAM,MAAM,IAAID,EAAMC,CAAM,IAAI,KAAK;AAAA,EAAA;AAEzF;AAKO,SAASC,EAAkBD,GAA6B;AAC7D,SAAO,EAAE,CAACA,CAAM,GAAG,EAAA;AACrB;AASO,SAASE,EACd5B,GACqB;AACrB,QAAM;AAAA,IACJ,UAAA6B;AAAA,IACA,iBAAA5B,IAAkB,CAAA;AAAA,IAClB,cAAAC,IAAe,CAAA;AAAA,IACf,cAAA4B,IAAe,CAAA;AAAA,IACf,cAAAC,IAAe,CAAA;AAAA,IACf,gBAAAC,IAAiB;AAAA,IACjB,aAAAC;AAAA,IACA,cAAAC,IAAe;AAAA,EAAA,IACblC,GAEEmC,IAAyC,CAAA,GAGzCC,IAGF,EAAE,GAAGnC,EAAA;AACT,aAAWoC,KAASP;AAClB,IAAAM,EAAyBC,CAAK,IAAI;AAEpC,aAAWA,KAASN;AAClB,IAAAK,EAAyBC,CAAK,IAAI;AAGpC,WAASC,EAAQzC,GAAUC,GAAWC,GAAuC;AAC3E,QAAIK;AAEJ,YAAQyB,GAAA;AAAA,MACN,KAAK;AACH,QAAAzB,IAAS;AAAA,UACP,MAAMtB,EAAUgB,CAAM;AAAA,UACtB,cAAc;AAAA,UACd,WAAW,CAAA;AAAA,UACX,UAAU;AAAA,YACR,UAAU;AAAA,YACV,YAAY,KAAK,IAAA;AAAA,UAAI;AAAA,QACvB;AAEF;AAAA,MAEF,KAAK;AACH,QAAAM,IAAS;AAAA,UACP,MAAMtB,EAAUe,CAAK;AAAA,UACrB,cAAc;AAAA,UACd,WAAW,CAAA;AAAA,UACX,UAAU;AAAA,YACR,UAAU;AAAA,YACV,YAAY,KAAK,IAAA;AAAA,UAAI;AAAA,QACvB;AAEF;AAAA,MAEF,KAAK,eAAe;AAClB,cAAM0C,IAAWtD,EAAUY,GAAO,CAACmC,CAAc,CAAC,KAAgB,GAC5DQ,IAAYvD,EAAUa,GAAQ,CAACkC,CAAc,CAAC,KAAgB;AACpE,QAAA5B,IAAS;AAAA,UACP,MAAMtB,EAAUyD,IAAUC,IAAW3C,IAAQC,CAAM;AAAA,UACnD,cAAc;AAAA,UACd,WAAW,CAAA;AAAA,UACX,UAAU;AAAA,YACR,UAAU;AAAA,YACV,YAAY,KAAK,IAAA;AAAA,UAAI;AAAA,QACvB;AAEF;AAAA,MACF;AAAA,MAEA,KAAK;AACH,QAAIC,IACFK,IAASR,EAAcC,GAAOC,GAAQC,GAAM;AAAA,UAC1C,iBAAiBqC;AAAA,UACjB,cAAAlC;AAAA,QAAA,CACD,IAGDE,IAASqC,EAAkB5C,GAAOC,CAAM;AAE1C;AAAA,MAEF,KAAK;AACH,QAAAM,IAASqC,EAAkB5C,GAAOC,CAAM;AACxC;AAAA,MAEF,KAAK;AACH,QAAImC,IACF7B,IAAS;AAAA,UACP,MAAM6B,EAAYpC,GAAOC,GAAQC,CAAI;AAAA,UACrC,cAAc;AAAA,UACd,WAAW,CAAA;AAAA,UACX,UAAU;AAAA,YACR,UAAU;AAAA,YACV,YAAY,KAAK,IAAA;AAAA,UAAI;AAAA,QACvB,IAIFK,IAAS;AAAA,UACP,MAAMtB,EAAUgB,CAAM;AAAA,UACtB,cAAc;AAAA,UACd,WAAW,CAAA;AAAA,UACX,UAAU;AAAA,YACR,UAAU;AAAA,YACV,YAAY,KAAK,IAAA;AAAA,UAAI;AAAA,QACvB;AAGJ;AAAA,MAEF;AACE,QAAAM,IAAS;AAAA,UACP,MAAMtB,EAAUgB,CAAM;AAAA,UACtB,cAAc;AAAA,UACd,WAAW,CAAA;AAAA,UACX,UAAU;AAAA,YACR,UAAU;AAAA,YACV,YAAY,KAAK,IAAA;AAAA,UAAI;AAAA,QACvB;AAAA,IACF;AAGJ,WAAIoC,KACFC,EAAQ,KAAK/B,CAAM,GAGdA;AAAA,EACT;AAEA,WAASqC,EAAkB5C,GAAUC,GAAwC;AAC3E,UAAMK,IAAwB,CAAA,GACxBC,IAAStB,EAAUgB,CAAM,GAEzBO,wBAAe,IAAA;AACrB,IAAAd,EAAYM,CAAK,EAAE,QAAQ,CAACS,MAAMD,EAAS,IAAIC,EAAE,KAAK,GAAG,CAAC,CAAC,GAC3Df,EAAYO,CAAM,EAAE,QAAQ,CAACQ,MAAMD,EAAS,IAAIC,EAAE,KAAK,GAAG,CAAC,CAAC;AAE5D,eAAWC,KAAWF,GAAU;AAC9B,YAAMnB,IAAOqB,EAAQ,MAAM,GAAG;AAE9B,UAAIL,EAAa,KAAK,CAACM,MAAMD,EAAQ,WAAWC,CAAC,CAAC;AAChD;AAGF,YAAMC,IAAaxB,EAAUY,GAAOX,CAAI,GAClCwB,IAAczB,EAAUa,GAAQZ,CAAI;AAE1C,UAAId,EAAUqC,GAAYC,CAAW;AACnC;AAGF,YAAMI,IACJsB,EAAyB7B,CAAO,KAChC6B,EAAyBlD,EAAK,CAAC,CAAW,KAC1C;AAEF,UAAI6B,GACAC;AAEJ,UAAI,OAAOF,KAAkB;AAC3B,QAAAC,IAAgBD,EAAcL,GAAYC,CAAW,GACrDM,IAAa;AAAA;AAEb,gBAAQF,GAAA;AAAA,UACN,KAAK;AACH,YAAAC,IAAgBN,GAChBO,IAAa;AACb;AAAA,UACF,KAAK,UAAU;AACb,kBAAMuB,IAAWtD,EAAUY,GAAO,CAACmC,CAAc,CAAC,KAAgB,GAC5DQ,IAAYvD,EAAUa,GAAQ,CAACkC,CAAc,CAAC,KAAgB;AACpE,YAAAjB,IAAgBwB,IAAUC,IAAW/B,IAAaC,GAClDM,IAAauB,IAAUC,IAAW,iBAAiB;AACnD;AAAA,UACF;AAAA,UACA;AACE,YAAAzB,IAAgBL,GAChBM,IAAa;AAAA,QAAA;AAInB,MAAAb,EAAU,KAAK;AAAA,QACb,MAAAjB;AAAA,QACA,YAAAuB;AAAA,QACA,aAAAC;AAAA,QACA,eAAAK;AAAA,QACA,YAAAC;AAAA,MAAA,CACD,GAED5B,EAAUgB,GAAalB,GAAM6B,CAAa;AAAA,IAC5C;AAEA,WAAO;AAAA,MACL,MAAMX;AAAA,MACN,cAAcD,EAAU,SAAS;AAAA,MACjC,WAAAA;AAAA,MACA,UAAU;AAAA,QACR,UAAU;AAAA,QACV,YAAY,KAAK,IAAA;AAAA,MAAI;AAAA,IACvB;AAAA,EAEJ;AAEA,WAASuC,EAAgB7C,GAAUC,GAAWC,GAAsB;AAClE,UAAMI,IAAwB,CAAA,GAExBE,wBAAe,IAAA;AACrB,IAAAd,EAAYM,CAAK,EAAE,QAAQ,CAACS,MAAMD,EAAS,IAAIC,EAAE,KAAK,GAAG,CAAC,CAAC,GAC3Df,EAAYO,CAAM,EAAE,QAAQ,CAACQ,MAAMD,EAAS,IAAIC,EAAE,KAAK,GAAG,CAAC,CAAC;AAE5D,eAAWC,KAAWF,GAAU;AAC9B,YAAMnB,IAAOqB,EAAQ,MAAM,GAAG;AAE9B,UAAIL,EAAa,KAAK,CAACM,MAAMD,EAAQ,WAAWC,CAAC,CAAC;AAChD;AAGF,YAAMC,IAAaxB,EAAUY,GAAOX,CAAI,GAClCwB,IAAczB,EAAUa,GAAQZ,CAAI,GACpCyB,IAAYZ,IAAOd,EAAUc,GAAMb,CAAI,IAAI;AAEjD,UAAI,CAAAd,EAAUqC,GAAYC,CAAW;AAIrC,YAAIX,GAAM;AACR,gBAAMa,IAAe,CAACxC,EAAUqC,GAAYE,CAAS,GAC/CE,IAAgB,CAACzC,EAAUsC,GAAaC,CAAS;AAEvD,UAAIC,KAAgBC,KAClBV,EAAU,KAAK;AAAA,YACb,MAAAjB;AAAA,YACA,YAAAuB;AAAA,YACA,aAAAC;AAAA,YACA,WAAAC;AAAA,UAAA,CACD;AAAA,QAEL;AACE,UAAAR,EAAU,KAAK;AAAA,YACb,MAAAjB;AAAA,YACA,YAAAuB;AAAA,YACA,aAAAC;AAAA,UAAA,CACD;AAAA,IAEL;AAEA,WAAOP;AAAA,EACT;AAEA,SAAO;AAAA,IACL,SAAAmC;AAAA,IACA,iBAAAI;AAAA,IAEA,iBAAiB,CAACC,GAAYC,MAAgB;AAC5C,YAAMxC,IAASa,EAAoB0B,GAAYC,CAAW;AAC1D,aAAIxC,MAAW,YAAkB,gBAC7BA,MAAW,YAAkB,iBAC1BA;AAAA,IACT;AAAA,IAEA,aAAamB;AAAA,IAEb,YAAY,MAAM,CAAC,GAAGY,CAAO;AAAA,IAC7B,cAAc,MAAM;AAClB,MAAAA,EAAQ,SAAS;AAAA,IACnB;AAAA,EAAA;AAEJ;AASO,MAAMU,IAAqB,MAChCjB,EAA0B,EAAE,UAAU,eAAe,GAK1CkB,IAAqB,MAChClB,EAA0B,EAAE,UAAU,eAAe,GAK1CmB,IAAqB,CAChCf,IAAiB,gBACOJ,EAA0B,EAAE,UAAU,eAAe,gBAAAI,EAAA,CAAgB,GAKlFgB,IAAwB,CACnCC,MAEArB,EAA0B;AAAA,EACxB,UAAU;AAAA,EACV,GAAGqB;AACL,CAAC;"}