DmitrMakeev commited on
Commit
bc1f924
·
verified ·
1 Parent(s): 93fb46e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +142 -103
app.py CHANGED
@@ -684,26 +684,18 @@ NO3_RATIO = 9.000
684
  NH4_RATIO = 1.00
685
  VOLUME_LITERS = 100
686
 
687
- # Коэффициенты электропроводности для каждого элемента (мСм/см на ppm)
688
  EC_COEFFICIENTS = {
689
- 'P': 0.0012,
690
- 'K': 0.0018,
691
- 'Mg': 0.0015,
692
- 'Ca': 0.0016,
693
- 'S': 0.0014,
694
- 'N (NO3-)': 0.0017,
695
- 'N (NH4+)': 0.0019
696
  }
697
 
698
  # Целевые значения
699
  BASE_PROFILE = {
700
- 'P': 31.000,
701
- 'K': 210.000,
702
- 'Mg': 24.000,
703
- 'Ca': 84.000,
704
- 'S': 56.439,
705
- 'N (NO3-)': 0,
706
- 'N (NH4+)': 0
707
  }
708
 
709
  FERTILIZERS = {
@@ -722,7 +714,7 @@ class NutrientCalculator:
722
  self.target_profile = BASE_PROFILE.copy()
723
  self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
724
  self.fertilizers = FERTILIZERS
725
- self.total_ec = 0.0 # Накопленное значение EC
726
 
727
  # Расчёт азота
728
  total_parts = NO3_RATIO + NH4_RATIO
@@ -733,108 +725,155 @@ class NutrientCalculator:
733
  "NH4+": self.target_profile['N (NH4+)']
734
  }
735
 
 
 
 
 
 
 
 
 
736
  def calculate(self):
737
- self._apply("Сульфат магния", "Mg", self.target_profile['Mg'])
738
- self._apply("Кальциевая селитра", "Ca", self.target_profile['Ca'])
739
- self._apply("Монофосфат калия", "P", self.target_profile['P'])
740
- self._apply("Аммоний азотнокислый", "N (NH4+)", self.target_profile['N (NH4+)'])
741
-
742
- current_no3 = self.actual_profile['N (NO3-)']
743
- no3_needed = self.target_profile['N (NO3-)'] - current_no3
744
-
745
- if no3_needed > 0.1:
746
- self._apply("Калий азотнокислый", "N (NO3-)", no3_needed)
747
-
748
- self._apply_k_sulfate()
749
-
750
- k_deficit = self.target_profile['K'] - self.actual_profile['K']
751
- if k_deficit > 0.1:
752
- self._apply("Калий азотнокислый", "K", k_deficit)
753
-
754
- return self.results
 
 
 
 
755
 
756
  def _apply(self, fert_name, main_element, required_ppm):
757
  if required_ppm <= 0:
758
  return
759
 
760
- content = self.fertilizers[fert_name][main_element]
761
- grams = required_ppm * self.volume / (content * 1000)
762
-
763
- if fert_name not in self.results:
764
- result = {
765
- 'граммы': 0.0,
766
- 'миллиграммы': 0,
767
- 'вклад в EC': 0.0
768
- }
769
- for element in self.fertilizers[fert_name]:
770
- result[f'внесет {self._label(element)}'] = 0.0
771
- self.results[fert_name] = result
772
 
773
- self.results[fert_name]['граммы'] += grams
774
- self.results[fert_name]['миллиграммы'] += int(grams * 1000)
775
-
776
- fert_ec = 0.0
777
- for element, percent in self.fertilizers[fert_name].items():
778
- added_ppm = grams * percent * 1000 / self.volume
779
- self.results[fert_name][f'внесет {self._label(element)}'] += added_ppm
780
- self.actual_profile[element] += added_ppm
781
- fert_ec += added_ppm * EC_COEFFICIENTS[element]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
782
 
783
- self.results[fert_name]['вклад в EC'] += fert_ec
784
- self.total_ec += fert_ec
785
-
786
- # ... остальные методы остаются без изменений ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
787
 
788
  def calculate_ec(self):
789
  return round(self.total_ec, 2)
790
 
791
  def print_report(self):
792
- print("\n" + "="*60)
793
- print("ПРОФИЛЬ ПИТАТЕЛЬНОГО РАСТВОРА (ИТОГО):")
794
- print("="*60)
795
- table = [[el, round(self.actual_profile[el], 1)] for el in self.actual_profile]
796
- print(tabulate(table, headers=["Элемент", "ppm"]))
797
-
798
- print("\nИсходный расчёт азота:")
799
- for form, val in self.initial_n_profile.items():
800
- print(f" {form}: {round(val, 1)} ppm")
801
-
802
- print("\n" + "="*60)
803
- print(f"РАСЧЕТ ДЛЯ {self.volume} ЛИТРОВ РАСТВОРА")
804
- print("="*60)
805
- print(f"Общая концентрация: {round(sum(self.actual_profile.values()), 1)} ppm")
806
- print(f"EC: {self.calculate_ec()} mS/cm")
807
-
808
- print("\nРЕКОМЕНДУЕМЫЕ УДОБРЕНИЯ:")
809
- fert_table = []
810
- for fert, data in self.results.items():
811
- adds = [f"+{k}: {v:.1f} ppm" for k, v in data.items() if k.startswith('внесет')]
812
- fert_table.append([
813
- fert,
814
- round(data['граммы'], 3),
815
- data['миллиграммы'],
816
- round(data['вклад в EC'], 3),
817
- "\n".join(adds)
818
- ])
819
- print(tabulate(fert_table,
820
- headers=["Удобрение", "Граммы", "Миллиграммы", "EC (мСм/см)", "Добавит"]))
821
-
822
- print("\nОСТАТОЧНЫЙ ДЕФИЦИТ:")
823
- deficit = {
824
- k: round(self.target_profile[k] - self.actual_profile[k], 1)
825
- for k in self.target_profile
826
- if abs(self.target_profile[k] - self.actual_profile[k]) > 0.1
827
- }
828
- if deficit:
829
- for el, val in deficit.items():
830
- print(f" {el}: {val} ppm")
831
- else:
832
- print(" Все элементы покрыты полностью")
 
 
 
 
833
 
834
  if __name__ == "__main__":
835
- calculator = NutrientCalculator(volume_liters=VOLUME_LITERS)
836
- calculator.calculate()
837
- calculator.print_report()
 
 
 
838
 
839
 
840
 
 
684
  NH4_RATIO = 1.00
685
  VOLUME_LITERS = 100
686
 
687
+ # Коэффициенты электропроводности
688
  EC_COEFFICIENTS = {
689
+ 'P': 0.0012, 'K': 0.0018, 'Mg': 0.0015,
690
+ 'Ca': 0.0016, 'S': 0.0014,
691
+ 'N (NO3-)': 0.0017, 'N (NH4+)': 0.0019
 
 
 
 
692
  }
693
 
694
  # Целевые значения
695
  BASE_PROFILE = {
696
+ 'P': 31.000, 'K': 210.000, 'Mg': 24.000,
697
+ 'Ca': 84.000, 'S': 56.439,
698
+ 'N (NO3-)': 0, 'N (NH4+)': 0
 
 
 
 
699
  }
700
 
701
  FERTILIZERS = {
 
714
  self.target_profile = BASE_PROFILE.copy()
715
  self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
716
  self.fertilizers = FERTILIZERS
717
+ self.total_ec = 0.0
718
 
719
  # Расчёт азота
720
  total_parts = NO3_RATIO + NH4_RATIO
 
725
  "NH4+": self.target_profile['N (NH4+)']
726
  }
727
 
728
+ def _label(self, element):
729
+ """Форматирование названий элементов для вывода"""
730
+ labels = {
731
+ 'N (NO3-)': 'NO3',
732
+ 'N (NH4+)': 'NH4'
733
+ }
734
+ return labels.get(element, element)
735
+
736
  def calculate(self):
737
+ try:
738
+ self._apply("Сульфат магния", "Mg", self.target_profile['Mg'])
739
+ self._apply("Кальциевая селитра", "Ca", self.target_profile['Ca'])
740
+ self._apply("Монофосфат калия", "P", self.target_profile['P'])
741
+ self._apply("Аммоний азотнокислый", "N (NH4+)", self.target_profile['N (NH4+)'])
742
+
743
+ current_no3 = self.actual_profile['N (NO3-)']
744
+ no3_needed = self.target_profile['N (NO3-)'] - current_no3
745
+
746
+ if no3_needed > 0.1:
747
+ self._apply("Калий азотнокислый", "N (NO3-)", no3_needed)
748
+
749
+ self._apply_k_sulfate()
750
+
751
+ k_deficit = self.target_profile['K'] - self.actual_profile['K']
752
+ if k_deficit > 0.1:
753
+ self._apply("Калий азотнокислый", "K", k_deficit)
754
+
755
+ return self.results
756
+ except Exception as e:
757
+ print(f"Ошибка при расчёте: {str(e)}")
758
+ raise
759
 
760
  def _apply(self, fert_name, main_element, required_ppm):
761
  if required_ppm <= 0:
762
  return
763
 
764
+ try:
765
+ content = self.fertilizers[fert_name][main_element]
766
+ grams = required_ppm * self.volume / (content * 1000)
 
 
 
 
 
 
 
 
 
767
 
768
+ if fert_name not in self.results:
769
+ result = {
770
+ 'граммы': 0.0,
771
+ 'миллиграммы': 0,
772
+ 'вклад в EC': 0.0
773
+ }
774
+ for element in self.fertilizers[fert_name]:
775
+ result[f'внесет {self._label(element)}'] = 0.0
776
+ self.results[fert_name] = result
777
+
778
+ self.results[fert_name]['граммы'] += grams
779
+ self.results[fert_name]['миллиграммы'] += int(grams * 1000)
780
+
781
+ fert_ec = 0.0
782
+ for element, percent in self.fertilizers[fert_name].items():
783
+ added_ppm = grams * percent * 1000 / self.volume
784
+ self.results[fert_name][f'внесет {self._label(element)}'] += added_ppm
785
+ self.actual_profile[element] += added_ppm
786
+ fert_ec += added_ppm * EC_COEFFICIENTS.get(element, 0.0015) # Значение по умолчанию
787
+
788
+ self.results[fert_name]['вклад в EC'] += fert_ec
789
+ self.total_ec += fert_ec
790
+ except KeyError as e:
791
+ print(f"Ошибка: отсутствует элемент {str(e)} в удобрении {fert_name}")
792
+ raise
793
+
794
+ def _apply_k_sulfate(self):
795
+ fert = "Калий сернокислый"
796
+ k_def = self.target_profile['K'] - self.actual_profile['K']
797
+ s_def = self.target_profile['S'] - self.actual_profile['S']
798
 
799
+ if k_def <= 0 and s_def <= 0:
800
+ return
801
+
802
+ try:
803
+ if s_def > 0.1:
804
+ s_content = self.fertilizers[fert]["S"]
805
+ grams_s = s_def * self.volume / (s_content * 1000)
806
+
807
+ k_content = self.fertilizers[fert]["K"]
808
+ k_from_s = grams_s * k_content * 1000 / self.volume
809
+
810
+ if k_from_s > k_def and k_def > 0.1:
811
+ grams = k_def * self.volume / (k_content * 1000)
812
+ else:
813
+ grams = grams_s
814
+
815
+ self._apply(fert, "S", s_def)
816
+ except Exception as e:
817
+ print(f"Ошибка при расчёте сульфата калия: {str(e)}")
818
+ raise
819
 
820
  def calculate_ec(self):
821
  return round(self.total_ec, 2)
822
 
823
  def print_report(self):
824
+ try:
825
+ print("\n" + "="*60)
826
+ print("ПРОФИЛЬ ПИТАТЕЛЬНОГО РАСТВОРА (ИТОГО):")
827
+ print("="*60)
828
+ table = [[el, round(self.actual_profile[el], 1)] for el in self.actual_profile]
829
+ print(tabulate(table, headers=["Элемент", "ppm"]))
830
+
831
+ print("\nИсходный расчёт азота:")
832
+ for form, val in self.initial_n_profile.items():
833
+ print(f" {form}: {round(val, 1)} ppm")
834
+
835
+ print("\n" + "="*60)
836
+ print(f"РАСЧЕТ ДЛЯ {self.volume} ЛИТРОВ РАСТВОРА")
837
+ print("="*60)
838
+ print(f"Общая концентрация: {round(sum(self.actual_profile.values()), 1)} ppm")
839
+ print(f"EC: {self.calculate_ec()} mS/cm")
840
+
841
+ print("\nРЕКОМЕНДУЕМЫЕ УДОБРЕНИЯ:")
842
+ fert_table = []
843
+ for fert, data in self.results.items():
844
+ adds = [f"+{k}: {v:.1f} ppm" for k, v in data.items() if k.startswith('внесет')]
845
+ fert_table.append([
846
+ fert,
847
+ round(data['граммы'], 3),
848
+ data['миллиграммы'],
849
+ round(data['вклад в EC'], 3),
850
+ "\n".join(adds)
851
+ ])
852
+ print(tabulate(fert_table,
853
+ headers=["Удобрение", "Граммы", "Миллиграммы", "EC (мСм/см)", "Добавит"]))
854
+
855
+ print("\nОСТАТОЧНЫЙ ДЕФИЦИТ:")
856
+ deficit = {
857
+ k: round(self.target_profile[k] - self.actual_profile[k], 1)
858
+ for k in self.target_profile
859
+ if abs(self.target_profile[k] - self.actual_profile[k]) > 0.1
860
+ }
861
+ if deficit:
862
+ for el, val in deficit.items():
863
+ print(f" {el}: {val} ppm")
864
+ else:
865
+ print(" Все элементы покрыты полностью")
866
+ except Exception as e:
867
+ print(f"Ошибка при выводе отчёта: {str(e)}")
868
+ raise
869
 
870
  if __name__ == "__main__":
871
+ try:
872
+ calculator = NutrientCalculator(volume_liters=VOLUME_LITERS)
873
+ calculator.calculate()
874
+ calculator.print_report()
875
+ except Exception as e:
876
+ print(f"Критическая ошибка: {str(e)}")
877
 
878
 
879