65 lines
2.1 KiB
Python
65 lines
2.1 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from app.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
|