DmitrMakeev commited on
Commit
856c5f2
·
verified ·
1 Parent(s): 9b8498a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +108 -67
app.py CHANGED
@@ -723,6 +723,41 @@ NUTRIENT_CONTENT_IN_FERTILIZERS = {
723
 
724
 
725
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
726
  from tabulate import tabulate
727
 
728
  # Константы
@@ -755,15 +790,15 @@ NUTRIENT_CONTENT_IN_FERTILIZERS = {
755
  }
756
 
757
  class NutrientCalculator:
758
- def __init__(self, volume_liters: float = 1.0):
759
  self.volume = volume_liters
760
- self.results: Dict[str, Dict[str, Any]] = {}
761
  self.target_profile = BASE_PROFILE.copy()
762
  self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
763
  self.fertilizers = NUTRIENT_CONTENT_IN_FERTILIZERS
764
  self.total_ec = 0.0
765
 
766
- # Расчет азота
767
  total_parts = NO3_RATIO + NH4_RATIO
768
  self.target_profile['N (NO3-)'] = TOTAL_NITROGEN * (NO3_RATIO / total_parts)
769
  self.target_profile['N (NH4+)'] = TOTAL_NITROGEN * (NH4_RATIO / total_parts)
@@ -772,101 +807,98 @@ class NutrientCalculator:
772
  "NH4+": self.target_profile['N (NH4+)']
773
  }
774
 
775
- # Настройки компенсации по умолчанию
776
- self.compensation_weights = {
777
- 'KNO3': 0.5, # Вес калийной селитры (0-1)
778
- 'CaNO3': 0.3, # Вес кальциевой селитры (0-1)
779
- 'K2SO4': 0.2 # Вес сульфата калия (0-1)
780
- }
781
-
782
- def _label(self, element: str) -> str:
783
  """Форматирование названий элементов для вывода"""
784
  labels = {
785
  'N (NO3-)': 'NO3',
786
  'N (NH4+)': 'NH4'
787
  }
788
  return labels.get(element, element)
789
- def _apply(self, fert_name: str, main_element: str, required_ppm: float):
790
- """Применяет удобрение и обновляет профиль"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
791
  if required_ppm <= 0:
792
  return
793
-
794
  try:
795
- # Получаем содержание элемента в удобрении
796
  content = self.fertilizers[fert_name][main_element]
797
-
798
- # Рассчитываем граммы удобрения
799
  grams = (required_ppm * self.volume) / (content * 1000)
800
-
801
- # Инициализируем запись, если удобрение применяется впервые
802
  if fert_name not in self.results:
803
- self.results[fert_name] = {
804
  'граммы': 0.0,
805
  'миллиграммы': 0,
806
  'вклад в EC': 0.0
807
  }
808
- # Добавляем поля для каждого элемента в удобрении
809
  for element in self.fertilizers[fert_name]:
810
- self.results[fert_name][f'внесет {self._label(element)}'] = 0.0
811
-
812
- # Обновляем результаты
813
  self.results[fert_name]['граммы'] += grams
814
- self.results[fert_name]['миллиграммы'] = int(grams * 1000)
815
-
816
- # Рассчитываем вклад в EC и обновляем профиль
817
  fert_ec = 0.0
818
  for element, percent in self.fertilizers[fert_name].items():
819
  added_ppm = (grams * percent * 1000) / self.volume
820
  self.results[fert_name][f'внесет {self._label(element)}'] += added_ppm
821
  self.actual_profile[element] += added_ppm
822
  fert_ec += added_ppm * EC_COEFFICIENTS.get(element, 0.0015)
823
-
824
  self.results[fert_name]['вклад в EC'] += fert_ec
825
  self.total_ec += fert_ec
826
-
827
  except KeyError as e:
828
  print(f"Ошибка: отсутствует элемент {str(e)} в удобрении {fert_name}")
829
  raise
830
- def set_compensation_weights(self, kno3_weight: float, cano3_weight: float, k2so4_weight: float):
831
- """Установка весов для компенсации элементов"""
832
- total = kno3_weight + cano3_weight + k2so4_weight
833
- self.compensation_weights = {
834
- 'KNO3': kno3_weight / total,
835
- 'CaNO3': cano3_weight / total,
836
- 'K2SO4': k2so4_weight / total
837
- }
838
 
839
- def calculate(self) -> Dict[str, Any]:
840
- """Основной метод расчета с новой логикой"""
841
- try:
842
- # 1. Вносим Mg и S
843
- self._apply("Сульфат магния", "Mg", self.target_profile['Mg'])
844
-
845
- # 2. Балансируем азот с учетом компенсации
846
- self._balance_nitrogen_with_compensation()
847
-
848
- # 3. Вносим Ca (остаток)
849
- ca_needed = self.target_profile['Ca'] - self.actual_profile['Ca']
850
- if ca_needed > 0.1:
851
- self._apply("Кальциевая селитра", "Ca", ca_needed)
852
-
853
- # 4. Вносим P
854
- p_needed = self.target_profile['P'] - self.actual_profile['P']
855
- if p_needed > 0.1:
856
- self._apply("Монофосфат калия", "P", p_needed)
857
-
858
- # 5. Корректируем K через сульфат калия (если остался дефицит)
859
- k_needed = self.target_profile['K'] - self.actual_profile['K']
860
- if k_needed > 0.1:
861
- self._apply("Калий сернокислый", "K", k_needed)
862
-
863
- return self.results
864
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
865
  except Exception as e:
866
- print(f"Ошибка при расчёте: {str(e)}")
867
  raise
868
 
869
-
870
  def calculate_ec(self):
871
  return round(self.total_ec, 2)
872
 
@@ -927,7 +959,17 @@ if __name__ == "__main__":
927
 
928
 
929
 
930
- def round_floats(obj: Union[float, Dict, List], ndigits: int = 3) -> Union[float, Dict, List]:
 
 
 
 
 
 
 
 
 
 
931
  """Рекурсивно округляет все float значения в структуре данных"""
932
  if isinstance(obj, float):
933
  return round(obj, ndigits)
@@ -937,7 +979,6 @@ def round_floats(obj: Union[float, Dict, List], ndigits: int = 3) -> Union[float
937
  return [round_floats(x, ndigits) for x in obj]
938
  return obj
939
 
940
-
941
  @app.route('/calculation', methods=['POST'])
942
  def handle_calculation():
943
  try:
@@ -1031,7 +1072,7 @@ def handle_calculation():
1031
  if 'fertilizers' in rounded_response:
1032
  for fert in rounded_response['fertilizers'].values():
1033
  if 'миллиграммы' in fert:
1034
- fert['миллиграммы'] = int(round(fert['граммы'] * 1000))
1035
 
1036
  return jsonify(rounded_response)
1037
 
 
723
 
724
 
725
 
726
+ from tabulate import tabulate
727
+
728
+ # Константы
729
+ TOTAL_NITROGEN = 125.000
730
+ NO3_RATIO = 8.25
731
+ NH4_RATIO = 1.00
732
+ VOLUME_LITERS = 100
733
+
734
+ # Коэффициенты электропроводности
735
+ EC_COEFFICIENTS = {
736
+ 'P': 0.0012, 'K': 0.0018, 'Mg': 0.0015,
737
+ 'Ca': 0.0016, 'S': 0.0014,
738
+ 'N (NO3-)': 0.0017, 'N (NH4+)': 0.0019
739
+ }
740
+
741
+ # Целевые значения
742
+ BASE_PROFILE = {
743
+ 'P': 31.000, 'K': 210.000, 'Mg': 24.000,
744
+ 'Ca': 84.000, 'S': 56.439,
745
+ 'N (NO3-)': 0, 'N (NH4+)': 0
746
+ }
747
+
748
+ NUTRIENT_CONTENT_IN_FERTILIZERS = {
749
+ "Кальциевая селитра": {"N (NO3-)": 0.11863, "Ca": 0.16972},
750
+ "Калий азотнокислый": {"N (NO3-)": 0.136, "K": 0.382},
751
+ "Калий сернокислый": {"K": 0.44874, "S": 0.18401},
752
+ "Аммоний азотнокислый": {"N (NO3-)": 0.17499, "N (NH4+)": 0.17499},
753
+ "Сульфат магния": {"Mg": 0.09861, "S": 0.13010},
754
+ "Монофосфат калия": {"P": 0.218, "K": 0.275}
755
+ }
756
+
757
+
758
+
759
+
760
+
761
  from tabulate import tabulate
762
 
763
  # Константы
 
790
  }
791
 
792
  class NutrientCalculator:
793
+ def __init__(self, volume_liters=1.0):
794
  self.volume = volume_liters
795
+ self.results = {}
796
  self.target_profile = BASE_PROFILE.copy()
797
  self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
798
  self.fertilizers = NUTRIENT_CONTENT_IN_FERTILIZERS
799
  self.total_ec = 0.0
800
 
801
+ # Расчёт азота
802
  total_parts = NO3_RATIO + NH4_RATIO
803
  self.target_profile['N (NO3-)'] = TOTAL_NITROGEN * (NO3_RATIO / total_parts)
804
  self.target_profile['N (NH4+)'] = TOTAL_NITROGEN * (NH4_RATIO / total_parts)
 
807
  "NH4+": self.target_profile['N (NH4+)']
808
  }
809
 
810
+ def _label(self, element):
 
 
 
 
 
 
 
811
  """Форматирование названий элементов для вывода"""
812
  labels = {
813
  'N (NO3-)': 'NO3',
814
  'N (NH4+)': 'NH4'
815
  }
816
  return labels.get(element, element)
817
+
818
+ def calculate(self):
819
+ try:
820
+ self._apply("Сульфат магния", "Mg", self.target_profile['Mg'])
821
+ self._apply("Кальциевая селитра", "Ca", self.target_profile['Ca'])
822
+ self._apply("Монофосфат калия", "P", self.target_profile['P'])
823
+ self._apply("Аммоний азотнокислый", "N (NH4+)", self.target_profile['N (NH4+)'])
824
+
825
+ current_no3 = self.actual_profile['N (NO3-)']
826
+ no3_needed = self.target_profile['N (NO3-)'] - current_no3
827
+
828
+ if no3_needed > 0.1:
829
+ self._apply("Калий азотнокислый", "N (NO3-)", no3_needed)
830
+
831
+ self._apply_k_sulfate()
832
+
833
+ k_deficit = self.target_profile['K'] - self.actual_profile['K']
834
+ if k_deficit > 0.1:
835
+ self._apply("Калий азотнокислый", "K", k_deficit)
836
+
837
+ return self.results
838
+ except Exception as e:
839
+ print(f"Ошибка при расчёте: {str(e)}")
840
+ raise
841
+
842
+ def _apply(self, fert_name, main_element, required_ppm):
843
  if required_ppm <= 0:
844
  return
845
+
846
  try:
 
847
  content = self.fertilizers[fert_name][main_element]
 
 
848
  grams = (required_ppm * self.volume) / (content * 1000)
849
+
 
850
  if fert_name not in self.results:
851
+ result = {
852
  'граммы': 0.0,
853
  'миллиграммы': 0,
854
  'вклад в EC': 0.0
855
  }
 
856
  for element in self.fertilizers[fert_name]:
857
+ result[f'внесет {self._label(element)}'] = 0.0
858
+ self.results[fert_name] = result
859
+
860
  self.results[fert_name]['граммы'] += grams
861
+ self.results[fert_name]['миллиграммы'] += int(grams * 1000)
862
+
 
863
  fert_ec = 0.0
864
  for element, percent in self.fertilizers[fert_name].items():
865
  added_ppm = (grams * percent * 1000) / self.volume
866
  self.results[fert_name][f'внесет {self._label(element)}'] += added_ppm
867
  self.actual_profile[element] += added_ppm
868
  fert_ec += added_ppm * EC_COEFFICIENTS.get(element, 0.0015)
869
+
870
  self.results[fert_name]['вклад в EC'] += fert_ec
871
  self.total_ec += fert_ec
 
872
  except KeyError as e:
873
  print(f"Ошибка: отсутствует элемент {str(e)} в удобрении {fert_name}")
874
  raise
 
 
 
 
 
 
 
 
875
 
876
+ def _apply_k_sulfate(self):
877
+ fert = "Калий сернокислый"
878
+ k_def = self.target_profile['K'] - self.actual_profile['K']
879
+ s_def = self.target_profile['S'] - self.actual_profile['S']
880
+
881
+ if k_def <= 0 and s_def <= 0:
882
+ return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
883
 
884
+ try:
885
+ if s_def > 0.1:
886
+ s_content = self.fertilizers[fert]["S"]
887
+ grams_s = (s_def * self.volume) / (s_content * 1000)
888
+
889
+ k_content = self.fertilizers[fert]["K"]
890
+ k_from_s = (grams_s * k_content * 1000) / self.volume
891
+
892
+ if k_from_s > k_def and k_def > 0.1:
893
+ grams = (k_def * self.volume) / (k_content * 1000)
894
+ else:
895
+ grams = grams_s
896
+
897
+ self._apply(fert, "S", s_def)
898
  except Exception as e:
899
+ print(f"Ошибка при расчёте сульфата калия: {str(e)}")
900
  raise
901
 
 
902
  def calculate_ec(self):
903
  return round(self.total_ec, 2)
904
 
 
959
 
960
 
961
 
962
+
963
+
964
+
965
+
966
+
967
+
968
+
969
+
970
+ from flask import request, jsonify
971
+
972
+ def round_floats(obj, ndigits=3):
973
  """Рекурсивно округляет все float значения в структуре данных"""
974
  if isinstance(obj, float):
975
  return round(obj, ndigits)
 
979
  return [round_floats(x, ndigits) for x in obj]
980
  return obj
981
 
 
982
  @app.route('/calculation', methods=['POST'])
983
  def handle_calculation():
984
  try:
 
1072
  if 'fertilizers' in rounded_response:
1073
  for fert in rounded_response['fertilizers'].values():
1074
  if 'миллиграммы' in fert:
1075
+ fert['миллиграммы'] = int(round(fert['миллиграммы']))
1076
 
1077
  return jsonify(rounded_response)
1078