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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +105 -67
app.py CHANGED
@@ -61,28 +61,17 @@ def agrupar_por_administradora(dataframe):
61
  grupos[row['administradora']].append(row.to_dict())
62
  return grupos
63
 
64
- def buscar_combinacoes(credito_desejado, entrada_desejada, parcela_desejada, administradoras=None):
65
- """Busca combinações de cotas com tolerâncias automáticas."""
66
  try:
67
  if df is None:
68
  if not carregar_planilha():
69
  return "❌ Erro: Planilha não carregada."
70
 
71
- print(f"🔍 Buscando: Crédito={credito_desejado}, Entrada={entrada_desejada}, Parcela={parcela_desejada}")
72
-
73
- # TOLERÂNCIAS AUTOMÁTICAS BASEADAS NO VALOR
74
- if credito_desejado > 1000000:
75
- # Valores altos: tolerâncias mais amplas
76
- credito_min, credito_max = credito_desejado * 0.70, credito_desejado * 1.30
77
- entrada_min, entrada_max = entrada_desejada * 0.50, entrada_desejada * 1.50
78
- parcela_min, parcela_max = parcela_desejada * 0.40, parcela_desejada * 2.50
79
- else:
80
- # Valores normais: tolerâncias padrão
81
- credito_min, credito_max = credito_desejado * 0.80, credito_desejado * 1.20
82
- entrada_min, entrada_max = entrada_desejada * 0.70, entrada_desejada * 1.30
83
- parcela_min, parcela_max = parcela_desejada * 0.60, parcela_desejada * 1.80
84
-
85
- print(f"📈 Tolerâncias: Crédito={credito_min}-{credito_max}, Entrada={entrada_min}-{entrada_max}, Parcela={parcela_min}-{parcela_max}")
86
 
87
  # Filtra por tipo de bem
88
  df_filtrado = df[df['tipo_do_bem'].str.lower() == 'imovel']
@@ -93,35 +82,47 @@ def buscar_combinacoes(credito_desejado, entrada_desejada, parcela_desejada, adm
93
  df_filtrado = df_filtrado[df_filtrado['administradora'].isin(administradoras)]
94
 
95
  if df_filtrado.empty:
96
- return "🚫 Nenhuma cota encontrada com os filtros aplicados."
97
 
98
  grupos = agrupar_por_administradora(df_filtrado)
99
  resultados = []
 
100
  MIN_COTAS = 3
101
- MAX_COTAS = 6
 
 
102
 
103
  for adm, cotas in grupos.items():
104
- # FILTRO RÁPIDO: apenas cotas com valores razoáveis
 
 
 
 
 
 
105
  cotas_validas = []
106
  for cota in cotas:
107
- try:
108
- credito = cota.get('valor_credito', 0)
109
- parcela = cota.get('valor_parcela', 0)
110
- if credito_min <= credito <= credito_max and parcela_min <= parcela <= parcela_max:
111
- cotas_validas.append(cota)
112
- except:
113
- continue
114
 
115
  if len(cotas_validas) < MIN_COTAS:
116
  continue
117
 
118
- # AMOSTRAGEM INTELIGENTE: pega até 12 cotas por admin
119
  if len(cotas_validas) > 12:
120
- cotas_validas = sorted(cotas_validas, key=lambda x: abs(x.get('valor_credito', 0) - credito_desejado/3))[:12]
 
 
121
 
122
- # BUSCA COMBINAÇÕES
123
- for r in range(MIN_COTAS, min(MAX_COTAS, len(cotas_validas)) + 1):
124
- for i in range(0, len(cotas_validas) - r + 1):
 
 
 
 
125
  combinacao = cotas_validas[i:i+r]
126
 
127
  total_credito = sum(c.get('valor_credito', 0) for c in combinacao)
@@ -135,54 +136,91 @@ def buscar_combinacoes(credito_desejado, entrada_desejada, parcela_desejada, adm
135
 
136
  resultados.append((adm, combinacao, 0))
137
 
138
- if len(resultados) >= 8:
139
  break
140
 
141
- if len(resultados) >= 8:
142
  break
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
- if len(resultados) >= 8:
 
 
 
145
  break
146
 
 
 
 
 
 
 
147
  if not resultados:
148
- # FALLBACK: mostra pelo menos alguma combinação
149
- return gerar_resultados_fallback(credito_desejado, entrada_desejada, parcela_desejada)
 
150
 
151
- return formatar_resultados(resultados[:8])
152
-
153
  except Exception as e:
154
  return f"❌ Erro: {str(e)}"
155
 
156
- def gerar_resultados_fallback(credito, entrada, parcela):
157
- """Gera resultados de fallback quando não encontra combinações."""
158
- return f"""
159
- 🏢 **Itaú - Imóvel**
160
-
161
- ### Crédito
162
- **R$ {credito*0.8:,.2f}**".replace(",", "v").replace(".", ",").replace("v", ".")
163
-
164
- **Entrada:** R$ {entrada*0.7:,.2f}**".replace(",", "v").replace(".", ",").replace("v", ".")
165
- **Prazo:** 60 meses
166
- **Parcela:** R$ {parcela*0.8:,.2f}**".replace(",", "v").replace(".", ",").replace("v", ".")
167
-
168
- **Saldo Devedor:** R$ {credito*0.6:,.2f}**".replace(",", "v").replace(".", ",").replace("v", ".")
169
- **Taxa Mensal:** 0.75%
170
- **Taxa Anual:** 9.00%
171
- **Código:** G3061, P4109, G2001
172
-
173
- ---
174
-
175
- ### Ver mais detalhes
176
-
177
- **Valor Final:** R$ {(entrada*0.7 + credito*0.6):,.2f}**".replace(",", "v").replace(".", ",").replace("v", ".")
178
- **Crédito Líquido:** R$ {(credito*0.8 - entrada*0.7):,.2f}**".replace(",", "v").replace(".", ",").replace("v", ".")
179
- **Taxa Total:** 35.42%
180
- **Nº de Cotas:** 3
181
 
182
- ---
 
 
183
 
184
- 💡 *Resultado simulado - ajuste os valores para encontrar mais combinações*
185
- """
 
 
 
 
 
186
 
187
  # ✅ MODIFIQUE A FUNÇÃO PRINCIPAL PARA USAR FALLBACK
188
  def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, administradoras):
 
61
  grupos[row['administradora']].append(row.to_dict())
62
  return grupos
63
 
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']
 
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)
 
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
162
+ parcela_min <= total_parcelas <= parcela_max):
163
+
164
+ resultados.append((adm, combinacao, 0))
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):