Arthur-Attili commited on
Commit
76525e5
·
verified ·
1 Parent(s): 543325c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -135
app.py CHANGED
@@ -92,43 +92,18 @@ def buscar_combinacoes_otimizado(credito_desejado, entrada_desejada, parcela_des
92
 
93
  print(f"🔍 Total de administradoras no filtro: {len(grupos_filtrados)}")
94
 
95
- # ANÁLISE DAS COTAS DISPONÍVEIS - CRÍTICO PARA VALORES ALTOS
96
- todas_cotas = []
97
- for adm, cotas in grupos_filtrados.items():
98
- todas_cotas.extend(cotas)
99
- print(f"📊 {adm}: {len(cotas)} cotas")
100
-
101
- if not todas_cotas:
102
- return "🚫 Nenhuma cota disponível para análise."
103
-
104
- # Calcula estatísticas das cotas
105
- creditos = [c['valor_credito'] for c in todas_cotas]
106
- max_credito = max(creditos)
107
- avg_credito = sum(creditos) / len(creditos)
108
-
109
- print(f"📊 Estatísticas das cotas disponíveis:")
110
- print(f"📊 Maior crédito individual: R$ {max_credito:,.2f}")
111
- print(f"📊 Crédito médio: R$ {avg_credito:,.2f}")
112
- print(f"📊 Total de cotas: {len(todas_cotas)}")
113
-
114
- # TOLERÂNCIAS INTELIGENTES BASEADAS NAS ESTATÍSTICAS
115
- # Para valores muito altos, aumentamos significativamente as tolerâncias
116
- if credito_desejado > 1000000: # Acima de 1 milhão
117
- # Quanto maior o valor, maior a tolerância necessária
118
- fator_ajuste = min(1.0, credito_desejado / 5000000) # Normaliza entre 0 e 1
119
-
120
- tolerancia_credito = 0.20 + (0.30 * fator_ajuste) # 20% a 50%
121
- tolerancia_entrada = 0.20 + (0.25 * fator_ajuste) # 20% a 45%
122
- tolerancia_parcela = 0.40 + (0.40 * fator_ajuste) # 40% a 80%
123
-
124
- # Ajusta número máximo de cotas baseado na necessidade
125
- cotas_estimadas = max(3, min(10, math.ceil(credito_desejado / avg_credito)))
126
- max_cotas_combinacao = min(12, cotas_estimadas + 3)
127
  else:
128
- tolerancia_credito = 0.10
129
- tolerancia_entrada = 0.10
130
- tolerancia_parcela = 0.30
131
- max_cotas_combinacao = 4
132
 
133
  # Define faixas de tolerância
134
  credito_min = credito_desejado * (1 - tolerancia_credito)
@@ -145,32 +120,29 @@ def buscar_combinacoes_otimizado(credito_desejado, entrada_desejada, parcela_des
145
  print(f"🔧 Faixas aceitáveis: Parcela: R$ {parcela_min:,.2f} - R$ {parcela_max:,.2f}")
146
  print(f"🔧 Máximo de cotas por combinação: {max_cotas_combinacao}")
147
 
148
- # ESTRATÉGIA DE BUSCA OTIMIZADA PARA VALORES ALTOS
149
  resultados = []
 
150
 
151
- # 1. PRIMEIRO: busca combinações progressivas por número de cotas
152
- for num_cotas in range(1, max_cotas_combinacao + 1):
153
- if len(resultados) >= max_combinacoes:
154
- break
155
-
156
- print(f"🔍 Buscando combinações com {num_cotas} cota(s)...")
157
 
158
- for adm, cotas in grupos_filtrados.items():
159
- if len(resultados) >= max_combinacoes:
160
- break
161
-
162
- # Para valores altos, prioriza cotas maiores primeiro
163
- cotas_ordenadas = sorted(cotas, key=lambda x: x['valor_credito'], reverse=True)
164
-
165
- # Limita o número de testes por administradora
166
- max_testes = 150
167
- testes_realizados = 0
168
 
169
- for combinacao in itertools.combinations(cotas_ordenadas, num_cotas):
170
- if testes_realizados >= max_testes:
171
  break
172
 
173
- testes_realizados += 1
 
174
 
175
  total_credito = sum(c['valor_credito'] for c in combinacao)
176
  total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
@@ -188,28 +160,30 @@ def buscar_combinacoes_otimizado(credito_desejado, entrada_desejada, parcela_des
188
 
189
  resultados.append((adm, combinacao, diferenca))
190
 
191
- if len(resultados) >= max_combinacoes * 2:
 
192
  break
193
 
194
- if len(resultados) >= max_combinacoes * 2:
195
  break
196
 
197
- if len(resultados) >= max_combinacoes * 2:
198
  break
199
 
 
200
  print(f"🔍 Combinações válidas encontradas: {len(resultados)}")
201
 
202
- # 2. SE NÃO ENCONTROU, TENTA BUSCA COM TOLERÂNCIAS MAIS AMPLAS
203
  if not resultados:
 
204
  print("🔍 Nenhuma combinação encontrada. Tentando busca ampla...")
205
  return buscar_combinacoes_amplo(credito_desejado, entrada_desejada, parcela_desejada, administradoras, max_combinacoes)
206
 
207
- # 3. ORDENA E RETORNA OS MELHORES RESULTADOS
208
  resultados.sort(key=lambda x: x[2])
209
  return formatar_resultados(resultados[:max_combinacoes])
210
 
211
  def buscar_combinacoes_amplo(credito_desejado, entrada_desejada, parcela_desejada, administradoras=None, max_combinacoes=10):
212
- """Busca combinações com tolerâncias extremamente amplas para valores altos."""
213
  global grupos_imovel
214
 
215
  # Filtra administradoras se especificado
@@ -218,18 +192,17 @@ def buscar_combinacoes_amplo(credito_desejado, entrada_desejada, parcela_desejad
218
  else:
219
  grupos_filtrados = grupos_imovel
220
 
221
- # TOLERÂNCIAS MUITO AMPLAS ESPECIALMENTE PARA VALORES ALTOS
222
- if credito_desejado > 1000000:
223
- # Tolerâncias extremas para valores muito altos
224
- tolerancia_credito = 0.50 # 50%
225
- tolerancia_entrada = 0.50 # 50%
226
- tolerancia_parcela = 1.00 # 100%
227
- max_cotas_combinacao = 15 # Até 15 cotas por combinação
228
  else:
229
- tolerancia_credito = 0.30
230
- tolerancia_entrada = 0.30
231
- tolerancia_parcela = 0.70
232
- max_cotas_combinacao = 8
233
 
234
  credito_min = credito_desejado * (1 - tolerancia_credito)
235
  credito_max = credito_desejado * (1 + tolerancia_credito)
@@ -242,27 +215,22 @@ def buscar_combinacoes_amplo(credito_desejado, entrada_desejada, parcela_desejad
242
  print(f"🔍 BUSCA AMPLA: Máximo de cotas por combinação: {max_cotas_combinacao}")
243
 
244
  resultados = []
 
245
 
246
- # Estratégia de busca mais agressiva
247
- for num_cotas in range(2, max_cotas_combinacao + 1): # Começa com 2 cotas
248
- if len(resultados) >= max_combinacoes:
249
- break
250
-
251
- print(f"🔍 BUSCA AMPLA - Procurando com {num_cotas} cotas...")
252
 
253
- for adm, cotas in grupos_filtrados.items():
254
- if len(resultados) >= max_combinacoes:
255
- break
256
-
257
- # Testa combinações de forma mais ampla
258
- max_testes = 100
259
- testes_realizados = 0
260
 
261
- for combinacao in itertools.combinations(cotas, num_cotas):
262
- if testes_realizados >= max_testes:
263
  break
264
 
265
- testes_realizados += 1
 
266
 
267
  total_credito = sum(c['valor_credito'] for c in combinacao)
268
  total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
@@ -279,52 +247,34 @@ def buscar_combinacoes_amplo(credito_desejado, entrada_desejada, parcela_desejad
279
 
280
  resultados.append((adm, combinacao, diferenca))
281
 
282
- if len(resultados) >= max_combinacoes:
283
  break
 
 
 
 
 
 
284
 
 
285
  print(f"🔍 BUSCA AMPLA: Combinações válidas encontradas: {len(resultados)}")
286
 
287
  if not resultados:
288
- # Última tentativa: busca a combinação mais próxima possível
289
- return gerar_sugestao_mais_proxima(credito_desejado, entrada_desejada, parcela_desejada, grupos_filtrados)
290
 
291
  resultados.sort(key=lambda x: x[2])
292
  return formatar_resultados(resultados[:max_combinacoes])
293
 
294
- def gerar_sugestao_mais_proxima(credito_desejado, entrada_desejada, parcela_desejada, grupos_filtrados):
295
- """Gera sugestão da combinação mais próxima quando não encontra resultados exatos."""
296
- todas_cotas = []
297
- for cotas in grupos_filtrados.values():
298
- todas_cotas.extend(cotas)
299
-
300
- if not todas_cotas:
301
- return "🚫 Nenhuma cota disponível para análise."
302
-
303
- melhor_combinacao = None
304
- menor_diferenca = float('inf')
305
-
306
- # Testa combinações de 2 a 10 cotas
307
- for num_cotas in range(2, 11):
308
- for adm, cotas in grupos_filtrados.items():
309
- for combinacao in itertools.combinations(cotas, num_cotas):
310
- total_credito = sum(c['valor_credito'] for c in combinacao)
311
- total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
312
- total_entrada = total_entrada_base + (total_credito * 0.085)
313
- total_parcelas = sum(c['valor_parcela'] for c in combinacao)
314
-
315
- # Calcula diferenças percentuais
316
- diff_credito = abs(total_credito - credito_desejado) / credito_desejado
317
- diff_entrada = abs(total_entrada - entrada_desejada) / entrada_desejada
318
- diff_parcela = abs(total_parcelas - parcela_desejada) / parcela_desejada if parcela_desejada > 0 else 0
319
-
320
- diferenca_total = diff_credito + diff_entrada + diff_parcela
321
-
322
- if diferenca_total < menor_diferenca:
323
- menor_diferenca = diferenca_total
324
- melhor_combinacao = (adm, combinacao, diferenca_total)
325
 
326
- if melhor_combinacao:
327
- adm, combinacao, _ = melhor_combinacao
328
  codigos = [str(c.get('codigo', 'N/A')) for c in combinacao]
329
  total_credito = sum(c['valor_credito'] for c in combinacao)
330
  total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
@@ -339,24 +289,22 @@ def gerar_sugestao_mais_proxima(credito_desejado, entrada_desejada, parcela_dese
339
  taxa_percentual = (taxa_total / credito_real) * 100 if credito_real > 0 else 0
340
  taxa_mensal = taxa_percentual / maior_prazo if maior_prazo > 0 else 0
341
 
342
- return f"""
343
- ⚠️ Nenhuma combinação exata encontrada, mas aqui está a mais próxima:
344
-
345
  🏢 Administradora: {adm}
346
  🔢 Códigos: {', '.join(codigos)} ({len(combinacao)} cotas)
347
- 💰 Crédito Total: {formatar_moeda(total_credito)} (Desejado: {formatar_moeda(credito_desejado)})
348
- 💵 Entrada: {formatar_moeda(total_entrada)} (Desejado: {formatar_moeda(entrada_desejada)})
349
- 💲 Parcela: {formatar_moeda(total_parcelas)} (Desejado: {formatar_moeda(parcela_desejada)})
350
  📉 Saldo Devedor: {formatar_moeda(total_saldo)}
 
351
  ⏳ Prazo: {maior_prazo} meses
352
  🔚 Valor Final: {formatar_moeda(valor_final)}
353
  💠 Crédito Líquido: {formatar_moeda(credito_real)}
354
  📊 Taxa Total: {taxa_percentual:.2f}% ({formatar_moeda(taxa_total)})
355
-
356
- 💡 Sugestão: Ajuste seus parâmetros ou considere múltiplas administradoras.
357
  """
358
-
359
- return "🚫 Nenhuma combinação adequada encontrada com os parâmetros fornecidos."
360
 
361
  # Carrega a planilha uma vez quando o aplicativo inicia
362
  carregar_planilha()
 
92
 
93
  print(f"🔍 Total de administradoras no filtro: {len(grupos_filtrados)}")
94
 
95
+ # TOLERÂNCIAS - Ajustadas para valores altos
96
+ # Para valores muito altos, aumentamos as tolerâncias
97
+ if credito_desejado > 5000000: # Para valores acima de 5 milhões
98
+ tolerancia_credito = 0.15 # 15%
99
+ tolerancia_entrada = 0.15 # 15%
100
+ tolerancia_parcela = 0.40 # 40%
101
+ max_cotas_combinacao = 6 # Até 6 cotas por combinação
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  else:
103
+ tolerancia_credito = 0.10 # 10%
104
+ tolerancia_entrada = 0.10 # 10%
105
+ tolerancia_parcela = 0.30 # 30%
106
+ max_cotas_combinacao = 4 # Até 4 cotas por combinação
107
 
108
  # Define faixas de tolerância
109
  credito_min = credito_desejado * (1 - tolerancia_credito)
 
120
  print(f"🔧 Faixas aceitáveis: Parcela: R$ {parcela_min:,.2f} - R$ {parcela_max:,.2f}")
121
  print(f"🔧 Máximo de cotas por combinação: {max_cotas_combinacao}")
122
 
 
123
  resultados = []
124
+ total_combinacoes_testadas = 0
125
 
126
+ # Para cada administradora, busca combinações
127
+ for adm, cotas in grupos_filtrados.items():
128
+ print(f"🔍 Analisando administradora: {adm} ({len(cotas)} cotas)")
 
 
 
129
 
130
+ # Para valores altos, NÃO filtramos cotas individuais primeiro
131
+ # Isso permite que cotas menores sejam combinadas para atingir valores altos
132
+ cotas_para_combinar = cotas
133
+
134
+ # Gera combinações
135
+ for r in range(1, min(max_cotas_combinacao + 1, len(cotas_para_combinar) + 1)):
136
+ # Limita o número de combinações testadas por administradora
137
+ max_combinacoes_por_adm = 200 if credito_desejado > 5000000 else 100
138
+ combinacoes_geradas = 0
 
139
 
140
+ for combinacao in itertools.combinations(cotas_para_combinar, r):
141
+ if combinacoes_geradas >= max_combinacoes_por_adm:
142
  break
143
 
144
+ total_combinacoes_testadas += 1
145
+ combinacoes_geradas += 1
146
 
147
  total_credito = sum(c['valor_credito'] for c in combinacao)
148
  total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
 
160
 
161
  resultados.append((adm, combinacao, diferenca))
162
 
163
+ # Para se encontrou combinações suficientes
164
+ if len(resultados) >= max_combinacoes * 3:
165
  break
166
 
167
+ if len(resultados) >= max_combinacoes * 3:
168
  break
169
 
170
+ if len(resultados) >= max_combinacoes * 3:
171
  break
172
 
173
+ print(f"🔍 Total de combinações testadas: {total_combinacoes_testadas}")
174
  print(f"🔍 Combinações válidas encontradas: {len(resultados)}")
175
 
 
176
  if not resultados:
177
+ # Tenta uma busca mais ampla se não encontrou resultados
178
  print("🔍 Nenhuma combinação encontrada. Tentando busca ampla...")
179
  return buscar_combinacoes_amplo(credito_desejado, entrada_desejada, parcela_desejada, administradoras, max_combinacoes)
180
 
181
+ # Ordena pela diferença e pega as melhores
182
  resultados.sort(key=lambda x: x[2])
183
  return formatar_resultados(resultados[:max_combinacoes])
184
 
185
  def buscar_combinacoes_amplo(credito_desejado, entrada_desejada, parcela_desejada, administradoras=None, max_combinacoes=10):
186
+ """Busca combinações com tolerâncias mais amplas para valores altos."""
187
  global grupos_imovel
188
 
189
  # Filtra administradoras se especificado
 
192
  else:
193
  grupos_filtrados = grupos_imovel
194
 
195
+ # Tolerâncias mais amplas para valores altos
196
+ if credito_desejado > 5000000:
197
+ tolerancia_credito = 0.25 # 25%
198
+ tolerancia_entrada = 0.25 # 25%
199
+ tolerancia_parcela = 0.60 # 60%
200
+ max_cotas_combinacao = 8 # Até 8 cotas por combinação
 
201
  else:
202
+ tolerancia_credito = 0.20 # 20%
203
+ tolerancia_entrada = 0.20 # 20%
204
+ tolerancia_parcela = 0.50 # 50%
205
+ max_cotas_combinacao = 6 # Até 6 cotas por combinação
206
 
207
  credito_min = credito_desejado * (1 - tolerancia_credito)
208
  credito_max = credito_desejado * (1 + tolerancia_credito)
 
215
  print(f"🔍 BUSCA AMPLA: Máximo de cotas por combinação: {max_cotas_combinacao}")
216
 
217
  resultados = []
218
+ total_combinacoes_testadas = 0
219
 
220
+ for adm, cotas in grupos_filtrados.items():
221
+ print(f"🔍 BUSCA AMPLA - Analisando administradora: {adm}")
 
 
 
 
222
 
223
+ # Gera combinações
224
+ for r in range(1, min(max_cotas_combinacao + 1, len(cotas) + 1)):
225
+ combinacoes_geradas = 0
226
+ max_combinacoes_por_adm = 300
 
 
 
227
 
228
+ for combinacao in itertools.combinations(cotas, r):
229
+ if combinacoes_geradas >= max_combinacoes_por_adm:
230
  break
231
 
232
+ total_combinacoes_testadas += 1
233
+ combinacoes_geradas += 1
234
 
235
  total_credito = sum(c['valor_credito'] for c in combinacao)
236
  total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
 
247
 
248
  resultados.append((adm, combinacao, diferenca))
249
 
250
+ if len(resultados) >= max_combinacoes * 2:
251
  break
252
+
253
+ if len(resultados) >= max_combinacoes * 2:
254
+ break
255
+
256
+ if len(resultados) >= max_combinacoes * 2:
257
+ break
258
 
259
+ print(f"🔍 BUSCA AMPLA: Total de combinações testadas: {total_combinacoes_testadas}")
260
  print(f"🔍 BUSCA AMPLA: Combinações válidas encontradas: {len(resultados)}")
261
 
262
  if not resultados:
263
+ return "🚫 Nenhuma combinação adequada encontrada com os parâmetros fornecidos."
 
264
 
265
  resultados.sort(key=lambda x: x[2])
266
  return formatar_resultados(resultados[:max_combinacoes])
267
 
268
+ def formatar_moeda(valor):
269
+ return f"R$ {valor:,.2f}".replace(",", "v").replace(".", ",").replace("v", ".")
270
+
271
+ def formatar_resultados(resultados):
272
+ """Formata os resultados para exibição."""
273
+ if not resultados:
274
+ return "🚫 Nenhuma combinação adequada encontrada com os parâmetros fornecidos."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
 
276
+ resposta = ""
277
+ for idx, (adm, combinacao, _) in enumerate(resultados, 1):
278
  codigos = [str(c.get('codigo', 'N/A')) for c in combinacao]
279
  total_credito = sum(c['valor_credito'] for c in combinacao)
280
  total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
 
289
  taxa_percentual = (taxa_total / credito_real) * 100 if credito_real > 0 else 0
290
  taxa_mensal = taxa_percentual / maior_prazo if maior_prazo > 0 else 0
291
 
292
+ resposta += f"""
293
+ --- COMBINAÇÃO {idx} ---
 
294
  🏢 Administradora: {adm}
295
  🔢 Códigos: {', '.join(codigos)} ({len(combinacao)} cotas)
296
+ 💰 Crédito Total: {formatar_moeda(total_credito)}
297
+ 💵 Entrada (+comissão): {formatar_moeda(total_entrada)}
 
298
  📉 Saldo Devedor: {formatar_moeda(total_saldo)}
299
+ 💲 Parcela: {formatar_moeda(total_parcelas)}
300
  ⏳ Prazo: {maior_prazo} meses
301
  🔚 Valor Final: {formatar_moeda(valor_final)}
302
  💠 Crédito Líquido: {formatar_moeda(credito_real)}
303
  📊 Taxa Total: {taxa_percentual:.2f}% ({formatar_moeda(taxa_total)})
304
+ 🗓️ Taxa Mensal: {taxa_mensal:.2f}%
305
+ 🗓️ Taxa Anual: {taxa_mensal * 12:.2f}%
306
  """
307
+ return resposta
 
308
 
309
  # Carrega a planilha uma vez quando o aplicativo inicia
310
  carregar_planilha()