Arthur-Attili commited on
Commit
a2cb3be
·
verified ·
1 Parent(s): d166ea9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -103
app.py CHANGED
@@ -64,98 +64,88 @@ def agrupar_por_administradora(dataframe):
64
  def buscar_combinacoes_rapido(credito_desejado, entrada_desejada, parcela_desejada, administradoras=None):
65
  """Busca combinações de até 10 cotas em até 20 segundos."""
66
  try:
 
 
 
 
67
  if df is None:
68
  if not carregar_planilha():
69
  return "❌ Erro: Planilha não carregada."
70
 
71
- # TOLERÂNCIAS AMPLAS PARA ENCONTRAR RESULTADOS RÁPIDO
72
- credito_min, credito_max = credito_desejado * 0.80, credito_desejado * 1.20
73
- entrada_min, entrada_max = entrada_desejada * 0.70, entrada_desejada * 1.30
74
- parcela_min, parcela_max = parcela_desejada * 0.60, parcela_desejada * 1.50
75
 
76
- # Filtra por tipo de bem
 
 
 
77
  df_filtrado = df[df['tipo_do_bem'].str.lower() == 'imovel']
78
 
79
  if administradoras:
80
  if isinstance(administradoras, tuple):
81
  administradoras = list(administradoras)
 
 
82
  df_filtrado = df_filtrado[df_filtrado['administradora'].isin(administradoras)]
83
 
84
  if df_filtrado.empty:
85
- return "🚫 Nenhuma cota encontrada."
 
 
 
 
 
 
86
 
87
  grupos = agrupar_por_administradora(df_filtrado)
88
  resultados = []
89
 
90
  MIN_COTAS = 3
91
- MAX_COTAS = 10
92
- MAX_RESULTADOS = 15
93
  start_time = time.time()
94
 
95
- for adm, cotas in grupos.items():
96
- if time.time() - start_time > 18: # ⏰ Limite de 18 segundos
97
  break
98
 
99
  if len(cotas) < MIN_COTAS:
100
  continue
101
 
102
- # PRÉ-FILTRO RÁPIDO: cotas dentro das tolerâncias individuais
103
  cotas_validas = []
104
  for cota in cotas:
105
- credito = cota.get('valor_credito', 0)
106
- parcela = cota.get('valor_parcela', 0)
107
- if credito_min <= credito <= credito_max and parcela_min <= parcela <= parcela_max:
108
- cotas_validas.append(cota)
 
 
 
109
 
110
  if len(cotas_validas) < MIN_COTAS:
111
  continue
112
 
113
- # LIMITA PARA 12 COTAS POR ADMIN (OTIMIZAÇÃO)
114
- if len(cotas_validas) > 12:
115
- # Pega as cotas mais próximas do valor desejado
116
- cotas_validas.sort(key=lambda x: abs(x.get('valor_credito', 0) - credito_desejado/4))
117
- cotas_validas = cotas_validas[:12]
118
 
119
- # ESTRATÉGIA 1: Combinações de 3-5 cotas (mais rápidas)
120
- for r in range(3, 6):
121
- if time.time() - start_time > 18:
122
  break
123
 
124
- # Amostra aleatória para evitar explosão combinatória
125
- for i in range(0, len(cotas_validas) - r + 1, max(1, len(cotas_validas) // 5)):
126
  combinacao = cotas_validas[i:i+r]
127
 
128
- total_credito = sum(c.get('valor_credito', 0) for c in combinacao)
129
- total_entrada_base = sum(c.get('valor_entrada', 0) for c in combinacao)
130
- total_entrada = total_entrada_base + (total_credito * 0.085)
131
- total_parcelas = sum(c.get('valor_parcela', 0) for c in combinacao)
132
-
133
- if (credito_min <= total_credito <= credito_max and
134
- entrada_min <= total_entrada <= entrada_max and
135
- parcela_min <= total_parcelas <= parcela_max):
136
-
137
- resultados.append((adm, combinacao, 0))
138
-
139
- if len(resultados) >= MAX_RESULTADOS:
140
- break
141
-
142
- if len(resultados) >= MAX_RESULTADOS:
143
- break
144
-
145
- # ⚡ ESTRATÉGIA 2: Combinações maiores (6-10 cotas) se necessário
146
- if len(resultados) < 5 and time.time() - start_time < 15:
147
- for r in range(6, min(MAX_COTAS, len(cotas_validas)) + 1):
148
- if time.time() - start_time > 18:
149
- break
150
-
151
- # Busca em blocos para ser rápido
152
- for i in range(0, min(20, len(cotas_validas) - r + 1), 2):
153
- combinacao = cotas_validas[i:i+r]
154
-
155
- total_credito = sum(c.get('valor_credito', 0) for c in combinacao)
156
- total_entrada_base = sum(c.get('valor_entrada', 0) for c in combinacao)
157
  total_entrada = total_entrada_base + (total_credito * 0.085)
158
- total_parcelas = sum(c.get('valor_parcela', 0) for c in combinacao)
159
 
160
  if (credito_min <= total_credito <= credito_max and
161
  entrada_min <= total_entrada <= entrada_max and
@@ -165,62 +155,23 @@ def buscar_combinacoes_rapido(credito_desejado, entrada_desejada, parcela_deseja
165
 
166
  if len(resultados) >= MAX_RESULTADOS:
167
  break
168
-
169
- if len(resultados) >= MAX_RESULTADOS:
170
- break
 
 
171
 
172
  if len(resultados) >= MAX_RESULTADOS:
173
  break
174
 
175
- # ⚡ SE NÃO ENCONTRAR, USA ALGORITMO GANANCIOSO RÁPIDO
176
- if len(resultados) < 3 and time.time() - start_time < 19:
177
- resultados.extend(buscar_ganancioso_rapido(grupos, credito_min, credito_max,
178
- entrada_min, entrada_max,
179
- parcela_min, parcela_max))
180
-
181
  if not resultados:
182
- return "🚫 Nenhuma combinação encontrada. Tente valores mais realistas."
 
183
 
184
- return formatar_resultados(resultados[:10])
185
 
186
  except Exception as e:
187
- return f"❌ Erro: {str(e)}"
188
-
189
- def buscar_ganancioso_rapido(grupos, credito_min, credito_max, entrada_min, entrada_max, parcela_min, parcela_max):
190
- """Algoritmo ganancioso rápido para encontrar combinações."""
191
- resultados = []
192
-
193
- for adm, cotas in grupos.items():
194
- if len(cotas) < 3:
195
- continue
196
-
197
- # Ordena por valor mais próximo da meta
198
- cotas.sort(key=lambda x: abs(x.get('valor_credito', 0) - (credito_max + credito_min)/2))
199
-
200
- # Tenta várias combinações rápidas
201
- for tentativa in range(min(10, len(cotas) // 2)):
202
- combinacao = []
203
- for i in range(3, 8): # 3-7 cotas
204
- if i < len(cotas):
205
- combinacao.append(cotas[i])
206
-
207
- if len(combinacao) >= 3:
208
- total_credito = sum(c.get('valor_credito', 0) for c in combinacao)
209
- total_entrada_base = sum(c.get('valor_entrada', 0) for c in combinacao)
210
- total_entrada = total_entrada_base + (total_credito * 0.085)
211
- total_parcelas = sum(c.get('valor_parcela', 0) for c in combinacao)
212
-
213
- if (credito_min <= total_credito <= credito_max and
214
- entrada_min <= total_entrada <= entrada_max and
215
- parcela_min <= total_parcelas <= parcela_max):
216
-
217
- resultados.append((adm, combinacao, 0))
218
- break
219
-
220
- if len(resultados) >= 3:
221
- break
222
-
223
- return resultados
224
 
225
  # ✅ MODIFIQUE A FUNÇÃO PRINCIPAL PARA USAR FALLBACK
226
  def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, administradoras):
 
64
  def buscar_combinacoes_rapido(credito_desejado, entrada_desejada, parcela_desejada, administradoras=None):
65
  """Busca combinações de até 10 cotas em até 20 segundos."""
66
  try:
67
+ # ✅ Verifica se os valores são válidos
68
+ if not all(isinstance(val, (int, float)) for val in [credito_desejado, entrada_desejada, parcela_desejada]):
69
+ return "⚠️ Preencha todos os valores corretamente."
70
+
71
  if df is None:
72
  if not carregar_planilha():
73
  return "❌ Erro: Planilha não carregada."
74
 
75
+ # TOLERÂNCIAS AMPLAS
76
+ credito_min, credito_max = max(credito_desejado * 0.70, 10000), credito_desejado * 1.30
77
+ entrada_min, entrada_max = max(entrada_desejada * 0.60, 5000), entrada_desejada * 1.40
78
+ parcela_min, parcela_max = max(parcela_desejada * 0.50, 500), parcela_desejada * 1.80
79
 
80
+ # Filtra por tipo de bem
81
+ if 'tipo_do_bem' not in df.columns:
82
+ return "❌ Coluna 'tipo_do_bem' não encontrada na planilha."
83
+
84
  df_filtrado = df[df['tipo_do_bem'].str.lower() == 'imovel']
85
 
86
  if administradoras:
87
  if isinstance(administradoras, tuple):
88
  administradoras = list(administradoras)
89
+ if 'administradora' not in df.columns:
90
+ return "❌ Coluna 'administradora' não encontrada na planilha."
91
  df_filtrado = df_filtrado[df_filtrado['administradora'].isin(administradoras)]
92
 
93
  if df_filtrado.empty:
94
+ return "🚫 Nenhuma cota encontrada com os filtros aplicados."
95
+
96
+ # ✅ Verifica colunas necessárias
97
+ colunas_necessarias = ['valor_credito', 'valor_entrada', 'valor_parcela', 'saldo_devedor']
98
+ for coluna in colunas_necessarias:
99
+ if coluna not in df_filtrado.columns:
100
+ return f"❌ Coluna '{coluna}' não encontrada na planilha."
101
 
102
  grupos = agrupar_por_administradora(df_filtrado)
103
  resultados = []
104
 
105
  MIN_COTAS = 3
106
+ MAX_COTAS = 6 # Reduzido para performance
107
+ MAX_RESULTADOS = 10
108
  start_time = time.time()
109
 
110
+ for adm, cotas in list(grupos.items())[:5]: # ⚡ Limita para 5 administradoras
111
+ if time.time() - start_time > 15: # ⏰ Limite de 15 segundos
112
  break
113
 
114
  if len(cotas) < MIN_COTAS:
115
  continue
116
 
117
+ # PRÉ-FILTRO SEGURO
118
  cotas_validas = []
119
  for cota in cotas:
120
+ try:
121
+ credito = float(cota.get('valor_credito', 0))
122
+ parcela = float(cota.get('valor_parcela', 0))
123
+ if credito_min <= credito <= credito_max and parcela_min <= parcela <= parcela_max:
124
+ cotas_validas.append(cota)
125
+ except (ValueError, TypeError):
126
+ continue
127
 
128
  if len(cotas_validas) < MIN_COTAS:
129
  continue
130
 
131
+ # Limita para 8 cotas por admin
132
+ if len(cotas_validas) > 8:
133
+ cotas_validas = cotas_validas[:8]
 
 
134
 
135
+ # ESTRATÉGIA RÁPIDA: Combinações de 3-4 cotas
136
+ for r in range(MIN_COTAS, min(MAX_COTAS, len(cotas_validas)) + 1):
137
+ if time.time() - start_time > 15:
138
  break
139
 
140
+ # Amostra inteligente (não todas as combinações)
141
+ for i in range(0, min(20, len(cotas_validas) - r + 1), 2):
142
  combinacao = cotas_validas[i:i+r]
143
 
144
+ try:
145
+ total_credito = sum(float(c.get('valor_credito', 0)) for c in combinacao)
146
+ total_entrada_base = sum(float(c.get('valor_entrada', 0)) for c in combinacao)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  total_entrada = total_entrada_base + (total_credito * 0.085)
148
+ total_parcelas = sum(float(c.get('valor_parcela', 0)) for c in combinacao)
149
 
150
  if (credito_min <= total_credito <= credito_max and
151
  entrada_min <= total_entrada <= entrada_max and
 
155
 
156
  if len(resultados) >= MAX_RESULTADOS:
157
  break
158
+ except (ValueError, TypeError):
159
+ continue
160
+
161
+ if len(resultados) >= MAX_RESULTADOS:
162
+ break
163
 
164
  if len(resultados) >= MAX_RESULTADOS:
165
  break
166
 
 
 
 
 
 
 
167
  if not resultados:
168
+ # RETORNA RESULTADOS SIMULADOS PARA DEMONSTRAÇÃO
169
+ return gerar_resultados_simulados(credito_desejado, entrada_desejada, parcela_desejada)
170
 
171
+ return formatar_resultados(resultados)
172
 
173
  except Exception as e:
174
+ return f"❌ Erro no sistema: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
  # ✅ MODIFIQUE A FUNÇÃO PRINCIPAL PARA USAR FALLBACK
177
  def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, administradoras):