Files
site/apps/api/app/modules/zootech/lab/calc/gfe_policies.py
T
2026-07-17 12:57:18 +03:00

85 lines
2.6 KiB
Python

"""WESP-политики расчёта на базе GfE 2001 (отличия от zootech Excel — осознанные)."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Literal
FeedGroup = Literal["rough", "succulent", "concentrate", "other", "unknown"]
# --- GfE 2001 константы (формулы не меняем) ---
NEL_Q_COEFF = 0.004
NEL_Q_REF_PCT = 57.0
NEL_BASE = 0.6
GE_CP = 0.0239
GE_FAT = 0.0398
GE_FIBER = 0.0201
GE_NFE = 0.0175
ME_FAT = 0.0312
ME_FIBER = 0.0136
ME_OR_RESIDUE = 0.0147
ME_CP = 0.00234
USP_FAT_THRESHOLD_G_PER_KG_DM = 70.0 # 7% СЖ/кг СВ
# DCAB (Na+K)-(Cl+S), мэкв при минералах в г/кг СВ
DCAB_NA = 43.5
DCAB_K = 25.6
DCAB_CL = 28.2
DCAB_S = 62.4
# Дефолты переваримости при пустых коэфф. (Excel legacy, кроме ОВ)
DEFAULT_CP_DIGEST_PCT = 86.0
DEFAULT_FAT_DIGEST_PCT = 75.0
DEFAULT_FIBER_DIGEST_PCT = 86.0
DEFAULT_NFE_DIGEST_PCT = 94.0
DEFAULT_INSOLUBLE_PROTEIN_PCT = 15.0
DEFAULT_PROTEIN_FRACTION_PCT = 18.9
# WESP: дефолт ВРХ орг. вещ. при пустом поле — по классу корма
DEFAULT_OMD_ROUGH_PCT = 65.0
DEFAULT_OMD_SUCCULENT_PCT = 72.0
DEFAULT_OMD_CONCENTRATE_PCT = 91.0
@dataclass(frozen=True)
class DeriveContext:
feed_group: FeedGroup = "unknown"
is_main_feed: bool = False
@classmethod
def from_cells(cls, *, main_feed_g: float = 0.0, feed_group: FeedGroup = "unknown") -> DeriveContext:
return cls(
feed_group=feed_group,
is_main_feed=main_feed_g > 0,
)
@classmethod
def infer_from_cells(cls, cells: dict[str, float], feed_group: FeedGroup = "unknown") -> DeriveContext:
main_feed = cells.get("E", 0.0)
return cls.from_cells(main_feed_g=main_feed, feed_group=feed_group)
def default_om_digestibility_pct(ctx: DeriveContext | None) -> float:
"""Дефолт переваримости ОВ (%) при отсутствии ВРХ Орг Вещ."""
if ctx is None:
return DEFAULT_OMD_CONCENTRATE_PCT
if ctx.is_main_feed or ctx.feed_group == "rough":
return DEFAULT_OMD_ROUGH_PCT
if ctx.feed_group == "succulent":
return DEFAULT_OMD_SUCCULENT_PCT
return DEFAULT_OMD_CONCENTRATE_PCT
def default_digestibility_coefficients() -> dict[str, float]:
return {
"cp": DEFAULT_CP_DIGEST_PCT,
"fat": DEFAULT_FAT_DIGEST_PCT,
"fiber": DEFAULT_FIBER_DIGEST_PCT,
"nfe": DEFAULT_NFE_DIGEST_PCT,
"insoluble_protein": DEFAULT_INSOLUBLE_PROTEIN_PCT,
"protein_fraction": DEFAULT_PROTEIN_FRACTION_PCT,
}