agroplan-ai-cli 1.0.10 → 1.0.12
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.
package/backend-template/api.py
CHANGED
|
@@ -422,30 +422,65 @@ def get_cenarios(
|
|
|
422
422
|
# Formata resposta
|
|
423
423
|
cenarios_formatados = {}
|
|
424
424
|
|
|
425
|
+
# Aplicar ajuste climático em todos os cenários se disponível
|
|
426
|
+
ajuste_risco = contexto_climatico.get("ajuste_risco", 0) if contexto_climatico else 0
|
|
427
|
+
|
|
425
428
|
for key, cenario in cenarios.items():
|
|
429
|
+
# Aplicar ajuste climático no risco de cada item do plano
|
|
430
|
+
plano_ajustado = []
|
|
431
|
+
soma_risco_area = 0
|
|
432
|
+
soma_area = 0
|
|
433
|
+
|
|
434
|
+
for p in cenario['plano']:
|
|
435
|
+
risco_original = float(p['risco']) # Em pontos percentuais (30, 35, etc.)
|
|
436
|
+
area = float(p['area'])
|
|
437
|
+
|
|
438
|
+
# Aplicar ajuste se houver (ajuste também em pontos percentuais: -3, +5, +15)
|
|
439
|
+
if ajuste_risco != 0:
|
|
440
|
+
novo_risco = min(95, max(5, risco_original + ajuste_risco))
|
|
441
|
+
else:
|
|
442
|
+
novo_risco = risco_original
|
|
443
|
+
|
|
444
|
+
item_plano = {
|
|
445
|
+
"talhao": int(p['talhao']),
|
|
446
|
+
"area": area,
|
|
447
|
+
"solo": str(talhoes_dict[int(p['talhao'])]['solo']),
|
|
448
|
+
"clima": str(talhoes_dict[int(p['talhao'])]['clima']),
|
|
449
|
+
"relevo": str(talhoes_dict[int(p['talhao'])]['relevo']),
|
|
450
|
+
"agua": str(talhoes_dict[int(p['talhao'])]['agua']),
|
|
451
|
+
"cultura": str(p['cultura']),
|
|
452
|
+
"lucro_estimado": float(p['lucro_estimado']),
|
|
453
|
+
"risco": round(novo_risco, 1), # Em pontos percentuais
|
|
454
|
+
"nota": float(p['nota']),
|
|
455
|
+
"tempo": 0
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
# Adicionar campos de ajuste se aplicado
|
|
459
|
+
if ajuste_risco != 0:
|
|
460
|
+
item_plano["risco_original"] = round(risco_original, 1)
|
|
461
|
+
item_plano["ajuste_aplicado"] = round(ajuste_risco, 1)
|
|
462
|
+
|
|
463
|
+
plano_ajustado.append(item_plano)
|
|
464
|
+
|
|
465
|
+
# Acumular para recalcular risco médio
|
|
466
|
+
soma_risco_area += novo_risco * area
|
|
467
|
+
soma_area += area
|
|
468
|
+
|
|
469
|
+
# Recalcular risco médio ponderado
|
|
470
|
+
risco_medio_ajustado = soma_risco_area / soma_area if soma_area > 0 else cenario['risco_medio']
|
|
471
|
+
|
|
426
472
|
cenarios_formatados[key] = {
|
|
427
473
|
'nome': str(cenario['nome']),
|
|
428
474
|
'descricao': str(cenario['descricao']),
|
|
429
475
|
'lucro_total': float(cenario['lucro_total']),
|
|
430
|
-
'risco_medio':
|
|
476
|
+
'risco_medio': round(risco_medio_ajustado, 1), # Em pontos percentuais
|
|
431
477
|
'area_total': float(cenario['area_total']),
|
|
432
|
-
'plano':
|
|
433
|
-
{
|
|
434
|
-
"talhao": int(p['talhao']),
|
|
435
|
-
"area": float(p['area']),
|
|
436
|
-
"solo": str(talhoes_dict[int(p['talhao'])]['solo']),
|
|
437
|
-
"clima": str(talhoes_dict[int(p['talhao'])]['clima']),
|
|
438
|
-
"relevo": str(talhoes_dict[int(p['talhao'])]['relevo']),
|
|
439
|
-
"agua": str(talhoes_dict[int(p['talhao'])]['agua']),
|
|
440
|
-
"cultura": str(p['cultura']),
|
|
441
|
-
"lucro_estimado": float(p['lucro_estimado']),
|
|
442
|
-
"risco": float(p['risco']),
|
|
443
|
-
"nota": float(p['nota']),
|
|
444
|
-
"tempo": 0 # Não disponível nos cenários simples
|
|
445
|
-
}
|
|
446
|
-
for p in cenario['plano']
|
|
447
|
-
]
|
|
478
|
+
'plano': plano_ajustado
|
|
448
479
|
}
|
|
480
|
+
|
|
481
|
+
# Adicionar risco médio original se ajuste foi aplicado
|
|
482
|
+
if ajuste_risco != 0:
|
|
483
|
+
cenarios_formatados[key]['risco_medio_original'] = round(float(cenario['risco_medio']), 1)
|
|
449
484
|
|
|
450
485
|
# Adiciona AG com contexto climático
|
|
451
486
|
cenarios_formatados['genetico'] = {
|
|
@@ -642,36 +677,18 @@ def relatorio(request: RelatorioRequest):
|
|
|
642
677
|
from core.climate_adapter import obter_contexto_climatico_por_coordenadas
|
|
643
678
|
contexto_climatico = obter_contexto_climatico_por_coordenadas(request.lat, request.lon, request.days)
|
|
644
679
|
|
|
645
|
-
# Gera relatório
|
|
646
|
-
# TODO: Atualizar report_generator para aceitar contexto climático
|
|
680
|
+
# Gera relatório com contexto climático integrado
|
|
647
681
|
caminho = gerar_relatorio_completo(
|
|
648
682
|
culturas, talhoes, regras,
|
|
649
683
|
objetivo=request.objetivo,
|
|
650
|
-
formato=request.formato
|
|
684
|
+
formato=request.formato,
|
|
685
|
+
contexto_climatico=contexto_climatico
|
|
651
686
|
)
|
|
652
687
|
|
|
653
688
|
# Lê conteúdo
|
|
654
689
|
with open(caminho, 'r', encoding='utf-8') as f:
|
|
655
690
|
conteudo = f.read()
|
|
656
691
|
|
|
657
|
-
# Adiciona informações climáticas ao final se disponível
|
|
658
|
-
if contexto_climatico and not contexto_climatico.get("fallback", True):
|
|
659
|
-
clima_info = f"""
|
|
660
|
-
|
|
661
|
-
## Dados Climáticos Reais
|
|
662
|
-
|
|
663
|
-
**Fonte:** {contexto_climatico.get('fonte', 'N/A')}
|
|
664
|
-
**Temperatura Média:** {contexto_climatico.get('temperatura_media', 'N/A')}°C
|
|
665
|
-
**Precipitação Total:** {contexto_climatico.get('precipitacao_total', 'N/A')}mm
|
|
666
|
-
**Risco Climático:** {contexto_climatico.get('risco_climatico_estimado', 'N/A')}
|
|
667
|
-
**Clima Observado:** {contexto_climatico.get('clima_observado', 'N/A')}
|
|
668
|
-
**Água Observada:** {contexto_climatico.get('agua_observada', 'N/A')}
|
|
669
|
-
**Ajuste de Risco:** {contexto_climatico.get('ajuste_risco', 0):+.1%}
|
|
670
|
-
|
|
671
|
-
*Dados climáticos integrados ao planejamento para maior precisão.*
|
|
672
|
-
"""
|
|
673
|
-
conteudo += clima_info
|
|
674
|
-
|
|
675
692
|
resultado = {
|
|
676
693
|
"caminho": caminho,
|
|
677
694
|
"conteudo": conteudo,
|
|
@@ -28,11 +28,15 @@ def classificar_agua_por_precipitacao(precipitacao_total: Optional[float]) -> Op
|
|
|
28
28
|
return "media"
|
|
29
29
|
|
|
30
30
|
def calcular_ajuste_risco_climatico(risco_climatico: str) -> float:
|
|
31
|
-
"""Calcula ajuste de risco baseado no risco climático estimado
|
|
31
|
+
"""Calcula ajuste de risco baseado no risco climático estimado
|
|
32
|
+
|
|
33
|
+
Retorna ajuste em pontos percentuais (não decimal)
|
|
34
|
+
Exemplo: retorna 15 para +15 pontos percentuais, não 0.15
|
|
35
|
+
"""
|
|
32
36
|
ajustes = {
|
|
33
|
-
"alto":
|
|
34
|
-
"medio":
|
|
35
|
-
"baixo": -
|
|
37
|
+
"alto": 15, # +15 pontos percentuais
|
|
38
|
+
"medio": 5, # +5 pontos percentuais
|
|
39
|
+
"baixo": -3, # -3 pontos percentuais (leve benefício)
|
|
36
40
|
"indeterminado": 0
|
|
37
41
|
}
|
|
38
42
|
return ajustes.get(risco_climatico, 0)
|
|
@@ -62,33 +66,66 @@ def criar_contexto_climatico(weather_summary: WeatherSummary) -> Dict[str, Any]:
|
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
def aplicar_contexto_climatico_no_plano(resultado_ag: Dict[str, Any], contexto_climatico: Dict[str, Any]) -> Dict[str, Any]:
|
|
65
|
-
"""Aplica ajustes climáticos no resultado do algoritmo genético
|
|
69
|
+
"""Aplica ajustes climáticos no resultado do algoritmo genético
|
|
70
|
+
|
|
71
|
+
O risco no sistema está em formato de pontos percentuais (30 = 30%, não 0.30)
|
|
72
|
+
"""
|
|
66
73
|
|
|
67
74
|
if not contexto_climatico or contexto_climatico.get("ajuste_risco", 0) == 0:
|
|
68
|
-
# Sem ajuste necessário
|
|
75
|
+
# Sem ajuste necessário, mas ainda adiciona contexto
|
|
69
76
|
resultado_ag["ajuste_climatico_aplicado"] = False
|
|
70
77
|
resultado_ag["contexto_climatico"] = contexto_climatico
|
|
71
78
|
return resultado_ag
|
|
72
79
|
|
|
73
|
-
ajuste_risco = contexto_climatico["ajuste_risco"]
|
|
80
|
+
ajuste_risco = contexto_climatico["ajuste_risco"] # Em pontos percentuais (ex: -3, +5, +15)
|
|
81
|
+
|
|
82
|
+
# Salvar risco médio original antes de aplicar ajustes
|
|
83
|
+
risco_medio_original = resultado_ag.get("risco_medio", 0)
|
|
84
|
+
|
|
85
|
+
# Aplicar ajuste no plano (formato padrão do gerar_plano_genetico)
|
|
86
|
+
if "plano" in resultado_ag:
|
|
87
|
+
soma_risco_area = 0
|
|
88
|
+
soma_area = 0
|
|
89
|
+
|
|
90
|
+
for item in resultado_ag["plano"]:
|
|
91
|
+
if "risco" in item and "area" in item:
|
|
92
|
+
risco_original = item["risco"] # Em pontos percentuais (ex: 30, 35, 40)
|
|
93
|
+
area = item["area"]
|
|
94
|
+
|
|
95
|
+
# Aplicar ajuste mantendo risco entre 5 e 95 pontos percentuais
|
|
96
|
+
novo_risco = min(95, max(5, risco_original + ajuste_risco))
|
|
97
|
+
|
|
98
|
+
# Salvar valores
|
|
99
|
+
item["risco_original"] = round(risco_original, 1)
|
|
100
|
+
item["risco"] = round(novo_risco, 1)
|
|
101
|
+
item["ajuste_aplicado"] = round(ajuste_risco, 1)
|
|
102
|
+
|
|
103
|
+
# Acumular para recalcular risco médio
|
|
104
|
+
soma_risco_area += novo_risco * area
|
|
105
|
+
soma_area += area
|
|
106
|
+
|
|
107
|
+
# Recalcular risco médio ponderado por área
|
|
108
|
+
if soma_area > 0:
|
|
109
|
+
novo_risco_medio = soma_risco_area / soma_area
|
|
110
|
+
resultado_ag["risco_medio_original"] = round(risco_medio_original, 1)
|
|
111
|
+
resultado_ag["risco_medio"] = round(novo_risco_medio, 1)
|
|
74
112
|
|
|
75
|
-
#
|
|
76
|
-
|
|
113
|
+
# Também suportar formato alternativo (plano_otimizado)
|
|
114
|
+
elif "plano_otimizado" in resultado_ag:
|
|
77
115
|
for item in resultado_ag["plano_otimizado"]:
|
|
78
116
|
if "risco" in item:
|
|
79
117
|
risco_original = item["risco"]
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
item["risco"] = round(novo_risco,
|
|
83
|
-
item["
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
resultado_ag["metricas"]["risco_medio_original"] = risco_original
|
|
118
|
+
novo_risco = min(95, max(5, risco_original + ajuste_risco))
|
|
119
|
+
item["risco_original"] = round(risco_original, 1)
|
|
120
|
+
item["risco"] = round(novo_risco, 1)
|
|
121
|
+
item["ajuste_aplicado"] = round(ajuste_risco, 1)
|
|
122
|
+
|
|
123
|
+
# Recalcular métricas se existirem
|
|
124
|
+
if "metricas" in resultado_ag and "risco_medio" in resultado_ag["metricas"]:
|
|
125
|
+
risco_original = resultado_ag["metricas"]["risco_medio"]
|
|
126
|
+
novo_risco = min(95, max(5, risco_original + ajuste_risco))
|
|
127
|
+
resultado_ag["metricas"]["risco_medio_original"] = round(risco_original, 1)
|
|
128
|
+
resultado_ag["metricas"]["risco_medio"] = round(novo_risco, 1)
|
|
92
129
|
|
|
93
130
|
# Marcar que ajuste foi aplicado
|
|
94
131
|
resultado_ag["ajuste_climatico_aplicado"] = True
|
|
@@ -85,7 +85,7 @@ def get_objetivo_description(objetivo):
|
|
|
85
85
|
return descriptions.get(objetivo, "otimizou múltiplos critérios")
|
|
86
86
|
|
|
87
87
|
|
|
88
|
-
def gerar_relatorio_completo(culturas, talhoes, regras, objetivo='equilibrado', formato='md'):
|
|
88
|
+
def gerar_relatorio_completo(culturas, talhoes, regras, objetivo='equilibrado', formato='md', contexto_climatico=None):
|
|
89
89
|
"""
|
|
90
90
|
Gera relatório completo do sistema
|
|
91
91
|
|
|
@@ -95,6 +95,7 @@ def gerar_relatorio_completo(culturas, talhoes, regras, objetivo='equilibrado',
|
|
|
95
95
|
regras: DataFrame com regras
|
|
96
96
|
objetivo: objetivo do AG
|
|
97
97
|
formato: 'md' ou 'txt'
|
|
98
|
+
contexto_climatico: Dicionário com dados climáticos reais (opcional)
|
|
98
99
|
|
|
99
100
|
Returns:
|
|
100
101
|
Caminho do arquivo gerado
|
|
@@ -104,7 +105,13 @@ def gerar_relatorio_completo(culturas, talhoes, regras, objetivo='equilibrado',
|
|
|
104
105
|
cenarios = gerar_cenarios(culturas, talhoes, regras)
|
|
105
106
|
|
|
106
107
|
print(" 🧬 Executando Algoritmo Genético...")
|
|
107
|
-
|
|
108
|
+
# Aplicar contexto climático se disponível
|
|
109
|
+
if contexto_climatico:
|
|
110
|
+
from core.climate_adapter import aplicar_contexto_climatico_no_plano
|
|
111
|
+
resultado_ag = gerar_plano_genetico(culturas, talhoes, regras, objetivo, seed=42)
|
|
112
|
+
resultado_ag = aplicar_contexto_climatico_no_plano(resultado_ag, contexto_climatico)
|
|
113
|
+
else:
|
|
114
|
+
resultado_ag = gerar_plano_genetico(culturas, talhoes, regras, objetivo, seed=42)
|
|
108
115
|
|
|
109
116
|
print(" 🔬 Validando com força bruta...")
|
|
110
117
|
validacao = comparar_ag_com_forca_bruta(culturas, talhoes, regras, objetivo, seed=42)
|
|
@@ -126,6 +133,11 @@ def gerar_relatorio_completo(culturas, talhoes, regras, objetivo='equilibrado',
|
|
|
126
133
|
)
|
|
127
134
|
extensao = 'txt'
|
|
128
135
|
|
|
136
|
+
# Adicionar seção climática se disponível
|
|
137
|
+
if contexto_climatico:
|
|
138
|
+
secao_clima = gerar_secao_climatica(contexto_climatico, formato)
|
|
139
|
+
conteudo += "\n\n" + secao_clima
|
|
140
|
+
|
|
129
141
|
# Salva arquivo
|
|
130
142
|
os.makedirs('reports', exist_ok=True)
|
|
131
143
|
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
|
@@ -138,6 +150,74 @@ def gerar_relatorio_completo(culturas, talhoes, regras, objetivo='equilibrado',
|
|
|
138
150
|
return caminho
|
|
139
151
|
|
|
140
152
|
|
|
153
|
+
def gerar_secao_climatica(contexto_climatico, formato='md'):
|
|
154
|
+
"""Gera seção de dados climáticos para o relatório"""
|
|
155
|
+
if not contexto_climatico or contexto_climatico.get("fallback", True):
|
|
156
|
+
if formato == 'md':
|
|
157
|
+
return "## Dados Climáticos\n\nEste relatório foi gerado com base nos dados internos simulados."
|
|
158
|
+
else:
|
|
159
|
+
return "DADOS CLIMÁTICOS\n\nEste relatório foi gerado com base nos dados internos simulados."
|
|
160
|
+
|
|
161
|
+
if formato == 'md':
|
|
162
|
+
secao = "## Dados Climáticos Reais Utilizados\n\n"
|
|
163
|
+
secao += f"**Fonte:** {contexto_climatico.get('fonte', 'N/A')}\n\n"
|
|
164
|
+
|
|
165
|
+
if contexto_climatico.get('temperatura_media'):
|
|
166
|
+
secao += f"**Temperatura Média:** {contexto_climatico['temperatura_media']:.1f}°C\n\n"
|
|
167
|
+
if contexto_climatico.get('temperatura_maxima'):
|
|
168
|
+
secao += f"**Temperatura Máxima:** {contexto_climatico['temperatura_maxima']:.1f}°C\n\n"
|
|
169
|
+
if contexto_climatico.get('temperatura_minima'):
|
|
170
|
+
secao += f"**Temperatura Mínima:** {contexto_climatico['temperatura_minima']:.1f}°C\n\n"
|
|
171
|
+
if contexto_climatico.get('precipitacao_total'):
|
|
172
|
+
secao += f"**Precipitação Total (30 dias):** {contexto_climatico['precipitacao_total']:.1f}mm\n\n"
|
|
173
|
+
if contexto_climatico.get('risco_climatico_estimado'):
|
|
174
|
+
secao += f"**Risco Climático Estimado:** {contexto_climatico['risco_climatico_estimado']}\n\n"
|
|
175
|
+
if contexto_climatico.get('clima_observado'):
|
|
176
|
+
secao += f"**Clima Observado:** {contexto_climatico['clima_observado']}\n\n"
|
|
177
|
+
if contexto_climatico.get('agua_observada'):
|
|
178
|
+
secao += f"**Disponibilidade Hídrica:** {contexto_climatico['agua_observada']}\n\n"
|
|
179
|
+
if contexto_climatico.get('ajuste_risco') is not None:
|
|
180
|
+
ajuste = contexto_climatico['ajuste_risco']
|
|
181
|
+
sinal = '+' if ajuste > 0 else ''
|
|
182
|
+
secao += f"**Ajuste de Risco Aplicado:** {sinal}{ajuste} pontos percentuais\n\n"
|
|
183
|
+
|
|
184
|
+
secao += "**Impacto no Planejamento:**\n\n"
|
|
185
|
+
secao += "Os dados climáticos reais foram integrados ao algoritmo de otimização, "
|
|
186
|
+
secao += "ajustando automaticamente os níveis de risco de cada cultura com base nas "
|
|
187
|
+
secao += "condições meteorológicas observadas. Este ajuste proporciona maior precisão "
|
|
188
|
+
secao += "nas recomendações de plantio.\n"
|
|
189
|
+
else:
|
|
190
|
+
secao = "DADOS CLIMÁTICOS REAIS UTILIZADOS\n\n"
|
|
191
|
+
secao += f"Fonte: {contexto_climatico.get('fonte', 'N/A')}\n\n"
|
|
192
|
+
|
|
193
|
+
if contexto_climatico.get('temperatura_media'):
|
|
194
|
+
secao += f"Temperatura Média: {contexto_climatico['temperatura_media']:.1f}°C\n"
|
|
195
|
+
if contexto_climatico.get('temperatura_maxima'):
|
|
196
|
+
secao += f"Temperatura Máxima: {contexto_climatico['temperatura_maxima']:.1f}°C\n"
|
|
197
|
+
if contexto_climatico.get('temperatura_minima'):
|
|
198
|
+
secao += f"Temperatura Mínima: {contexto_climatico['temperatura_minima']:.1f}°C\n"
|
|
199
|
+
if contexto_climatico.get('precipitacao_total'):
|
|
200
|
+
secao += f"Precipitação Total (30 dias): {contexto_climatico['precipitacao_total']:.1f}mm\n"
|
|
201
|
+
if contexto_climatico.get('risco_climatico_estimado'):
|
|
202
|
+
secao += f"Risco Climático Estimado: {contexto_climatico['risco_climatico_estimado']}\n"
|
|
203
|
+
if contexto_climatico.get('clima_observado'):
|
|
204
|
+
secao += f"Clima Observado: {contexto_climatico['clima_observado']}\n"
|
|
205
|
+
if contexto_climatico.get('agua_observada'):
|
|
206
|
+
secao += f"Disponibilidade Hídrica: {contexto_climatico['agua_observada']}\n"
|
|
207
|
+
if contexto_climatico.get('ajuste_risco') is not None:
|
|
208
|
+
ajuste = contexto_climatico['ajuste_risco']
|
|
209
|
+
sinal = '+' if ajuste > 0 else ''
|
|
210
|
+
secao += f"Ajuste de Risco Aplicado: {sinal}{ajuste} pontos percentuais\n"
|
|
211
|
+
|
|
212
|
+
secao += "\nImpacto no Planejamento:\n\n"
|
|
213
|
+
secao += "Os dados climáticos reais foram integrados ao algoritmo de otimização, "
|
|
214
|
+
secao += "ajustando automaticamente os níveis de risco de cada cultura com base nas "
|
|
215
|
+
secao += "condições meteorológicas observadas. Este ajuste proporciona maior precisão "
|
|
216
|
+
secao += "nas recomendações de plantio.\n"
|
|
217
|
+
|
|
218
|
+
return secao
|
|
219
|
+
|
|
220
|
+
|
|
141
221
|
def gerar_relatorio_markdown(culturas, talhoes, regras, objetivo, cenarios, resultado_ag, validacao, estabilidade):
|
|
142
222
|
"""Gera relatório em formato Markdown"""
|
|
143
223
|
|
|
@@ -417,8 +497,8 @@ def gerar_relatorio_markdown(culturas, talhoes, regras, objetivo, cenarios, resu
|
|
|
417
497
|
md.append("1. **Dados Simulados:** Os dados atuais são estimativas, não medições reais de campo")
|
|
418
498
|
md.append("2. **Modelo Simplificado:** Não considera todos os fatores agronômicos (pragas, doenças, mercado local)")
|
|
419
499
|
md.append("3. **Sem Análise Laboratorial:** Não utiliza análise química e física do solo")
|
|
420
|
-
md.append("4. **
|
|
421
|
-
md.append("5. **Sem Preços de Mercado Reais:**
|
|
500
|
+
md.append("4. **Dados Climáticos Regionais:** O sistema já utiliza dados climáticos reais via Open-Meteo, mas ainda trabalha em escala regional, sem análise individualizada por polígono/talhão real")
|
|
501
|
+
md.append("5. **Sem Preços de Mercado Reais:** Ainda utiliza preços simulados, sem integração com cotações oficiais como Conab/CEPEA")
|
|
422
502
|
md.append("6. **Não Substitui Agrônomo:** As recomendações devem ser validadas por profissional qualificado")
|
|
423
503
|
md.append("")
|
|
424
504
|
md.append("**Recomendação:** Use este sistema como ferramenta de apoio à decisão, não como decisão final.")
|
|
@@ -429,25 +509,19 @@ def gerar_relatorio_markdown(culturas, talhoes, regras, objetivo, cenarios, resu
|
|
|
429
509
|
# 9. Próximas Evoluções
|
|
430
510
|
md.append("## 9. 🚀 Próximas Evoluções")
|
|
431
511
|
md.append("")
|
|
432
|
-
md.append("###
|
|
433
|
-
md.append("-
|
|
434
|
-
md.append("-
|
|
435
|
-
md.append("-
|
|
436
|
-
md.append("-
|
|
437
|
-
md.append("")
|
|
438
|
-
md.append("### Fase 6 - Integração com APIs Reais")
|
|
439
|
-
md.append("- Dados climáticos (INMET, OpenWeather)")
|
|
440
|
-
md.append("- Preços de mercado (CEPEA, CONAB)")
|
|
441
|
-
md.append("- Análise de solo (laboratórios)")
|
|
442
|
-
md.append("- Imagens de satélite")
|
|
512
|
+
md.append("### Próximas Integrações de Dados Reais")
|
|
513
|
+
md.append("- **ZARC:** Zoneamento Agrícola de Risco Climático (dados oficiais MAPA)")
|
|
514
|
+
md.append("- **Preços Agrícolas:** Integração com Conab/CEPEA para cotações oficiais")
|
|
515
|
+
md.append("- **Dados Agroclimáticos:** NASA POWER para radiação solar e evapotranspiração")
|
|
516
|
+
md.append("- **Análise Geográfica:** Análise individualizada por propriedade/talhão em fase futura")
|
|
443
517
|
md.append("")
|
|
444
|
-
md.append("###
|
|
518
|
+
md.append("### Machine Learning")
|
|
445
519
|
md.append("- Previsão de produtividade")
|
|
446
520
|
md.append("- Previsão de preços")
|
|
447
521
|
md.append("- Detecção de anomalias")
|
|
448
522
|
md.append("- Recomendação personalizada")
|
|
449
523
|
md.append("")
|
|
450
|
-
md.append("###
|
|
524
|
+
md.append("### Sistema Completo")
|
|
451
525
|
md.append("- Cadastro de propriedades")
|
|
452
526
|
md.append("- Gestão de usuários")
|
|
453
527
|
md.append("- Histórico de safras")
|
|
@@ -739,8 +813,11 @@ def gerar_relatorio_txt(culturas, talhoes, regras, objetivo, cenarios, resultado
|
|
|
739
813
|
txt.append("1. Dados Simulados: Os dados atuais são estimativas, não medições reais")
|
|
740
814
|
txt.append("2. Modelo Simplificado: Não considera todos os fatores agronômicos")
|
|
741
815
|
txt.append("3. Sem Análise Laboratorial: Não utiliza análise química e física do solo")
|
|
742
|
-
txt.append("4.
|
|
743
|
-
txt.append("
|
|
816
|
+
txt.append("4. Dados Climáticos Regionais: O sistema já utiliza dados climáticos reais")
|
|
817
|
+
txt.append(" via Open-Meteo, mas ainda trabalha em escala regional, sem análise")
|
|
818
|
+
txt.append(" individualizada por polígono/talhão real")
|
|
819
|
+
txt.append("5. Sem Preços de Mercado Reais: Ainda utiliza preços simulados, sem")
|
|
820
|
+
txt.append(" integração com cotações oficiais como Conab/CEPEA")
|
|
744
821
|
txt.append("6. Não Substitui Agrônomo: As recomendações devem ser validadas")
|
|
745
822
|
txt.append("")
|
|
746
823
|
txt.append("RECOMENDAÇÃO: Use este sistema como ferramenta de apoio à decisão,")
|