Arthur-Attili commited on
Commit
41bb393
·
verified ·
1 Parent(s): 89658d8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +139 -57
app.py CHANGED
@@ -1,10 +1,4 @@
1
- """Imovel.ipynb
2
- Automatically generated by Colab.
3
- Original file is located at
4
- https://colab.research.google.com/drive/1DZAQZfrXvTy358Vg2qfUg_ge6b3kcgBy
5
- """
6
-
7
- # app.py OTIMIZADO
8
  import pandas as pd
9
  import requests
10
  import io
@@ -22,10 +16,16 @@ URL = f"https://drive.google.com/uc?export=download&id={FILE_ID}"
22
  df = None
23
  df_imovel = None
24
  grupos_imovel = None
 
25
 
26
  def carregar_planilha():
27
  """Carrega e prepara a planilha para análise."""
28
- global df, df_imovel, grupos_imovel
 
 
 
 
 
29
  try:
30
  print("⏳ Carregando planilha...")
31
  response = requests.get(URL)
@@ -53,7 +53,10 @@ def carregar_planilha():
53
  df_imovel = df[df['tipo_do_bem'].str.lower() == 'imovel'].copy()
54
  grupos_imovel = agrupar_por_administradora(df_imovel)
55
 
 
56
  print("✅ Planilha carregada e pré-processada com sucesso")
 
 
57
  return True
58
 
59
  except Exception as e:
@@ -77,37 +80,30 @@ def buscar_combinacoes_otimizado(credito_desejado, entrada_desejada, parcela_des
77
  return "❌ Erro: Planilha não carregada. Por favor, tente novamente."
78
 
79
  # Filtra administradoras se especificado
80
- if administradoras:
81
  grupos_filtrados = {adm: cotas for adm, cotas in grupos_imovel.items() if adm in administradoras}
 
82
  else:
83
  grupos_filtrados = grupos_imovel
 
84
 
85
  if not grupos_filtrados:
86
  return "🚫 Nenhuma cota encontrada com os filtros aplicados. Tente ajustar os parâmetros."
87
 
88
- # TOLERÂNCIAS ADAPTATIVAS - Ajusta com base no valor
89
- # Para valores altos, aumenta a tolerância percentual
90
- def calcular_tolerancia(valor, tolerancia_base, tolerancia_min, tolerancia_max):
91
- if valor > 1000000: # Para valores acima de 1 milhão
92
- # Aumenta a tolerância para valores muito altos
93
- fator = min(tolerancia_max, tolerancia_base * (1 + math.log10(valor / 1000000) * 0.2))
94
- return fator
95
- return tolerancia_base
96
-
97
- # Tolerâncias base
98
- tolerancia_credito_base = 0.10 # 10%
99
- tolerancia_entrada_base = 0.10 # 10%
100
- tolerancia_parcela_base = 0.30 # 30%
101
-
102
- # Tolerâncias máximas
103
- tolerancia_max_credito = 0.40 # 40%
104
- tolerancia_max_entrada = 0.40 # 40%
105
- tolerancia_max_parcela = 0.60 # 60%
106
-
107
- # Calcula tolerâncias adaptativas
108
- tolerancia_credito = calcular_tolerancia(credito_desejado, tolerancia_credito_base, tolerancia_credito_base, tolerancia_max_credito)
109
- tolerancia_entrada = calcular_tolerancia(entrada_desejada, tolerancia_entrada_base, tolerancia_entrada_base, tolerancia_max_entrada)
110
- tolerancia_parcela = calcular_tolerancia(parcela_desejada, tolerancia_parcela_base, tolerancia_parcela_base, tolerancia_max_parcela)
111
 
112
  # Define faixas de tolerância
113
  credito_min = credito_desejado * (1 - tolerancia_credito)
@@ -117,44 +113,43 @@ def buscar_combinacoes_otimizado(credito_desejado, entrada_desejada, parcela_des
117
  parcela_min = parcela_desejada * (1 - tolerancia_parcela)
118
  parcela_max = parcela_desejada * (1 + tolerancia_parcela)
119
 
120
- print(f"🔧 Tolerâncias aplicadas: Crédito: ±{tolerancia_credito*100:.1f}%, Entrada: ±{tolerancia_entrada*100:.1f}%, Parcela: ±{tolerancia_parcela*100:.1f}%")
121
- print(f"🔧 Faixas: Crédito: {credito_min:,.0f} - {credito_max:,.0f}, Entrada: {entrada_min:,.0f} - {entrada_max:,.0f}, Parcela: {parcela_min:,.0f} - {parcela_max:,.0f}")
 
 
 
 
122
 
123
  resultados = []
 
124
 
125
  # Para cada administradora, busca combinações
126
  for adm, cotas in grupos_filtrados.items():
127
- # Pré-filtra cotas que individualmente estão dentro das faixas de tolerância
128
- cotas_filtradas = []
129
- for cota in cotas:
130
- cota_credito = cota['valor_credito']
131
- cota_entrada = cota['valor_entrada'] + (cota_credito * 0.085)
132
- cota_parcela = cota['valor_parcela']
133
-
134
- if (credito_min <= cota_credito <= credito_max and
135
- entrada_min <= cota_entrada <= entrada_max and
136
- parcela_min <= cota_parcela <= parcela_max):
137
- cotas_filtradas.append(cota)
138
 
139
- # Se não cotas individuais dentro da tolerância, tenta combinações
140
- if not cotas_filtradas:
141
- cotas_filtradas = cotas # Usa todas as cotas para combinações
142
 
143
- # Gera combinações (até 3 cotas por combinação para performance)
144
- for r in range(1, min(4, len(cotas_filtradas) + 1)):
145
  # Limita o número de combinações testadas por administradora
146
- max_combinacoes_por_adm = 50
147
  combinacoes_geradas = 0
148
 
149
- for combinacao in itertools.combinations(cotas_filtradas, r):
150
  if combinacoes_geradas >= max_combinacoes_por_adm:
151
  break
152
 
 
 
 
153
  total_credito = sum(c['valor_credito'] for c in combinacao)
154
  total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
155
  total_entrada = total_entrada_base + (total_credito * 0.085)
156
  total_parcelas = sum(c['valor_parcela'] for c in combinacao)
157
 
 
158
  if (credito_min <= total_credito <= credito_max and
159
  entrada_min <= total_entrada <= entrada_max and
160
  parcela_min <= total_parcelas <= parcela_max):
@@ -164,10 +159,9 @@ def buscar_combinacoes_otimizado(credito_desejado, entrada_desejada, parcela_des
164
  diferenca = abs(valor_final - total_credito)
165
 
166
  resultados.append((adm, combinacao, diferenca))
167
- combinacoes_geradas += 1
168
 
169
  # Para se já encontrou combinações suficientes
170
- if len(resultados) >= max_combinacoes * 3: # Coleta mais para depois filtrar as melhores
171
  break
172
 
173
  if len(resultados) >= max_combinacoes * 3:
@@ -176,13 +170,101 @@ def buscar_combinacoes_otimizado(credito_desejado, entrada_desejada, parcela_des
176
  if len(resultados) >= max_combinacoes * 3:
177
  break
178
 
 
 
 
179
  if not resultados:
180
- return "🚫 Nenhuma combinação adequada encontrada com os parâmetros fornecidos."
 
 
181
 
182
  # Ordena pela diferença e pega as melhores
183
  resultados.sort(key=lambda x: x[2])
184
  return formatar_resultados(resultados[:max_combinacoes])
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  def formatar_moeda(valor):
187
  return f"R$ {valor:,.2f}".replace(",", "v").replace(".", ",").replace("v", ".")
188
 
@@ -210,7 +292,7 @@ def formatar_resultados(resultados):
210
  resposta += f"""
211
  --- COMBINAÇÃO {idx} ---
212
  🏢 Administradora: {adm}
213
- 🔢 Códigos: {', '.join(codigos)}
214
  💰 Crédito Total: {formatar_moeda(total_credito)}
215
  💵 Entrada (+comissão): {formatar_moeda(total_entrada)}
216
  📉 Saldo Devedor: {formatar_moeda(total_saldo)}
@@ -233,7 +315,7 @@ def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, admin
233
 
234
  # Prepara a lista de administradoras para o Gradio
235
  def get_administradoras_options():
236
- if df is not None:
237
  adm_list = df[df['tipo_do_bem'].str.lower() == 'imovel']['administradora'].unique()
238
  return sorted(adm_list)
239
  return []
 
1
+ # app.py - VERSÃO CORRIGIDA E OTIMIZADA
 
 
 
 
 
 
2
  import pandas as pd
3
  import requests
4
  import io
 
16
  df = None
17
  df_imovel = None
18
  grupos_imovel = None
19
+ planilha_carregada = False
20
 
21
  def carregar_planilha():
22
  """Carrega e prepara a planilha para análise."""
23
+ global df, df_imovel, grupos_imovel, planilha_carregada
24
+
25
+ # Se já carregou, não precisa carregar novamente
26
+ if planilha_carregada:
27
+ return True
28
+
29
  try:
30
  print("⏳ Carregando planilha...")
31
  response = requests.get(URL)
 
53
  df_imovel = df[df['tipo_do_bem'].str.lower() == 'imovel'].copy()
54
  grupos_imovel = agrupar_por_administradora(df_imovel)
55
 
56
+ planilha_carregada = True
57
  print("✅ Planilha carregada e pré-processada com sucesso")
58
+ print(f"✅ Total de cotas de imóvel: {len(df_imovel)}")
59
+ print(f"✅ Administradoras disponíveis: {list(grupos_imovel.keys())}")
60
  return True
61
 
62
  except Exception as e:
 
80
  return "❌ Erro: Planilha não carregada. Por favor, tente novamente."
81
 
82
  # Filtra administradoras se especificado
83
+ if administradoras and len(administradoras) > 0:
84
  grupos_filtrados = {adm: cotas for adm, cotas in grupos_imovel.items() if adm in administradoras}
85
+ print(f"🔍 Filtrando por administradoras: {administradoras}")
86
  else:
87
  grupos_filtrados = grupos_imovel
88
+ print("🔍 Buscando em todas as administradoras")
89
 
90
  if not grupos_filtrados:
91
  return "🚫 Nenhuma cota encontrada com os filtros aplicados. Tente ajustar os parâmetros."
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)
 
113
  parcela_min = parcela_desejada * (1 - tolerancia_parcela)
114
  parcela_max = parcela_desejada * (1 + tolerancia_parcela)
115
 
116
+ print(f"💰 Valores desejados: Crédito: R$ {credito_desejado:,.2f}, Entrada: R$ {entrada_desejada:,.2f}, Parcela: R$ {parcela_desejada:,.2f}")
117
+ print(f"🔧 Tolerâncias: Crédito: ±{tolerancia_credito*100:.1f}%, Entrada: ±{tolerancia_entrada*100:.1f}%, Parcela: ±{tolerancia_parcela*100:.1f}%")
118
+ print(f"🔧 Faixas aceitáveis: Crédito: R$ {credito_min:,.2f} - R$ {credito_max:,.2f}")
119
+ print(f"🔧 Faixas aceitáveis: Entrada: R$ {entrada_min:,.2f} - R$ {entrada_max:,.2f}")
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)
149
  total_entrada = total_entrada_base + (total_credito * 0.085)
150
  total_parcelas = sum(c['valor_parcela'] for c in combinacao)
151
 
152
+ # Verifica se a combinação está dentro das tolerâncias
153
  if (credito_min <= total_credito <= credito_max and
154
  entrada_min <= total_entrada <= entrada_max and
155
  parcela_min <= total_parcelas <= parcela_max):
 
159
  diferenca = abs(valor_final - total_credito)
160
 
161
  resultados.append((adm, combinacao, diferenca))
 
162
 
163
  # Para se já encontrou combinações suficientes
164
+ if len(resultados) >= max_combinacoes * 3:
165
  break
166
 
167
  if len(resultados) >= max_combinacoes * 3:
 
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
190
+ if administradoras and len(administradoras) > 0:
191
+ grupos_filtrados = {adm: cotas for adm, cotas in grupos_imovel.items() if adm in administradoras}
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)
209
+ entrada_min = entrada_desejada * (1 - tolerancia_entrada)
210
+ entrada_max = entrada_desejada * (1 + tolerancia_entrada)
211
+ parcela_min = parcela_desejada * (1 - tolerancia_parcela)
212
+ parcela_max = parcela_desejada * (1 + tolerancia_parcela)
213
+
214
+ print(f"🔍 BUSCA AMPLA: Tolerâncias: Crédito: ±{tolerancia_credito*100:.1f}%, Entrada: ±{tolerancia_entrada*100:.1f}%, Parcela: ±{tolerancia_parcela*100:.1f}%")
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)
237
+ total_entrada = total_entrada_base + (total_credito * 0.085)
238
+ total_parcelas = sum(c['valor_parcela'] for c in combinacao)
239
+
240
+ if (credito_min <= total_credito <= credito_max and
241
+ entrada_min <= total_entrada <= entrada_max and
242
+ parcela_min <= total_parcelas <= parcela_max):
243
+
244
+ total_saldo = sum(c['saldo_devedor'] for c in combinacao)
245
+ valor_final = round(total_entrada + total_saldo, 2)
246
+ diferenca = abs(valor_final - total_credito)
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
 
 
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)}
 
315
 
316
  # Prepara a lista de administradoras para o Gradio
317
  def get_administradoras_options():
318
+ if df is not None and planilha_carregada:
319
  adm_list = df[df['tipo_do_bem'].str.lower() == 'imovel']['administradora'].unique()
320
  return sorted(adm_list)
321
  return []