import mysql.connector
import streamlit as st
import streamlit.components.v1 as components
import pandas as pd
import ifcopenshell
import ifcopenshell.util.element as Element
import tempfile
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio
import os
import json
import re
import matplotlib.pyplot as plt
import base64
hide_st_style = """
"""
st.markdown(hide_st_style, unsafe_allow_html=True)
connection = mysql.connector.connect(
host="srv1885.hstgr.io",
user="u539776097_HQQNV",
password="Nekoryu1234.",
database="u539776097_zCV5L"
)
if "button_clicked" not in st.session_state:
st.session_state.button_clicked = False
def callback():
st.session_state.button_clicked = True
licenceifc=st.text_input("Ingrese su licencia","")
if st.button("Acceso",on_click=callback) or st.session_state.button_clicked :
cursor = connection.cursor()
cursor2 = connection.cursor()
select_patient_query = "select licencia_ifc from wp_lmfwc_licenses where licencia_ifc = %s"
data=[(licenceifc)]
cursor.execute(select_patient_query,data)
licen = cursor.fetchone()
if licen=="":
st.write("La licencia esta correcto")
else:
cursor = connection.cursor()
cursor2 = connection.cursor()
select_patient_query = "select creditos from wp_lmfwc_licenses where licencia_ifc = %s"
data=[(licenceifc)]
cursor.execute(select_patient_query,data)
patient = cursor.fetchone()
final=re.sub(r'[,\(\)\"\']','',str(patient))
final=int(float(final))
if final > 0:
# Crear la aplicación Streamlit
st.title("Estandarización del modelo Ifc")
def cargar_datos_desde_json(tipo_modelo, nivel_avance):
# Genera la ruta completa del archivo JSON basado en la selección del usuario
nombre_archivo = f"{tipo_modelo}_{nivel_avance}.json"
ruta_archivo = os.path.join( nombre_archivo)
try:
# Intenta abrir y cargar el archivo JSON correspondiente
with open(ruta_archivo, 'r') as file:
data = json.load(file)
return data
except FileNotFoundError:
st.error(f"El archivo JSON '{nombre_archivo}' no se encontró en la ubicación '{ruta_archivo}'.")
return None
except Exception as e:
st.error(f"Error al cargar datos desde el archivo JSON: {str(e)}")
return None
def obtener_informacion(data, tipo_modelo, nivel_avance):
if data and tipo_modelo in data and nivel_avance in data[tipo_modelo]:
info_seleccionada = data[tipo_modelo][nivel_avance]
rows = []
for entidad, ndi_info in info_seleccionada.items():
for ndi, ndi_data in ndi_info.items():
atributos = ndi_data.get('Atributos', None)
Propiedades = ndi_data.get('Propiedades', None)
# Utiliza apply con una función lambda para formatear la columna 'Atributos'
atributos_str = ', '.join(atributos) if atributos else ''
rows.append([entidad, ndi, atributos_str, Propiedades])
df = pd.DataFrame(rows, columns=['Entidad', 'NDI', 'Atributos', 'Propiedades'])
return df
else:
return pd.DataFrame({'Mensaje': ['No se encontró información para la selección']})
# Crear la aplicación de Streamlit con el tamaño de título personalizado
#st.markdown("
Revisor de Modelos IFC
", unsafe_allow_html=True)
# Definir las listas de tipos de modelo y niveles de avance
tipos_modelo = ["Sitio", "Volumétrico", "Arquitectura", "Diseño de Infraestructura", "Estructura",
"MEP", "Coordinación", "Construcción", "As-Built", "Operación"]
nivel_avance = ["DC", "DA", "DB", "DD", "CC", "CM","AB","PM","GM"]
# Etiqueta para el tipo de modelo
st.write("Seleccione el tipo de modelo:")
tipo_modelo = st.selectbox("Tipo de Modelo:", tipos_modelo)
# Etiqueta para el nivel de avance
st.write("Seleccione el EAIM:")
nivel_avance = st.selectbox("EAIM:", nivel_avance)
data = cargar_datos_desde_json(tipo_modelo, nivel_avance)
# Agrega un botón de "Aceptar"
if st.button("Aceptar"):
st.write("Entidades, atributos y propiedades minimas de EBPP")
# Código que se ejecutará cuando se presione el botón
resultado_df = obtener_informacion(data, tipo_modelo, nivel_avance)
#st.write(resultado_df) # Muestra el resultado en la aplicación
resultado_df = obtener_informacion(data, tipo_modelo, nivel_avance)
def get_objects_data_by_class(entity):
psets = Element.get_psets(entity)
attribute_names = [attribute for attribute in dir(entity) if not attribute.startswith("_")]
# Initialize a dictionary to store properties grouped by Pset name
propiedades_dict = {}
for pset_name, properties in psets.items():
propiedades = []
for property_name, property_value in properties.items():
if isinstance(property_value, ifcopenshell.entity_instance):
property_value = property_value.Name
propiedades.append(property_name)
propiedades_dict[pset_name] = propiedades
object_data = {
'Entidad': entity.is_a(),
'Atributos': ', '.join(attribute_names),
'Propiedades': propiedades_dict,
}
return object_data
#cargar dataframe
df1 = resultado_df[['Entidad', 'Propiedades']]
def transformar_dataframe(df1):
# Lista para almacenar los nuevos datos
nuevas_filas = []
# Itera sobre cada fila del dataframe original
for index, row in df1.iterrows():
element = row['Entidad']
properties = row['Propiedades']
# Verifica si properties es una cadena, de lo contrario ya es un diccionario
if isinstance(properties, str):
properties_dict = json.loads(properties)
else:
properties_dict = properties
# Itera sobre cada grupo de propiedades y sus propiedades
for grupo, propiedades in properties_dict.items():
for propiedad in propiedades:
nuevas_filas.append({
'Entidad': element,
'Grupo': grupo,
'Propiedades': propiedad
})
# Crea un nuevo dataframe con las filas nuevas
nuevo_df = pd.DataFrame(nuevas_filas)
return nuevo_df
# Transformar el dataframe
nuevo_df = transformar_dataframe(df1)
st.write("Propiedades a cargar en el modelo")
# Mostrar el nuevo dataframe con Streamlit
st.write(nuevo_df)
ifcfile = None # Definir ifcfile en el ámbito global
ifc_path = None # Definir ifc_path en el ámbito global
save_path = None # Definir save_path en el ámbito global
# Función para cargar el archivo IFC
def cargar_archivo_ifc(ifc_file):
global ifcfile, ifc_path # Usar las variables ifcfile e ifc_path globales
if ifc_file is not None:
with tempfile.NamedTemporaryFile(delete=False, suffix=".ifc") as temp_file:
temp_file.write(ifc_file.read())
ifc_path = temp_file.name
ifcfile = ifcopenshell.open(ifc_path)
return ifcfile
# Función para procesar los archivos cargados
def procesar_archivos(ifcfile, json_data):
if ifcfile is not None and json_data is not None:
owner_history = ifcfile.by_type("IfcProduct")[0]
for entity_type, entity_info in json_data.get(f"{tipo_modelo}", {}).get(f"{nivel_avance}", {}).items():
for _, data in entity_info.items():
propiedades = data.get("Propiedades", {})
try:
# Filtrar entidades por tipo
entities = set([entity for entity in ifcfile.by_type(entity_type) if entity.is_a(entity_type)])
for entity in entities:
for pset_name, properties in propiedades.items():
property_set = None
existing_property_sets = entity.IsDefinedBy
for existing_pset in existing_property_sets:
if hasattr(existing_pset, "RelatingPropertyDefinition") and hasattr(existing_pset.RelatingPropertyDefinition, "HasProperties") and hasattr(existing_pset.RelatingPropertyDefinition, "Name"):
if existing_pset.RelatingPropertyDefinition.Name == pset_name:
property_set = existing_pset
break
if property_set is None:
property_values = []
for property_name in set(properties): # Utiliza un conjunto para obtener propiedades únicas
# Verificar si la propiedad ya existe por su nombre
if not any(p.Name == property_name for p in property_values):
property_values.append(
ifcfile.createIfcPropertySingleValue(property_name, "Value", ifcfile.create_entity("IfcText", "0"), None)
)
#print(f"Propiedades a agregar al conjunto: {property_values}")
# Crear un nuevo conjunto de propiedades y asignarlo a la entidad
property_set = ifcfile.createIfcPropertySet(entity.GlobalId, owner_history, pset_name, None, property_values)
ifcfile.createIfcRelDefinesByProperties(entity.GlobalId, owner_history, None, None, [entity], property_set)
else:
# Si se encontró un conjunto de propiedades existente, verificar y crear propiedades que falten
existing_properties = set(p.Name for p in property_set.RelatingPropertyDefinition.HasProperties)
missing_properties = set(properties) - existing_properties
if missing_properties:
missing_property_values = []
for property_name in missing_properties:
if not any(p.Name == property_name for p in property_values):
missing_property_values.append(
ifcfile.createIfcPropertySingleValue(property_name, "Value", ifcfile.create_entity("IfcText", "0"), None)
)
# Actualizar el conjunto de propiedades existente con las propiedades faltantes
property_set.RelatingPropertyDefinition.HasProperties = list(property_set.RelatingPropertyDefinition.HasProperties) + missing_property_values
#print(f"Propiedades agregadas al conjunto existente: {missing_properties}")
except Exception as e:
print(f"Error al procesar entidad '{entity_type}': {str(e)}")
if ifcfile is None:
print("cargar archivo")
# Función para obtener el enlace de descarga
def get_binary_file_downloader_html(bin_file, label='Archivo'):
if bin_file is not None:
with open(bin_file, 'rb') as f:
data = f.read()
b64 = base64.b64encode(data).decode()
href = f'{label}'
return href
else:
return '' # Si no se ha cargado un archivo IFC, devuelve una cadena vacía
# Función para generar un enlace de descarga para un DataFrame de Pandas en formato Excel
def get_table_download_link(nuevo_df, filename="Propiedades cargadas al modelo.xlsx", link_text="Descargar reporte de propiedades cargadas al modelo"):
# Crear un BytesIO buffer para escribir el archivo Excel
excel_buffer = pd.ExcelWriter(filename, engine="xlsxwriter")
nuevo_df.to_excel(excel_buffer, index=False)
excel_buffer._save()
# Leer el archivo Excel en binario y codificarlo en base64
excel_binary = open(filename, 'rb').read()
excel_base64 = base64.b64encode(excel_binary).decode()
# Crear el enlace de descarga
href = f'{link_text}'
return href
st.write("**Carga un archivo IFC para crear las propiedades faltantes en las entidades existentes del archivo IFC.**")
ifc_file = st.file_uploader("Seleccionar archivo IFC", type=["ifc"])
#json_file = st.file_uploader("Seleccionar archivo JSON", type=["json"])
def obtener_nombre_archivo_ifc(ifc_file):
if ifc_file is not None:
nombre_archivo = os.path.basename(ifc_file.name)
nombre_sin_extension, _ = os.path.splitext(nombre_archivo)
return nombre_sin_extension
else:
return None
nombre_archivo = obtener_nombre_archivo_ifc(ifc_file)
st.write("Cada vez que procese un archivo este consumirá, un crédito de la licencia")
if st.button("Procesar Archivos"):
ifcfile = cargar_archivo_ifc(ifc_file)
json_data = data
procesar_archivos(ifcfile, json_data)
# Create a temporary directory to save the processed IFC file
with tempfile.TemporaryDirectory() as temp_dir:
processed_ifc_path = os.path.join(temp_dir,f"{nombre_archivo}" "_Archivo_procesado.ifc")
ifcfile.write(processed_ifc_path)
# Display a download link for the processed IFC file
st.markdown(get_binary_file_downloader_html(processed_ifc_path, label='Descargar Archivo IFC Procesado'), unsafe_allow_html=True)
# Generar y mostrar el enlace de descarga
st.markdown(get_table_download_link(nuevo_df), unsafe_allow_html=True)
update_credit = "UPDATE wp_lmfwc_licenses set creditos = %s where licencia_ifc = %s"
final=final-1
datacredit=[(final)]
cursor2.execute(update_credit,(final,licenceifc))
connection.commit()
st.write("Queda actualemente ",final," creditos para esta licencia")
st.write("Espere a que aparesca el link de descargas y este texto no este en color gris")
else :
st.write("licencia sin creditos, Porfavor comprar otra licecnia para poder utilizar la herramienta")