Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -691,101 +691,102 @@ class NutrientCalculator:
|
|
691 |
def __init__(self, volume_liters=1.0):
|
692 |
self.volume = volume_liters
|
693 |
self.results = {}
|
694 |
-
self.target_profile = {
|
695 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
696 |
self.fertilizers = {}
|
697 |
self.total_ec = 0.0
|
698 |
|
699 |
-
def set_target_profile(self,
|
700 |
-
"""Устанавливаем
|
701 |
-
|
702 |
-
|
|
|
703 |
|
704 |
-
def set_fertilizers(self,
|
705 |
-
"""
|
706 |
-
self.fertilizers =
|
707 |
|
708 |
def calculate(self):
|
709 |
-
"""
|
710 |
try:
|
711 |
-
#
|
712 |
-
self.
|
713 |
-
self.
|
714 |
-
self.
|
715 |
-
self.
|
716 |
|
717 |
# Довносим NO3 если нужно
|
718 |
no3_needed = self.target_profile['N (NO3-)'] - self.actual_profile['N (NO3-)']
|
719 |
if no3_needed > 0.1:
|
720 |
-
self.
|
721 |
|
722 |
# Довносим калий если нужно
|
723 |
-
|
724 |
-
if
|
725 |
-
self.
|
726 |
-
|
727 |
-
# Довносим серу если нужно
|
728 |
-
s_needed = self.target_profile['S'] - self.actual_profile['S']
|
729 |
-
if s_needed > 0.1:
|
730 |
-
self._apply_fertilizer("Калий сернокислый", "S", s_needed)
|
731 |
|
732 |
return True
|
733 |
except Exception as e:
|
734 |
-
print(f"
|
735 |
return False
|
736 |
|
737 |
-
def
|
738 |
"""Универсальный метод внесения удобрений"""
|
739 |
-
if
|
740 |
return
|
741 |
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
if required_ppm <= 0:
|
746 |
-
return
|
747 |
-
|
748 |
-
content = self.fertilizers[name].get(element, 0)
|
749 |
-
if content == 0:
|
750 |
return
|
751 |
|
752 |
grams = (required_ppm * self.volume) / (content * 1000)
|
753 |
|
754 |
-
#
|
755 |
-
if
|
756 |
-
self.results[
|
|
|
|
|
|
|
757 |
|
758 |
-
self.results[
|
759 |
|
760 |
-
# Обновляем
|
761 |
-
for nutrient, percent in self.fertilizers[
|
762 |
added_ppm = (grams * percent * 1000) / self.volume
|
763 |
self.actual_profile[nutrient] = self.actual_profile.get(nutrient, 0) + added_ppm
|
764 |
-
self.results[
|
765 |
|
766 |
# Расчёт EC
|
767 |
self.total_ec += sum(
|
768 |
-
added_ppm *
|
769 |
-
|
|
|
|
|
|
|
|
|
770 |
)
|
771 |
|
772 |
def get_results(self):
|
773 |
-
"""
|
774 |
return {
|
775 |
'fertilizers': [
|
776 |
{
|
777 |
'name': name,
|
778 |
'grams': round(data['grams'], 3),
|
779 |
'adds': {k: round(v, 3) for k, v in data['adds'].items()}
|
780 |
-
}
|
781 |
-
for name, data in self.results.items()
|
782 |
],
|
783 |
'profile': [
|
784 |
{
|
785 |
'element': k.replace(' (NO3-)', '-NO3').replace(' (NH4+)', '-NH4'),
|
786 |
'ppm': round(v, 3)
|
787 |
-
}
|
788 |
-
for k, v in self.actual_profile.items()
|
789 |
],
|
790 |
'ec': round(self.total_ec, 2),
|
791 |
'deficits': {
|
@@ -799,30 +800,20 @@ def handle_calculation():
|
|
799 |
try:
|
800 |
data = request.json
|
801 |
|
|
|
|
|
|
|
|
|
802 |
# Создаём калькулятор
|
803 |
calculator = NutrientCalculator(volume_liters=data['profileSettings']['liters'])
|
804 |
|
805 |
-
# Настраиваем профиль
|
806 |
-
calculator.set_target_profile(
|
807 |
-
'P': float(data['profileSettings']['P']),
|
808 |
-
'K': float(data['profileSettings']['K']),
|
809 |
-
'Mg': float(data['profileSettings']['Mg']),
|
810 |
-
'Ca': float(data['profileSettings']['Ca']),
|
811 |
-
'S': float(data['profileSettings']['S']),
|
812 |
-
'N (NO3-)': float(data['profileSettings']['N (NO3-)']),
|
813 |
-
'N (NH4+)': float(data['profileSettings']['N (NH4+)'])
|
814 |
-
})
|
815 |
|
816 |
-
# Настраиваем удобрения
|
817 |
-
calculator.set_fertilizers(
|
818 |
-
"Кальциевая селитра": {
|
819 |
-
"N (NO3-)": float(data['fertilizerConstants']['CaN2O6']['NO3']) / 100,
|
820 |
-
"Ca": float(data['fertilizerConstants']['CaN2O6']['Ca']) / 100
|
821 |
-
},
|
822 |
-
# ... остальные удобрения аналогично
|
823 |
-
})
|
824 |
|
825 |
-
#
|
826 |
if calculator.calculate():
|
827 |
return jsonify({
|
828 |
'status': 'success',
|
@@ -858,7 +849,6 @@ def handle_calculation():
|
|
858 |
|
859 |
|
860 |
|
861 |
-
|
862 |
|
863 |
if __name__ == '__main__':
|
864 |
app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 7860)))
|
|
|
691 |
def __init__(self, volume_liters=1.0):
|
692 |
self.volume = volume_liters
|
693 |
self.results = {}
|
694 |
+
self.target_profile = {
|
695 |
+
'P': 0, 'K': 0, 'Mg': 0, 'Ca': 0, 'S': 0,
|
696 |
+
'N (NO3-)': 0, 'N (NH4+)': 0
|
697 |
+
}
|
698 |
+
self.actual_profile = {
|
699 |
+
'P': 0.0, 'K': 0.0, 'Mg': 0.0, 'Ca': 0.0, 'S': 0.0,
|
700 |
+
'N (NO3-)': 0.0, 'N (NH4+)': 0.0
|
701 |
+
}
|
702 |
self.fertilizers = {}
|
703 |
self.total_ec = 0.0
|
704 |
|
705 |
+
def set_target_profile(self, profile_data):
|
706 |
+
"""Устанавливаем целевые значения"""
|
707 |
+
for key in profile_data:
|
708 |
+
if key in self.target_profile:
|
709 |
+
self.target_profile[key] = float(profile_data[key])
|
710 |
|
711 |
+
def set_fertilizers(self, fertilizers_data):
|
712 |
+
"""Принимаем удобрения в любом формате (рус/англ)"""
|
713 |
+
self.fertilizers = fertilizers_data
|
714 |
|
715 |
def calculate(self):
|
716 |
+
"""Основная логика расчёта без изменений"""
|
717 |
try:
|
718 |
+
# Порядок внесения удобрений
|
719 |
+
self._apply("Сульфат магния", "Mg", self.target_profile['Mg'])
|
720 |
+
self._apply("Кальциевая селитра", "Ca", self.target_profile['Ca'])
|
721 |
+
self._apply("Монофосфат калия", "P", self.target_profile['P'])
|
722 |
+
self._apply("Аммоний азотнокислый", "N (NH4+)", self.target_profile['N (NH4+)'])
|
723 |
|
724 |
# Довносим NO3 если нужно
|
725 |
no3_needed = self.target_profile['N (NO3-)'] - self.actual_profile['N (NO3-)']
|
726 |
if no3_needed > 0.1:
|
727 |
+
self._apply("Калий азотнокислый", "N (NO3-)", no3_needed)
|
728 |
|
729 |
# Довносим калий если нужно
|
730 |
+
k_deficit = self.target_profile['K'] - self.actual_profile['K']
|
731 |
+
if k_deficit > 0.1:
|
732 |
+
self._apply("Калий азотнокислый", "K", k_deficit)
|
|
|
|
|
|
|
|
|
|
|
733 |
|
734 |
return True
|
735 |
except Exception as e:
|
736 |
+
print(f"Ошибка расчёта: {str(e)}")
|
737 |
return False
|
738 |
|
739 |
+
def _apply(self, fert_name, element, required_ppm):
|
740 |
"""Универсальный метод внесения удобрений"""
|
741 |
+
if fert_name not in self.fertilizers or required_ppm <= 0:
|
742 |
return
|
743 |
|
744 |
+
content = self.fertilizers[fert_name].get(element, 0)
|
745 |
+
if content <= 0:
|
|
|
|
|
|
|
|
|
|
|
|
|
746 |
return
|
747 |
|
748 |
grams = (required_ppm * self.volume) / (content * 1000)
|
749 |
|
750 |
+
# Сохраняем результаты
|
751 |
+
if fert_name not in self.results:
|
752 |
+
self.results[fert_name] = {
|
753 |
+
'grams': 0.0,
|
754 |
+
'adds': {}
|
755 |
+
}
|
756 |
|
757 |
+
self.results[fert_name]['grams'] += grams
|
758 |
|
759 |
+
# Обновляем профиль
|
760 |
+
for nutrient, percent in self.fertilizers[fert_name].items():
|
761 |
added_ppm = (grams * percent * 1000) / self.volume
|
762 |
self.actual_profile[nutrient] = self.actual_profile.get(nutrient, 0) + added_ppm
|
763 |
+
self.results[fert_name]['adds'][nutrient] = self.results[fert_name]['adds'].get(nutrient, 0) + added_ppm
|
764 |
|
765 |
# Расчёт EC
|
766 |
self.total_ec += sum(
|
767 |
+
added_ppm * {
|
768 |
+
'P': 0.0012, 'K': 0.0018, 'Mg': 0.0015,
|
769 |
+
'Ca': 0.0016, 'S': 0.0014,
|
770 |
+
'N (NO3-)': 0.0017, 'N (NH4+)': 0.0019
|
771 |
+
}.get(nutrient, 0.0015)
|
772 |
+
for nutrient, added_ppm in self.results[fert_name]['adds'].items()
|
773 |
)
|
774 |
|
775 |
def get_results(self):
|
776 |
+
"""Форматируем результаты"""
|
777 |
return {
|
778 |
'fertilizers': [
|
779 |
{
|
780 |
'name': name,
|
781 |
'grams': round(data['grams'], 3),
|
782 |
'adds': {k: round(v, 3) for k, v in data['adds'].items()}
|
783 |
+
} for name, data in self.results.items()
|
|
|
784 |
],
|
785 |
'profile': [
|
786 |
{
|
787 |
'element': k.replace(' (NO3-)', '-NO3').replace(' (NH4+)', '-NH4'),
|
788 |
'ppm': round(v, 3)
|
789 |
+
} for k, v in self.actual_profile.items()
|
|
|
790 |
],
|
791 |
'ec': round(self.total_ec, 2),
|
792 |
'deficits': {
|
|
|
800 |
try:
|
801 |
data = request.json
|
802 |
|
803 |
+
# Проверяем обязательные поля
|
804 |
+
if 'fertilizerConstants' not in data or 'profileSettings' not in data:
|
805 |
+
return jsonify({'status': 'error', 'message': 'Missing required fields'}), 400
|
806 |
+
|
807 |
# Создаём калькулятор
|
808 |
calculator = NutrientCalculator(volume_liters=data['profileSettings']['liters'])
|
809 |
|
810 |
+
# Настраиваем профиль (принимаем как есть)
|
811 |
+
calculator.set_target_profile(data['profileSettings'])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
812 |
|
813 |
+
# Настраиваем удобрения (принимаем как есть, без преобразований)
|
814 |
+
calculator.set_fertilizers(data['fertilizerConstants'])
|
|
|
|
|
|
|
|
|
|
|
|
|
815 |
|
816 |
+
# Расчёт
|
817 |
if calculator.calculate():
|
818 |
return jsonify({
|
819 |
'status': 'success',
|
|
|
849 |
|
850 |
|
851 |
|
|
|
852 |
|
853 |
if __name__ == '__main__':
|
854 |
app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 7860)))
|