DmitrMakeev commited on
Commit
7e29db5
·
verified ·
1 Parent(s): 3ae6da0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -230
app.py CHANGED
@@ -697,236 +697,6 @@ def spoller():
697
 
698
 
699
 
700
- from tabulate import tabulate
701
-
702
- INPUT_DATA = {
703
- "fertilizerConstants": {
704
- "Кальциевая селитра": {"N (NO3-)": 0.11863, "Ca_nitrate": 0.16972},
705
- "Хелат кальция": {"Ca_chelate": 0.10},
706
- "Калий азотнокислый": {"N (NO3-)": 0.13854, "K": 0.36672},
707
- "Аммоний азотнокислый": {"N (NO3-)": 0.17499, "N (NH4+)": 0.17499},
708
- "Сульфат магния": {"Mg": 0.10220, "S": 0.13483},
709
- "Монофосфат калия": {"P": 0.22761, "K": 0.28731},
710
- "Калий сернокислый": {"K": 0.44874, "S": 0.18401}
711
- },
712
- "profileSettings": {
713
- "P": 50, "K": 220, "Mg": 24, "S": 60,
714
- "Ca_nitrate_target": 60,
715
- "Ca_chelate_target": 20,
716
- "NO3_RAT": 4, "TOTAL_NITROG": 125, "liters": 100
717
- }
718
-
719
- }
720
-
721
- class NutrientCalculator:
722
- def __init__(self, fertilizer_constants, profile_settings, liters, rounding_precision):
723
- self.fertilizers = fertilizer_constants
724
- self.profile = profile_settings
725
- self.volume = liters
726
- self.rounding_precision = rounding_precision
727
-
728
- total_parts = self.profile["NO3_RAT"] + 1
729
- self.target = {
730
- 'P': self.profile["P"],
731
- 'K': self.profile["K"],
732
- 'Mg': self.profile["Mg"],
733
- 'S': self.profile["S"],
734
- 'Ca_nitrate': self.profile["Ca_nitrate_target"],
735
- 'Ca_chelate': self.profile["Ca_chelate_target"],
736
- 'N (NO3-)': self.profile["TOTAL_NITROG"] * (self.profile["NO3_RAT"] / total_parts),
737
- 'N (NH4+)': self.profile["TOTAL_NITROG"] * (1 / total_parts)
738
- }
739
-
740
- self.actual = {
741
- 'P': 0.0, 'K': 0.0, 'Mg': 0.0, 'S': 0.0,
742
- 'Ca_nitrate': 0.0, 'Ca_chelate': 0.0,
743
- 'N (NO3-)': 0.0, 'N (NH4+)': 0.0
744
- }
745
- self.results = {fert: {'граммы': 0.0} for fert in self.fertilizers}
746
-
747
- def _apply_fertilizer(self, name, element, target_ppm):
748
- if name not in self.fertilizers:
749
- raise KeyError(f"Удобрение '{name}' не найдено!")
750
- content = self.fertilizers[name].get(element, 0)
751
- if content == 0:
752
- print(f"ПРЕДУПРЕЖДЕНИЕ: Удобрение '{name}' не содержит элемент '{element}'")
753
- return
754
- grams = (target_ppm * self.volume) / (content * 1000)
755
- self.results[name]['граммы'] += round(grams, self.rounding_precision)
756
- for el, val in self.fertilizers[name].items():
757
- if el in self.actual:
758
- added_ppm = (grams * val * 1000) / self.volume
759
- self.actual[el] += round(added_ppm, self.rounding_precision)
760
-
761
- def _balance_k_s(self):
762
- k_needed = self.target["K"] - self.actual["K"]
763
- s_needed = self.target["S"] - self.actual["S"]
764
-
765
- if k_needed > 0 and s_needed > 0:
766
- k_fraction = self.fertilizers["Калий сернокислый"].get("K", 0)
767
- s_fraction = self.fertilizers["Калий сернокислый"].get("S", 0)
768
- if k_fraction == 0 or s_fraction == 0:
769
- return
770
- k_from_k2so4 = min(k_needed, s_needed * k_fraction / s_fraction)
771
- self._apply_fertilizer("Калий сернокислый", "K", k_from_k2so4)
772
-
773
- remaining_k = self.target["K"] - self.actual["K"]
774
- if remaining_k > 0:
775
- self._apply_fertilizer("Калий азотнокислый", "K", remaining_k)
776
-
777
- def _verify_results(self):
778
- deficits = {}
779
- for el in self.target:
780
- diff = self.target[el] - self.actual[el]
781
- if abs(diff) > 0.1:
782
- deficits[el] = round(diff, self.rounding_precision)
783
- return {
784
- 'fertilizers': {k: round(v['граммы'], self.rounding_precision) for k, v in self.results.items() if v['граммы'] > 0},
785
- 'actual_profile': {k: round(v, self.rounding_precision) for k, v in self.actual.items()},
786
- 'deficits': deficits
787
- }
788
-
789
- def calculate(self):
790
- # 1. Вносим хелатный кальций - строго 20 ppm
791
- self._apply_fertilizer("Хелат кальция", "Ca_chelate", self.target["Ca_chelate"])
792
-
793
- # 2. Вносим нитратный кальций - строго 60 ppm
794
- self._apply_fertilizer("Кальциевая селитра", "Ca_nitrate", self.target["Ca_nitrate"])
795
-
796
- # 3. Остальные элементы
797
- self._apply_fertilizer("Аммоний азотнокислый", "N (NH4+)", self.target["N (NH4+)"])
798
- self._apply_fertilizer("Монофосфат калия", "P", self.target["P"])
799
- self._apply_fertilizer("Сульфат магния", "Mg", self.target["Mg"])
800
- self._balance_k_s()
801
-
802
- # 4. Балансируем нитратный азот
803
- no3_needed = self.target["N (NO3-)"] - self.actual["N (NO3-)"]
804
- if no3_needed > 0:
805
- self._apply_fertilizer("Калий азотнокислый", "N (NO3-)", no3_needed)
806
-
807
- return self._verify_results()
808
-
809
- def generate_report(self, results):
810
- fert_table = []
811
- for name, data in results['fertilizers'].items():
812
- fert_table.append([name, f"{data} г"])
813
-
814
- total_ca = self.actual['Ca_nitrate'] + self.actual['Ca_chelate']
815
- ca_diff = total_ca - (self.target['Ca_nitrate'] + self.target['Ca_chelate'])
816
-
817
- element_table = [
818
- ["P", f"{self.target['P']} ppm", f"{self.actual['P']} ppm"],
819
- ["K", f"{self.target['K']} ppm", f"{self.actual['K']} ppm"],
820
- ["Mg", f"{self.target['Mg']} ppm", f"{self.actual['Mg']} ppm"],
821
- ["S", f"{self.target['S']} ppm", f"{self.actual['S']} ppm"],
822
- ["Ca (нитрат)", f"{self.target['Ca_nitrate']} ppm", f"{self.actual['Ca_nitrate']} ppm"],
823
- ["Ca (хелат)", f"{self.target['Ca_chelate']} ppm", f"{self.actual['Ca_chelate']} ppm"],
824
- ["Ca (общий)", f"80 ppm", f"{total_ca} ppm", f"{ca_diff:+.2f} ppm"],
825
- ["N-NO3", f"{self.target['N (NO3-)']} ppm", f"{self.actual['N (NO3-)']} ppm"],
826
- ["N-NH4", f"{self.target['N (NH4+)']} ppm", f"{self.actual['N (NH4+)']} ppm"]
827
- ]
828
-
829
- report = "РЕКОМЕНДУЕМЫЕ УДОБРЕНИЯ:\n"
830
- report += tabulate(fert_table, headers=["Удобрение", "Количество"], tablefmt="grid")
831
- report += "\n\nБАЛАНС ЭЛЕМЕНТОВ:\n"
832
- report += tabulate(element_table,
833
- headers=["Элемент", "Цель", "Факт", "Отклонение"],
834
- tablefmt="grid")
835
- if results['deficits']:
836
- report += "\n\nВНИМАНИЕ: Обнаружены небольшие отклонения:"
837
- for el, diff in results['deficits'].items():
838
- report += f"\n- {el}: не хватает {abs(diff)} ppm"
839
- return report
840
-
841
- # Запуск расчета
842
- calculator = NutrientCalculator(
843
- fertilizer_constants=INPUT_DATA["fertilizerConstants"],
844
- profile_settings=INPUT_DATA["profileSettings"],
845
- liters=INPUT_DATA["profileSettings"]["liters"],
846
- rounding_precision=3
847
- )
848
-
849
- results = calculator.calculate()
850
- print(calculator.generate_report(results))
851
-
852
- @app.route('/calculation', methods=['POST'])
853
- def handle_calculation():
854
- try:
855
- # 1. Получаем и парсим данные
856
- data = request.get_json()
857
- if not data:
858
- return jsonify({"error": "No JSON data received"}), 400
859
-
860
- # Логируем входные данные для отладки
861
- print("\n=== ВХОДНЫЕ ДАННЫЕ ===")
862
- print(json.dumps(data, indent=2, ensure_ascii=False))
863
-
864
- # 2. Извлекаем основные параметры
865
- fertilizer_constants = data.get("fertilizerConstants", {})
866
- profile_settings = data.get("profileSettings", {})
867
-
868
- # Проверяем наличие необходимых полей
869
- if not fertilizer_constants or not profile_settings:
870
- return jsonify({"error": "Missing fertilizerConstants or profileSettings"}), 400
871
-
872
- # 3. Извлекаем дополнительные параметры
873
- liters = profile_settings.get("liters", 100) # Объем раствора (литры)
874
- rounding_precision = profile_settings.get("rounding_precision", 3) # Точность округления
875
-
876
- # 4. Создаем и запускаем калькулятор
877
- calculator = NutrientCalculator(
878
- fertilizer_constants=fertilizer_constants,
879
- profile_settings=profile_settings,
880
- liters=liters,
881
- rounding_precision=rounding_precision
882
- )
883
- results = calculator.calculate()
884
-
885
- # 5. Формируем дополнительные данные
886
- element_contributions = {}
887
- for fert_name in calculator.fertilizers.keys():
888
- grams = calculator.results[fert_name]['граммы']
889
- element_contributions[fert_name] = {}
890
- for element, percent in calculator.fertilizers[fert_name].items():
891
- added_ppm = (grams * percent * 1000) / calculator.volume
892
- element_contributions[fert_name][element] = round(added_ppm, rounding_precision)
893
-
894
- # 6. Формируем полный ответ
895
- response = {
896
- "fertilizers": results['fertilizers'],
897
- "actual_profile": results['actual_profile'],
898
- "deficits": results['deficits'],
899
- "total_ppm": results['total_ppm'],
900
- "element_contributions": element_contributions,
901
- "nitrogen_ratios": {
902
- "NH4_RATIO": 1,
903
- "NO3_RATIO": profile_settings.get("NO3_RAT", 0),
904
- "TOTAL_NITROGEN": profile_settings.get("TOTAL_NITROG", 0)
905
- }
906
- }
907
-
908
- return jsonify(response), 200
909
-
910
- except Exception as e:
911
- error_msg = f"Server error: {str(e)}"
912
- print(error_msg)
913
- return jsonify({
914
- "error": error_msg,
915
- "fertilizers": {},
916
- "actual_profile": {},
917
- "deficits": {},
918
- "element_contributions": {},
919
- "total_ppm": 0
920
- }), 500
921
-
922
-
923
-
924
-
925
-
926
-
927
-
928
-
929
-
930
 
931
 
932
 
 
697
 
698
 
699
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
700
 
701
 
702