{"version":3,"file":"statistics.mjs","names":[],"sources":["../../../src/batteries/tools/statistics/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for descriptive statistics, correlation, quantiles, and numeric summaries.\n *\n * @module @nhtio/adk/batteries/tools/statistics\n *\n * @remarks\n * Pre-constructed bundled tools for the `statistics` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { validator } from '@nhtio/validation'\nimport { Tool, SpooledJsonArtifact } from '@nhtio/adk/common'\nimport {\n  bigSum,\n  bigMean,\n  formatBig,\n  bigToNumber,\n  DEFAULT_PRECISION,\n} from '@nhtio/adk/lib/helpers/bignum'\nimport {\n  equalIntervalBreaks,\n  interquartileRange,\n  max,\n  mean,\n  median,\n  min,\n  mode,\n  quantile,\n  sampleCorrelation,\n  standardDeviation,\n  sum,\n  variance,\n  zScore,\n} from 'simple-statistics'\n\n/**\n * Normalise the `numbers`/`x`/`y` input to a `number[]`.\n *\n * @remarks\n * The input schema is `validator.array().items(validator.number())`, which already rejects\n * `NaN`, `±Infinity`, and magnitudes `> Number.MAX_SAFE_INTEGER` before the handler runs — so by\n * the time a value reaches here it is a finite, in-range float64. This guard only enforces\n * non-emptiness (and defensively re-checks the array shape). It deliberately NO LONGER silently\n * drops non-finite entries: those can't arrive through the typed schema, and a silent filter hid\n * real input errors.\n */\nfunction parseNumbers(input: unknown): number[] | { error: string } {\n  if (!Array.isArray(input)) return { error: 'Input must be an array of numbers.' }\n  if (input.length === 0) return { error: 'Array must contain at least one number.' }\n  return input as number[]\n}\n\n/** Shared `precision` schema fragment (significant digits for numeric output, default 8). */\nconst precisionField = validator\n  .number()\n  .default(DEFAULT_PRECISION)\n  .description(`Significant digits for numeric output (default: ${DEFAULT_PRECISION}).`)\n\n/**\n * Compute descriptive statistics for a JSON array of numbers.\n *\n * @remarks\n * Returns count, sum, min/max/range, mean, median, mode, variance, standard deviation,\n * quartiles (Q1/Q2/Q3), IQR, and key percentiles (P10/P90/P95/P99) as a pretty-printed JSON\n * object. Non-numeric and non-finite entries are silently filtered.\n */\nexport const statsDescribeTool = new Tool({\n  name: 'stats_describe',\n  description:\n    'Compute descriptive statistics for a numeric array: count, sum, min, max, range, mean, median, mode, variance, standard deviation, quartiles (Q1–Q3), IQR, and key percentiles.',\n  inputSchema: validator.object({\n    numbers: validator.array().items(validator.number()).required().description('Array of numbers'),\n    precision: precisionField,\n  }),\n  artifactConstructor: () => SpooledJsonArtifact,\n  handler: async (args) => {\n    const { numbers, precision } = args as { numbers: number[]; precision: number }\n    const nums = parseNumbers(numbers)\n    if ('error' in nums) return `Error: ${nums.error}`\n\n    const sorted = [...nums].sort((a, b) => a - b)\n    const modeVal = mode(nums)\n    // Computed aggregates (sum/mean/variance/std_dev) are emitted as `precision`-significant-digit\n    // STRINGS via BigNumber: this is lossless (no toPrecision round-trip) and overflow-safe (a sum\n    // exceeding float64 stays exact, e.g. 2e308 instead of Infinity). Order statistics\n    // (min/max/median/quartiles/range) are always input elements or midpoints — in-range by\n    // construction — so they remain numbers.\n    const fmt = (n: number): string => formatBig(n, precision)\n\n    return JSON.stringify(\n      {\n        count: nums.length,\n        sum: formatBig(bigSum(nums), precision),\n        min: min(nums),\n        max: max(nums),\n        range: max(nums) - min(nums),\n        mean: formatBig(bigMean(nums), precision),\n        median: median(nums),\n        mode: modeVal,\n        variance: fmt(variance(nums)),\n        std_dev: fmt(standardDeviation(nums)),\n        q1: quantile(sorted, 0.25),\n        q2: quantile(sorted, 0.5),\n        q3: quantile(sorted, 0.75),\n        iqr: interquartileRange(nums),\n        p10: quantile(sorted, 0.1),\n        p90: quantile(sorted, 0.9),\n        p95: quantile(sorted, 0.95),\n        p99: quantile(sorted, 0.99),\n      },\n      null,\n      2\n    )\n  },\n})\n\n/**\n * Compute the Pearson correlation coefficient between two numeric arrays.\n *\n * @remarks\n * Returns `r`, `r²` (as a percentage of explained variance), and a plain-English interpretation\n * of strength and direction. Arrays must be the same length and contain at least two points.\n */\nexport const statsCorrelateTool = new Tool({\n  name: 'stats_correlate',\n  description:\n    'Compute the Pearson correlation coefficient between two numeric arrays. Returns the r value (-1 to 1), r², and a plain-English interpretation.',\n  inputSchema: validator.object({\n    x: validator\n      .array()\n      .items(validator.number())\n      .required()\n      .description('Array of numbers (first variable)'),\n    y: validator\n      .array()\n      .items(validator.number())\n      .required()\n      .description('Array of numbers (second variable, same length as x)'),\n  }),\n  handler: async (args) => {\n    const { x: rawX, y: rawY } = args as { x: number[]; y: number[] }\n    const x = parseNumbers(rawX)\n    if ('error' in x) return `Error in x: ${x.error}`\n    const y = parseNumbers(rawY)\n    if ('error' in y) return `Error in y: ${y.error}`\n\n    if (x.length !== y.length)\n      return `Error: Arrays must be the same length (x: ${x.length}, y: ${y.length}).`\n    if (x.length < 2) return 'Error: At least 2 data points required.'\n\n    // Pearson r is undefined when either variable has zero variance (constant) — the formula\n    // divides by a standard deviation of 0. Report that explicitly instead of emitting `r = NaN`,\n    // which reads like a real (negligible) correlation.\n    if (standardDeviation(x) === 0 || standardDeviation(y) === 0) {\n      return 'Correlation is undefined: at least one variable is constant (zero variance), so Pearson r cannot be computed.'\n    }\n\n    try {\n      const r = sampleCorrelation(x, y)\n      const absR = Math.abs(r)\n      const direction = r > 0 ? 'positive' : r < 0 ? 'negative' : 'no'\n      const strength =\n        absR >= 0.9\n          ? 'very strong'\n          : absR >= 0.7\n            ? 'strong'\n            : absR >= 0.5\n              ? 'moderate'\n              : absR >= 0.3\n                ? 'weak'\n                : 'very weak / negligible'\n      return `r = ${r.toFixed(6)}\\nr² = ${(r * r * 100).toFixed(2)}% (explained variance)\\nInterpretation: ${strength} ${direction} correlation`\n    } catch (err) {\n      return `Error: ${isError(err) ? err.message : String(err)}`\n    }\n  },\n})\n\n/**\n * Transform a numeric array — normalise, smooth, rank, or detect outliers.\n *\n * @remarks\n * Supported operations: `normalize_min_max`, `normalize_z_score`, `normalize_percent_of_sum`,\n * `running_total`, `rolling_avg`, `pct_change`, `rank`, `outliers_iqr`, `outliers_zscore`. Most\n * operations return a JSON array of transformed values; outlier operations return a\n * human-readable report.\n */\nexport const statsTransformTool = new Tool({\n  name: 'stats_transform',\n  description:\n    'Transform a numeric array: normalize (min-max or z-score), compute running totals, rolling averages, percent change between consecutive values, rank each value, or detect outliers.',\n  inputSchema: validator.object({\n    numbers: validator.array().items(validator.number()).required().description('Array of numbers'),\n    operation: validator\n      .string()\n      .valid(\n        'normalize_min_max',\n        'normalize_z_score',\n        'normalize_percent_of_sum',\n        'running_total',\n        'rolling_avg',\n        'pct_change',\n        'rank',\n        'outliers_iqr',\n        'outliers_zscore'\n      )\n      .required()\n      .description('Transformation to apply'),\n    window: validator.number().default(3).description('For rolling_avg: window size (default: 3)'),\n    threshold: validator\n      .number()\n      .default(3.0)\n      .description('For outliers_zscore: z-score threshold (default: 3.0)'),\n    precision: precisionField,\n  }),\n  handler: async (args) => {\n    const { numbers, operation, window, threshold, precision } = args as {\n      numbers: number[]\n      operation: string\n      window: number\n      threshold: number\n      precision: number\n    }\n    const nums = parseNumbers(numbers)\n    if ('error' in nums) return `Error: ${nums.error}`\n\n    // Round a float to `precision` significant digits without the toPrecision/parse noise.\n    const round = (n: number): number => Number.parseFloat(formatBig(n, precision))\n\n    switch (operation) {\n      case 'normalize_min_max': {\n        const lo = min(nums)\n        const hi = max(nums)\n        if (lo === hi) return JSON.stringify(nums.map(() => 0))\n        return JSON.stringify(nums.map((v) => round((v - lo) / (hi - lo))))\n      }\n\n      case 'normalize_z_score': {\n        const m = mean(nums)\n        const sd = standardDeviation(nums)\n        if (sd === 0) return JSON.stringify(nums.map(() => 0))\n        return JSON.stringify(nums.map((v) => round(zScore(v, m, sd))))\n      }\n\n      case 'normalize_percent_of_sum': {\n        const total = sum(nums)\n        if (total === 0) return JSON.stringify(nums.map(() => 0))\n        return JSON.stringify(nums.map((v) => round((v / total) * 100)))\n      }\n\n      case 'running_total': {\n        // Each prefix sum is computed exactly via BigNumber (so a cumulative total exceeding\n        // float64 stays exact instead of overflowing to Infinity). Each entry is a plain number\n        // when it fits float64 (the common case), or a precise string when it would otherwise\n        // overflow to Infinity → JSON null.\n        return JSON.stringify(\n          nums.map((_, i) => {\n            const big = bigSum(nums.slice(0, i + 1))\n            const asNum = bigToNumber(big)\n            // Number only when exactly representable; otherwise the exact string (covers both\n            // overflow and the silent-rounding gap above 2^53).\n            if (Number.isFinite(asNum) && Math.abs(asNum) <= Number.MAX_SAFE_INTEGER) {\n              return round(asNum)\n            }\n            return formatBig(big, precision)\n          })\n        )\n      }\n\n      case 'rolling_avg': {\n        const w = Math.max(1, Math.floor(window))\n        return JSON.stringify(\n          nums.map((_, i) => {\n            const slice = nums.slice(Math.max(0, i - w + 1), i + 1)\n            return round(mean(slice))\n          })\n        )\n      }\n\n      case 'pct_change': {\n        const changes: (number | null)[] = [null]\n        for (let i = 1; i < nums.length; i++) {\n          if (nums[i - 1] === 0) {\n            changes.push(null)\n          } else {\n            changes.push(\n              Number.parseFloat(\n                (((nums[i] - nums[i - 1]) / Math.abs(nums[i - 1])) * 100).toFixed(4)\n              )\n            )\n          }\n        }\n        return JSON.stringify(changes)\n      }\n\n      case 'rank': {\n        const sorted = [...nums].sort((a, b) => a - b)\n        return JSON.stringify(nums.map((v) => sorted.indexOf(v) + 1))\n      }\n\n      case 'outliers_iqr': {\n        const sorted = [...nums].sort((a, b) => a - b)\n        const q1 = quantile(sorted, 0.25)\n        const q3 = quantile(sorted, 0.75)\n        const iqr = q3 - q1\n        const lo = q1 - 1.5 * iqr\n        const hi = q3 + 1.5 * iqr\n        const outliers = nums\n          .map((v, i) => ({ index: i, value: v }))\n          .filter(({ value }) => value < lo || value > hi)\n        if (outliers.length === 0) return 'No outliers detected (IQR method).'\n        return `${outliers.length} outlier(s) detected:\\n${outliers.map((o) => `  [${o.index}] = ${o.value}`).join('\\n')}`\n      }\n\n      case 'outliers_zscore': {\n        const m = mean(nums)\n        const sd = standardDeviation(nums)\n        const outliers = nums\n          .map((v, i) => ({ index: i, value: v, z: sd === 0 ? 0 : Math.abs(zScore(v, m, sd)) }))\n          .filter((o) => o.z > threshold)\n        if (outliers.length === 0) return `No outliers detected (|z| > ${threshold}).`\n        return `${outliers.length} outlier(s) detected (|z| > ${threshold}):\\n${outliers.map((o) => `  [${o.index}] = ${o.value} (z = ${o.z.toFixed(3)})`).join('\\n')}`\n      }\n\n      default:\n        return `Error: Unknown operation \"${operation}\".`\n    }\n  },\n})\n\n/**\n * Bin a numeric array into equal-width histogram buckets.\n *\n * @remarks\n * Output is a text histogram showing each bin's range, count, percentage of total, and a bar\n * chart. The last bin is inclusive on both ends; preceding bins are half-open. `bins` is clamped\n * to `[2, 100]`.\n */\nexport const statsHistogramTool = new Tool({\n  name: 'stats_histogram',\n  description: 'Bin a numeric array into equal-width histogram buckets and display counts.',\n  inputSchema: validator.object({\n    numbers: validator.array().items(validator.number()).required().description('Array of numbers'),\n    bins: validator.number().default(10).description('Number of bins (default: 10, max: 100)'),\n    precision: precisionField,\n  }),\n  handler: async (args) => {\n    const { numbers, bins, precision } = args as {\n      numbers: number[]\n      bins: number\n      precision: number\n    }\n    const nums = parseNumbers(numbers)\n    if ('error' in nums) return `Error: ${nums.error}`\n\n    const binCount = Math.max(2, Math.min(100, Math.floor(bins)))\n\n    try {\n      const breaks = equalIntervalBreaks(nums, binCount)\n      const rows: string[] = []\n      const maxCount = (() => {\n        let m = 0\n        for (let i = 0; i < breaks.length - 1; i++) {\n          const isLast = i === breaks.length - 2\n          const count = nums.filter((v) =>\n            isLast ? v >= breaks[i] && v <= breaks[i + 1] : v >= breaks[i] && v < breaks[i + 1]\n          ).length\n          if (count > m) m = count\n        }\n        return m\n      })()\n\n      for (let i = 0; i < breaks.length - 1; i++) {\n        const isLast = i === breaks.length - 2\n        const count = nums.filter((v) =>\n          isLast ? v >= breaks[i] && v <= breaks[i + 1] : v >= breaks[i] && v < breaks[i + 1]\n        ).length\n        const pct = ((count / nums.length) * 100).toFixed(1)\n        const bar = '█'.repeat(maxCount > 0 ? Math.round((count / maxCount) * 20) : 0)\n        const range = `[${formatBig(breaks[i], precision)}, ${formatBig(breaks[i + 1], precision)}${isLast ? ']' : ')'}`\n        rows.push(`${range.padEnd(22)} ${String(count).padStart(4)} (${pct.padStart(5)}%) ${bar}`)\n      }\n\n      return rows.join('\\n')\n    } catch (err) {\n      return `Error: ${isError(err) ? err.message : String(err)}`\n    }\n  },\n})\n"],"mappings":"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"}