{"files": {"main.ts": "import {run} from './core.ts';\nimport {POLICY} from './policy.ts';\nexport function evaluate(payload: any): any { return run(payload, POLICY); }\n", "core.ts": "import {parseDecimal, addDecimal, formatDecimal} from './helpers.ts';\nexport function run(payload: any, policy: any): any {\n  const now: any = payload ? payload.now : undefined;\n  const raw: any[] = payload && Array.isArray(payload.events) ? payload.events : [];\n  const maxAge: any = policy ? policy.max_age : undefined;\n  const inclusiveAge: boolean = !!(policy && policy.inclusive_age);\n  const auditDuplicate: boolean = !!(policy && policy.audit_duplicate);\n  const scopeTenant: boolean = !!(policy && policy.scope_key === 'tenant');\n  const duplicates: any[] = [];\n  const seen: any = new Set();\n  const kept: any[] = [];\n  for (let i = 0; i < raw.length; i++) {\n    const e: any = raw[i];\n    if (maxAge !== undefined && maxAge !== null && typeof now === 'number' && typeof e.ts === 'number') {\n      const age: number = now - e.ts;\n      if (inclusiveAge ? age > maxAge : age >= maxAge) continue;\n    }\n    const dedupKey: string = scopeTenant ? String(e.tenant) + '\\u0000' + String(e.id) : String(e.id);\n    if (seen.has(dedupKey)) {\n      if (auditDuplicate) duplicates.push(e.id);\n      continue;\n    }\n    seen.add(dedupKey);\n    kept.push({event: e, index: i});\n  }\n  const groups: any = new Map();\n  for (const item of kept) {\n    const e: any = item.event;\n    const gk: string = String(e.tenant) + '\\u0000' + String(e.entity);\n    if (!groups.has(gk)) groups.set(gk, {tenant: e.tenant, entity: e.entity, items: [], earliest: item.index});\n    const g: any = groups.get(gk);\n    g.items.push(item);\n    if (item.index < g.earliest) g.earliest = item.index;\n  }\n  const sortField: string = policy && (policy.latest_by === 'seq' || policy.latest_by === 'sequence') ? 'seq' : 'ts';\n  const tieLast: boolean = !!(policy && policy.tie_policy === 'last');\n  const gapIgnore: boolean = !!(policy && policy.gap_policy === 'ignore');\n  const allowResurrection: boolean = !!(policy && policy.allow_resurrection);\n  const absolute: boolean = !!(policy && policy.amount_mode === 'absolute');\n  const deleteWins: boolean = !!(policy && policy.delete_wins);\n  const precision: number = policy && typeof policy.precision === 'number' ? policy.precision : 0;\n  const results: any[] = [];\n  for (const g of groups.values()) {\n    const byTie: any = new Map();\n    for (const item of g.items) {\n      const key: any = item.event[sortField];\n      if (!byTie.has(key) || tieLast) byTie.set(key, item);\n    }\n    const retained: any[] = Array.from(byTie.values());\n    retained.sort((a: any, b: any) => {\n      const av: number = a.event[sortField];\n      const bv: number = b.event[sortField];\n      if (av < bv) return -1;\n      if (av > bv) return 1;\n      return a.index - b.index;\n    });\n    let prevSeq: number = 0;\n    let coeff: any = BigInt(0);\n    let scale: number = 0;\n    let deleted: boolean = false;\n    let hasDelete: boolean = false;\n    for (const item of retained) if (item.event.kind === 'delete') hasDelete = true;\n    for (const item of retained) {\n      const e: any = item.event;\n      if (gapIgnore && e.seq !== prevSeq + 1) continue;\n      prevSeq = e.seq;\n      if (e.kind === 'delete') {\n        deleted = true;\n      } else if (e.kind === 'set') {\n        if (!deleted || allowResurrection) {\n          deleted = false;\n          const amt: any = parseDecimal(e.amount === undefined || e.amount === null ? '0' : e.amount);\n          if (absolute) { coeff = amt.coeff; scale = amt.scale; }\n          else { const r: any = addDecimal(coeff, scale, amt.coeff, amt.scale); coeff = r.coeff; scale = r.scale; }\n        }\n      }\n    }\n    if (deleteWins && hasDelete) deleted = true;\n    results.push({tenant: g.tenant, entity: g.entity, value: formatDecimal(coeff, scale, precision), deleted: deleted, earliest: g.earliest});\n  }\n  if (policy && policy.order === 'key') {\n    results.sort((a: any, b: any) => {\n      if (String(a.tenant) < String(b.tenant)) return -1;\n      if (String(a.tenant) > String(b.tenant)) return 1;\n      if (String(a.entity) < String(b.entity)) return -1;\n      if (String(a.entity) > String(b.entity)) return 1;\n      return a.earliest - b.earliest;\n    });\n  } else {\n    results.sort((a: any, b: any) => a.earliest - b.earliest);\n  }\n  const entities: any[] = results.map((r: any) => ({tenant: r.tenant, entity: r.entity, value: r.value, deleted: r.deleted}));\n  return {entities: entities, duplicates: duplicates};\n}\n", "policy.ts": "export const POLICY: any = {\"delete_wins\": false, \"latest_by\": \"timestamp\", \"scope_key\": \"global\", \"tie_policy\": \"last\", \"allow_resurrection\": false, \"amount_mode\": \"delta\", \"gap_policy\": \"ignore\", \"precision\": 2, \"inclusive_age\": false, \"max_age\": 120, \"audit_duplicate\": false, \"order\": \"input\"};\n", "helpers.ts": "export function parseDecimal(input: any): any {\n  const s: string = String(input).trim();\n  const m: any = /^([+-]?)(\\d*)(?:\\.(\\d*))?(?:[eE]([+-]?\\d+))?$/.exec(s);\n  if (!m || (m[2] === '' && (m[3] === undefined || m[3] === ''))) return {coeff: BigInt(0), scale: 0};\n  const intPart: string = m[2] || '';\n  const fracPart: string = m[3] || '';\n  let digits: string = intPart + fracPart;\n  digits = digits.replace(/^0+(?=\\d)/, '');\n  if (digits === '') digits = '0';\n  let coeff: any = BigInt(digits);\n  if (m[1] === '-') coeff = -coeff;\n  let scale: number = fracPart.length;\n  if (m[4] !== undefined) scale -= parseInt(m[4], 10);\n  if (scale < 0) { coeff = coeff * BigInt(10) ** BigInt(-scale); scale = 0; }\n  return {coeff: coeff, scale: scale};\n}\nexport function addDecimal(aCoeff: any, aScale: number, bCoeff: any, bScale: number): any {\n  if (aScale === bScale) return {coeff: aCoeff + bCoeff, scale: aScale};\n  if (aScale > bScale) return {coeff: aCoeff + bCoeff * BigInt(10) ** BigInt(aScale - bScale), scale: aScale};\n  return {coeff: aCoeff * BigInt(10) ** BigInt(bScale - aScale) + bCoeff, scale: bScale};\n}\nexport function formatDecimal(coeffIn: any, scale: number, precision: number): string {\n  let coeff: any = coeffIn;\n  const negative: boolean = coeff < BigInt(0);\n  let mag: any = negative ? -coeff : coeff;\n  if (scale > precision) {\n    const divisor: any = BigInt(10) ** BigInt(scale - precision);\n    const q: any = mag / divisor;\n    const r: any = mag % divisor;\n    mag = r * BigInt(2) >= divisor ? q + BigInt(1) : q;\n  } else if (scale < precision) {\n    mag = mag * BigInt(10) ** BigInt(precision - scale);\n  }\n  const sign: string = negative && mag !== BigInt(0) ? '-' : '';\n  if (precision === 0) return sign + mag.toString();\n  const base: any = BigInt(10) ** BigInt(precision);\n  const intPart: any = mag / base;\n  const fracPart: any = mag % base;\n  return sign + intPart.toString() + '.' + fracPart.toString().padStart(precision, '0');\n}\n"}}