"""Solution for finetune_practice.py."""
import math

FIELDS = ["intent", "order_id", "sku", "urgency"]
NULLS = {None, "", "null", "none", "n/a", "na"}


def lora_params(shapes: list[tuple[int, int]], r: int, layers: int) -> int:
    return layers * sum(r * (d_in + d_out) for d_in, d_out in shapes)


def _norm(field: str, value):
    if isinstance(value, str):
        value = value.strip()
        if value.lower() in NULLS:
            return None
        return value.upper() if field in ("order_id", "sku") else value.lower()
    return None if value in NULLS else value


def score(pred: dict | None, gold: dict) -> dict:
    pred = pred or {}
    out = {f: f in pred and _norm(f, pred[f]) == _norm(f, gold[f]) for f in FIELDS}
    out["all"] = all(out[f] for f in FIELDS)
    return out


def invented_rate(preds: list[dict | None], golds: list[dict]) -> float:
    none = [(p or {}) for p, g in zip(preds, golds) if _norm("order_id", g["order_id"]) is None]
    if not none:
        return 0.0
    return sum(_norm("order_id", p.get("order_id")) is not None for p in none) / len(none)


def mcnemar_p(a: list[bool], b: list[bool]) -> float:
    a_only = sum(x and not y for x, y in zip(a, b))
    b_only = sum(y and not x for x, y in zip(a, b))
    n = a_only + b_only
    if n == 0:
        return 1.0
    k = min(a_only, b_only)
    return min(1.0, 2 * sum(math.comb(n, i) for i in range(k + 1)) / 2 ** n)
