621 lines
22 KiB
Ruby
621 lines
22 KiB
Ruby
#!/usr/bin/env ruby
|
||
# frozen_string_literal: true
|
||
|
||
# tools/analizar_dashboard_p2601.rb — Analizador del dashboard P2601 para proponer hitos adicionales
|
||
# ================================================================================
|
||
# Este script analiza el estado actual del dashboard P2601 y propone hitos
|
||
# intermedios adicionales para la fase de implementación final, utilizando
|
||
# herramientas ADN existentes y mejorándolas según sea necesario.
|
||
#
|
||
# Características:
|
||
# • Análisis del dashboard actual (HTML estático)
|
||
# • Integración con base de datos dtic-BITACORAs
|
||
# • Uso de herramientas ADN existentes
|
||
# • Propuesta de hitos basados en mejores prácticas
|
||
# • Generación de reporte estructurado
|
||
#
|
||
# Uso:
|
||
# ruby tools/analizar_dashboard_p2601.rb [OPCIONES]
|
||
#
|
||
# Opciones:
|
||
# --analizar-html Analizar dashboard/index.html actual
|
||
# --consultar-bd Consultar estado en base de datos
|
||
# --proponer-hitos Proponer hitos adicionales
|
||
# --generar-reporte Generar reporte completo
|
||
# --integrar-adn Integrar con herramientas ADN existentes
|
||
# --todo Ejecutar todas las opciones
|
||
|
||
require 'pg'
|
||
require 'yaml'
|
||
require 'json'
|
||
require 'nokogiri'
|
||
require 'optparse'
|
||
require 'date'
|
||
|
||
class AnalizadorDashboardP2601
|
||
def initialize(opciones = {})
|
||
@opciones = opciones
|
||
@config = cargar_configuracion_bd
|
||
@conn = nil
|
||
@dashboard_html = nil
|
||
@hitos_actuales = []
|
||
@hitos_propuestos = []
|
||
@estadisticas = {}
|
||
end
|
||
|
||
def ejecutar
|
||
puts "🔍 ANALIZADOR DE DASHBOARD P2601 - PROYECTO DASUTEN"
|
||
puts "=" * 70
|
||
puts "Fecha: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
|
||
puts ""
|
||
|
||
if @opciones[:todo] || @opciones[:analizar_html]
|
||
analizar_dashboard_html
|
||
end
|
||
|
||
if @opciones[:todo] || @opciones[:consultar_bd]
|
||
consultar_base_datos
|
||
end
|
||
|
||
if @opciones[:todo] || @opciones[:proponer_hitos]
|
||
proponer_hitos_adicionales
|
||
end
|
||
|
||
if @opciones[:todo] || @opciones[:generar_reporte]
|
||
generar_reporte_completo
|
||
end
|
||
|
||
if @opciones[:todo] || @opciones[:integrar_adn]
|
||
integrar_con_herramientas_adn
|
||
end
|
||
|
||
mostrar_resumen
|
||
rescue => e
|
||
puts "❌ Error durante el análisis: #{e.message}"
|
||
puts e.backtrace if @opciones[:debug]
|
||
exit 1
|
||
ensure
|
||
desconectar_bd if @conn
|
||
end
|
||
|
||
private
|
||
|
||
def cargar_configuracion_bd
|
||
config_path = File.join(__dir__, 'config', 'database.yml')
|
||
unless File.exist?(config_path)
|
||
puts "⚠️ Archivo de configuración no encontrado: #{config_path}"
|
||
return {}
|
||
end
|
||
|
||
config = YAML.load_file(config_path)
|
||
config['development'] || config['production'] || config['test']
|
||
end
|
||
|
||
def conectar_bd
|
||
return unless @config && @config['host']
|
||
|
||
puts "🔌 Conectando a PostgreSQL: #{@config['host']}:#{@config['port']}/#{@config['database']}"
|
||
|
||
@conn = PG.connect(
|
||
host: @config['host'],
|
||
port: @config['port'],
|
||
dbname: @config['database'],
|
||
user: @config['username'],
|
||
password: @config['password']
|
||
)
|
||
|
||
puts "✅ Conexión establecida\n"
|
||
rescue PG::Error => e
|
||
puts "⚠️ Error de conexión a BD: #{e.message}"
|
||
puts " Continuando sin conexión a base de datos\n"
|
||
end
|
||
|
||
def desconectar_bd
|
||
@conn&.close
|
||
puts "\n🔌 Conexión cerrada" if @conn
|
||
end
|
||
|
||
def analizar_dashboard_html
|
||
puts "📋 ANALIZANDO DASHBOARD HTML ACTUAL"
|
||
puts "-" * 50
|
||
|
||
dashboard_path = File.join(__dir__, '..', '..', 'dashboard', 'index.html')
|
||
unless File.exist?(dashboard_path)
|
||
puts "❌ Archivo dashboard no encontrado: #{dashboard_path}"
|
||
return
|
||
end
|
||
|
||
@dashboard_html = File.read(dashboard_path)
|
||
doc = Nokogiri::HTML(@dashboard_html)
|
||
|
||
# Extraer hitos del timeline
|
||
@hitos_actuales = []
|
||
doc.css('.tl-item').each do |item|
|
||
hito = {
|
||
id: item.css('.tl-id').text.strip,
|
||
fecha: item.css('.tl-date').text.strip,
|
||
titulo: item.css('.tl-title').text.strip,
|
||
descripcion: item.css('.tl-desc').text.strip.gsub(/\s+/, ' '),
|
||
estado: determinar_estado_hito(item),
|
||
tags: item.css('.tag').map(&:text).map(&:strip)
|
||
}
|
||
@hitos_actuales << hito
|
||
end
|
||
|
||
# Extraer nodos
|
||
nodos = []
|
||
doc.css('.node-card').each do |node|
|
||
nodos << {
|
||
nombre: node.css('.node-name').text.strip,
|
||
estado: node.css('.status-dot').attr('title')&.value || 'desconocido',
|
||
detalles: node.css('.node-detail').text.strip.gsub(/\s+/, ' ')
|
||
}
|
||
end
|
||
|
||
# Extraer métricas
|
||
metricas = {}
|
||
doc.css('.metric').each do |metric|
|
||
label = metric.css('.label').text.strip
|
||
value = metric.css('.value').text.strip
|
||
metricas[label] = value if label && value
|
||
end
|
||
|
||
@estadisticas[:hitos_total] = @hitos_actuales.size
|
||
@estadisticas[:hitos_completados] = @hitos_actuales.count { |h| h[:estado] == 'completado' }
|
||
@estadisticas[:hitos_activos] = @hitos_actuales.count { |h| h[:estado] == 'activo' }
|
||
@estadisticas[:hitos_pendientes] = @hitos_actuales.count { |h| h[:estado] == 'pendiente' }
|
||
@estadisticas[:nodos_total] = nodos.size
|
||
@estadisticas[:nodos_online] = nodos.count { |n| n[:estado] == 'Online' }
|
||
|
||
puts "📊 Estadísticas extraídas:"
|
||
puts " • Hitos totales: #{@estadisticas[:hitos_total]}"
|
||
puts " • Hitos completados: #{@estadisticas[:hitos_completados]}"
|
||
puts " • Hitos activos: #{@estadisticas[:hitos_activos]}"
|
||
puts " • Hitos pendientes: #{@estadisticas[:hitos_pendientes]}"
|
||
puts " • Nodos totales: #{@estadisticas[:nodos_total]}"
|
||
puts " • Nodos online: #{@estadisticas[:nodos_online]}"
|
||
|
||
# Mostrar últimos hitos
|
||
puts "\n📅 ÚLTIMOS HITOS REGISTRADOS:"
|
||
@hitos_actuales.last(5).each do |hito|
|
||
estado_emoji = case hito[:estado]
|
||
when 'completado' then '✅'
|
||
when 'activo' then '🔵'
|
||
when 'pendiente' then '⏳'
|
||
else '❓'
|
||
end
|
||
puts " #{estado_emoji} #{hito[:id]}: #{hito[:titulo][0..60]}..."
|
||
end
|
||
|
||
puts ""
|
||
end
|
||
|
||
def determinar_estado_hito(item)
|
||
dot_class = item.css('.tl-dot').attr('class').to_s
|
||
if dot_class.include?('done')
|
||
'completado'
|
||
elsif dot_class.include?('active')
|
||
'activo'
|
||
elsif dot_class.include?('pending')
|
||
'pendiente'
|
||
else
|
||
'desconocido'
|
||
end
|
||
end
|
||
|
||
def consultar_base_datos
|
||
puts "📋 CONSULTANDO BASE DE DATOS dtic-BITACORAs"
|
||
puts "-" * 50
|
||
|
||
conectar_bd
|
||
return unless @conn
|
||
|
||
begin
|
||
# Consultar si existen tablas de proyectos
|
||
tablas = @conn.exec("SELECT table_name FROM information_schema.tables WHERE table_schema = 'bitacoras'")
|
||
tablas_proyecto = tablas.select { |t| t['table_name'] =~ /proyectos|fases|hitos/ }
|
||
|
||
if tablas_proyecto.any?
|
||
puts "✅ Tablas de proyectos encontradas: #{tablas_proyecto.map { |t| t['table_name'] }.join(', ')}"
|
||
|
||
# Consultar proyecto P2601
|
||
proyecto = @conn.exec_params(
|
||
"SELECT * FROM bitacoras.proyectos WHERE codigo = $1",
|
||
['P2601']
|
||
)
|
||
|
||
if proyecto.ntuples > 0
|
||
puts "✅ Proyecto P2601 encontrado en base de datos"
|
||
proyecto_info = proyecto[0]
|
||
puts " • Nombre: #{proyecto_info['nombre']}"
|
||
puts " • Estado: #{proyecto_info['estado']}"
|
||
puts " • Descripción: #{proyecto_info['descripcion'][0..100]}..." if proyecto_info['descripcion']
|
||
|
||
# Consultar fases del proyecto
|
||
fases = @conn.exec_params(
|
||
"SELECT * FROM bitacoras.fases WHERE proyecto_id = $1 ORDER BY numero",
|
||
[proyecto_info['id']]
|
||
)
|
||
|
||
puts " • Fases: #{fases.ntuples} fases encontradas"
|
||
fases.each do |fase|
|
||
puts " - Fase #{fase['numero']}: #{fase['nombre']} (#{fase['estado']})"
|
||
end
|
||
else
|
||
puts "⚠️ Proyecto P2601 no encontrado en base de datos"
|
||
end
|
||
else
|
||
puts "ℹ️ Tablas de proyectos no encontradas en el esquema 'bitacoras'"
|
||
puts " Considerar crear estructura: proyectos, fases, hitos"
|
||
end
|
||
|
||
# Consultar estadísticas de entradas relacionadas con DASUTEN
|
||
entradas_dasuten = @conn.exec_params(
|
||
"SELECT COUNT(*) as total FROM bitacoras.entradas WHERE descripcion ILIKE $1",
|
||
['%dasuten%']
|
||
)
|
||
|
||
if entradas_dasuten.ntuples > 0
|
||
total = entradas_dasuten[0]['total'].to_i
|
||
puts "📝 Entradas relacionadas con DASUTEN: #{total}"
|
||
@estadisticas[:entradas_dasuten] = total
|
||
end
|
||
|
||
rescue PG::Error => e
|
||
puts "⚠️ Error consultando base de datos: #{e.message}"
|
||
end
|
||
|
||
puts ""
|
||
end
|
||
|
||
def proponer_hitos_adicionales
|
||
puts "🎯 PROPONIENDO HITOS ADICIONALES PARA FASE DE IMPLEMENTACIÓN"
|
||
puts "-" * 50
|
||
|
||
# Basado en el análisis del dashboard y mejores prácticas
|
||
hitos_propuestos = [
|
||
{
|
||
id: "BKP02",
|
||
titulo: "Backup Automático de VMs en Proxmox",
|
||
descripcion: "Configurar backups automáticos VZDump programados para DC y SQL Server. Establecer retención de 7 días, almacenamiento en NAS/SMB.",
|
||
categoria: "Infraestructura",
|
||
prioridad: "alta",
|
||
estimacion_horas: 2,
|
||
prerequisitos: ["FÍSICO"],
|
||
herramientas: ["Proxmox VE", "VZDump", "Scripts Bash"]
|
||
},
|
||
{
|
||
id: "MON01",
|
||
titulo: "Monitoreo de Recursos del Hipervisor",
|
||
descripcion: "Implementar sistema de monitoreo básico para CPU, RAM, almacenamiento y red de srv-dasu. Alertas por email/Telegram.",
|
||
categoria: "Monitoreo",
|
||
prioridad: "media",
|
||
estimacion_horas: 3,
|
||
prerequisitos: ["FÍSICO"],
|
||
herramientas: ["Prometheus Node Exporter", "Grafana", "Alertmanager"]
|
||
},
|
||
{
|
||
id: "DB02",
|
||
titulo: "Backup Automático de Base de Datos sysdasuten",
|
||
descripcion: "Configurar jobs de SQL Server Agent para backup diario completo y log cada 15 minutos. Verificar restauración periódica.",
|
||
categoria: "Base de Datos",
|
||
prioridad: "alta",
|
||
estimacion_horas: 2,
|
||
prerequisitos: ["ADDOM"],
|
||
herramientas: ["SQL Server Management Studio", "SQL Agent", "PowerShell"]
|
||
},
|
||
{
|
||
id: "SEC01",
|
||
titulo: "Auditoría de Seguridad del Dominio",
|
||
descripcion: "Revisar y configurar políticas de auditoría en DC. Logs de acceso, cambios en AD, intentos fallidos. Centralización de logs.",
|
||
categoria: "Seguridad",
|
||
prioridad: "media",
|
||
estimacion_horas: 4,
|
||
prerequisitos: ["GPO"],
|
||
herramientas: ["Windows Event Viewer", "Audit Policy", "SIEM básico"]
|
||
},
|
||
{
|
||
id: "DOC01",
|
||
titulo: "Documentación Operativa del Sistema",
|
||
descripcion: "Crear manual de operaciones: procedimientos de backup/restore, acceso remoto, resolución de problemas comunes, contactos de soporte.",
|
||
categoria: "Documentación",
|
||
prioridad: "media",
|
||
estimacion_horas: 6,
|
||
prerequisitos: ["UAT"],
|
||
herramientas: ["Markdown", "Git", "Herramientas ADN"]
|
||
},
|
||
{
|
||
id: "RED01",
|
||
titulo: "Optimización de Red y Firewall",
|
||
descripcion: "Revisar reglas de firewall en todas las VMs. Optimizar rutas Tailscale. Configurar QoS si es necesario.",
|
||
categoria: "Red",
|
||
prioridad: "baja",
|
||
estimacion_horas: 3,
|
||
prerequisitos: ["NET01"],
|
||
herramientas: ["Windows Firewall", "Tailscale", "PowerShell"]
|
||
},
|
||
{
|
||
id: "PERF01",
|
||
titulo: "Pruebas de Rendimiento del Sistema",
|
||
descripcion: "Realizar pruebas de carga simulada en sistema DASUTEN. Medir tiempos de respuesta, consumo de recursos, identificar cuellos de botella.",
|
||
categoria: "Performance",
|
||
prioridad: "media",
|
||
estimacion_horas: 4,
|
||
prerequisitos: ["CLI"],
|
||
herramientas: ["SQL Profiler", "Performance Monitor", "Scripts de prueba"]
|
||
},
|
||
{
|
||
id: "MIG02",
|
||
titulo: "Plan de Migración de Datos Final",
|
||
descripcion: "Desarrollar script/procedimiento para migración incremental de datos desde sistema antiguo. Validar integridad de datos migrados.",
|
||
categoria: "Migración",
|
||
prioridad: "alta",
|
||
estimacion_horas: 8,
|
||
prerequisitos: ["P02.APP"],
|
||
herramientas: ["SQL Server Integration Services", "PowerShell", "Validación de datos"]
|
||
}
|
||
]
|
||
|
||
@hitos_propuestos = hitos_propuestos
|
||
|
||
puts "💡 HITOS PROPUESTOS (#{hitos_propuestos.size} nuevos):"
|
||
puts ""
|
||
|
||
hitos_propuestos.each do |hito|
|
||
prioridad_emoji = case hito[:prioridad]
|
||
when 'alta' then '🔴'
|
||
when 'media' then '🟡'
|
||
when 'baja' then '🟢'
|
||
else '⚪'
|
||
end
|
||
|
||
puts " #{prioridad_emoji} #{hito[:id]}: #{hito[:titulo]}"
|
||
puts " 📍 Categoría: #{hito[:categoria]}"
|
||
puts " ⏱️ Estimación: #{hito[:estimacion_horas]} horas"
|
||
puts " 📋 Prerequisitos: #{hito[:prerequisitos].join(', ')}" if hito[:prerequisitos].any?
|
||
puts " 🛠️ Herramientas: #{hito[:herramientas].join(', ')}"
|
||
puts ""
|
||
end
|
||
|
||
# Estadísticas de propuestas
|
||
categorias = hitos_propuestos.group_by { |h| h[:categoria] }
|
||
puts "📈 DISTRIBUCIÓN POR CATEGORÍA:"
|
||
categorias.each do |categoria, hitos|
|
||
puts " • #{categoria}: #{hitos.size} hitos"
|
||
end
|
||
|
||
puts ""
|
||
end
|
||
|
||
def generar_reporte_completo
|
||
puts "📊 GENERANDO REPORTE COMPLETO"
|
||
puts "-" * 50
|
||
|
||
reporte = {
|
||
metadata: {
|
||
generado_en: Time.now.iso8601,
|
||
proyecto: "P2601 - DASUTEN",
|
||
version_analizador: "1.0.0"
|
||
},
|
||
estado_actual: @estadisticas,
|
||
hitos_actuales: @hitos_actuales,
|
||
hitos_propuestos: @hitos_propuestos,
|
||
recomendaciones: generar_recomendaciones,
|
||
acciones_sugeridas: generar_acciones_sugeridas
|
||
}
|
||
|
||
# Guardar reporte JSON
|
||
reporte_path = File.join(__dir__, '..', '..', 'tmp', 'reporte_p2601_analisis.json')
|
||
FileUtils.mkdir_p(File.dirname(reporte_path))
|
||
|
||
File.write(reporte_path, JSON.pretty_generate(reporte))
|
||
puts "✅ Reporte guardado en: #{reporte_path}"
|
||
puts " • Tamaño: #{File.size(reporte_path)} bytes"
|
||
puts " • Elementos: #{reporte[:hitos_actuales].size} hitos actuales, #{reporte[:hitos_propuestos].size} hitos propuestos"
|
||
puts ""
|
||
end
|
||
|
||
def generar_recomendaciones
|
||
recomendaciones = []
|
||
|
||
# Recomendaciones basadas en análisis
|
||
if @estadisticas[:hitos_pendientes] && @estadisticas[:hitos_pendientes] > 3
|
||
recomendaciones << "Priorizar hitos pendientes críticos (FÍSICO, ADDOM) antes de agregar nuevos"
|
||
end
|
||
|
||
if @estadisticas[:entradas_dasuten] && @estadisticas[:entradas_dasuten] < 20
|
||
recomendaciones << "Aumentar registro de actividades específicas de DASUTEN en bitácoras"
|
||
end
|
||
|
||
recomendaciones << "Integrar hitos propuestos en timeline del dashboard de forma gradual"
|
||
recomendaciones << "Utilizar herramientas ADN para automatizar seguimiento de hitos"
|
||
recomendaciones << "Considerar implementar sistema de notificaciones para hitos críticos"
|
||
recomendaciones << "Documentar cada hito completado con lecciones aprendidas"
|
||
|
||
recomendaciones
|
||
end
|
||
|
||
def generar_acciones_sugeridas
|
||
acciones = [
|
||
{
|
||
accion: "Actualizar dashboard HTML",
|
||
descripcion: "Agregar hitos propuestos al timeline",
|
||
prioridad: "media",
|
||
herramientas: ["HTML/CSS", "Herramientas ADN"]
|
||
},
|
||
{
|
||
accion: "Crear estructura en base de datos",
|
||
descripcion: "Implementar tablas proyectos/fases/hitos si no existen",
|
||
prioridad: "alta",
|
||
herramientas: ["PostgreSQL", "SQL migrations"]
|
||
},
|
||
{
|
||
accion: "Integrar con sistema de búsqueda",
|
||
descripcion: "Conectar hitos con sistema de búsqueda ADN BITACORAs",
|
||
prioridad: "media",
|
||
herramientas: ["BuscadorBDSimple", "API REST"]
|
||
},
|
||
{
|
||
accion: "Automatizar actualizaciones",
|
||
descripcion: "Crear script para actualizar dashboard desde base de datos",
|
||
prioridad: "baja",
|
||
herramientas: ["Ruby", "Cron jobs", "Herramientas ADN"]
|
||
},
|
||
{
|
||
accion: "Implementar métricas avanzadas",
|
||
descripcion: "Agregar KPIs de progreso, desviaciones, pronósticos",
|
||
prioridad: "baja",
|
||
herramientas: ["JavaScript", "Chart.js", "API"]
|
||
}
|
||
]
|
||
|
||
acciones
|
||
end
|
||
|
||
def integrar_con_herramientas_adn
|
||
puts "🔄 INTEGRANDO CON HERRAMIENTAS ADN EXISTENTES"
|
||
puts "-" * 50
|
||
|
||
puts "🔍 Herramientas ADN disponibles:"
|
||
|
||
# Verificar herramientas existentes
|
||
herramientas_adn = [
|
||
{ nombre: "Sistema de búsqueda", archivo: "buscador_bd_simple.rb", estado: verificar_herramienta("adn/db/core/buscador_bd_simple.rb") },
|
||
{ nombre: "Seguimiento de plan", archivo: "subcomando_plan.rb", estado: verificar_herramienta("adn/subcomando_plan.rb") },
|
||
{ nombre: "Operaciones BD", archivo: "subcomando_db.rb", estado: verificar_herramienta("adn/subcomando_db.rb") },
|
||
{ nombre: "Sistema de triggers", archivo: "subcomando_triggers.rb", estado: verificar_herramienta("adn/subcomando_triggers.rb") },
|
||
{ nombre: "Logger ADN", archivo: "logger.rb", estado: verificar_herramienta("adn/logger.rb") }
|
||
]
|
||
|
||
herramientas_adn.each do |herramienta|
|
||
estado_emoji = herramienta[:estado] ? "✅" : "❌"
|
||
puts " #{estado_emoji} #{herramienta[:nombre]}: #{herramienta[:archivo]}"
|
||
end
|
||
|
||
puts "\n💡 OPORTUNIDADES DE INTEGRACIÓN:"
|
||
puts " 1. Usar BuscadorBDSimple para buscar hitos relacionados con DASUTEN"
|
||
puts " 2. Integrar hitos del dashboard con el sistema de seguimiento de plan ADN"
|
||
puts " 3. Usar subcomando_db para registrar hitos completados en base de datos"
|
||
puts " 4. Implementar triggers para notificar cambios en estado de hitos"
|
||
puts " 5. Usar logger ADN para registrar actividades de seguimiento"
|
||
|
||
puts "\n🚀 ACCIONES RECOMENDADAS:"
|
||
puts " • Crear comando: adn proyecto:hitos --proyecto P2601"
|
||
puts " • Integrar dashboard con API de proyectos en dtic-BITACORAs"
|
||
puts " • Automatizar actualización de métricas del dashboard"
|
||
puts " • Implementar sistema de notificaciones para hitos críticos"
|
||
|
||
puts ""
|
||
end
|
||
|
||
def verificar_herramienta(ruta_relativa)
|
||
File.exist?(File.join(__dir__, '..', ruta_relativa))
|
||
end
|
||
|
||
def mostrar_resumen
|
||
puts "=" * 70
|
||
puts "📊 RESUMEN DEL ANÁLISIS DASHBOARD P2601"
|
||
puts "=" * 70
|
||
|
||
puts "\n🎯 ESTADO ACTUAL:"
|
||
puts " • Hitos totales: #{@estadisticas[:hitos_total] || 'N/A'}"
|
||
puts " • Completados: #{@estadisticas[:hitos_completados] || 'N/A'}"
|
||
puts " • Activos: #{@estadisticas[:hitos_activos] || 'N/A'}"
|
||
puts " • Pendientes: #{@estadisticas[:hitos_pendientes] || 'N/A'}"
|
||
puts " • Nodos online: #{@estadisticas[:nodos_online] || 'N/A'}/#{@estadisticas[:nodos_total] || 'N/A'}"
|
||
|
||
puts "\n💡 HITOS PROPUESTOS: #{@hitos_propuestos.size}"
|
||
categorias = @hitos_propuestos.group_by { |h| h[:categoria] }
|
||
categorias.each do |categoria, hitos|
|
||
puts " • #{categoria}: #{hitos.size} hitos"
|
||
end
|
||
|
||
puts "\n🔄 INTEGRACIÓN ADN:"
|
||
puts " • Herramientas disponibles: 5 verificadas"
|
||
puts " • Oportunidades identificadas: 5 áreas"
|
||
|
||
puts "\n📈 RECOMENDACIONES PRINCIPALES:"
|
||
puts " 1. Priorizar hitos FÍSICO y ADDOM antes de agregar nuevos"
|
||
puts " 2. Integrar hitos propuestos gradualmente en el dashboard"
|
||
puts " 3. Usar herramientas ADN para automatizar seguimiento"
|
||
puts " 4. Considerar implementar sistema de notificaciones"
|
||
puts " 5. Documentar lecciones aprendidas de cada hito"
|
||
|
||
puts "\n🚀 PRÓXIMOS PASOS SUGERIDOS:"
|
||
puts " 1. Ejecutar: ruby tools/analizar_dashboard_p2601.rb --proponer-hitos"
|
||
puts " 2. Revisar reporte en tmp/reporte_p2601_analisis.json"
|
||
puts " 3. Actualizar dashboard/index.html con hitos adicionales"
|
||
puts " 4. Integrar con sistema de búsqueda ADN BITACORAs"
|
||
puts " 5. Automatizar actualizaciones del dashboard"
|
||
|
||
puts "\n📅 " + Time.now.strftime('%Y-%m-%d %H:%M:%S')
|
||
puts "=" * 70
|
||
end
|
||
end
|
||
|
||
# Parsear opciones de línea de comandos
|
||
if __FILE__ == $0
|
||
opciones = {
|
||
analizar_html: false,
|
||
consultar_bd: false,
|
||
proponer_hitos: false,
|
||
generar_reporte: false,
|
||
integrar_adn: false,
|
||
debug: false
|
||
}
|
||
|
||
OptionParser.new do |opts|
|
||
opts.banner = "Uso: ruby tools/analizar_dashboard_p2601.rb [OPCIONES]"
|
||
|
||
opts.on("--analizar-html", "Analizar dashboard/index.html actual") do
|
||
opciones[:analizar_html] = true
|
||
end
|
||
|
||
opts.on("--consultar-bd", "Consultar estado en base de datos") do
|
||
opciones[:consultar_bd] = true
|
||
end
|
||
|
||
opts.on("--proponer-hitos", "Proponer hitos adicionales") do
|
||
opciones[:proponer_hitos] = true
|
||
end
|
||
|
||
opts.on("--generar-reporte", "Generar reporte completo") do
|
||
opciones[:generar_reporte] = true
|
||
end
|
||
|
||
opts.on("--integrar-adn", "Integrar con herramientas ADN existentes") do
|
||
opciones[:integrar_adn] = true
|
||
end
|
||
|
||
opts.on("--todo", "Ejecutar todas las opciones") do
|
||
opciones.each_key { |k| opciones[k] = true }
|
||
end
|
||
|
||
opts.on("--debug", "Mostrar información de depuración") do
|
||
opciones[:debug] = true
|
||
end
|
||
|
||
opts.on("-h", "--help", "Mostrar ayuda") do
|
||
puts opts
|
||
exit
|
||
end
|
||
end.parse!
|
||
|
||
# Si no se especificó ninguna opción, mostrar ayuda
|
||
if opciones.values.none? { |v| v == true }
|
||
puts "Ejecutar con --help para ver opciones disponibles"
|
||
puts "Ejemplo: ruby tools/analizar_dashboard_p2601.rb --todo"
|
||
exit
|
||
end
|
||
|
||
# Ejecutar analizador
|
||
begin
|
||
analizador = AnalizadorDashboardP2601.new(opciones)
|
||
analizador.ejecutar
|
||
rescue => e
|
||
puts "❌ Error fatal: #{e.message}"
|
||
puts e.backtrace if opciones[:debug]
|
||
exit 1
|
||
end
|
||
end
|