DmitrMakeev commited on
Commit
b99af28
·
verified ·
1 Parent(s): b4271ed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +103 -49
app.py CHANGED
@@ -858,24 +858,62 @@ NUTRIENT_CONTENT_IN_FERTILIZERS = {
858
  }
859
 
860
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
861
 
862
  class NutrientCalculator:
863
  def __init__(self, volume_liters=1.0):
 
864
  self.volume = volume_liters
865
  self.results = {}
866
  self.target_profile = BASE_PROFILE.copy()
867
  self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
868
- self.fertilizers = NUTRIENT_CONTENT_IN_FERTILIZERS
869
  self.total_ec = 0.0
870
 
871
- # Веса компенсации для элементов (кроме азотов)
872
  self.element_compensation_weights = {
873
- "POTASSIUM_SULFATE": {"weight": -0.18, "fert": "Калий сернокислый", "main_element": "K"},
874
- "MAGNESIUM_SULFATE": {"weight": -0.1, "fert": "Сульфат магния", "main_element": "Mg"},
875
- "MONOPOTASSIUM_PHOSPHATE": {"weight": -0.14, "fert": "Монофосфат калия", "main_element": "P"}
876
  }
877
 
878
- # Расчёт азота
 
 
 
 
 
 
879
  total_parts = NO3_RATIO + NH4_RATIO
880
  self.target_profile['N (NO3-)'] = TOTAL_NITROGEN * (NO3_RATIO / total_parts)
881
  self.target_profile['N (NH4+)'] = TOTAL_NITROGEN * (NH4_RATIO / total_parts)
@@ -889,29 +927,21 @@ class NutrientCalculator:
889
  return labels.get(element, element)
890
 
891
  def calculate(self):
 
892
  try:
893
- # Вносим магний через компенсацию
894
- self._compensate_element("Mg")
895
-
896
- # Вносим кальций напрямую
897
- self._apply("Кальциевая селитра", "Ca", self.target_profile['Ca'])
898
-
899
- # Вносим фосфор через компенсацию
900
- self._compensate_element("P")
901
 
902
- # Вносим аммонийный азот напрямую
903
  self._apply("Аммоний азотнокислый", "N (NH4+)", self.target_profile['N (NH4+)'])
904
 
905
- # Компенсируем нитратный азот напрямую
906
- current_no3 = self.actual_profile['N (NO3-)']
907
- no3_needed = self.target_profile['N (NO3-)'] - current_no3
908
- if no3_needed > 0.1:
909
- self._apply("Калий азотнокислый", "N (NO3-)", no3_needed)
910
 
911
- # Компенсируем серу через компенсацию
 
 
912
  self._compensate_element("S")
913
-
914
- # Ком��енсируем калий через компенсацию
915
  self._compensate_element("K")
916
 
917
  return self.results
@@ -919,7 +949,55 @@ class NutrientCalculator:
919
  print(f"Ошибка при расчёте: {str(e)}")
920
  raise
921
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
922
  def _apply(self, fert_name, main_element, required_ppm):
 
923
  if required_ppm <= 0:
924
  return
925
 
@@ -953,34 +1031,12 @@ class NutrientCalculator:
953
  print(f"Ошибка: отсутствует элемент {str(e)} в удобрении {fert_name}")
954
  raise
955
 
956
- def _compensate_element(self, element):
957
- needed = self.target_profile[element] - self.actual_profile.get(element, 0)
958
- if needed <= 0:
959
- return
960
-
961
- candidates = []
962
- for weight_key, weight_data in self.element_compensation_weights.items():
963
- fert_name = weight_data["fert"]
964
- if element in self.fertilizers.get(fert_name, {}):
965
- candidates.append({
966
- 'name': fert_name,
967
- 'weight': weight_data["weight"],
968
- 'content': self.fertilizers[fert_name][element]
969
- })
970
-
971
- if not candidates:
972
- raise ValueError(f"Нет удобрений для элемента {element}")
973
-
974
- total_weight = sum(c['weight'] for c in candidates)
975
- for candidate in candidates:
976
- share = candidate['weight'] / total_weight
977
- ppm_to_apply = needed * share
978
- self._apply(candidate['name'], element, ppm_to_apply)
979
-
980
  def calculate_ec(self):
 
981
  return round(self.total_ec, 2)
982
 
983
  def print_report(self):
 
984
  try:
985
  print("\n" + "="*60)
986
  print("ПРОФИЛЬ ПИТАТЕЛЬНОГО РАСТВОРА (ИТОГО):")
@@ -1023,8 +1079,6 @@ class NutrientCalculator:
1023
  print(f"Ошибка при выводе отчёта: {str(e)}")
1024
  raise
1025
 
1026
-
1027
-
1028
  @app.route('/calculation', methods=['POST'])
1029
  def handle_calculation():
1030
  try:
 
858
  }
859
 
860
 
861
+ from tabulate import tabulate
862
+
863
+ # Константы
864
+ TOTAL_NITROGEN = 125.000
865
+ NO3_RATIO = 8.25
866
+ NH4_RATIO = 1.00
867
+ VOLUME_LITERS = 100
868
+
869
+ # Коэффициенты электропроводности
870
+ EC_COEFFICIENTS = {
871
+ 'P': 0.0012, 'K': 0.0018, 'Mg': 0.0015,
872
+ 'Ca': 0.0016, 'S': 0.0014,
873
+ 'N (NO3-)': 0.0017, 'N (NH4+)': 0.0019
874
+ }
875
+
876
+ # Базовый профиль питательного раствора
877
+ BASE_PROFILE = {
878
+ 'P': 31.000, 'K': 210.000, 'Mg': 24.000,
879
+ 'Ca': 84.000, 'S': 56.439,
880
+ 'N (NO3-)': 0, 'N (NH4+)': 0
881
+ }
882
+
883
+ # Содержание элементов в удобрениях
884
+ NUTRIENT_CONTENT_IN_FERTILIZERS = {
885
+ "Кальциевая селитра": {"N (NO3-)": 0.11863, "Ca": 0.16972},
886
+ "Калий азотнокислый": {"N (NO3-)": 0.136, "K": 0.382},
887
+ "Аммоний азотнокислый": {"N (NO3-)": 0.17499, "N (NH4+)": 0.17499},
888
+ "Сульфат магния": {"Mg": 0.09861, "S": 0.13010},
889
+ "Монофосфат калия": {"P": 0.218, "K": 0.275},
890
+ "Калий сернокислый": {"K": 0.44874, "S": 0.18401}
891
+ }
892
 
893
  class NutrientCalculator:
894
  def __init__(self, volume_liters=1.0):
895
+ # Общие параметры
896
  self.volume = volume_liters
897
  self.results = {}
898
  self.target_profile = BASE_PROFILE.copy()
899
  self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
900
+ self.fertilizers = NUTRIENT_CONTENT_IN_FERTILIZERS
901
  self.total_ec = 0.0
902
 
903
+ # Веса компенсации для элементов
904
  self.element_compensation_weights = {
905
+ "POTASSIUM_SULFATE": {"weight": 0.18, "fert": "Калий сернокислый", "main_element": "K"},
906
+ "MAGNESIUM_SULFATE": {"weight": 0.1, "fert": "Сульфат магния", "main_element": "Mg"},
907
+ "MONOPOTASSIUM_PHOSPHATE": {"weight": 0.14, "fert": "Монофосфат калия", "main_element": "P"}
908
  }
909
 
910
+ # Коэффициенты распределения для кальциевой селитры
911
+ self.calcium_nitrate_ratios = {
912
+ "Ca": 0.7, # 70% дефицита кальция покрываем кальциевой селитрой
913
+ "NO3": 0.3 # 30% дефицита NO3 покрываем кальциевой селитрой
914
+ }
915
+
916
+ # Расчёт соотношений азотов
917
  total_parts = NO3_RATIO + NH4_RATIO
918
  self.target_profile['N (NO3-)'] = TOTAL_NITROGEN * (NO3_RATIO / total_parts)
919
  self.target_profile['N (NH4+)'] = TOTAL_NITROGEN * (NH4_RATIO / total_parts)
 
927
  return labels.get(element, element)
928
 
929
  def calculate(self):
930
+ """Основной метод расчета"""
931
  try:
932
+ # 1. Вносим кальциевую селитру для Ca и частично для NO3
933
+ self._apply_calcium_nitrate()
 
 
 
 
 
 
934
 
935
+ # 2. Вносим аммонийный азот напрямую
936
  self._apply("Аммоний азотнокислый", "N (NH4+)", self.target_profile['N (NH4+)'])
937
 
938
+ # 3. Компенсируем остаток NO3 через калийную селитру
939
+ self._compensate_no3()
 
 
 
940
 
941
+ # 4. Компенсируем остальные элементы через веса компенсации
942
+ self._compensate_element("Mg")
943
+ self._compensate_element("P")
944
  self._compensate_element("S")
 
 
945
  self._compensate_element("K")
946
 
947
  return self.results
 
949
  print(f"Ошибка при расчёте: {str(e)}")
950
  raise
951
 
952
+ def _apply_calcium_nitrate(self):
953
+ """Специальный метод для внесения кальциевой селитры"""
954
+ # Вносим кальций
955
+ ca_needed = self.target_profile['Ca'] - self.actual_profile.get('Ca', 0)
956
+ if ca_needed > 0.1:
957
+ ca_share = self.calcium_nitrate_ratios['Ca']
958
+ ca_to_apply = ca_needed * ca_share
959
+ self._apply("Кальциевая селитра", "Ca", ca_to_apply)
960
+
961
+ # Вносим часть NO3 из кальциевой селитры
962
+ no3_needed = self.target_profile['N (NO3-)'] - self.actual_profile.get('N (NO3-)', 0)
963
+ if no3_needed > 0.1:
964
+ no3_share = self.calcium_nitrate_ratios['NO3']
965
+ no3_to_apply = no3_needed * no3_share
966
+ self._apply("Кальциевая селитра", "N (NO3-)", no3_to_apply)
967
+
968
+ def _compensate_no3(self):
969
+ """Компенсация остатка NO3 после внесения кальциевой селитры"""
970
+ no3_needed = self.target_profile['N (NO3-)'] - self.actual_profile.get('N (NO3-)', 0)
971
+ if no3_needed > 0.1:
972
+ self._apply("Калий азотнокислый", "N (NO3-)", no3_needed)
973
+
974
+ def _compensate_element(self, element):
975
+ """Общий метод компенсации для других элементов"""
976
+ needed = self.target_profile[element] - self.actual_profile.get(element, 0)
977
+ if abs(needed) < 0.1:
978
+ return
979
+
980
+ candidates = []
981
+ for weight_key, weight_data in self.element_compensation_weights.items():
982
+ fert_name = weight_data["fert"]
983
+ if element in self.fertilizers.get(fert_name, {}):
984
+ candidates.append({
985
+ 'name': fert_name,
986
+ 'weight': weight_data["weight"],
987
+ 'content': self.fertilizers[fert_name][element]
988
+ })
989
+
990
+ if not candidates:
991
+ raise ValueError(f"Нет удобрений для элемента {element}")
992
+
993
+ total_weight = sum(c['weight'] for c in candidates)
994
+ for candidate in candidates:
995
+ share = candidate['weight'] / total_weight
996
+ ppm_to_apply = needed * share
997
+ self._apply(candidate['name'], element, ppm_to_apply)
998
+
999
  def _apply(self, fert_name, main_element, required_ppm):
1000
+ """Применение удобрения для конкретного элемента"""
1001
  if required_ppm <= 0:
1002
  return
1003
 
 
1031
  print(f"Ошибка: отсутствует элемент {str(e)} в удобрении {fert_name}")
1032
  raise
1033
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1034
  def calculate_ec(self):
1035
+ """Расчет общей электропроводности (EC)"""
1036
  return round(self.total_ec, 2)
1037
 
1038
  def print_report(self):
1039
+ """Вывод отчета о расчетах"""
1040
  try:
1041
  print("\n" + "="*60)
1042
  print("ПРОФИЛЬ ПИТАТЕЛЬНОГО РАСТВОРА (ИТОГО):")
 
1079
  print(f"Ошибка при выводе отчёта: {str(e)}")
1080
  raise
1081
 
 
 
1082
  @app.route('/calculation', methods=['POST'])
1083
  def handle_calculation():
1084
  try: