DmitrMakeev commited on
Commit
a997bc2
·
verified ·
1 Parent(s): d8868ab

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -92
app.py CHANGED
@@ -693,6 +693,10 @@ def nutri_call():
693
 
694
 
695
 
 
 
 
 
696
  from tabulate import tabulate
697
 
698
  # Константы
@@ -708,50 +712,39 @@ EC_COEFFICIENTS = {
708
  'N (NO3-)': 0.0017, 'N (NH4+)': 0.0019
709
  }
710
 
711
- # Базовый профиль питательного раствора
712
  BASE_PROFILE = {
713
  'P': 31.000, 'K': 210.000, 'Mg': 24.000,
714
  'Ca': 84.000, 'S': 56.439,
715
  'N (NO3-)': 0, 'N (NH4+)': 0
716
  }
717
 
718
- # Содержание элементов в удобрениях
719
  NUTRIENT_CONTENT_IN_FERTILIZERS = {
720
  "Кальциевая селитра": {"N (NO3-)": 0.11863, "Ca": 0.16972},
721
  "Калий азотнокислый": {"N (NO3-)": 0.136, "K": 0.382},
 
722
  "Аммоний азотнокислый": {"N (NO3-)": 0.17499, "N (NH4+)": 0.17499},
723
  "Сульфат магния": {"Mg": 0.09861, "S": 0.13010},
724
- "Монофосфат калия": {"P": 0.218, "K": 0.275},
725
- "Калий сернокислый": {"K": 0.44874, "S": 0.18401}
726
  }
727
 
728
  class NutrientCalculator:
729
  def __init__(self, volume_liters=1.0):
730
- # Общие параметры
731
  self.volume = volume_liters
732
  self.results = {}
733
  self.target_profile = BASE_PROFILE.copy()
734
  self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
735
- self.fertilizers = NUTRIENT_CONTENT_IN_FERTILIZERS
736
  self.total_ec = 0.0
737
 
738
- # Веса компенсации для элементов
739
- self.element_compensation_weights = {
740
- "POTASSIUM_SULFATE": {"weight": -0.08, "fert": "Калий сернокислый", "main_element": "K"},
741
- "MAGNESIUM_SULFATE": {"weight": -0.28, "fert": "Сульфат магния", "main_element": "Mg"},
742
- "MONOPOTASSIUM_PHOSPHATE": {"weight": -0.08, "fert": "Монофосфат калия", "main_element": "P"}
743
- }
744
-
745
- # Коэффициенты распределения для кальциевой селитры
746
- self.calcium_nitrate_ratios = {
747
- "Ca": 0.7, # 70% дефицита кальция покрываем кальциевой селитрой
748
- "NO3": 0.29 # 30% дефицита NO3 покрываем кальциевой селитрой
749
- }
750
-
751
- # Расчёт соотношений азотов
752
  total_parts = NO3_RATIO + NH4_RATIO
753
  self.target_profile['N (NO3-)'] = TOTAL_NITROGEN * (NO3_RATIO / total_parts)
754
  self.target_profile['N (NH4+)'] = TOTAL_NITROGEN * (NH4_RATIO / total_parts)
 
 
 
 
755
 
756
  def _label(self, element):
757
  """Форматирование названий элементов для вывода"""
@@ -762,84 +755,37 @@ class NutrientCalculator:
762
  return labels.get(element, element)
763
 
764
  def calculate(self):
765
- """Основной метод расчета"""
766
  try:
767
- # 1. Вносим кальциевую селитру для Ca и частично для NO3
768
- self._apply_calcium_nitrate()
769
-
770
- # 2. Вносим аммонийный азот напрямую
771
  self._apply("Аммоний азотнокислый", "N (NH4+)", self.target_profile['N (NH4+)'])
772
-
773
- # 3. Компенсируем остаток NO3 через калийную селитру
774
- self._compensate_no3()
775
-
776
- # 4. Компенсируем остальные элементы через веса компенсации
777
- self._compensate_element("Mg")
778
- self._compensate_element("P")
779
- self._compensate_element("S")
780
- self._compensate_element("K")
781
-
 
 
 
782
  return self.results
783
  except Exception as e:
784
  print(f"Ошибка при расчёте: {str(e)}")
785
  raise
786
 
787
- def _apply_calcium_nitrate(self):
788
- """Специальный метод для внесения кальциевой селитры"""
789
- # Вносим кальций
790
- ca_needed = self.target_profile['Ca'] - self.actual_profile.get('Ca', 0)
791
- if ca_needed > 0.1:
792
- ca_share = self.calcium_nitrate_ratios['Ca']
793
- ca_to_apply = ca_needed * ca_share
794
- self._apply("Кальциевая селитра", "Ca", ca_to_apply)
795
-
796
- # Вносим часть NO3 из кальциевой селитры
797
- no3_needed = self.target_profile['N (NO3-)'] - self.actual_profile.get('N (NO3-)', 0)
798
- if no3_needed > 0.1:
799
- no3_share = self.calcium_nitrate_ratios['NO3']
800
- no3_to_apply = no3_needed * no3_share
801
- self._apply("Кальциевая селитра", "N (NO3-)", no3_to_apply)
802
-
803
- def _compensate_no3(self):
804
- """Компенсация остатка NO3 после внесения кальциевой селитры"""
805
- no3_needed = self.target_profile['N (NO3-)'] - self.actual_profile.get('N (NO3-)', 0)
806
- if no3_needed > 0.1:
807
- self._apply("Калий азотнокислый", "N (NO3-)", no3_needed)
808
-
809
- def _compensate_element(self, element):
810
- """Общий метод компенсации для других элементов"""
811
- needed = self.target_profile[element] - self.actual_profile.get(element, 0)
812
- if abs(needed) < 0.1:
813
- return
814
-
815
- candidates = []
816
- for weight_key, weight_data in self.element_compensation_weights.items():
817
- fert_name = weight_data["fert"]
818
- if element in self.fertilizers.get(fert_name, {}):
819
- candidates.append({
820
- 'name': fert_name,
821
- 'weight': weight_data["weight"],
822
- 'content': self.fertilizers[fert_name][element]
823
- })
824
-
825
- if not candidates:
826
- raise ValueError(f"Нет удобрений для элемента {element}")
827
-
828
- total_weight = sum(c['weight'] for c in candidates)
829
- for candidate in candidates:
830
- share = candidate['weight'] / total_weight
831
- ppm_to_apply = needed * share
832
- self._apply(candidate['name'], element, ppm_to_apply)
833
-
834
  def _apply(self, fert_name, main_element, required_ppm):
835
- """Применение удобрения для конкретного элемента"""
836
  if required_ppm <= 0:
837
  return
838
-
839
  try:
840
  content = self.fertilizers[fert_name][main_element]
841
  grams = (required_ppm * self.volume) / (content * 1000)
842
-
843
  if fert_name not in self.results:
844
  result = {
845
  'граммы': 0.0,
@@ -849,29 +795,53 @@ class NutrientCalculator:
849
  for element in self.fertilizers[fert_name]:
850
  result[f'внесет {self._label(element)}'] = 0.0
851
  self.results[fert_name] = result
852
-
853
  self.results[fert_name]['граммы'] += grams
854
  self.results[fert_name]['миллиграммы'] += int(grams * 1000)
855
-
856
  fert_ec = 0.0
857
  for element, percent in self.fertilizers[fert_name].items():
858
  added_ppm = (grams * percent * 1000) / self.volume
859
  self.results[fert_name][f'внесет {self._label(element)}'] += added_ppm
860
  self.actual_profile[element] += added_ppm
861
  fert_ec += added_ppm * EC_COEFFICIENTS.get(element, 0.0015)
862
-
863
  self.results[fert_name]['вклад в EC'] += fert_ec
864
  self.total_ec += fert_ec
865
  except KeyError as e:
866
  print(f"Ошибка: отсутствует элемент {str(e)} в удобрении {fert_name}")
867
  raise
868
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
869
  def calculate_ec(self):
870
- """Расчет общей электропроводности (EC)"""
871
  return round(self.total_ec, 2)
872
 
873
  def print_report(self):
874
- """Вывод отчета о расчетах"""
875
  try:
876
  print("\n" + "="*60)
877
  print("ПРОФИЛЬ ПИТАТЕЛЬНОГО РАСТВОРА (ИТОГО):")
@@ -879,6 +849,10 @@ class NutrientCalculator:
879
  table = [[el, round(self.actual_profile[el], 1)] for el in self.actual_profile]
880
  print(tabulate(table, headers=["Элемент", "ppm"]))
881
 
 
 
 
 
882
  print("\n" + "="*60)
883
  print(f"РАСЧЕТ ДЛЯ {self.volume} ЛИТРОВ РАСТВОРА")
884
  print("="*60)
@@ -914,8 +888,6 @@ class NutrientCalculator:
914
  print(f"Ошибка при выводе отчёта: {str(e)}")
915
  raise
916
 
917
-
918
-
919
  if __name__ == "__main__":
920
  try:
921
  calculator = NutrientCalculator(volume_liters=VOLUME_LITERS)
 
693
 
694
 
695
 
696
+
697
+
698
+
699
+
700
  from tabulate import tabulate
701
 
702
  # Константы
 
712
  'N (NO3-)': 0.0017, 'N (NH4+)': 0.0019
713
  }
714
 
715
+ # Целевые значения
716
  BASE_PROFILE = {
717
  'P': 31.000, 'K': 210.000, 'Mg': 24.000,
718
  'Ca': 84.000, 'S': 56.439,
719
  'N (NO3-)': 0, 'N (NH4+)': 0
720
  }
721
 
 
722
  NUTRIENT_CONTENT_IN_FERTILIZERS = {
723
  "Кальциевая селитра": {"N (NO3-)": 0.11863, "Ca": 0.16972},
724
  "Калий азотнокислый": {"N (NO3-)": 0.136, "K": 0.382},
725
+ "Калий сернокислый": {"K": 0.44874, "S": 0.18401},
726
  "Аммоний азотнокислый": {"N (NO3-)": 0.17499, "N (NH4+)": 0.17499},
727
  "Сульфат магния": {"Mg": 0.09861, "S": 0.13010},
728
+ "Монофосфат калия": {"P": 0.218, "K": 0.275}
 
729
  }
730
 
731
  class NutrientCalculator:
732
  def __init__(self, volume_liters=1.0):
 
733
  self.volume = volume_liters
734
  self.results = {}
735
  self.target_profile = BASE_PROFILE.copy()
736
  self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
737
+ self.fertilizers = NUTRIENT_CONTENT_IN_FERTILIZERS
738
  self.total_ec = 0.0
739
 
740
+ # Расчёт азота
 
 
 
 
 
 
 
 
 
 
 
 
 
741
  total_parts = NO3_RATIO + NH4_RATIO
742
  self.target_profile['N (NO3-)'] = TOTAL_NITROGEN * (NO3_RATIO / total_parts)
743
  self.target_profile['N (NH4+)'] = TOTAL_NITROGEN * (NH4_RATIO / total_parts)
744
+ self.initial_n_profile = {
745
+ "NO3-": self.target_profile['N (NO3-)'],
746
+ "NH4+": self.target_profile['N (NH4+)']
747
+ }
748
 
749
  def _label(self, element):
750
  """Форматирование названий элементов для вывода"""
 
755
  return labels.get(element, element)
756
 
757
  def calculate(self):
 
758
  try:
759
+ self._apply("Сульфат магния", "Mg", self.target_profile['Mg'])
760
+ self._apply("Кальциевая селитра", "Ca", self.target_profile['Ca'])
761
+ self._apply("Монофосфат калия", "P", self.target_profile['P'])
 
762
  self._apply("Аммоний азотнокислый", "N (NH4+)", self.target_profile['N (NH4+)'])
763
+
764
+ current_no3 = self.actual_profile['N (NO3-)']
765
+ no3_needed = self.target_profile['N (NO3-)'] - current_no3
766
+
767
+ if no3_needed > 0.1:
768
+ self._apply("Калий азотнокислый", "N (NO3-)", no3_needed)
769
+
770
+ self._apply_k_sulfate()
771
+
772
+ k_deficit = self.target_profile['K'] - self.actual_profile['K']
773
+ if k_deficit > 0.1:
774
+ self._apply("Калий азотнокислый", "K", k_deficit)
775
+
776
  return self.results
777
  except Exception as e:
778
  print(f"Ошибка при расчёте: {str(e)}")
779
  raise
780
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
781
  def _apply(self, fert_name, main_element, required_ppm):
 
782
  if required_ppm <= 0:
783
  return
784
+
785
  try:
786
  content = self.fertilizers[fert_name][main_element]
787
  grams = (required_ppm * self.volume) / (content * 1000)
788
+
789
  if fert_name not in self.results:
790
  result = {
791
  'граммы': 0.0,
 
795
  for element in self.fertilizers[fert_name]:
796
  result[f'внесет {self._label(element)}'] = 0.0
797
  self.results[fert_name] = result
798
+
799
  self.results[fert_name]['граммы'] += grams
800
  self.results[fert_name]['миллиграммы'] += int(grams * 1000)
801
+
802
  fert_ec = 0.0
803
  for element, percent in self.fertilizers[fert_name].items():
804
  added_ppm = (grams * percent * 1000) / self.volume
805
  self.results[fert_name][f'внесет {self._label(element)}'] += added_ppm
806
  self.actual_profile[element] += added_ppm
807
  fert_ec += added_ppm * EC_COEFFICIENTS.get(element, 0.0015)
808
+
809
  self.results[fert_name]['вклад в EC'] += fert_ec
810
  self.total_ec += fert_ec
811
  except KeyError as e:
812
  print(f"Ошибка: отсутствует элемент {str(e)} в удобрении {fert_name}")
813
  raise
814
 
815
+ def _apply_k_sulfate(self):
816
+ fert = "Калий сернокислый"
817
+ k_def = self.target_profile['K'] - self.actual_profile['K']
818
+ s_def = self.target_profile['S'] - self.actual_profile['S']
819
+
820
+ if k_def <= 0 and s_def <= 0:
821
+ return
822
+
823
+ try:
824
+ if s_def > 0.1:
825
+ s_content = self.fertilizers[fert]["S"]
826
+ grams_s = (s_def * self.volume) / (s_content * 1000)
827
+
828
+ k_content = self.fertilizers[fert]["K"]
829
+ k_from_s = (grams_s * k_content * 1000) / self.volume
830
+
831
+ if k_from_s > k_def and k_def > 0.1:
832
+ grams = (k_def * self.volume) / (k_content * 1000)
833
+ else:
834
+ grams = grams_s
835
+
836
+ self._apply(fert, "S", s_def)
837
+ except Exception as e:
838
+ print(f"Ошибка при расчёте сульфата калия: {str(e)}")
839
+ raise
840
+
841
  def calculate_ec(self):
 
842
  return round(self.total_ec, 2)
843
 
844
  def print_report(self):
 
845
  try:
846
  print("\n" + "="*60)
847
  print("ПРОФИЛЬ ПИТАТЕЛЬНОГО РАСТВОРА (ИТОГО):")
 
849
  table = [[el, round(self.actual_profile[el], 1)] for el in self.actual_profile]
850
  print(tabulate(table, headers=["Элемент", "ppm"]))
851
 
852
+ print("\nИсходный расчёт азота:")
853
+ for form, val in self.initial_n_profile.items():
854
+ print(f" {form}: {round(val, 1)} ppm")
855
+
856
  print("\n" + "="*60)
857
  print(f"РАСЧЕТ ДЛЯ {self.volume} ЛИТРОВ РАСТВОРА")
858
  print("="*60)
 
888
  print(f"Ошибка при выводе отчёта: {str(e)}")
889
  raise
890
 
 
 
891
  if __name__ == "__main__":
892
  try:
893
  calculator = NutrientCalculator(volume_liters=VOLUME_LITERS)