DmitrMakeev commited on
Commit
f9a03ae
·
verified ·
1 Parent(s): 4493dfe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -97
app.py CHANGED
@@ -767,86 +767,70 @@ class NutrientCalculator:
767
 
768
  def calculate(self):
769
  try:
770
- # Первый проход: компенсация основных элементов
771
- self._compensate_main_elements()
 
 
 
772
 
773
- # Второй проход: компенсация азота
774
- self._compensate_nitrogen()
775
 
776
- # Третий проход: компенсация второстепенных элементов
777
- self._compensate_secondary_elements()
778
 
779
- # Четвертый проход: корректировка перебора
780
- self._adjust_overages()
 
 
 
 
 
 
 
781
 
782
- return self.results
783
  except Exception as e:
784
  print(f"Ошибка при расчёте: {str(e)}")
785
  raise
786
 
787
- def _compensate_main_elements(self):
788
- """Компенсация основных элементов (Ca, Mg, P)"""
789
- for element, weight_data in self.compensation_weights.items():
790
- if element in ["Ca", "Mg", "P"]:
791
- fert_name = weight_data["fert"]
792
- main_element = weight_data["main_element"]
793
- required_ppm = self.target_profile[main_element] - self.actual_profile[main_element]
794
- if required_ppm > 0.1:
795
- self._apply_with_limit(fert_name, main_element, required_ppm)
796
-
797
- def _compensate_nitrogen(self):
798
- """Компенсация азота (NO3-, NH4+)"""
799
- for nitrogen_type in ["N (NO3-)", "N (NH4+)"]:
800
- required_ppm = self.target_profile[nitrogen_type] - self.actual_profile[nitrogen_type]
801
- if required_ppm > 0.1:
802
- fert_name = self.compensation_weights[nitrogen_type]["fert"]
803
- self._apply_with_limit(fert_name, nitrogen_type, required_ppm)
804
-
805
- def _compensate_secondary_elements(self):
806
- """Компенсация второстепенных элементов (K, S)"""
807
- for element, weight_data in self.compensation_weights.items():
808
- if element in ["K", "S"]:
809
- fert_name = weight_data["fert"]
810
- main_element = weight_data["main_element"]
811
- required_ppm = self.target_profile[main_element] - self.actual_profile[main_element]
812
  if required_ppm > 0.1:
813
- self._apply_with_limit(fert_name, main_element, required_ppm)
 
 
 
 
 
 
 
 
 
 
 
 
814
 
815
- def _apply_with_limit(self, fert_name, main_element, required_ppm):
816
- """Применение удобрения с ограничением по перебору"""
817
- if required_ppm <= 0:
818
- return
819
 
820
- try:
821
- content = self.fertilizers[fert_name][main_element]
822
- max_allowed_ppm = self.target_profile[main_element] - self.actual_profile[main_element]
823
- grams = min((required_ppm * self.volume) / (content * 1000), (max_allowed_ppm * self.volume) / (content * 1000))
824
-
825
- if fert_name not in self.results:
826
- result = {
827
- 'граммы': 0.0,
828
- 'миллиграммы': 0,
829
- 'вклад в EC': 0.0
830
- }
831
- for element in self.fertilizers[fert_name]:
832
- result[f'внесет {self._label(element)}'] = 0.0
833
- self.results[fert_name] = result
834
-
835
- self.results[fert_name]['граммы'] += grams
836
- self.results[fert_name]['миллиграммы'] += int(grams * 1000)
837
-
838
- fert_ec = 0.0
839
- for element, percent in self.fertilizers[fert_name].items():
840
- added_ppm = (grams * percent * 1000) / self.volume
841
- self.results[fert_name][f'внесет {self._label(element)}'] += added_ppm
842
- self.actual_profile[element] += added_ppm
843
- fert_ec += added_ppm * EC_COEFFICIENTS.get(element, 0.0015)
844
-
845
- self.results[fert_name]['вклад в EC'] += fert_ec
846
- self.total_ec += fert_ec
847
- except KeyError as e:
848
- print(f"Ошибка: отсутствует элемент {str(e)} в удобрении {fert_name}")
849
- raise
850
 
851
  def _adjust_overages(self):
852
  """Корректировка перебора элементов"""
@@ -854,45 +838,41 @@ class NutrientCalculator:
854
  if self.actual_profile[element] > self.target_profile[element]:
855
  overage = self.actual_profile[element] - self.target_profile[element]
856
  print(f"Корректировка перебора: {element} уменьшен на {overage:.2f} ppm")
857
-
858
  # Уменьшаем фактическое значение
859
  self.actual_profile[element] -= overage
860
-
861
  # Обновляем результаты удобрений
862
  for fert_name, fert_data in self.results.items():
863
  if f'внесет {self._label(element)}' in fert_data:
864
- fert_data[f'внесет {self._label(element)}'] -= overage
865
-
 
 
 
 
 
 
866
  # Пересчитываем граммы удобрения
867
  if element in self.fertilizers[fert_name]:
868
  content = self.fertilizers[fert_name][element]
869
- grams_to_remove = (overage * self.volume) / (content * 1000)
870
  fert_data['граммы'] -= grams_to_remove
871
  fert_data['миллиграммы'] -= int(grams_to_remove * 1000)
872
 
873
- def calculate_ec(self):
874
- return round(self.total_ec, 2)
875
-
876
- def print_initial_nitrogen_report(self):
877
- try:
878
- print("Исходный расчёт азота:")
879
- print(f" NO3-: {self.initial_n_profile['NO3-']} ppm")
880
- print(f" NH4+: {self.initial_n_profile['NH4+']} ppm")
881
- except Exception as e:
882
- print(f"Ошибка при выводе отчёта: {str(e)}")
883
- raise
884
-
885
- def calculate_ec(self):
886
- return round(self.total_ec, 2)
887
-
888
- def print_initial_nitrogen_report(self):
889
- try:
890
- print("Исходный расчёт азота:")
891
- print(f" NO3-: {self.initial_n_profile['NO3-']} ppm")
892
- print(f" NH4+: {self.initial_n_profile['NH4+']} ppm")
893
- except Exception as e:
894
- print(f"Ошибка при выводе отчёта: {str(e)}")
895
- raise
896
 
897
  def calculate_ec(self):
898
  return round(self.total_ec, 2)
 
767
 
768
  def calculate(self):
769
  try:
770
+ max_iterations = 100 # Максимальное количество итераций
771
+ iteration = 0
772
+ while iteration < max_iterations:
773
+ iteration += 1
774
+ print(f"Итерация {iteration} из {max_iterations}")
775
 
776
+ # Сброс фактического профиля
777
+ self._reset_actual_profile()
778
 
779
+ # Применение удобрений
780
+ self._apply_fertilizers()
781
 
782
+ # Проверка результатов
783
+ if self.validate_results():
784
+ print("Успешная комбинация найдена!")
785
+ return self.results
786
+
787
+ # Корректировка перебора
788
+ self._adjust_overages()
789
+
790
+ raise ValueError("Не удалось найти подходящую комбинацию удобрений после максимального количества итераций.")
791
 
 
792
  except Exception as e:
793
  print(f"Ошибка при расчёте: {str(e)}")
794
  raise
795
 
796
+ def _reset_actual_profile(self):
797
+ """Сброс фактического профиля перед новой итерацией"""
798
+ self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
799
+ self.total_ec = 0.0
800
+ self.results = {}
801
+
802
+ def _apply_fertilizers(self):
803
+ """Применение удобрений"""
804
+ for fert_name, fert_data in self.fertilizers.items():
805
+ for element, content in fert_data.items():
806
+ required_ppm = self.target_profile[element] - self.actual_profile[element]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
807
  if required_ppm > 0.1:
808
+ grams = min((required_ppm * self.volume) / (content * 1000), 100) # Ограничение на граммы
809
+ self._apply_with_limit(fert_name, element, grams, content)
810
+
811
+ def _apply_with_limit(self, fert_name, element, grams, content):
812
+ """Применение удобрения с ограничением"""
813
+ if fert_name not in self.results:
814
+ self.results[fert_name] = {
815
+ 'граммы': 0.0,
816
+ 'миллиграммы': 0,
817
+ 'вклад в EC': 0.0
818
+ }
819
+ for elem in self.fertilizers[fert_name]:
820
+ self.results[fert_name][f'внесет {self._label(elem)}'] = 0.0
821
 
822
+ self.results[fert_name]['граммы'] += grams
823
+ self.results[fert_name]['миллиграммы'] += int(grams * 1000)
 
 
824
 
825
+ fert_ec = 0.0
826
+ for elem, percent in self.fertilizers[fert_name].items():
827
+ added_ppm = (grams * percent * 1000) / self.volume
828
+ self.results[fert_name][f'внесет {self._label(elem)}'] += added_ppm
829
+ self.actual_profile[elem] += added_ppm
830
+ fert_ec += added_ppm * EC_COEFFICIENTS.get(elem, 0.0015)
831
+
832
+ self.results[fert_name]['вклад в EC'] += fert_ec
833
+ self.total_ec += fert_ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
834
 
835
  def _adjust_overages(self):
836
  """Корректировка перебора элементов"""
 
838
  if self.actual_profile[element] > self.target_profile[element]:
839
  overage = self.actual_profile[element] - self.target_profile[element]
840
  print(f"Корректировка перебора: {element} уменьшен на {overage:.2f} ppm")
841
+
842
  # Уменьшаем фактическое значение
843
  self.actual_profile[element] -= overage
844
+
845
  # Обновляем результаты удобрений
846
  for fert_name, fert_data in self.results.items():
847
  if f'внесет {self._label(element)}' in fert_data:
848
+ current_value = fert_data[f'внесет {self._label(element)}']
849
+ if current_value > overage:
850
+ fert_data[f'внесет {self._label(element)}'] -= overage
851
+ overage = 0
852
+ else:
853
+ overage -= current_value
854
+ fert_data[f'внесет {self._label(element)}'] = 0
855
+
856
  # Пересчитываем граммы удобрения
857
  if element in self.fertilizers[fert_name]:
858
  content = self.fertilizers[fert_name][element]
859
+ grams_to_remove = (current_value * self.volume) / (content * 1000)
860
  fert_data['граммы'] -= grams_to_remove
861
  fert_data['миллиграммы'] -= int(grams_to_remove * 1000)
862
 
863
+ # Убеждаемся, что граммы не отрицательны
864
+ if fert_data['граммы'] < 0:
865
+ fert_data['граммы'] = 0
866
+ fert_data['миллиграммы'] = 0
867
+
868
+ def validate_results(self):
869
+ """Проверка соответствия целевым значениям"""
870
+ for element, target_value in self.target_profile.items():
871
+ actual_value = self.actual_profile[element]
872
+ if abs(actual_value - target_value) > 0.1: # Допустимая погрешность
873
+ print(f"Несоответствие: {element} (цель: {target_value:.2f}, фактически: {actual_value:.2f})")
874
+ return False
875
+ return True
 
 
 
 
 
 
 
 
 
 
876
 
877
  def calculate_ec(self):
878
  return round(self.total_ec, 2)