from __future__ import annotations from typing import Any from app.modules.zootech.lab.calc.nutrients import rnb def apply_content_derived( content_by_key: dict[str, float | None], defn: dict[str, Any], *, total_kg: float = 0, heads_per_trip: int = 1, profile_mass_kg: float | None = None, compound_mode: bool = False, ) -> float | None: derived = defn.get("derived") if derived == "alias": return content_by_key.get(defn.get("alias_of")) if derived == "pct_of_dm": src = content_by_key.get(defn.get("from_key")) dm = content_by_key.get("dry_matter") if src is None or not dm or dm <= 0: return None return src / dm * 100.0 if derived == "g_per_kg_dm": src = content_by_key.get(defn.get("from_key")) dm = content_by_key.get("dry_matter") if src is None or not dm or dm <= 0: return None if compound_mode: return src return src / (dm / 1000.0) if derived == "nel_per_kg_dm": dm = content_by_key.get("dry_matter") nel = content_by_key.get("nel") if not dm or dm <= 0 or nel is None: return None if compound_mode: return nel return nel / (dm / 1000.0) if derived == "ratio": num = content_by_key.get(defn.get("ratio_num")) den = content_by_key.get(defn.get("ratio_den")) if num is None or den is None or den == 0: return None return num / den if derived == "dm_pct_bw": dm = content_by_key.get("dry_matter") if dm is None or not profile_mass_kg or profile_mass_kg <= 0: return None return (dm / 1000.0 / profile_mass_kg) * 100.0 if derived == "ration_pct_bw": if not profile_mass_kg or profile_mass_kg <= 0 or total_kg <= 0: return None heads = max(int(heads_per_trip or 1), 1) kg_per_head = total_kg / heads return (kg_per_head / profile_mass_kg) * 100.0 if derived in ("rnb", "bra_rnb"): return rnb( content_by_key.get("crude_protein"), content_by_key.get("usp"), ) return None