Arthur-Attili commited on
Commit
4ecc33f
·
verified ·
1 Parent(s): a7fbf48

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +15 -107
app.py CHANGED
@@ -1,104 +1,75 @@
1
- # app.py - VERSÃO COM MARGEM ABSOLUTA FIXA
2
  import pandas as pd
3
  import requests
4
  import io
5
  import itertools
6
  from collections import defaultdict
7
  import gradio as gr
 
8
 
9
  # 🔧 CONFIGURAÇÕES GLOBAIS
10
  FILE_ID = "1XvNz7DlWioT64uNdcfBSL8Ui2nRSi9gT"
11
  URL = f"https://drive.google.com/uc?export=download&id={FILE_ID}"
12
 
13
- # Variáveis globais para armazenamento
14
  df = None
15
  df_imovel = None
16
  grupos_imovel = None
17
  planilha_carregada = False
18
 
19
  def carregar_planilha():
20
- """Carrega e prepara a planilha para análise."""
21
  global df, df_imovel, grupos_imovel, planilha_carregada
22
-
23
  if planilha_carregada:
24
  return True
25
-
26
  try:
27
  print("⏳ Carregando planilha...")
28
- response = requests.get(URL)
29
  response.raise_for_status()
30
  data = io.BytesIO(response.content)
31
  df = pd.read_excel(data)
32
-
33
- # Padroniza nomes das colunas
34
  df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
35
-
36
- # Colunas numéricas
37
  colunas_numericas = ['valor_credito', 'valor_entrada', 'valor_parcela', 'saldo_devedor', 'qtd_parcelas']
38
  for coluna in colunas_numericas:
39
  if coluna in df.columns:
40
  df[coluna] = pd.to_numeric(df[coluna], errors='coerce').fillna(0)
41
-
42
- # Verifica colunas essenciais
43
  if 'tipo_do_bem' not in df.columns or 'administradora' not in df.columns:
44
  raise ValueError("Colunas essenciais não encontradas")
45
-
46
  df.drop_duplicates(inplace=True)
47
-
48
- # Pré‑processa imóvel
49
  df_imovel = df[df['tipo_do_bem'].str.lower() == 'imovel'].copy()
50
  grupos_imovel = agrupar_por_administradora(df_imovel)
51
-
52
  planilha_carregada = True
53
- print("✅ Planilha carregada e pré-processada com sucesso")
54
- print(f"✅ Total de cotas de imóvel: {len(df_imovel)}")
55
- print(f"✅ Administradoras disponíveis: {list(grupos_imovel.keys())}")
56
  return True
57
-
58
  except Exception as e:
59
  print(f"❌ Erro ao carregar planilha: {str(e)}")
60
  return False
61
 
62
-
63
  def agrupar_por_administradora(dataframe):
64
- """Agrupa cotas por administradora."""
65
  grupos = defaultdict(list)
66
  for _, row in dataframe.iterrows():
67
  grupos[row['administradora']].append(row.to_dict())
68
  return grupos
69
 
70
-
71
  def formatar_moeda(valor):
72
  return f"R$ {valor:,.2f}".replace(",", "v").replace(".", ",").replace("v", ".")
73
 
74
-
75
  def calcular_tempo_parcelas(combinacao):
76
- """Calcula o tempo de parcelas baseado nas cotas da combinação."""
77
  if not combinacao:
78
  return ""
79
-
80
  try:
81
  cotas_ordenadas = sorted(combinacao, key=lambda x: int(x.get('qtd_parcelas', 0)))
82
  prazos = sorted(set(int(c.get('qtd_parcelas', 0)) for c in combinacao))
83
-
84
  if not prazos or prazos[0] <= 0:
85
  return ""
86
-
87
  resultado = []
88
  prazo_anterior = 0
89
-
90
  for prazo_atual in prazos:
91
  cotas_ativas = [c for c in cotas_ordenadas if int(c.get('qtd_parcelas', 0)) >= prazo_anterior + 1]
92
  valor_parcela_total = sum(c.get('valor_parcela', 0) for c in cotas_ativas)
93
-
94
  inicio = prazo_anterior + 1
95
  fim = prazo_atual
96
-
97
  if inicio <= fim and valor_parcela_total > 0:
98
  resultado.append(f"{inicio}x à {fim}x: {formatar_moeda(valor_parcela_total)}/mês")
99
-
100
  prazo_anterior = prazo_atual
101
-
102
  if prazos and prazo_anterior < max(prazos):
103
  cotas_ativas_finais = [c for c in cotas_ordenadas if int(c.get('qtd_parcelas', 0)) > prazo_anterior]
104
  if cotas_ativas_finais:
@@ -107,126 +78,77 @@ def calcular_tempo_parcelas(combinacao):
107
  fim_final = max(prazos)
108
  if valor_parcela_final > 0:
109
  resultado.append(f"{inicio_final}x à {fim_final}x: {formatar_moeda(valor_parcela_final)}/mês")
110
-
111
  return "\\n".join(resultado) if resultado else ""
112
-
113
  except Exception as e:
114
- print(f"❌ Erro ao calcular tempo de parcelas: {str(e)}")
115
  return ""
116
 
117
-
118
  def definir_margens_absolutas(credito_desejado, entrada_desejada, parcela_desejada):
119
- """Define margens fixas em R$ para crédito, entrada e parcela."""
120
- # Margens em R$ (ex.: 500.000 → 480.000–520.000)
121
- margem_credito = 40_000
122
- margem_entrada = 10_000
123
- margem_parcela = 1_000
124
-
125
  credito_min = max(0, credito_desejado - margem_credito)
126
  credito_max = credito_desejado + margem_credito
127
-
128
  entrada_min = max(0, entrada_desejada - margem_entrada)
129
  entrada_max = entrada_desejada + margem_entrada
130
-
131
  parcela_min = max(0, parcela_desejada - margem_parcela)
132
  parcela_max = parcela_desejada + margem_parcela
133
-
134
  return credito_min, credito_max, entrada_min, entrada_max, parcela_min, parcela_max
135
 
136
-
137
  def filtrar_cotas_por_faixa(cotas, credito_min, credito_max):
138
- """Filtra cotas que pelo menos têm chance de entrar na faixa de crédito."""
139
  return [c for c in cotas if c['valor_credito'] < credito_max * 2]
140
 
141
-
142
  def buscar_combinacoes_otimizado(credito_desejado, entrada_desejada, parcela_desejada, administradoras=None, max_combinacoes=15):
143
- """Busca combinações de cotas dentro de margens fixas absolutas."""
144
  global df_imovel, grupos_imovel
145
-
146
  if not planilha_carregada:
147
  if not carregar_planilha():
148
- return "❌ Erro: Planilha não carregada. Por favor, tente novamente."
149
-
150
- # Filtra administradoras
151
  if administradoras and len(administradoras) > 0:
152
  grupos_filtrados = {adm: cotas for adm, cotas in grupos_imovel.items() if adm in administradoras}
153
  else:
154
  grupos_filtrados = grupos_imovel
155
-
156
  if not grupos_filtrados:
157
- return "🚫 Nenhuma cota encontrada com os filtros aplicados. Tente ajustar os parâmetros."
158
-
159
- print(f"🔍 Total de administradoras no filtro: {len(grupos_filtrados)}")
160
-
161
- # Usa margens fixas em R$
162
  credito_min, credito_max, entrada_min, entrada_max, parcela_min, parcela_max = definir_margens_absolutas(
163
  credito_desejado, entrada_desejada, parcela_desejada
164
  )
165
-
166
- print(f"💰 Valores desejados: Crédito: R$ {credito_desejado:,.2f}, Entrada: R$ {entrada_desejada:,.2f}, Parcela: R$ {parcela_desejada:,.2f}")
167
- print(f"🔍 Margem de crédito: de R$ {credito_min:,.2f} até R$ {credito_max:,.2f}")
168
-
169
- # Limites de busca
170
  max_cotas_combinacao = 15
171
- max_combinacoes_por_adm = 4000 # para evitar explosão de combinações [web:12][web:18]
172
-
173
  resultados = []
174
  total_combinacoes_testadas = 0
175
-
176
  for adm, cotas in grupos_filtrados.items():
177
- print(f"🔍 Analisando administradora: {adm} ({len(cotas)} cotas)")
178
-
179
  cotas_filtradas = filtrar_cotas_por_faixa(cotas, credito_min, credito_max)
180
-
181
  for r in range(1, min(max_cotas_combinacao + 1, len(cotas_filtradas) + 1)):
182
  combinacoes_geradas = 0
183
  for combinacao in itertools.combinations(cotas_filtradas, r):
184
  if combinacoes_geradas >= max_combinacoes_por_adm:
185
  break
186
-
187
  total_combinacoes_testadas += 1
188
  combinacoes_geradas += 1
189
-
190
  total_credito = sum(c['valor_credito'] for c in combinacao)
191
  total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
192
  total_entrada = total_entrada_base + (total_credito * 0.085)
193
  total_parcelas = sum(c['valor_parcela'] for c in combinacao)
194
-
195
- # Verifica margens fixas
196
  if (credito_min <= total_credito <= credito_max and
197
  entrada_min <= total_entrada <= entrada_max and
198
  parcela_min <= total_parcelas <= parcela_max):
199
-
200
  total_saldo = sum(c['saldo_devedor'] for c in combinacao)
201
  valor_final = round(total_entrada + total_saldo, 2)
202
  diferenca = abs(valor_final - total_credito)
203
-
204
  resultados.append((adm, combinacao, diferenca))
205
-
206
  if len(resultados) >= max_combinacoes * 2:
207
  break
208
-
209
  if len(resultados) >= max_combinacoes * 2:
210
  break
211
-
212
  if len(resultados) >= max_combinacoes * 2:
213
  break
214
-
215
- print(f"🔍 Total de combinações testadas: {total_combinacoes_testadas}")
216
- print(f"🔍 Combinações válidas encontradas: {len(resultados)}")
217
-
218
  if not resultados:
219
- return "🚫 Nenhuma combinação adequada encontrada com os parâmetros fornecidos."
220
-
221
- resultados.sort(key=lambda x: x[2]) # ordena pela menor diferença
222
  return formatar_resultados(resultados[:max_combinacoes])
223
 
224
-
225
  def formatar_resultados(resultados):
226
- """Formata os resultados para exibição incluindo tempo de parcelas."""
227
  if not resultados:
228
- return "🚫 Nenhuma combinação adequada encontrada com os parâmetros fornecidos."
229
-
230
  resposta = ""
231
  for idx, (adm, combinacao, _) in enumerate(resultados, 1):
232
  codigos = [str(c.get('codigo', 'N/A')) for c in combinacao]
@@ -236,15 +158,12 @@ def formatar_resultados(resultados):
236
  total_saldo = sum(c['saldo_devedor'] for c in combinacao)
237
  total_parcelas = sum(c['valor_parcela'] for c in combinacao)
238
  maior_prazo = max(int(c.get('qtd_parcelas', 0)) for c in combinacao)
239
-
240
  valor_final = round(total_entrada + total_saldo, 2)
241
  credito_real = round(total_credito - total_entrada, 2)
242
  taxa_total = total_saldo - credito_real
243
  taxa_percentual = (taxa_total / credito_real) * 100 if credito_real > 0 else 0
244
  taxa_mensal = taxa_percentual / maior_prazo if maior_prazo > 0 else 0
245
-
246
  tempo_parcelas = calcular_tempo_parcelas(combinacao)
247
-
248
  resposta += f"""
249
  --- COMBINAÇÃO {idx} ---
250
  🏢 Administradora: {adm}
@@ -264,11 +183,9 @@ def formatar_resultados(resultados):
264
  """
265
  return resposta
266
 
267
-
268
- # Carrega a planilha uma vez quando o aplicativo inicia
269
  carregar_planilha()
270
 
271
-
272
  def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, administradoras):
273
  return buscar_combinacoes_otimizado(
274
  float(credito_desejado or 0),
@@ -278,14 +195,12 @@ def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, admin
278
  max_combinacoes=15
279
  )
280
 
281
-
282
  def get_administradoras_options():
283
  if df is not None and planilha_carregada:
284
  adm_list = df[df['tipo_do_bem'].str.lower() == 'imovel']['administradora'].unique()
285
  return sorted(adm_list)
286
  return []
287
 
288
-
289
  # Interface Gradio
290
  with gr.Blocks(title="Sistema de Busca de Consórcio Imóvel") as demo:
291
  gr.HTML("""
@@ -310,33 +225,26 @@ with gr.Blocks(title="Sistema de Busca de Consórcio Imóvel") as demo:
310
  .gr-button:hover { background-color: #fff3e0 !important; }
311
  </style>
312
  """)
313
-
314
  gr.Markdown("# 🏠 Busca de Combinações de Consórcio Imóvel")
315
  gr.Markdown("Insira os valores desejados para crédito, entrada e parcela, e filtre por administradora.")
316
-
317
  with gr.Row():
318
  credito_input = gr.Number(label="Crédito Desejado (R$)", value=300000, step=1000)
319
  entrada_input = gr.Number(label="Entrada Desejada (R$)", value=30000, step=1000)
320
  parcela_input = gr.Number(label="Parcela Desejada (R$)", value=1500, step=100)
321
-
322
  administradoras_multiselect = gr.CheckboxGroup(
323
  label="Filtrar por Administradoras",
324
  choices=get_administradoras_options(),
325
  value=get_administradoras_options()
326
  )
327
-
328
  submit_btn = gr.Button("🔍 Buscar Combinações", variant="primary")
329
  output_text = gr.Textbox(label="Resultados da Busca", lines=20, max_lines=40, interactive=False, placeholder="Os resultados aparecerão aqui...")
330
-
331
  submit_btn.click(
332
  fn=ajustar_e_buscar,
333
  inputs=[credito_input, entrada_input, parcela_input, administradoras_multiselect],
334
  outputs=output_text
335
  )
336
-
337
  gr.Markdown("---")
338
  gr.Markdown("Desenvolvido para auxiliar na busca por cotas de consórcio ideais.")
339
 
340
  if __name__ == "__main__":
341
- demo.launch(api=True)
342
- #
 
1
+ # app.py - VERSÃO COM TRATAMENTO DE ERRO MELHORADO
2
  import pandas as pd
3
  import requests
4
  import io
5
  import itertools
6
  from collections import defaultdict
7
  import gradio as gr
8
+ import os
9
 
10
  # 🔧 CONFIGURAÇÕES GLOBAIS
11
  FILE_ID = "1XvNz7DlWioT64uNdcfBSL8Ui2nRSi9gT"
12
  URL = f"https://drive.google.com/uc?export=download&id={FILE_ID}"
13
 
 
14
  df = None
15
  df_imovel = None
16
  grupos_imovel = None
17
  planilha_carregada = False
18
 
19
  def carregar_planilha():
 
20
  global df, df_imovel, grupos_imovel, planilha_carregada
 
21
  if planilha_carregada:
22
  return True
 
23
  try:
24
  print("⏳ Carregando planilha...")
25
+ response = requests.get(URL, timeout=10)
26
  response.raise_for_status()
27
  data = io.BytesIO(response.content)
28
  df = pd.read_excel(data)
 
 
29
  df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
 
 
30
  colunas_numericas = ['valor_credito', 'valor_entrada', 'valor_parcela', 'saldo_devedor', 'qtd_parcelas']
31
  for coluna in colunas_numericas:
32
  if coluna in df.columns:
33
  df[coluna] = pd.to_numeric(df[coluna], errors='coerce').fillna(0)
 
 
34
  if 'tipo_do_bem' not in df.columns or 'administradora' not in df.columns:
35
  raise ValueError("Colunas essenciais não encontradas")
 
36
  df.drop_duplicates(inplace=True)
 
 
37
  df_imovel = df[df['tipo_do_bem'].str.lower() == 'imovel'].copy()
38
  grupos_imovel = agrupar_por_administradora(df_imovel)
 
39
  planilha_carregada = True
40
+ print(f"✅ Planilha carregada. Cotas: {len(df_imovel)}")
 
 
41
  return True
 
42
  except Exception as e:
43
  print(f"❌ Erro ao carregar planilha: {str(e)}")
44
  return False
45
 
 
46
  def agrupar_por_administradora(dataframe):
 
47
  grupos = defaultdict(list)
48
  for _, row in dataframe.iterrows():
49
  grupos[row['administradora']].append(row.to_dict())
50
  return grupos
51
 
 
52
  def formatar_moeda(valor):
53
  return f"R$ {valor:,.2f}".replace(",", "v").replace(".", ",").replace("v", ".")
54
 
 
55
  def calcular_tempo_parcelas(combinacao):
 
56
  if not combinacao:
57
  return ""
 
58
  try:
59
  cotas_ordenadas = sorted(combinacao, key=lambda x: int(x.get('qtd_parcelas', 0)))
60
  prazos = sorted(set(int(c.get('qtd_parcelas', 0)) for c in combinacao))
 
61
  if not prazos or prazos[0] <= 0:
62
  return ""
 
63
  resultado = []
64
  prazo_anterior = 0
 
65
  for prazo_atual in prazos:
66
  cotas_ativas = [c for c in cotas_ordenadas if int(c.get('qtd_parcelas', 0)) >= prazo_anterior + 1]
67
  valor_parcela_total = sum(c.get('valor_parcela', 0) for c in cotas_ativas)
 
68
  inicio = prazo_anterior + 1
69
  fim = prazo_atual
 
70
  if inicio <= fim and valor_parcela_total > 0:
71
  resultado.append(f"{inicio}x à {fim}x: {formatar_moeda(valor_parcela_total)}/mês")
 
72
  prazo_anterior = prazo_atual
 
73
  if prazos and prazo_anterior < max(prazos):
74
  cotas_ativas_finais = [c for c in cotas_ordenadas if int(c.get('qtd_parcelas', 0)) > prazo_anterior]
75
  if cotas_ativas_finais:
 
78
  fim_final = max(prazos)
79
  if valor_parcela_final > 0:
80
  resultado.append(f"{inicio_final}x à {fim_final}x: {formatar_moeda(valor_parcela_final)}/mês")
 
81
  return "\\n".join(resultado) if resultado else ""
 
82
  except Exception as e:
 
83
  return ""
84
 
 
85
  def definir_margens_absolutas(credito_desejado, entrada_desejada, parcela_desejada):
86
+ margem_credito = 40000
87
+ margem_entrada = 10000
88
+ margem_parcela = 1000
 
 
 
89
  credito_min = max(0, credito_desejado - margem_credito)
90
  credito_max = credito_desejado + margem_credito
 
91
  entrada_min = max(0, entrada_desejada - margem_entrada)
92
  entrada_max = entrada_desejada + margem_entrada
 
93
  parcela_min = max(0, parcela_desejada - margem_parcela)
94
  parcela_max = parcela_desejada + margem_parcela
 
95
  return credito_min, credito_max, entrada_min, entrada_max, parcela_min, parcela_max
96
 
 
97
  def filtrar_cotas_por_faixa(cotas, credito_min, credito_max):
 
98
  return [c for c in cotas if c['valor_credito'] < credito_max * 2]
99
 
 
100
  def buscar_combinacoes_otimizado(credito_desejado, entrada_desejada, parcela_desejada, administradoras=None, max_combinacoes=15):
 
101
  global df_imovel, grupos_imovel
 
102
  if not planilha_carregada:
103
  if not carregar_planilha():
104
+ return "❌ Erro: Planilha não carregada. Tente novamente mais tarde."
 
 
105
  if administradoras and len(administradoras) > 0:
106
  grupos_filtrados = {adm: cotas for adm, cotas in grupos_imovel.items() if adm in administradoras}
107
  else:
108
  grupos_filtrados = grupos_imovel
 
109
  if not grupos_filtrados:
110
+ return "🚫 Nenhuma cota encontrada com os filtros aplicados."
 
 
 
 
111
  credito_min, credito_max, entrada_min, entrada_max, parcela_min, parcela_max = definir_margens_absolutas(
112
  credito_desejado, entrada_desejada, parcela_desejada
113
  )
 
 
 
 
 
114
  max_cotas_combinacao = 15
115
+ max_combinacoes_por_adm = 4000
 
116
  resultados = []
117
  total_combinacoes_testadas = 0
 
118
  for adm, cotas in grupos_filtrados.items():
 
 
119
  cotas_filtradas = filtrar_cotas_por_faixa(cotas, credito_min, credito_max)
 
120
  for r in range(1, min(max_cotas_combinacao + 1, len(cotas_filtradas) + 1)):
121
  combinacoes_geradas = 0
122
  for combinacao in itertools.combinations(cotas_filtradas, r):
123
  if combinacoes_geradas >= max_combinacoes_por_adm:
124
  break
 
125
  total_combinacoes_testadas += 1
126
  combinacoes_geradas += 1
 
127
  total_credito = sum(c['valor_credito'] for c in combinacao)
128
  total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
129
  total_entrada = total_entrada_base + (total_credito * 0.085)
130
  total_parcelas = sum(c['valor_parcela'] for c in combinacao)
 
 
131
  if (credito_min <= total_credito <= credito_max and
132
  entrada_min <= total_entrada <= entrada_max and
133
  parcela_min <= total_parcelas <= parcela_max):
 
134
  total_saldo = sum(c['saldo_devedor'] for c in combinacao)
135
  valor_final = round(total_entrada + total_saldo, 2)
136
  diferenca = abs(valor_final - total_credito)
 
137
  resultados.append((adm, combinacao, diferenca))
 
138
  if len(resultados) >= max_combinacoes * 2:
139
  break
 
140
  if len(resultados) >= max_combinacoes * 2:
141
  break
 
142
  if len(resultados) >= max_combinacoes * 2:
143
  break
 
 
 
 
144
  if not resultados:
145
+ return "🚫 Nenhuma combinação adequada encontrada."
146
+ resultados.sort(key=lambda x: x[2])
 
147
  return formatar_resultados(resultados[:max_combinacoes])
148
 
 
149
  def formatar_resultados(resultados):
 
150
  if not resultados:
151
+ return "🚫 Nenhuma combinação adequada encontrada."
 
152
  resposta = ""
153
  for idx, (adm, combinacao, _) in enumerate(resultados, 1):
154
  codigos = [str(c.get('codigo', 'N/A')) for c in combinacao]
 
158
  total_saldo = sum(c['saldo_devedor'] for c in combinacao)
159
  total_parcelas = sum(c['valor_parcela'] for c in combinacao)
160
  maior_prazo = max(int(c.get('qtd_parcelas', 0)) for c in combinacao)
 
161
  valor_final = round(total_entrada + total_saldo, 2)
162
  credito_real = round(total_credito - total_entrada, 2)
163
  taxa_total = total_saldo - credito_real
164
  taxa_percentual = (taxa_total / credito_real) * 100 if credito_real > 0 else 0
165
  taxa_mensal = taxa_percentual / maior_prazo if maior_prazo > 0 else 0
 
166
  tempo_parcelas = calcular_tempo_parcelas(combinacao)
 
167
  resposta += f"""
168
  --- COMBINAÇÃO {idx} ---
169
  🏢 Administradora: {adm}
 
183
  """
184
  return resposta
185
 
186
+ # Carrega a planilha (tenta, mas não para o app se falhar)
 
187
  carregar_planilha()
188
 
 
189
  def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, administradoras):
190
  return buscar_combinacoes_otimizado(
191
  float(credito_desejado or 0),
 
195
  max_combinacoes=15
196
  )
197
 
 
198
  def get_administradoras_options():
199
  if df is not None and planilha_carregada:
200
  adm_list = df[df['tipo_do_bem'].str.lower() == 'imovel']['administradora'].unique()
201
  return sorted(adm_list)
202
  return []
203
 
 
204
  # Interface Gradio
205
  with gr.Blocks(title="Sistema de Busca de Consórcio Imóvel") as demo:
206
  gr.HTML("""
 
225
  .gr-button:hover { background-color: #fff3e0 !important; }
226
  </style>
227
  """)
 
228
  gr.Markdown("# 🏠 Busca de Combinações de Consórcio Imóvel")
229
  gr.Markdown("Insira os valores desejados para crédito, entrada e parcela, e filtre por administradora.")
 
230
  with gr.Row():
231
  credito_input = gr.Number(label="Crédito Desejado (R$)", value=300000, step=1000)
232
  entrada_input = gr.Number(label="Entrada Desejada (R$)", value=30000, step=1000)
233
  parcela_input = gr.Number(label="Parcela Desejada (R$)", value=1500, step=100)
 
234
  administradoras_multiselect = gr.CheckboxGroup(
235
  label="Filtrar por Administradoras",
236
  choices=get_administradoras_options(),
237
  value=get_administradoras_options()
238
  )
 
239
  submit_btn = gr.Button("🔍 Buscar Combinações", variant="primary")
240
  output_text = gr.Textbox(label="Resultados da Busca", lines=20, max_lines=40, interactive=False, placeholder="Os resultados aparecerão aqui...")
 
241
  submit_btn.click(
242
  fn=ajustar_e_buscar,
243
  inputs=[credito_input, entrada_input, parcela_input, administradoras_multiselect],
244
  outputs=output_text
245
  )
 
246
  gr.Markdown("---")
247
  gr.Markdown("Desenvolvido para auxiliar na busca por cotas de consórcio ideais.")
248
 
249
  if __name__ == "__main__":
250
+ demo.launch(api=True)