Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -833,51 +833,39 @@ class NutrientCalculator:
|
|
833 |
self.fertilizers = NUTRIENT_CONTENT_IN_FERTILIZERS
|
834 |
self.total_ec = 0.0
|
835 |
|
836 |
-
# Веса компенсации
|
837 |
self.element_compensation_weights = {
|
838 |
"POTASSIUM_SULFATE": {"weight": 0.18, "fert": "Калий сернокислый", "main_element": "K"},
|
839 |
"MAGNESIUM_SULFATE": {"weight": 0.1, "fert": "Сульфат магния", "main_element": "Mg"},
|
840 |
-
"MONOPOTASSIUM_PHOSPHATE": {"weight": 0.14, "fert": "Монофосфат калия", "main_element": "P"}
|
841 |
-
"CALCIUM_NITRATE": {"weight": 0.1, "fert": "Кальциевая селитра", "main_element": "Ca"},
|
842 |
-
"CALCIUM_NITRATE_NO3": {"weight": 0.1, "fert": "Кальциевая селитра", "main_element": "N (NO3-)"}
|
843 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
844 |
# Расчёт азота
|
845 |
total_parts = NO3_RATIO + NH4_RATIO
|
846 |
self.target_profile['N (NO3-)'] = TOTAL_NITROGEN * (NO3_RATIO / total_parts)
|
847 |
self.target_profile['N (NH4+)'] = TOTAL_NITROGEN * (NH4_RATIO / total_parts)
|
848 |
|
849 |
-
def _label(self, element):
|
850 |
-
"""Форматирование названий элементов для вывода"""
|
851 |
-
labels = {
|
852 |
-
'N (NO3-)': 'NO3',
|
853 |
-
'N (NH4+)': 'NH4'
|
854 |
-
}
|
855 |
-
return labels.get(element, element)
|
856 |
-
|
857 |
def calculate(self):
|
858 |
try:
|
859 |
-
# Вносим
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
860 |
self._compensate_element("Mg")
|
861 |
-
|
862 |
-
# Вносим кальций напрямую
|
863 |
-
self._apply("Кальциевая селитра", "Ca", self.target_profile['Ca'])
|
864 |
-
|
865 |
-
# Вносим фосфор через компенсацию
|
866 |
self._compensate_element("P")
|
867 |
-
|
868 |
-
# Вносим аммонийный азот напрямую
|
869 |
-
self._apply("Аммоний азотнокислый", "N (NH4+)", self.target_profile['N (NH4+)'])
|
870 |
-
|
871 |
-
# Компенсируем нитратный азот напрямую
|
872 |
-
current_no3 = self.actual_profile['N (NO3-)']
|
873 |
-
no3_needed = self.target_profile['N (NO3-)'] - current_no3
|
874 |
-
if no3_needed > 0.1:
|
875 |
-
self._apply("Калий азотнокислый", "N (NO3-)", no3_needed)
|
876 |
-
|
877 |
-
# Компенсируем серу через компенсацию
|
878 |
self._compensate_element("S")
|
879 |
-
|
880 |
-
# Компенсируем калий через компенсацию
|
881 |
self._compensate_element("K")
|
882 |
|
883 |
return self.results
|
@@ -885,6 +873,53 @@ class NutrientCalculator:
|
|
885 |
print(f"Ошибка при расчёте: {str(e)}")
|
886 |
raise
|
887 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
888 |
def _apply(self, fert_name, main_element, required_ppm):
|
889 |
if required_ppm <= 0:
|
890 |
return
|
|
|
833 |
self.fertilizers = NUTRIENT_CONTENT_IN_FERTILIZERS
|
834 |
self.total_ec = 0.0
|
835 |
|
836 |
+
# Веса компенсации (только для элементов, которые компенсируются)
|
837 |
self.element_compensation_weights = {
|
838 |
"POTASSIUM_SULFATE": {"weight": 0.18, "fert": "Калий сернокислый", "main_element": "K"},
|
839 |
"MAGNESIUM_SULFATE": {"weight": 0.1, "fert": "Сульфат магния", "main_element": "Mg"},
|
840 |
+
"MONOPOTASSIUM_PHOSPHATE": {"weight": 0.14, "fert": "Монофосфат калия", "main_element": "P"}
|
|
|
|
|
841 |
}
|
842 |
+
|
843 |
+
# Коэффициенты распределения для кальциевой селитры
|
844 |
+
self.calcium_nitrate_ratios = {
|
845 |
+
"Ca": 0.7, # 70% дефицита кальция покрываем кальциевой селитрой
|
846 |
+
"NO3": 0.3 # 30% дефицита NO3 покрываем кальциевой селитрой
|
847 |
+
}
|
848 |
+
|
849 |
# Расчёт азота
|
850 |
total_parts = NO3_RATIO + NH4_RATIO
|
851 |
self.target_profile['N (NO3-)'] = TOTAL_NITROGEN * (NO3_RATIO / total_parts)
|
852 |
self.target_profile['N (NH4+)'] = TOTAL_NITROGEN * (NH4_RATIO / total_parts)
|
853 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
854 |
def calculate(self):
|
855 |
try:
|
856 |
+
# 1. Вносим кальциевую селитру для Ca и частично для NO3
|
857 |
+
self._apply_calcium_nitrate()
|
858 |
+
|
859 |
+
# 2. Вносим аммонийный азот
|
860 |
+
self._apply("Аммоний азотнокислый", "N (NH4+)", self.target_profile['N (NH4+)'])
|
861 |
+
|
862 |
+
# 3. Компенсируем остаток NO3 калийной селитрой
|
863 |
+
self._compensate_no3()
|
864 |
+
|
865 |
+
# 4. Вносим остальные элементы через компенсацию
|
866 |
self._compensate_element("Mg")
|
|
|
|
|
|
|
|
|
|
|
867 |
self._compensate_element("P")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
868 |
self._compensate_element("S")
|
|
|
|
|
869 |
self._compensate_element("K")
|
870 |
|
871 |
return self.results
|
|
|
873 |
print(f"Ошибка при расчёте: {str(e)}")
|
874 |
raise
|
875 |
|
876 |
+
def _apply_calcium_nitrate(self):
|
877 |
+
"""Специальный метод для внесения кальциевой селитры"""
|
878 |
+
# Вносим кальций
|
879 |
+
ca_needed = self.target_profile['Ca'] - self.actual_profile.get('Ca', 0)
|
880 |
+
if ca_needed > 0.1:
|
881 |
+
ca_share = self.calcium_nitrate_ratios['Ca']
|
882 |
+
ca_to_apply = ca_needed * ca_share
|
883 |
+
self._apply("Кальциевая селитра", "Ca", ca_to_apply)
|
884 |
+
|
885 |
+
# Вносим часть NO3 из кальциевой селитры
|
886 |
+
no3_needed = self.target_profile['N (NO3-)'] - self.actual_profile.get('N (NO3-)', 0)
|
887 |
+
if no3_needed > 0.1:
|
888 |
+
no3_share = self.calcium_nitrate_ratios['NO3']
|
889 |
+
no3_to_apply = no3_needed * no3_share
|
890 |
+
self._apply("Кальциевая селитра", "N (NO3-)", no3_to_apply)
|
891 |
+
|
892 |
+
def _compensate_no3(self):
|
893 |
+
"""Компенсация остатка NO3 после внесения ка��ьциевой селитры"""
|
894 |
+
no3_needed = self.target_profile['N (NO3-)'] - self.actual_profile.get('N (NO3-)', 0)
|
895 |
+
if no3_needed > 0.1:
|
896 |
+
self._apply("Калий азотнокислый", "N (NO3-)", no3_needed)
|
897 |
+
|
898 |
+
def _compensate_element(self, element):
|
899 |
+
"""Общий метод компенсации для других элементов"""
|
900 |
+
needed = self.target_profile[element] - self.actual_profile.get(element, 0)
|
901 |
+
if abs(needed) < 0.1:
|
902 |
+
return
|
903 |
+
|
904 |
+
candidates = []
|
905 |
+
for weight_key, weight_data in self.element_compensation_weights.items():
|
906 |
+
fert_name = weight_data["fert"]
|
907 |
+
if element in self.fertilizers.get(fert_name, {}):
|
908 |
+
candidates.append({
|
909 |
+
'name': fert_name,
|
910 |
+
'weight': weight_data["weight"],
|
911 |
+
'content': self.fertilizers[fert_name][element]
|
912 |
+
})
|
913 |
+
|
914 |
+
if not candidates:
|
915 |
+
raise ValueError(f"Нет удобрений для элемента {element}")
|
916 |
+
|
917 |
+
total_weight = sum(c['weight'] for c in candidates)
|
918 |
+
for candidate in candidates:
|
919 |
+
share = candidate['weight'] / total_weight
|
920 |
+
ppm_to_apply = needed * share
|
921 |
+
self._apply(candidate['name'], element, ppm_to_apply)
|
922 |
+
|
923 |
def _apply(self, fert_name, main_element, required_ppm):
|
924 |
if required_ppm <= 0:
|
925 |
return
|