// utils/filterProperties.js import Fuse from 'fuse.js'; export const filterSimilarProperties = (properties) => { const options = { keys: ['dataValues.title'], // Buscamos similitud en el título dentro de dataValues threshold: 0.6, // 0.6 es un umbral para 40% de similitud includeScore: true // Incluye la puntuación de similitud }; const fuse = new Fuse(properties, options); const uniqueProperties = []; const seen = new Set(); // Usaremos un conjunto para rastrear propiedades vistas properties.forEach((property) => { const propertyData = property.dataValues; if (!seen.has(propertyData.id)) { // Inicializa el array para IDs similares en dataValues propertyData.similarIds = []; // Buscamos propiedades similares por título const result = fuse.search(propertyData.title).filter((res) => { const similarProperty = res.item.dataValues; // Filtramos resultados que no sean la misma propiedad y sean similares en título const isSimilar = res.item.dataValues.id !== propertyData.id && res.score < options.threshold; if (isSimilar) { propertyData.similarIds.push(similarProperty.id); // Enriquecer la propiedad actual con datos de la propiedad similar propertyData.title = getLongest(propertyData.title, similarProperty.title); propertyData.url = propertyData.url || similarProperty.url; propertyData.price = propertyData.price || similarProperty.price; propertyData.rooms = propertyData.rooms || similarProperty.rooms; propertyData.area = propertyData.area || similarProperty.area; propertyData.level = propertyData.level || similarProperty.level; propertyData.description = getLongest(propertyData.description, similarProperty.description); propertyData.pic = propertyData.pic || similarProperty.pic; propertyData.baths = propertyData.baths || similarProperty.baths; propertyData.neighborhood = propertyData.neighborhood || similarProperty.neighborhood; propertyData.phone = propertyData.phone || similarProperty.phone; // Marcar la propiedad similar como vista seen.add(similarProperty.id); } return isSimilar; }); // Comprobamos coincidencia exacta en price, rooms y area const matchingProperties = result.filter((res) => { const similarProperty = res.item.dataValues; return ( similarProperty.price === propertyData.price && (similarProperty.rooms === propertyData.rooms || similarProperty.area === propertyData.area) ); }); if (matchingProperties.length === 0) { uniqueProperties.push(property); } // Añadir los IDs de propiedades similares al array similarIds y marcarlas como vistas matchingProperties.forEach((res) => { const similarProperty = res.item.dataValues; propertyData.similarIds.push(similarProperty.id); seen.add(similarProperty.id); }); // Añadir la propiedad actual como vista seen.add(propertyData.id); } }); return uniqueProperties; }; const getLongest = (a, b) => { if (!a) return b; if (!b) return a; return a.length >= b.length ? a : b; };