Spaces:
Sleeping
Sleeping
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'])
|