Интегрирован 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
+202
View File
@@ -0,0 +1,202 @@
"""Подготовка параметров NORM_1_2_PREP (интервалы массы и концентрации)."""
from __future__ import annotations
from dataclasses import dataclass
from app.lab.calc.racion.interp import lerp
from app.lab.calc.racion.tables import load_normy_info
@dataclass(frozen=True)
class PiterPrepResult:
mass_ind: int
konc_pred: float
konc_sled: float
m_a: float
m_b: float
udoy_jir: float
wmassa: float
class PiterPrepError(ValueError):
def __init__(self, code: int, message: str, *, info: str | None = None) -> None:
super().__init__(message)
self.code = code
self.info = info
def _info_values(nperem: int) -> list[float]:
data = load_normy_info()
for row in data.get("rows") or []:
if row.get("nperem") == nperem:
return list(row.get("znachenie") or [])
return []
def _fl_from_str(values: list[float], index: int) -> float | None:
"""1-based index как FlFromStr в RACION."""
i = index - 1
if i < 0 or i >= len(values):
return None
return float(values[i])
def _wmassa(mass_kg: float, body_condition: int) -> float:
if body_condition > 1:
return mass_kg * 1.02
return mass_kg
def prepare_piter_calc(
*,
mass_kg: float,
milk_yield_kg: float,
milk_fat_pct: float,
konc_oe_sv: float,
body_condition: int = 1,
) -> PiterPrepResult:
"""Порт NORM_1_2_PREP: интервалы для NORM_1_2_CALC."""
if milk_yield_kg <= 0:
raise PiterPrepError(-11, "Укажите суточный удой, кг")
if milk_fat_pct <= 0:
raise PiterPrepError(-12, "Укажите жирность молока, %")
if mass_kg <= 0:
raise PiterPrepError(-14, "Укажите живую массу, кг")
if konc_oe_sv <= 0:
raise PiterPrepError(-15, "Укажите концентрацию ОЭ/СВ, МДж/кг СВ")
wmassa = _wmassa(mass_kg, body_condition)
udoy_jir = milk_yield_kg * milk_fat_pct * 0.25
kol_konc_vals = _info_values(7)
kol_mass_vals = _info_values(7)
if len(kol_konc_vals) < 2 or len(kol_mass_vals) < 2:
raise PiterPrepError(-1, "Справочник NORMY_INFO (NPerem=7) не задан")
kol_konc = int(kol_konc_vals[0])
kol_mass = int(kol_mass_vals[1])
if kol_konc < 2 or kol_mass < 2:
raise PiterPrepError(-1, "Некорректные размеры таблицы концентраций/масс")
masses = _info_values(6) or _info_values(14)
koncss = _info_values(3)
if not masses or not koncss or len(masses) < 2 or len(koncss) < 2:
raise PiterPrepError(-1, "Справочник NORMY_INFO: массы или концентрации не заданы")
# Интервал концентрации
konc_ind = 1
for i in range(2, kol_konc):
v = _fl_from_str(koncss, i)
if v is not None and konc_oe_sv >= v:
konc_ind = i
konc_pred = _fl_from_str(koncss, konc_ind)
konc_sled = _fl_from_str(koncss, konc_ind + 1)
if konc_pred is None or konc_sled is None or konc_pred < 0 or konc_sled < 0 or konc_pred == konc_sled:
raise PiterPrepError(-1, "Не удалось определить интервал концентрации")
# Интервал массы
mass_ind = 1
for i in range(2, kol_mass):
v = _fl_from_str(masses, i)
if v is not None and wmassa >= v:
mass_ind = i
m_a = _fl_from_str(masses, mass_ind)
m_b = _fl_from_str(masses, mass_ind + 1)
if m_a is None or m_b is None or m_a < 0 or m_b < 0 or m_a == m_b:
raise PiterPrepError(-1, "Не удалось определить интервал массы")
# Проверка удоя (NPerem=4,5)
udoy_str_4 = _info_values(4)
udoy_str_5 = _info_values(5)
udoy_min = _fl_from_str(udoy_str_4, 1) if udoy_str_4 else None
udoy_max = _fl_from_str(udoy_str_5, kol_konc) if udoy_str_5 else None
if udoy_min is not None and udoy_max is not None:
if udoy_jir < udoy_min or udoy_jir > udoy_max:
jir_str = _info_values(2)
gr_udoy1 = max(udoy_min * 4 / milk_fat_pct, udoy_min)
gr_udoy2 = min(udoy_max * 4 / milk_fat_pct, udoy_max)
gr_jir1 = udoy_min * 4 / milk_yield_kg
gr_jir2 = udoy_max * 4 / milk_yield_kg
if jir_str:
if len(jir_str) >= 1:
gr_jir1 = max(gr_jir1, jir_str[0])
if len(jir_str) >= 2:
gr_jir2 = min(gr_jir2, jir_str[1])
code = -4 if udoy_jir < udoy_min else -5
info = f"{gr_udoy1:.4f};{gr_udoy2:.4f};{gr_jir1:.3f};{gr_jir2:.3f};"
raise PiterPrepError(code, "Удой вне допустимого диапазона для жирности", info=info)
# Допустимый диапазон концентрации для udoy_jir
i = 1
if udoy_jir >= (_fl_from_str(udoy_str_4, 1) or 0):
while i < kol_konc - 1:
nxt = _fl_from_str(udoy_str_4, i + 1)
if nxt is None or nxt > udoy_jir:
break
i += 1
else:
while i < kol_konc - 1:
nxt = _fl_from_str(udoy_str_4, i + 1)
cur = _fl_from_str(udoy_str_4, i)
if nxt is None or cur is None or nxt != cur:
break
i += 1
ud_a = _fl_from_str(udoy_str_4, i)
ud_b = _fl_from_str(udoy_str_4, i + 1)
konc_a = _fl_from_str(koncss, i)
konc_b = _fl_from_str(koncss, i + 1)
if ud_a is not None and ud_b is not None and konc_a is not None and konc_b is not None:
if ud_a == ud_b:
konc_max = konc_b
else:
konc_max = lerp(udoy_jir, ud_a, konc_a, ud_b, konc_b)
i = kol_konc
if udoy_jir <= (_fl_from_str(udoy_str_5, kol_konc) or udoy_jir):
while i > 2:
prev = _fl_from_str(udoy_str_5, i - 1)
if prev is None or prev < udoy_jir:
break
i -= 1
else:
while i > 2:
prev = _fl_from_str(udoy_str_5, i - 1)
last = _fl_from_str(udoy_str_5, kol_konc)
if prev is None or last is None or prev != last:
break
i -= 1
ud_a2 = _fl_from_str(udoy_str_5, i - 1)
ud_b2 = _fl_from_str(udoy_str_5, i)
konc_a2 = _fl_from_str(koncss, i - 1)
konc_b2 = _fl_from_str(koncss, i)
if ud_a2 is not None and ud_b2 is not None and konc_a2 is not None and konc_b2 is not None:
if ud_a2 == ud_b2:
konc_min = konc_b2
else:
konc_min = lerp(udoy_jir, ud_a2, konc_a2, ud_b2, konc_b2)
konc_lo = _fl_from_str(koncss, 1) or konc_min
konc_hi = _fl_from_str(koncss, kol_konc) or konc_max
if konc_min < konc_lo:
konc_min = konc_lo
if konc_max > konc_hi:
konc_max = konc_hi
if round(konc_oe_sv, 1) < round(konc_min, 1) or round(konc_oe_sv, 1) > round(konc_max, 1):
code = -2 if round(konc_oe_sv, 1) < round(konc_min, 1) else -3
info = f"{round(konc_min, 1)};{round(konc_max, 1)};"
raise PiterPrepError(
code,
f"Концентрация ОЭ/СВ вне допустимого диапазона ({round(konc_min, 1)}{round(konc_max, 1)})",
info=info,
)
return PiterPrepResult(
mass_ind=mass_ind,
konc_pred=float(konc_pred),
konc_sled=float(konc_sled),
m_a=float(m_a),
m_b=float(m_b),
udoy_jir=udoy_jir,
wmassa=wmassa,
)