Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -708,112 +708,144 @@ def nutri_call():
|
|
708 |
|
709 |
|
710 |
|
711 |
-
|
712 |
|
713 |
|
714 |
from tabulate import tabulate
|
715 |
import numpy as np
|
716 |
-
import numpy as np
|
717 |
|
718 |
-
#
|
719 |
-
TOTAL_NITROGEN = 120.0
|
720 |
-
NO3_RATIO = 8.25
|
721 |
-
NH4_RATIO = 1.0
|
722 |
-
VOLUME_LITERS = 100
|
723 |
|
724 |
-
#
|
725 |
BASE_PROFILE = {
|
726 |
-
'P': 31.
|
727 |
-
'Ca': 84.
|
728 |
-
'N (NO3-)': 0, 'N (NH4+)': 0
|
729 |
}
|
730 |
|
731 |
-
|
|
|
732 |
"Кальциевая селитра": {"N (NO3-)": 0.11863, "Ca": 0.16972},
|
733 |
"Калий азотнокислый": {"N (NO3-)": 0.136, "K": 0.382},
|
734 |
"Калий сернокислый": {"K": 0.44874, "S": 0.18401},
|
735 |
"Аммоний азотнокислый": {"N (NO3-)": 0.17499, "N (NH4+)": 0.17499},
|
736 |
"Сульфат магния": {"Mg": 0.09861, "S": 0.13010},
|
737 |
"Монофосфат калия": {"P": 0.218, "K": 0.275},
|
738 |
-
"Сульфат кальция": {"Ca": 0.23, "S": 0.186}
|
739 |
-
"Кольцевая селитра": {"N (NO3-)": 0.15, "Ca": 0.20} # Новое удобрение
|
740 |
}
|
741 |
|
742 |
-
|
743 |
-
'P': 0.0012, 'K': 0.0018, 'Mg': 0.0015,
|
744 |
-
'Ca': 0.0016, 'S': 0.0014,
|
745 |
-
'N (NO3-)': 0.0017, 'N (NH4+)': 0.0019
|
746 |
-
}
|
747 |
-
|
748 |
-
nutrients_stencil = list(BASE_PROFILE.keys())
|
749 |
-
|
750 |
-
|
751 |
-
class NutrientCalculator:
|
752 |
def __init__(self):
|
753 |
self.volume = VOLUME_LITERS
|
754 |
-
self.
|
755 |
-
self.fertilizers =
|
756 |
-
self.
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
|
|
765 |
|
766 |
def calculate(self):
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
|
790 |
-
|
791 |
-
|
792 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
793 |
|
794 |
def generate_report(self, results):
|
795 |
-
"""Генерация отчета
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
806 |
|
|
|
807 |
if __name__ == "__main__":
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
if results:
|
812 |
-
print(calculator.generate_report(results))
|
813 |
-
else:
|
814 |
-
print("Решение не найдено.")
|
815 |
-
except Exception as e:
|
816 |
-
print(f"Критическая ошибка: {str(e)}")
|
817 |
|
818 |
|
819 |
@app.route('/calculation', methods=['POST'])
|
|
|
708 |
|
709 |
|
710 |
|
|
|
711 |
|
712 |
|
713 |
from tabulate import tabulate
|
714 |
import numpy as np
|
|
|
715 |
|
716 |
+
# Константы
|
717 |
+
TOTAL_NITROGEN = 120.0
|
718 |
+
NO3_RATIO = 8.25
|
719 |
+
NH4_RATIO = 1.0
|
720 |
+
VOLUME_LITERS = 100
|
721 |
|
722 |
+
# Целевой профиль (ppm)
|
723 |
BASE_PROFILE = {
|
724 |
+
'P': 31.0, 'K': 210.0, 'Mg': 24.0,
|
725 |
+
'Ca': 84.0, 'S': 56.439,
|
726 |
+
'N (NO3-)': 0, 'N (NH4+)': 0 # Будет рассчитано
|
727 |
}
|
728 |
|
729 |
+
# Состав удобрений (доли)
|
730 |
+
NUTRIENT_CONTENT = {
|
731 |
"Кальциевая селитра": {"N (NO3-)": 0.11863, "Ca": 0.16972},
|
732 |
"Калий азотнокислый": {"N (NO3-)": 0.136, "K": 0.382},
|
733 |
"Калий сернокислый": {"K": 0.44874, "S": 0.18401},
|
734 |
"Аммоний азотнокислый": {"N (NO3-)": 0.17499, "N (NH4+)": 0.17499},
|
735 |
"Сульфат магния": {"Mg": 0.09861, "S": 0.13010},
|
736 |
"Монофосфат калия": {"P": 0.218, "K": 0.275},
|
737 |
+
"Сульфат кальция": {"Ca": 0.23, "S": 0.186}
|
|
|
738 |
}
|
739 |
|
740 |
+
class PrecisionNutrientCalculator:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
741 |
def __init__(self):
|
742 |
self.volume = VOLUME_LITERS
|
743 |
+
self.target = self._calculate_nitrogen_profile()
|
744 |
+
self.fertilizers = NUTRIENT_CONTENT
|
745 |
+
self.results = {}
|
746 |
+
self.actual = {k: 0.0 for k in self.target}
|
747 |
+
|
748 |
+
def _calculate_nitrogen_profile(self):
|
749 |
+
"""Расчет азотных компонентов"""
|
750 |
+
profile = BASE_PROFILE.copy()
|
751 |
+
total = NO3_RATIO + NH4_RATIO
|
752 |
+
profile['N (NO3-)'] = TOTAL_NITROGEN * (NO3_RATIO / total)
|
753 |
+
profile['N (NH4+)'] = TOTAL_NITROGEN * (NH4_RATIO / total)
|
754 |
+
return profile
|
755 |
|
756 |
def calculate(self):
|
757 |
+
"""Основной метод расчета с проверкой"""
|
758 |
+
# 1. Вносим кальциевую селитру (Ca + NO3)
|
759 |
+
self._apply_fertilizer("Кальциевая селитра", "Ca", self.target['Ca'])
|
760 |
+
|
761 |
+
# 2. Вносим аммонийный азот
|
762 |
+
self._apply_fertilizer("Аммоний азотнокислый", "N (NH4+)", self.target['N (NH4+)'])
|
763 |
+
|
764 |
+
# 3. Компенсируем NO3 калийной селитрой
|
765 |
+
no3_needed = self.target['N (NO3-)'] - self.actual['N (NO3-)']
|
766 |
+
if no3_needed > 0:
|
767 |
+
self._apply_fertilizer("Калий азотнокислый", "N (NO3-)", no3_needed)
|
768 |
+
|
769 |
+
# 4. Вносим фосфор
|
770 |
+
self._apply_fertilizer("Монофосфат калия", "P", self.target['P'])
|
771 |
+
|
772 |
+
# 5. Вносим магний
|
773 |
+
self._apply_fertilizer("Сульфат магния", "Mg", self.target['Mg'])
|
774 |
+
|
775 |
+
# 6. Балансируем калий и серу
|
776 |
+
self._balance_k_s()
|
777 |
+
|
778 |
+
return self._verify_results()
|
779 |
|
780 |
+
def _apply_fertilizer(self, name, main_element, target_ppm):
|
781 |
+
"""Точное внесение удобрения для конкретного элемента"""
|
782 |
+
content = self.fertilizers[name][main_element]
|
783 |
+
grams = (target_ppm * self.volume) / (content * 1000)
|
784 |
+
|
785 |
+
if name not in self.results:
|
786 |
+
self.results[name] = {'граммы': 0.0}
|
787 |
+
|
788 |
+
self.results[name]['граммы'] += grams
|
789 |
+
|
790 |
+
# Учитываем все элементы из удобрения
|
791 |
+
for element, percent in self.fertilizers[name].items():
|
792 |
+
added_ppm = (grams * percent * 1000) / self.volume
|
793 |
+
self.actual[element] += added_ppm
|
794 |
+
|
795 |
+
def _balance_k_s(self):
|
796 |
+
"""Балансировка калия и серы"""
|
797 |
+
k_needed = self.target['K'] - self.actual['K']
|
798 |
+
s_needed = self.target['S'] - self.actual['S']
|
799 |
+
|
800 |
+
# Используем K2SO4 если нужна и сера и калий
|
801 |
+
if k_needed > 0 and s_needed > 0:
|
802 |
+
k_from_k2so4 = min(k_needed, s_needed * 0.44874/0.18401)
|
803 |
+
self._apply_fertilizer("Калий сернокислый", "K", k_from_k2so4)
|
804 |
+
|
805 |
+
# Добираем остаток калия KNO3
|
806 |
+
remaining_k = self.target['K'] - self.actual['K']
|
807 |
+
if remaining_k > 0:
|
808 |
+
self._apply_fertilizer("Калий азотнокислый", "K", remaining_k)
|
809 |
+
|
810 |
+
def _verify_results(self):
|
811 |
+
"""Проверка соответствия целевому профилю"""
|
812 |
+
deficits = {}
|
813 |
+
for element in self.target:
|
814 |
+
diff = self.target[element] - self.actual[element]
|
815 |
+
if abs(diff) > 0.1: # Допустимая погрешность 0.1 ppm
|
816 |
+
deficits[element] = round(diff, 3)
|
817 |
+
|
818 |
+
return {
|
819 |
+
'fertilizers': {k: round(v['граммы'], 3) for k, v in self.results.items()},
|
820 |
+
'actual_profile': {k: round(v, 3) for k, v in self.actual.items()},
|
821 |
+
'deficits': deficits,
|
822 |
+
'success': len(deficits) == 0
|
823 |
+
}
|
824 |
|
825 |
def generate_report(self, results):
|
826 |
+
"""Генерация читаемого отчета"""
|
827 |
+
report = "РЕКОМЕНДУЕМЫЕ УДОБРЕНИЯ:\n"
|
828 |
+
for fert, data in results['fertilizers'].items():
|
829 |
+
report += f"{fert}: {data} г\n"
|
830 |
+
|
831 |
+
report += "\nФАКТИЧЕСКИЙ ПРОФИЛЬ (ppm):\n"
|
832 |
+
for element, value in results['actual_profile'].items():
|
833 |
+
report += f"{element}: {value} (цель: {self.target[element]})\n"
|
834 |
+
|
835 |
+
if results['deficits']:
|
836 |
+
report += "\nДЕФИЦИТЫ:\n"
|
837 |
+
for element, diff in results['deficits'].items():
|
838 |
+
report += f"{element}: не хватает {diff} ppm\n"
|
839 |
+
else:
|
840 |
+
report += "\nВсе элементы сбалансированы идеально!"
|
841 |
+
|
842 |
+
return report
|
843 |
|
844 |
+
# Пример использования
|
845 |
if __name__ == "__main__":
|
846 |
+
calculator = PrecisionNutrientCalculator()
|
847 |
+
results = calculator.calculate()
|
848 |
+
print(calculator.generate_report(results))
|
|
|
|
|
|
|
|
|
|
|
|
|
849 |
|
850 |
|
851 |
@app.route('/calculation', methods=['POST'])
|