Интегрирован wesp в сайт
CI / quality (push) Canceled after 0s

This commit is contained in:
влад
2026-07-17 12:57:18 +03:00
parent 5dfa06ddbe
commit 355c0ef9f1
883 changed files with 194576 additions and 177 deletions
@@ -0,0 +1,107 @@
"""Методика Москва — лактирующие коровы (NORM_1_1_CALC)."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
from app.modules.zootech.lab.calc.racion.interp import popr_index
from app.modules.zootech.lab.calc.norms_derived import apply_derived_norms
from app.modules.zootech.lab.calc.racion.npitv_map import DAIRY_LACTIR_NPITV, NPITV_TO_INDICATOR
from app.modules.zootech.lab.calc.racion.tables import load_moskwa_lactir
@dataclass(frozen=True)
class MoscowDairyParams:
mass_kg: float
milk_yield_kg: float
milk_fat_pct: float = 4.0
lactation_no: int = 2
body_condition: int = 1
housing_system: int = 1
def _row_lookup(rows: list[dict], npitv: int) -> dict | None:
for row in rows:
if row["npitv"] == npitv and row["pom"] == 1:
return row
return None
def _popr_value(row: dict, udoy: float, boundaries: list[float]) -> tuple[float | None, float | None]:
popr = row.get("popr_k") or []
if not popr:
return None, None
idx = popr_index(udoy, boundaries) - 1
idx = max(0, min(idx, len(popr) - 1))
p_k = popr[idx]
koef = float(row.get("koef") or 0)
return p_k, koef
def compute_moscow_norm(npitv: int, params: MoscowDairyParams) -> float | None:
data = load_moskwa_lactir()
boundaries = data.get("udoy_boundaries") or []
row = _row_lookup(data.get("rows") or [], npitv)
if row is None:
return None
mass = params.mass_kg
udoy = params.milk_yield_kg
jir = params.milk_fat_pct
wmassa = mass * 1.02 if params.body_condition > 1 else mass
p_k, koef = _popr_value(row, udoy, boundaries)
if p_k is None:
return None
norma: float | None = None
if npitv == 1:
temp = 0.005 if udoy <= 22 else 0.0025
norma = temp * (wmassa - 500) + p_k * udoy - ((4 - jir) * udoy) / 148
elif npitv == 2:
temp = 0.09 if udoy <= 22 else 0.065
norma = temp * (wmassa - 500) + p_k * udoy - ((4 - jir) * udoy) / 15
elif npitv == 3:
temp = 0.017 if udoy <= 22 else 0.015
norma = temp * (wmassa - 500) + p_k * udoy
elif 4 <= npitv <= 24:
norma = p_k * udoy + (wmassa - 500) * koef
if npitv == 10:
norma *= 0.393
else:
return None
if norma is None:
return None
if params.lactation_no == 1:
norma *= 0.95
elif params.lactation_no == 3:
norma *= 1.05
if params.housing_system == 2:
norma *= 1.1
return round(norma, 3)
def resolve_moscow_dairy_norms(params: MoscowDairyParams) -> tuple[dict[str, dict[str, float | None]], dict[str, Any]]:
resolved: dict[str, dict[str, float | None]] = {}
dynamic: dict[str, Any] = {}
for npitv in DAIRY_LACTIR_NPITV:
value = compute_moscow_norm(npitv, params)
if value is None:
continue
key = NPITV_TO_INDICATOR.get(npitv)
if not key:
continue
resolved[key] = {"min": value, "max": None}
dynamic[key] = {"min": value, "npitv": npitv, "method": "racion_moscow", "source": "racion"}
resolved, derived_dyn = apply_derived_norms(resolved, mass_kg=params.mass_kg)
for k, v in derived_dyn.items():
dynamic[k] = {**v, "method": "racion_moscow", "source": "derived"}
meta = {
"method": "racion_moscow",
"massKg": params.mass_kg,
"milkYieldKg": params.milk_yield_kg,
"milkFatPct": params.milk_fat_pct,
}
return resolved, {"meta": meta, "dynamic": dynamic}