fertpy 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fertpy/__init__.py +15 -0
- fertpy/cli/parametros_cli.py +33 -0
- fertpy/core/domain/classe.py +21 -0
- fertpy/core/domain/criterio.py +47 -0
- fertpy/core/domain/exceptions.py +25 -0
- fertpy/core/domain/intervalo.py +41 -0
- fertpy/core/domain/modelo_agronomico.py +112 -0
- fertpy/core/domain/recomendacao.py +38 -0
- fertpy/core/engine/avaliador.py +73 -0
- fertpy/core/engine/calculo_calagem.py +37 -0
- fertpy/correcao_solo/__init__.py +3 -0
- fertpy/correcao_solo/calagem.py +46 -0
- fertpy/infra/loaders/adubacao_loader.py +36 -0
- fertpy/infra/loaders/correcao_loader.py +29 -0
- fertpy/infra/parsing/condicao.py +27 -0
- fertpy/infra/parsing/intervalo.py +72 -0
- fertpy/infra/parsing/modelo_agronomico.py +58 -0
- fertpy/knowledge/boletim_100/adubacao/milho/__init__.py +0 -0
- fertpy/knowledge/boletim_100/adubacao/milho/graos/fosforo.yaml +101 -0
- fertpy/knowledge/boletim_100/adubacao/milho/graos/nitrogenio.yaml +65 -0
- fertpy/knowledge/boletim_100/adubacao/milho/graos/potassio.yaml +90 -0
- fertpy/knowledge/boletim_100/adubacao/milho/silagem/fosforo.yaml +101 -0
- fertpy/knowledge/boletim_100/adubacao/milho/silagem/nitrogenio.yaml +65 -0
- fertpy/knowledge/boletim_100/adubacao/milho/silagem/potassio.yaml +79 -0
- fertpy/knowledge/boletim_100/calagem/milho.yaml +17 -0
- fertpy/knowledge/embrapa/solo/textura.yaml +51 -0
- fertpy/nutrientes/__init__.py +9 -0
- fertpy/nutrientes/fosforo.py +54 -0
- fertpy/nutrientes/nitrogenio.py +58 -0
- fertpy/nutrientes/potassio.py +54 -0
- fertpy/services/validacao_parametros.py +77 -0
- fertpy/utils/parametros.py +49 -0
- fertpy-0.2.1.dist-info/METADATA +588 -0
- fertpy-0.2.1.dist-info/RECORD +38 -0
- fertpy-0.2.1.dist-info/WHEEL +5 -0
- fertpy-0.2.1.dist-info/licenses/AUTHORS.md +36 -0
- fertpy-0.2.1.dist-info/licenses/LICENSE +206 -0
- fertpy-0.2.1.dist-info/top_level.txt +1 -0
fertpy/__init__.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
from fertpy.utils.parametros import extrair_parametros
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def imprimir_parametros(estrutura: dict[str, dict[str, list[str]]]) -> None:
|
|
18
|
+
linhas = []
|
|
19
|
+
|
|
20
|
+
for boletim, culturas in estrutura.items():
|
|
21
|
+
linhas.append(f"\nboletim: {boletim}")
|
|
22
|
+
|
|
23
|
+
for cultura, nutrientes in culturas.items():
|
|
24
|
+
linhas.append(f" Cultura: {cultura}")
|
|
25
|
+
|
|
26
|
+
for nutriente in nutrientes:
|
|
27
|
+
linhas.append(f" - {nutriente}")
|
|
28
|
+
|
|
29
|
+
return "\n".join(linhas)
|
|
30
|
+
|
|
31
|
+
def imprimir_parametros_cli():
|
|
32
|
+
dados = extrair_parametros()
|
|
33
|
+
print(imprimir_parametros(dados))
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class Classe:
|
|
19
|
+
nome: str
|
|
20
|
+
tipo: str = "faixa"
|
|
21
|
+
descricao: str | None = None
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from fertpy.core.domain.intervalo import Intervalo
|
|
18
|
+
from fertpy.core.domain.classe import Classe
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class Criterio:
|
|
23
|
+
|
|
24
|
+
condicoes: dict[str, Intervalo | str]
|
|
25
|
+
classe: Classe | None
|
|
26
|
+
recomendacao: Any
|
|
27
|
+
|
|
28
|
+
observacoes: str | None = None
|
|
29
|
+
|
|
30
|
+
def __post_init__(self):
|
|
31
|
+
|
|
32
|
+
if not isinstance(self.condicoes, dict):
|
|
33
|
+
raise TypeError("Condições deve ser um dict")
|
|
34
|
+
|
|
35
|
+
if not self.condicoes:
|
|
36
|
+
raise ValueError("Criterio precisa de pelo menos uma condição")
|
|
37
|
+
|
|
38
|
+
for nome, condicao in self.condicoes.items():
|
|
39
|
+
|
|
40
|
+
if not isinstance(nome, str) or not nome.strip():
|
|
41
|
+
raise TypeError("Nome de condição inválido")
|
|
42
|
+
|
|
43
|
+
if not isinstance(condicao, (Intervalo, str)):
|
|
44
|
+
raise TypeError(f"Condição inválida para {nome}")
|
|
45
|
+
|
|
46
|
+
if self.classe is not None and not isinstance(self.classe, Classe):
|
|
47
|
+
raise TypeError("Classe deve ser Classe ou None")
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
class ParametroInvalidoError(ValueError):
|
|
15
|
+
|
|
16
|
+
def __init__(self, parametro: str, valor: str, validos: list[str]):
|
|
17
|
+
mensagem = (
|
|
18
|
+
f"{parametro} inválido: '{valor}', "
|
|
19
|
+
f"Valores válidos: {', '.join(validos)}"
|
|
20
|
+
)
|
|
21
|
+
super().__init__(mensagem)
|
|
22
|
+
self.parametro = parametro
|
|
23
|
+
self.valor = valor
|
|
24
|
+
self.validos = validos
|
|
25
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class Intervalo:
|
|
18
|
+
minimo: float | None
|
|
19
|
+
maximo: float | None
|
|
20
|
+
inclui_min: bool = True
|
|
21
|
+
inclui_max: bool = False
|
|
22
|
+
|
|
23
|
+
def __post_init__(self):
|
|
24
|
+
if self.minimo is not None and self.maximo is not None:
|
|
25
|
+
if self.minimo > self.maximo:
|
|
26
|
+
raise ValueError("Minimo não pode ser maior que o maximo")
|
|
27
|
+
|
|
28
|
+
def contem(self, valor:float) -> bool:
|
|
29
|
+
if self.minimo is not None:
|
|
30
|
+
if self.inclui_min and valor < self.minimo:
|
|
31
|
+
return False
|
|
32
|
+
if not self.inclui_min and valor <= self.minimo:
|
|
33
|
+
return False
|
|
34
|
+
|
|
35
|
+
if self.maximo is not None:
|
|
36
|
+
if self.inclui_max and valor > self.maximo:
|
|
37
|
+
return False
|
|
38
|
+
if not self.inclui_max and valor >= self.maximo:
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
return True
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from collections import defaultdict
|
|
16
|
+
|
|
17
|
+
from fertpy.core.domain.criterio import Criterio
|
|
18
|
+
from fertpy.core.domain.exceptions import ParametroInvalidoError
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class ModeloAgronomico:
|
|
23
|
+
nutriente: str
|
|
24
|
+
unidade_saida: str
|
|
25
|
+
|
|
26
|
+
criterios: list[Criterio]
|
|
27
|
+
|
|
28
|
+
nutriente_recomendado: str | None = None
|
|
29
|
+
unidade_entrada: str | None = None
|
|
30
|
+
metodo_analitico: str | None = None
|
|
31
|
+
fonte_referencia: dict | None = None
|
|
32
|
+
|
|
33
|
+
def __post_init__(self):
|
|
34
|
+
|
|
35
|
+
if not self.nutriente:
|
|
36
|
+
raise ValueError("O modelo não possui nutriente declarado")
|
|
37
|
+
|
|
38
|
+
if not self.unidade_saida:
|
|
39
|
+
raise ValueError("O modelo não possui unidade de saida declarado")
|
|
40
|
+
|
|
41
|
+
if not self.criterios:
|
|
42
|
+
raise ValueError("Modelo precisa de critérios")
|
|
43
|
+
|
|
44
|
+
for c in self.criterios:
|
|
45
|
+
if not isinstance(c, Criterio):
|
|
46
|
+
raise TypeError("Todos os critérios devem ser instâncias de criterio")
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def variaveis_esperadas(self) -> set[str]:
|
|
50
|
+
variaveis = set()
|
|
51
|
+
|
|
52
|
+
for criterio in self.criterios:
|
|
53
|
+
variaveis.update(criterio.condicoes.keys())
|
|
54
|
+
|
|
55
|
+
return variaveis
|
|
56
|
+
|
|
57
|
+
def valores_discretos_por_variavel(self) -> dict[str, set]:
|
|
58
|
+
|
|
59
|
+
valores = defaultdict(set)
|
|
60
|
+
|
|
61
|
+
for criterio in self.criterios:
|
|
62
|
+
for var, cond in criterio.condicoes.items():
|
|
63
|
+
if isinstance(cond, str):
|
|
64
|
+
valores[var].add(cond)
|
|
65
|
+
|
|
66
|
+
return valores
|
|
67
|
+
|
|
68
|
+
def validar_contexto(self, contexto: dict):
|
|
69
|
+
faltando = self.variaveis_esperadas - contexto.keys()
|
|
70
|
+
if faltando:
|
|
71
|
+
raise ValueError(
|
|
72
|
+
f"Variáveis obrigatórias ausentes: {sorted(faltando)}"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
extras = contexto.keys() - self.variaveis_esperadas
|
|
76
|
+
if extras:
|
|
77
|
+
raise ValueError(
|
|
78
|
+
f"Variáveis inesperadas: {sorted(extras)}"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
for var, valor in contexto.items():
|
|
82
|
+
|
|
83
|
+
exemplos = [
|
|
84
|
+
criterio.condicoes[var]
|
|
85
|
+
for criterio in self.criterios
|
|
86
|
+
if var in criterio.condicoes
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
if not exemplos:
|
|
90
|
+
continue
|
|
91
|
+
|
|
92
|
+
exemplo = exemplos[0]
|
|
93
|
+
|
|
94
|
+
if isinstance(exemplo, str):
|
|
95
|
+
valores_validos = {
|
|
96
|
+
c.condicoes[var]
|
|
97
|
+
for c in self.criterios
|
|
98
|
+
if isinstance(c.condicoes[var], str)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if valor not in valores_validos:
|
|
102
|
+
raise ParametroInvalidoError(
|
|
103
|
+
var,
|
|
104
|
+
valor,
|
|
105
|
+
sorted(valores_validos)
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
else:
|
|
109
|
+
if not isinstance(valor, (int, float)):
|
|
110
|
+
raise TypeError(
|
|
111
|
+
f"Variável '{var}' deve ser numérica"
|
|
112
|
+
)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
|
|
16
|
+
from fertpy.core.domain.intervalo import Intervalo
|
|
17
|
+
from fertpy.core.domain.classe import Classe
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True)
|
|
21
|
+
class Recomendacao:
|
|
22
|
+
nutriente: str
|
|
23
|
+
|
|
24
|
+
dose: float | Intervalo | str
|
|
25
|
+
unidade: str
|
|
26
|
+
|
|
27
|
+
classe: Classe
|
|
28
|
+
|
|
29
|
+
observacoes: list[str] | None = None
|
|
30
|
+
fonte: dict | None = None
|
|
31
|
+
|
|
32
|
+
def __post_init__(self):
|
|
33
|
+
|
|
34
|
+
if not self.nutriente:
|
|
35
|
+
raise ValueError("Recomendação precisa do parâmetro nutriente")
|
|
36
|
+
|
|
37
|
+
if not self.unidade:
|
|
38
|
+
raise ValueError("Recomendação precisa do parâmetro unidade")
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
from fertpy.core.domain.classe import Classe
|
|
15
|
+
from fertpy.core.domain.criterio import Criterio
|
|
16
|
+
from fertpy.core.domain.intervalo import Intervalo
|
|
17
|
+
from fertpy.core.domain.recomendacao import Recomendacao
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Avaliador:
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def avaliar(
|
|
24
|
+
criterios: list[Criterio],
|
|
25
|
+
contexto: dict[str, float],
|
|
26
|
+
nutriente: str,
|
|
27
|
+
unidade: str,
|
|
28
|
+
observacoes: list[str] | None = None,
|
|
29
|
+
fonte: dict | None = None
|
|
30
|
+
) -> Recomendacao:
|
|
31
|
+
|
|
32
|
+
for criterio in criterios:
|
|
33
|
+
for variavel, intervalo in criterio.condicoes.items():
|
|
34
|
+
|
|
35
|
+
if variavel not in contexto:
|
|
36
|
+
break
|
|
37
|
+
|
|
38
|
+
valor = contexto[variavel]
|
|
39
|
+
|
|
40
|
+
if isinstance(intervalo, Intervalo):
|
|
41
|
+
|
|
42
|
+
if not isinstance(valor, (int, float)):
|
|
43
|
+
break
|
|
44
|
+
|
|
45
|
+
if not intervalo.contem(valor):
|
|
46
|
+
break
|
|
47
|
+
else:
|
|
48
|
+
if valor != intervalo:
|
|
49
|
+
break
|
|
50
|
+
|
|
51
|
+
else:
|
|
52
|
+
classe_final = criterio.classe or Classe(nome="dose")
|
|
53
|
+
|
|
54
|
+
obs_final = []
|
|
55
|
+
|
|
56
|
+
if observacoes:
|
|
57
|
+
obs_final.extend(observacoes)
|
|
58
|
+
|
|
59
|
+
if criterio.observacoes:
|
|
60
|
+
obs_final.append(criterio.observacoes)
|
|
61
|
+
|
|
62
|
+
obs_final = obs_final or None
|
|
63
|
+
|
|
64
|
+
return Recomendacao(
|
|
65
|
+
nutriente=nutriente,
|
|
66
|
+
dose=criterio.recomendacao,
|
|
67
|
+
unidade=unidade,
|
|
68
|
+
classe=classe_final,
|
|
69
|
+
observacoes=obs_final,
|
|
70
|
+
fonte=fonte
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
raise ValueError("Nenhum critério compatível encontrado.")
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
class CalagemEngine:
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def calcular(
|
|
18
|
+
v1: float,
|
|
19
|
+
ctc: float,
|
|
20
|
+
v2: float,
|
|
21
|
+
prnt: float,
|
|
22
|
+
dose_maxima: float | None = None,
|
|
23
|
+
dose_minima: float | None = None
|
|
24
|
+
) -> float:
|
|
25
|
+
|
|
26
|
+
nc = (ctc * (v2 - v1)) / (10 * prnt)
|
|
27
|
+
|
|
28
|
+
if nc <= 0:
|
|
29
|
+
return 0.0
|
|
30
|
+
|
|
31
|
+
if dose_maxima is not None and nc > dose_maxima:
|
|
32
|
+
nc = dose_maxima
|
|
33
|
+
|
|
34
|
+
if dose_minima is not None and nc < dose_minima:
|
|
35
|
+
nc = dose_minima
|
|
36
|
+
|
|
37
|
+
return round(nc, 2)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
from fertpy.infra.loaders.correcao_loader import carregar_modelo_correcao
|
|
15
|
+
from fertpy.core.engine.calculo_calagem import CalagemEngine
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Calagem:
|
|
19
|
+
|
|
20
|
+
def __init__(self, cultura: str):
|
|
21
|
+
|
|
22
|
+
yaml = carregar_modelo_correcao(
|
|
23
|
+
"boletim_100",
|
|
24
|
+
cultura
|
|
25
|
+
)["calagem"]
|
|
26
|
+
|
|
27
|
+
self.modelo = yaml
|
|
28
|
+
|
|
29
|
+
def calcular(
|
|
30
|
+
self,
|
|
31
|
+
v_atual: float,
|
|
32
|
+
ctc: float,
|
|
33
|
+
prnt: float | None = None
|
|
34
|
+
) -> float:
|
|
35
|
+
|
|
36
|
+
parametros = self.modelo["parametros"]
|
|
37
|
+
limites = self.modelo.get("limites", {})
|
|
38
|
+
|
|
39
|
+
return CalagemEngine.calcular(
|
|
40
|
+
v1=v_atual,
|
|
41
|
+
ctc=ctc,
|
|
42
|
+
v2=parametros["v2_desejado"],
|
|
43
|
+
prnt=prnt or parametros["prnt_padrao"],
|
|
44
|
+
dose_maxima=limites.get("dose_maxima"),
|
|
45
|
+
dose_minima=limites.get("dose_minima")
|
|
46
|
+
)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
from importlib import resources
|
|
15
|
+
import yaml
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def carregar_modelo_adubacao(
|
|
19
|
+
boletim: str,
|
|
20
|
+
cultura: str,
|
|
21
|
+
finalidade: str,
|
|
22
|
+
nutriente: str
|
|
23
|
+
):
|
|
24
|
+
|
|
25
|
+
pacote_base = (
|
|
26
|
+
f"fertpy.knowledge."
|
|
27
|
+
f"{boletim}.adubacao."
|
|
28
|
+
f"{cultura}.{finalidade}"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
nome_arquivo = f"{nutriente}.yaml"
|
|
32
|
+
|
|
33
|
+
with resources.files(pacote_base).joinpath(nome_arquivo).open(
|
|
34
|
+
"r", encoding="utf-8"
|
|
35
|
+
) as f:
|
|
36
|
+
return yaml.safe_load(f)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
from importlib import resources
|
|
15
|
+
import yaml
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def carregar_modelo_correcao(
|
|
19
|
+
boletim: str,
|
|
20
|
+
cultura: str
|
|
21
|
+
):
|
|
22
|
+
|
|
23
|
+
pacote_base = f"fertpy.knowledge.{boletim}.calagem"
|
|
24
|
+
nome_arquivo = f"{cultura}.yaml"
|
|
25
|
+
|
|
26
|
+
with resources.files(pacote_base).joinpath(nome_arquivo).open(
|
|
27
|
+
"r", encoding="utf-8"
|
|
28
|
+
) as f:
|
|
29
|
+
return yaml.safe_load(f)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
from fertpy.infra.parsing.intervalo import parse_intervalo
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def parse_condicao(valor):
|
|
18
|
+
if isinstance(valor, (int, float)):
|
|
19
|
+
return parse_intervalo(str(valor))
|
|
20
|
+
|
|
21
|
+
if isinstance(valor, str):
|
|
22
|
+
try:
|
|
23
|
+
return parse_intervalo(valor)
|
|
24
|
+
except ValueError:
|
|
25
|
+
return valor.strip()
|
|
26
|
+
|
|
27
|
+
return valor
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Copyright 2026 Luiz Henrique de Lima Peguin
|
|
2
|
+
# and Pedro Henrique Escaranaro Brasil
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
|
|
14
|
+
import re
|
|
15
|
+
|
|
16
|
+
from fertpy.core.domain.intervalo import Intervalo
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def parse_intervalo(texto: str) -> Intervalo:
|
|
20
|
+
texto = texto.strip()
|
|
21
|
+
|
|
22
|
+
#===============================================
|
|
23
|
+
# Forma matematica: x <= a <= y, x < a < y, etc
|
|
24
|
+
#===============================================
|
|
25
|
+
|
|
26
|
+
padrao_duplo = re.compile(
|
|
27
|
+
r"^\s*(-?\d+\.?\d*)\s*(<=|<)\s*[a-zA-Z_]+\s*(<=|<)\s*(-?\d+\.?\d*)\s*$"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
m = padrao_duplo.match(texto)
|
|
31
|
+
|
|
32
|
+
if m:
|
|
33
|
+
a = float(m.group(1))
|
|
34
|
+
limite_inferior = m.group(2)
|
|
35
|
+
limite_superior = m.group(3)
|
|
36
|
+
b = float(m.group(4))
|
|
37
|
+
|
|
38
|
+
if a >= b:
|
|
39
|
+
raise ValueError(f"intervalo inválido (a >= b): {texto}")
|
|
40
|
+
|
|
41
|
+
inc_min = limite_inferior == "<="
|
|
42
|
+
inc_max = limite_superior == "<="
|
|
43
|
+
|
|
44
|
+
return Intervalo(a, b, inc_min, inc_max)
|
|
45
|
+
|
|
46
|
+
#============================
|
|
47
|
+
# Intervalos abertos simples
|
|
48
|
+
#============================
|
|
49
|
+
|
|
50
|
+
if texto.startswith(">="):
|
|
51
|
+
return Intervalo(float(texto[2:].strip()), None, True, False)
|
|
52
|
+
|
|
53
|
+
if texto.startswith("<="):
|
|
54
|
+
return Intervalo(None, float(texto[2:].strip()), False, True)
|
|
55
|
+
|
|
56
|
+
if texto.startswith(">"):
|
|
57
|
+
return Intervalo(float(texto[1:].strip()), None, False, False)
|
|
58
|
+
|
|
59
|
+
if texto.startswith("<"):
|
|
60
|
+
return Intervalo(None, float(texto[1:].strip()), False, False)
|
|
61
|
+
|
|
62
|
+
#=============
|
|
63
|
+
# Valor exato
|
|
64
|
+
#=============
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
v = float(texto)
|
|
68
|
+
return Intervalo(v, v, True, True)
|
|
69
|
+
except ValueError:
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
raise ValueError(f"Intervalo inválido: {texto}")
|