#!/usr/bin/env python3
"""mpmath O3 for engineering.measurement.accuracy. bias = x̄ − xm. s is Bessel unless ddof=0."""
from __future__ import annotations
import json, math, shutil
from pathlib import Path
import mpmath as mp

def nums(raw):
    if isinstance(raw, str):
        raw = [p for p in raw.replace(";", ",").split(",") if p.strip()]
    return [mp.mpf(str(v)) for v in raw]

def row(vid, inputs, kind):
    xs = nums(inputs.get("values", inputs.get("sample")))
    n = len(xs)
    dd = int(inputs.get("ddof", 1))
    mean = sum(xs) / n
    s = mp.sqrt(sum((x - mean) ** 2 for x in xs) / (n - dd))
    xm = mp.mpf(str(inputs.get("xm", inputs.get("X"))))
    bias = mean - xm
    return {
        "id": vid, "kind": kind, "inputs": inputs,
        "bias_f64": float(bias), "abs_bias_f64": float(abs(bias)),
        "xbar_f64": float(mean), "s_f64": float(s), "xm_f64": float(xm),
        "n": n, "ddof": dd, "bias_decimal": mp.nstr(bias, 40, strip_zeros=False),
    }

def main():
    mp.mp.dps = 80
    here = Path(__file__).resolve().parent
    vectors = [
        row("o3-low", {"values": [6, 7, 8], "xm": 8}, "low"),
        row("o3-zero", {"values": [7, 8, 9], "xm": 8}, "zero"),
        row("o3-high", {"values": [8, 9, 10], "xm": 8}, "high"),
        row("o3-alias", {"sample": "6,7,8", "X": 8}, "alias"),
        row("o3-flat", {"values": [8, 8, 8], "xm": 8}, "flat"),
        row("o3-ddof0", {"values": [6, 7, 8], "xm": 8, "ddof": 0}, "ddof0"),
        row("o3-awkward", {"values": ["0.9", "1.15", "1.4"], "xm": "1.4"}, "awkward"),
        row("o3-wide", {"values": [2, 6, 10], "xm": 4}, "wide"),
    ]
    table = {
        "family": "measurement_accuracy", "generator_id": "measurement-accuracy-mpmath-o3",
        "generator_version": "1.0.0", "seed": "20260925.measurement-accuracy-o3",
        "mpmath_dps": 80, "precision_bits": int(80 * math.log2(10)),
        "library": f"mpmath {mp.__version__}",
        "notes": "Signed bias from a sample and a master value. Not Type A uncertainty and not a single-shot error.",
        "vectors": vectors,
    }
    dest = here / "measurement-accuracy-o3-tables.json"
    dest.write_text(json.dumps(table, indent=2) + "\n", encoding="utf-8")
    public = here.parents[3] / "public/developers/cvp/reproduce"
    public.mkdir(parents=True, exist_ok=True)
    shutil.copy2(dest, public / "measurement-accuracy-o3-tables.json")
    shutil.copy2(Path(__file__), public / "generate-measurement-accuracy-o3.py")
    print(f"wrote {dest} ({len(vectors)} vectors)")

if __name__ == "__main__":
    main()
