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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -107
app.py CHANGED
@@ -758,6 +758,41 @@ NUTRIENT_CONTENT_IN_FERTILIZERS = {
758
 
759
 
760
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
761
  from tabulate import tabulate
762
 
763
  # Константы
@@ -832,18 +867,12 @@ class NutrientCalculator:
832
  self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
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
  # Расчёт азота
@@ -851,21 +880,38 @@ class NutrientCalculator:
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,53 +919,6 @@ class NutrientCalculator:
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
@@ -956,56 +955,28 @@ class NutrientCalculator:
956
 
957
  def _compensate_element(self, element):
958
  needed = self.target_profile[element] - self.actual_profile.get(element, 0)
959
- if abs(needed) < 0.1: # Игнорируем незначительные отклонения
960
  return
961
 
962
  candidates = []
 
 
 
 
 
 
 
 
963
 
964
- # Для кальциевой селитры особый случай
965
- if element == "Ca":
966
- candidates.append({
967
- 'name': "Кальциевая селитра",
968
- 'weight': 0.7, # Основной вес для кальция
969
- 'content': self.fertilizers["Кальциевая селитра"]["Ca"]
970
- })
971
- elif element == "N (NO3-)":
972
- candidates.append({
973
- 'name': "Кальциевая селитра",
974
- 'weight': 0.3, # Дополнительный вес для NO3 из кальциевой селитры
975
- 'content': self.fertilizers["Кальциевая селитра"]["N (NO3-)"]
976
- })
977
- candidates.append({
978
- 'name': "Калий азотнокислый",
979
- 'weight': 0.7, # Основной вес для NO3
980
- 'content': self.fertilizers["Калий азотнокислый"]["N (NO3-)"]
981
- })
982
- else:
983
- # Стандартная компенсация для других элементов
984
- for weight_key, weight_data in self.element_compensation_weights.items():
985
- fert_name = weight_data["fert"]
986
- if element in self.fertilizers.get(fert_name, {}):
987
- candidates.append({
988
- 'name': fert_name,
989
- 'weight': weight_data["weight"],
990
- 'content': self.fertilizers[fert_name][element]
991
- })
992
-
993
- # Проверяем, есть ли кандидаты
994
  if not candidates:
995
  raise ValueError(f"Нет удобрений для элемента {element}")
996
 
997
- # Суммируем только положительные веса
998
- total_weight = sum(max(c['weight'], 0) for c in candidates)
999
- if total_weight == 0:
1000
- raise ValueError(f"Общий вес для элемента {element} равен нулю")
1001
-
1002
- # Распределяем доли
1003
  for candidate in candidates:
1004
- share = max(candidate['weight'], 0) / total_weight
1005
  ppm_to_apply = needed * share
1006
  self._apply(candidate['name'], element, ppm_to_apply)
1007
 
1008
-
1009
  def calculate_ec(self):
1010
  return round(self.total_ec, 2)
1011
 
 
758
 
759
 
760
 
761
+ from tabulate import tabulate
762
+
763
+ # Константы
764
+ TOTAL_NITROGEN = 125.000
765
+ NO3_RATIO = 8.25
766
+ NH4_RATIO = 1.00
767
+ VOLUME_LITERS = 100
768
+
769
+ # Коэффициенты электропроводности
770
+ EC_COEFFICIENTS = {
771
+ 'P': 0.0012, 'K': 0.0018, 'Mg': 0.0015,
772
+ 'Ca': 0.0016, 'S': 0.0014,
773
+ 'N (NO3-)': 0.0017, 'N (NH4+)': 0.0019
774
+ }
775
+
776
+ # Целевые значения
777
+ BASE_PROFILE = {
778
+ 'P': 31.000, 'K': 210.000, 'Mg': 24.000,
779
+ 'Ca': 84.000, 'S': 56.439,
780
+ 'N (NO3-)': 0, 'N (NH4+)': 0
781
+ }
782
+
783
+ NUTRIENT_CONTENT_IN_FERTILIZERS = {
784
+ "Кальциевая селитра": {"N (NO3-)": 0.11863, "Ca": 0.16972},
785
+ "Калий азотнокислый": {"N (NO3-)": 0.136, "K": 0.382},
786
+ "Калий сернокислый": {"K": 0.44874, "S": 0.18401},
787
+ "Аммоний азотнокислый": {"N (NO3-)": 0.17499, "N (NH4+)": 0.17499},
788
+ "Сульфат магния": {"Mg": 0.09861, "S": 0.13010},
789
+ "Монофосфат калия": {"P": 0.218, "K": 0.275}
790
+ }
791
+
792
+
793
+
794
+
795
+
796
  from tabulate import tabulate
797
 
798
  # Константы
 
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
  # Расчёт азота
 
880
  self.target_profile['N (NO3-)'] = TOTAL_NITROGEN * (NO3_RATIO / total_parts)
881
  self.target_profile['N (NH4+)'] = TOTAL_NITROGEN * (NH4_RATIO / total_parts)
882
 
883
+ def _label(self, element):
884
+ """Форматирование названий элементов для вывода"""
885
+ labels = {
886
+ 'N (NO3-)': 'NO3',
887
+ 'N (NH4+)': 'NH4'
888
+ }
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
  print(f"Ошибка при расчёте: {str(e)}")
920
  raise
921
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
922
  def _apply(self, fert_name, main_element, required_ppm):
923
  if required_ppm <= 0:
924
  return
 
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