Eliminación del archivo README.md del convertidor LAD a pseudocódigo estructurado, optimizando la estructura del proyecto y reduciendo la confusión en la documentación. Se mantiene la funcionalidad principal del convertidor sin cambios.
This commit is contained in:
parent
b74db36cf9
commit
def0f0b2d7
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "C:/Trabajo/SIDEL/13 - E5.007560 - Modifica O&U - SAE235/Reporte/ExportTwinCat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {}
|
||||||
|
}
|
|
@ -0,0 +1,463 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Script para generar documentación de adaptación de IOs
|
||||||
|
entre TwinCAT y TIA Portal - Proyecto SIDEL
|
||||||
|
|
||||||
|
Autor: Generado automáticamente
|
||||||
|
Proyecto: E5.007560 - Modifica O&U - SAE235
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import pandas as pd
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, List, Tuple, Optional
|
||||||
|
import argparse
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
# Configurar el path al directorio raíz del proyecto
|
||||||
|
script_root = os.path.dirname(
|
||||||
|
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||||
|
)
|
||||||
|
sys.path.append(script_root)
|
||||||
|
|
||||||
|
# Importar la función de configuración
|
||||||
|
from backend.script_utils import load_configuration
|
||||||
|
|
||||||
|
|
||||||
|
def load_tiaportal_adaptations(working_directory, file_path='IO Adapted.md'):
|
||||||
|
"""Carga las adaptaciones de TIA Portal desde el archivo markdown"""
|
||||||
|
full_file_path = os.path.join(working_directory, file_path)
|
||||||
|
print(f"Cargando adaptaciones de TIA Portal desde: {full_file_path}")
|
||||||
|
|
||||||
|
adaptations = {}
|
||||||
|
|
||||||
|
if not os.path.exists(full_file_path):
|
||||||
|
print(f"⚠️ Archivo {full_file_path} no encontrado")
|
||||||
|
return adaptations
|
||||||
|
|
||||||
|
with open(full_file_path, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Patrones mejorados para diferentes tipos de IOs
|
||||||
|
patterns = [
|
||||||
|
# Digitales: E0.0, A0.0
|
||||||
|
r'\|\s*([EA]\d+\.\d+)\s*\|\s*([^|]+?)\s*\|',
|
||||||
|
# Analógicos: PEW100, PAW100
|
||||||
|
r'\|\s*(P[EA]W\d+)\s*\|\s*([^|]+?)\s*\|',
|
||||||
|
# Profibus: EW 1640, AW 1640
|
||||||
|
r'\|\s*([EA]W\s+\d+)\s*\|\s*([^|]+?)\s*\|'
|
||||||
|
]
|
||||||
|
|
||||||
|
for pattern in patterns:
|
||||||
|
matches = re.findall(pattern, content, re.MULTILINE)
|
||||||
|
for io_addr, master_tag in matches:
|
||||||
|
io_addr = io_addr.strip()
|
||||||
|
master_tag = master_tag.strip()
|
||||||
|
if io_addr and master_tag and not master_tag.startswith('-'):
|
||||||
|
adaptations[io_addr] = master_tag
|
||||||
|
print(f" 📍 {io_addr} → {master_tag}")
|
||||||
|
|
||||||
|
print(f"✅ Cargadas {len(adaptations)} adaptaciones de TIA Portal")
|
||||||
|
return adaptations
|
||||||
|
|
||||||
|
def scan_twincat_definitions(working_directory, directory='TwinCat'):
|
||||||
|
"""Escanea archivos TwinCAT para encontrar definiciones de variables AT %"""
|
||||||
|
full_directory = os.path.join(working_directory, directory)
|
||||||
|
print(f"\n🔍 Escaneando definiciones TwinCAT en: {full_directory}")
|
||||||
|
|
||||||
|
definitions = {}
|
||||||
|
|
||||||
|
if not os.path.exists(full_directory):
|
||||||
|
print(f"⚠️ Directorio {full_directory} no encontrado")
|
||||||
|
return definitions
|
||||||
|
|
||||||
|
# Patrones para definiciones AT %
|
||||||
|
definition_patterns = [
|
||||||
|
r'(\w+)\s+AT\s+%([IQ][XWB]\d+(?:\.\d+)?)\s*:\s*(\w+);', # Activas
|
||||||
|
r'(\w+)\s+\(\*\s*AT\s+%([IQ][XWB]\d+(?:\.\d+)?)\s*\*\)\s*:\s*(\w+);', # Comentadas
|
||||||
|
]
|
||||||
|
|
||||||
|
for file_path in Path(full_directory).glob('*.scl'):
|
||||||
|
print(f" 📄 Procesando: {file_path.name}")
|
||||||
|
|
||||||
|
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
for pattern in definition_patterns:
|
||||||
|
matches = re.findall(pattern, content, re.MULTILINE | re.IGNORECASE)
|
||||||
|
for var_name, io_addr, data_type in matches:
|
||||||
|
var_name = var_name.strip()
|
||||||
|
io_addr = io_addr.strip()
|
||||||
|
data_type = data_type.strip()
|
||||||
|
|
||||||
|
definitions[var_name] = {
|
||||||
|
'address': io_addr,
|
||||||
|
'type': data_type,
|
||||||
|
'file': file_path.name,
|
||||||
|
'definition_line': content[:content.find(var_name)].count('\n') + 1
|
||||||
|
}
|
||||||
|
print(f" 🔗 {var_name} AT %{io_addr} : {data_type}")
|
||||||
|
|
||||||
|
print(f"✅ Encontradas {len(definitions)} definiciones TwinCAT")
|
||||||
|
return definitions
|
||||||
|
|
||||||
|
def scan_twincat_usage(working_directory, directory='TwinCat'):
|
||||||
|
"""Escanea archivos TwinCAT para encontrar uso de variables"""
|
||||||
|
full_directory = os.path.join(working_directory, directory)
|
||||||
|
print(f"\n🔍 Escaneando uso de variables TwinCAT en: {full_directory}")
|
||||||
|
|
||||||
|
usage_data = defaultdict(list)
|
||||||
|
|
||||||
|
if not os.path.exists(full_directory):
|
||||||
|
print(f"⚠️ Directorio {full_directory} no encontrado")
|
||||||
|
return usage_data
|
||||||
|
|
||||||
|
for file_path in Path(full_directory).glob('*.scl'):
|
||||||
|
print(f" 📄 Analizando uso en: {file_path.name}")
|
||||||
|
|
||||||
|
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
for line_num, line in enumerate(lines, 1):
|
||||||
|
# Buscar variables que empiecen con DI_, DO_, AI_, AO_
|
||||||
|
var_matches = re.findall(r'\b([DA][IO]_\w+)\b', line)
|
||||||
|
for var_name in var_matches:
|
||||||
|
usage_data[var_name].append({
|
||||||
|
'file': file_path.name,
|
||||||
|
'line': line_num,
|
||||||
|
'context': line.strip()[:100] + ('...' if len(line.strip()) > 100 else '')
|
||||||
|
})
|
||||||
|
|
||||||
|
print(f"✅ Encontrado uso de {len(usage_data)} variables diferentes")
|
||||||
|
return usage_data
|
||||||
|
|
||||||
|
def convert_tia_to_twincat(tia_addr):
|
||||||
|
"""Convierte direcciones TIA Portal a formato TwinCAT"""
|
||||||
|
conversions = []
|
||||||
|
|
||||||
|
# Digitales
|
||||||
|
if re.match(r'^E\d+\.\d+$', tia_addr): # E0.0 → IX0.0
|
||||||
|
twincat_addr = tia_addr.replace('E', 'IX')
|
||||||
|
conversions.append(twincat_addr)
|
||||||
|
elif re.match(r'^A\d+\.\d+$', tia_addr): # A0.0 → QX0.0
|
||||||
|
twincat_addr = tia_addr.replace('A', 'QX')
|
||||||
|
conversions.append(twincat_addr)
|
||||||
|
|
||||||
|
# Analógicos
|
||||||
|
elif re.match(r'^PEW\d+$', tia_addr): # PEW100 → IW100
|
||||||
|
twincat_addr = tia_addr.replace('PEW', 'IW')
|
||||||
|
conversions.append(twincat_addr)
|
||||||
|
elif re.match(r'^PAW\d+$', tia_addr): # PAW100 → QW100
|
||||||
|
twincat_addr = tia_addr.replace('PAW', 'QW')
|
||||||
|
conversions.append(twincat_addr)
|
||||||
|
|
||||||
|
# Profibus
|
||||||
|
elif re.match(r'^EW\s+\d+$', tia_addr): # EW 1234 → IB1234
|
||||||
|
addr_num = re.search(r'\d+', tia_addr).group()
|
||||||
|
conversions.append(f'IB{addr_num}')
|
||||||
|
elif re.match(r'^AW\s+\d+$', tia_addr): # AW 1234 → QB1234
|
||||||
|
addr_num = re.search(r'\d+', tia_addr).group()
|
||||||
|
conversions.append(f'QB{addr_num}')
|
||||||
|
|
||||||
|
return conversions
|
||||||
|
|
||||||
|
def find_variable_by_address(definitions, target_address):
|
||||||
|
"""Busca variable por dirección exacta"""
|
||||||
|
for var_name, info in definitions.items():
|
||||||
|
if info['address'] == target_address:
|
||||||
|
return var_name, info
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
def find_variable_by_name_similarity(definitions, usage_data, master_tag):
|
||||||
|
"""Busca variables por similitud de nombre"""
|
||||||
|
candidates = []
|
||||||
|
|
||||||
|
# Limpiar el master tag para comparación
|
||||||
|
clean_master = re.sub(r'^[DA][IO]_', '', master_tag).lower()
|
||||||
|
|
||||||
|
# Buscar en definiciones
|
||||||
|
for var_name, info in definitions.items():
|
||||||
|
clean_var = re.sub(r'^[DA][IO]_', '', var_name).lower()
|
||||||
|
if clean_master in clean_var or clean_var in clean_master:
|
||||||
|
candidates.append((var_name, info, 'definition'))
|
||||||
|
|
||||||
|
# Buscar en uso
|
||||||
|
for var_name in usage_data.keys():
|
||||||
|
clean_var = re.sub(r'^[DA][IO]_', '', var_name).lower()
|
||||||
|
if clean_master in clean_var or clean_var in clean_master:
|
||||||
|
# Intentar encontrar la definición de esta variable
|
||||||
|
var_info = definitions.get(var_name)
|
||||||
|
if not var_info:
|
||||||
|
var_info = {'address': 'Unknown', 'type': 'Unknown', 'file': 'Not found'}
|
||||||
|
candidates.append((var_name, var_info, 'usage'))
|
||||||
|
|
||||||
|
return candidates
|
||||||
|
|
||||||
|
def analyze_adaptations(tia_adaptations, twincat_definitions, twincat_usage):
|
||||||
|
"""Analiza las correlaciones entre TIA Portal y TwinCAT"""
|
||||||
|
print(f"\n📊 Analizando correlaciones...")
|
||||||
|
|
||||||
|
results = []
|
||||||
|
matches_found = 0
|
||||||
|
|
||||||
|
for tia_addr, master_tag in tia_adaptations.items():
|
||||||
|
result = {
|
||||||
|
'tia_address': tia_addr,
|
||||||
|
'master_tag': master_tag,
|
||||||
|
'twincat_variable': None,
|
||||||
|
'twincat_address': None,
|
||||||
|
'twincat_type': None,
|
||||||
|
'match_type': None,
|
||||||
|
'definition_file': None,
|
||||||
|
'usage_files': [],
|
||||||
|
'usage_count': 0,
|
||||||
|
'confidence': 'Low'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1. Buscar por conversión directa de dirección
|
||||||
|
twincat_addresses = convert_tia_to_twincat(tia_addr)
|
||||||
|
var_found = False
|
||||||
|
|
||||||
|
for twincat_addr in twincat_addresses:
|
||||||
|
var_name, var_info = find_variable_by_address(twincat_definitions, twincat_addr)
|
||||||
|
if var_name:
|
||||||
|
result.update({
|
||||||
|
'twincat_variable': var_name,
|
||||||
|
'twincat_address': var_info['address'],
|
||||||
|
'twincat_type': var_info['type'],
|
||||||
|
'match_type': 'Address Match',
|
||||||
|
'definition_file': var_info['file'],
|
||||||
|
'confidence': 'High'
|
||||||
|
})
|
||||||
|
var_found = True
|
||||||
|
matches_found += 1
|
||||||
|
break
|
||||||
|
|
||||||
|
# 2. Si no se encontró por dirección, buscar por nombre
|
||||||
|
if not var_found:
|
||||||
|
candidates = find_variable_by_name_similarity(twincat_definitions, twincat_usage, master_tag)
|
||||||
|
if candidates:
|
||||||
|
# Tomar el mejor candidato
|
||||||
|
best_candidate = candidates[0]
|
||||||
|
var_name, var_info, source = best_candidate
|
||||||
|
|
||||||
|
result.update({
|
||||||
|
'twincat_variable': var_name,
|
||||||
|
'twincat_address': var_info.get('address', 'Unknown'),
|
||||||
|
'twincat_type': var_info.get('type', 'Unknown'),
|
||||||
|
'match_type': f'Name Similarity ({source})',
|
||||||
|
'definition_file': var_info.get('file', 'Unknown'),
|
||||||
|
'confidence': 'Medium'
|
||||||
|
})
|
||||||
|
matches_found += 1
|
||||||
|
|
||||||
|
# 3. Buscar información de uso
|
||||||
|
if result['twincat_variable']:
|
||||||
|
var_name = result['twincat_variable']
|
||||||
|
if var_name in twincat_usage:
|
||||||
|
usage_info = twincat_usage[var_name]
|
||||||
|
result['usage_files'] = list(set([u['file'] for u in usage_info]))
|
||||||
|
result['usage_count'] = len(usage_info)
|
||||||
|
|
||||||
|
results.append(result)
|
||||||
|
|
||||||
|
# Log del progreso
|
||||||
|
status = "✅" if result['twincat_variable'] else "❌"
|
||||||
|
print(f" {status} {tia_addr} → {master_tag}")
|
||||||
|
if result['twincat_variable']:
|
||||||
|
print(f" 🔗 {result['twincat_variable']} AT %{result['twincat_address']}")
|
||||||
|
if result['usage_count'] > 0:
|
||||||
|
print(f" 📝 Usado en {result['usage_count']} lugares: {', '.join(result['usage_files'])}")
|
||||||
|
|
||||||
|
print(f"\n🎯 Resumen: {matches_found}/{len(tia_adaptations)} variables correlacionadas ({matches_found/len(tia_adaptations)*100:.1f}%)")
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def create_results_directory(working_directory):
|
||||||
|
"""Crea el directorio de resultados si no existe"""
|
||||||
|
results_dir = Path(working_directory) / 'resultados'
|
||||||
|
results_dir.mkdir(exist_ok=True)
|
||||||
|
print(f"📁 Directorio de resultados: {results_dir.absolute()}")
|
||||||
|
return results_dir
|
||||||
|
|
||||||
|
def generate_json_output(results, working_directory, output_file='io_adaptation_data.json'):
|
||||||
|
"""Genera archivo JSON con datos estructurados para análisis posterior"""
|
||||||
|
full_output_file = os.path.join(working_directory, 'resultados', output_file)
|
||||||
|
print(f"\n📄 Generando archivo JSON: {full_output_file}")
|
||||||
|
|
||||||
|
json_data = {
|
||||||
|
"metadata": {
|
||||||
|
"generated_at": pd.Timestamp.now().isoformat(),
|
||||||
|
"project": "E5.007560 - Modifica O&U - SAE235",
|
||||||
|
"total_adaptations": len(results),
|
||||||
|
"matched_variables": len([r for r in results if r['twincat_variable']]),
|
||||||
|
"high_confidence": len([r for r in results if r['confidence'] == 'High']),
|
||||||
|
"medium_confidence": len([r for r in results if r['confidence'] == 'Medium'])
|
||||||
|
},
|
||||||
|
"adaptations": []
|
||||||
|
}
|
||||||
|
|
||||||
|
for result in results:
|
||||||
|
adaptation = {
|
||||||
|
"tia_portal": {
|
||||||
|
"address": result['tia_address'],
|
||||||
|
"tag": result['master_tag']
|
||||||
|
},
|
||||||
|
"twincat": {
|
||||||
|
"variable": result['twincat_variable'],
|
||||||
|
"address": result['twincat_address'],
|
||||||
|
"data_type": result['twincat_type'],
|
||||||
|
"definition_file": result['definition_file']
|
||||||
|
},
|
||||||
|
"correlation": {
|
||||||
|
"match_type": result['match_type'],
|
||||||
|
"confidence": result['confidence'],
|
||||||
|
"found": result['twincat_variable'] is not None
|
||||||
|
},
|
||||||
|
"usage": {
|
||||||
|
"usage_count": result['usage_count'],
|
||||||
|
"usage_files": result['usage_files']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
json_data["adaptations"].append(adaptation)
|
||||||
|
|
||||||
|
with open(full_output_file, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(json_data, f, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
print(f"✅ Archivo JSON generado: {full_output_file}")
|
||||||
|
|
||||||
|
def generate_detailed_report(results, working_directory, output_file='IO_Detailed_Analysis_Report.md'):
|
||||||
|
"""Genera un reporte detallado con tabla markdown"""
|
||||||
|
full_output_file = os.path.join(working_directory, 'resultados', output_file)
|
||||||
|
print(f"\n📄 Generando reporte detallado: {full_output_file}")
|
||||||
|
|
||||||
|
with open(full_output_file, 'w', encoding='utf-8') as f:
|
||||||
|
f.write("# Reporte Detallado de Análisis de Adaptación IO\n\n")
|
||||||
|
f.write(f"**Fecha de generación:** {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
|
||||||
|
|
||||||
|
# Estadísticas
|
||||||
|
total = len(results)
|
||||||
|
matched = len([r for r in results if r['twincat_variable']])
|
||||||
|
high_conf = len([r for r in results if r['confidence'] == 'High'])
|
||||||
|
medium_conf = len([r for r in results if r['confidence'] == 'Medium'])
|
||||||
|
|
||||||
|
f.write("## 📊 Estadísticas Generales\n\n")
|
||||||
|
f.write(f"- **Total adaptaciones procesadas:** {total}\n")
|
||||||
|
f.write(f"- **Variables encontradas:** {matched} ({matched/total*100:.1f}%)\n")
|
||||||
|
f.write(f"- **Coincidencias de alta confianza:** {high_conf}\n")
|
||||||
|
f.write(f"- **Coincidencias de media confianza:** {medium_conf}\n\n")
|
||||||
|
|
||||||
|
# Tabla de variables correlacionadas exitosamente
|
||||||
|
f.write("## ✅ Variables Correlacionadas Exitosamente\n\n")
|
||||||
|
matched_results = [r for r in results if r['twincat_variable']]
|
||||||
|
|
||||||
|
if matched_results:
|
||||||
|
# Encabezado de la tabla
|
||||||
|
f.write("| TIA Address | TIA Tag | TwinCAT Variable | TwinCAT Address | Tipo | Método | Confianza | Archivo Def. | Uso | Archivos Uso |\n")
|
||||||
|
f.write("|-------------|---------|------------------|-----------------|------|--------|-----------|--------------|-----|---------------|\n")
|
||||||
|
|
||||||
|
# Filas de datos
|
||||||
|
for result in matched_results:
|
||||||
|
usage_files_str = ', '.join(result['usage_files'][:3]) # Limitar a 3 archivos
|
||||||
|
if len(result['usage_files']) > 3:
|
||||||
|
usage_files_str += "..."
|
||||||
|
|
||||||
|
f.write(f"| {result['tia_address']} | "
|
||||||
|
f"`{result['master_tag']}` | "
|
||||||
|
f"`{result['twincat_variable']}` | "
|
||||||
|
f"`%{result['twincat_address']}` | "
|
||||||
|
f"`{result['twincat_type']}` | "
|
||||||
|
f"{result['match_type']} | "
|
||||||
|
f"{result['confidence']} | "
|
||||||
|
f"{result['definition_file']} | "
|
||||||
|
f"{result['usage_count']} | "
|
||||||
|
f"{usage_files_str} |\n")
|
||||||
|
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
|
# Tabla de variables no encontradas
|
||||||
|
f.write("## ❌ Variables No Encontradas\n\n")
|
||||||
|
unmatched_results = [r for r in results if not r['twincat_variable']]
|
||||||
|
|
||||||
|
if unmatched_results:
|
||||||
|
f.write("| TIA Address | TIA Tag |\n")
|
||||||
|
f.write("|-------------|----------|\n")
|
||||||
|
|
||||||
|
for result in unmatched_results:
|
||||||
|
f.write(f"| {result['tia_address']} | `{result['master_tag']}` |\n")
|
||||||
|
|
||||||
|
f.write(f"\n**Total no encontradas:** {len(unmatched_results)}\n\n")
|
||||||
|
|
||||||
|
# Recomendaciones
|
||||||
|
f.write("## 💡 Recomendaciones\n\n")
|
||||||
|
f.write("1. **Variables de alta confianza** pueden migrarse directamente\n")
|
||||||
|
f.write("2. **Variables de media confianza** requieren verificación manual\n")
|
||||||
|
f.write("3. **Variables no encontradas** requieren mapeo manual o pueden ser obsoletas\n")
|
||||||
|
f.write("4. Variables con uso extensivo son prioritarias para la migración\n\n")
|
||||||
|
|
||||||
|
# Resumen por confianza
|
||||||
|
f.write("## 📈 Distribución por Confianza\n\n")
|
||||||
|
f.write("| Nivel de Confianza | Cantidad | Porcentaje |\n")
|
||||||
|
f.write("|--------------------|----------|------------|\n")
|
||||||
|
f.write(f"| Alta | {high_conf} | {high_conf/total*100:.1f}% |\n")
|
||||||
|
f.write(f"| Media | {medium_conf} | {medium_conf/total*100:.1f}% |\n")
|
||||||
|
f.write(f"| No encontradas | {total-matched} | {(total-matched)/total*100:.1f}% |\n")
|
||||||
|
|
||||||
|
print(f"✅ Reporte detallado generado: {full_output_file}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("🚀 Iniciando análisis detallado de adaptación de IOs TwinCAT ↔ TIA Portal")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
# Cargar configuración
|
||||||
|
configs = load_configuration()
|
||||||
|
|
||||||
|
# Verificar que se cargó correctamente
|
||||||
|
if not configs:
|
||||||
|
print("Advertencia: No se pudo cargar la configuración, usando valores por defecto")
|
||||||
|
working_directory = "./"
|
||||||
|
else:
|
||||||
|
working_directory = configs.get("working_directory", "./")
|
||||||
|
|
||||||
|
# Verificar directorio de trabajo
|
||||||
|
if not os.path.exists(working_directory):
|
||||||
|
print(f"Error: El directorio de trabajo no existe: {working_directory}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"📁 Directorio de trabajo: {working_directory}")
|
||||||
|
|
||||||
|
# Crear directorio de resultados
|
||||||
|
results_dir = create_results_directory(working_directory)
|
||||||
|
|
||||||
|
# Cargar datos
|
||||||
|
tia_adaptations = load_tiaportal_adaptations(working_directory)
|
||||||
|
twincat_definitions = scan_twincat_definitions(working_directory)
|
||||||
|
twincat_usage = scan_twincat_usage(working_directory)
|
||||||
|
|
||||||
|
# Analizar correlaciones
|
||||||
|
results = analyze_adaptations(tia_adaptations, twincat_definitions, twincat_usage)
|
||||||
|
|
||||||
|
# Generar reportes en el directorio de resultados
|
||||||
|
generate_detailed_report(results, working_directory)
|
||||||
|
generate_json_output(results, working_directory)
|
||||||
|
|
||||||
|
# Generar CSV para análisis adicional
|
||||||
|
df = pd.DataFrame(results)
|
||||||
|
csv_file = results_dir / 'io_detailed_analysis.csv'
|
||||||
|
df.to_csv(csv_file, index=False, encoding='utf-8')
|
||||||
|
print(f"✅ Datos exportados a CSV: {csv_file}")
|
||||||
|
|
||||||
|
print(f"\n🎉 Análisis completado exitosamente!")
|
||||||
|
print(f"📁 Archivos generados en: {results_dir.absolute()}")
|
||||||
|
print(f" 📄 {results_dir / 'IO_Detailed_Analysis_Report.md'}")
|
||||||
|
print(f" 📄 {results_dir / 'io_adaptation_data.json'}")
|
||||||
|
print(f" 📄 {results_dir / 'io_detailed_analysis.csv'}")
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
results = main()
|
|
@ -0,0 +1,115 @@
|
||||||
|
# Análisis de Adaptación IO - TwinCAT ↔ TIA Portal
|
||||||
|
|
||||||
|
Scripts de análisis automático para correlacionar variables IO entre plataformas TwinCAT y TIA Portal en el proyecto SIDEL E5.007560.
|
||||||
|
|
||||||
|
## 📋 Descripción General
|
||||||
|
|
||||||
|
Este proyecto automatiza el análisis de adaptación de variables de entrada/salida (IO) entre:
|
||||||
|
- **TIA Portal** (Siemens) - Sistema actual
|
||||||
|
- **TwinCAT** (Beckhoff) - Sistema objetivo de migración
|
||||||
|
|
||||||
|
## 🔧 Scripts Incluidos
|
||||||
|
|
||||||
|
### 1. `x1_io_adaptation_script.py` - Análisis de Correlación IO
|
||||||
|
|
||||||
|
**Propósito:** Encuentra y correlaciona variables IO entre ambas plataformas generando reportes detallados.
|
||||||
|
|
||||||
|
**Archivos requeridos:**
|
||||||
|
- `IO Adapted.md` - Tabla de adaptaciones TIA Portal (debe estar en directorio raíz)
|
||||||
|
- `TwinCat/` - Directorio con archivos `.scl` de TwinCAT
|
||||||
|
- `TiaPortal/` - Directorio con archivos `.md` de TIA Portal
|
||||||
|
|
||||||
|
**Archivos generados:**
|
||||||
|
- `resultados/IO_Detailed_Analysis_Report.md` - Reporte con tablas markdown
|
||||||
|
- `resultados/io_adaptation_data.json` - Datos estructurados para análisis
|
||||||
|
- `resultados/io_detailed_analysis.csv` - Datos tabulares
|
||||||
|
|
||||||
|
### 2. `x2_code_snippets_generator.py` - Generador de Snippets de Código
|
||||||
|
|
||||||
|
**Propósito:** Genera snippets de código mostrando el uso real de cada variable en ambas plataformas.
|
||||||
|
|
||||||
|
**Archivos requeridos:**
|
||||||
|
- `resultados/io_adaptation_data.json` - Generado por el script 1
|
||||||
|
- `TwinCat/` - Directorio con archivos `.scl`
|
||||||
|
- `TiaPortal/` - Directorio con archivos `.md`
|
||||||
|
|
||||||
|
**Archivos generados:**
|
||||||
|
- `resultados/IO_Code_Snippets_Report.md` - Snippets de código con contexto
|
||||||
|
- `resultados/IO_Usage_Statistics.md` - Estadísticas de uso
|
||||||
|
|
||||||
|
## 🚀 Uso
|
||||||
|
|
||||||
|
### Paso 1: Ejecutar análisis de correlación
|
||||||
|
```bash
|
||||||
|
python x1_io_adaptation_script.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Paso 2: Generar snippets de código
|
||||||
|
```bash
|
||||||
|
python x2_code_snippets_generator.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 Estructura de Directorios Requerida
|
||||||
|
|
||||||
|
```
|
||||||
|
proyecto/
|
||||||
|
├── x1_io_adaptation_script.py
|
||||||
|
├── x2_code_snippets_generator.py
|
||||||
|
├── IO Adapted.md # Tabla de adaptaciones TIA
|
||||||
|
├── TwinCat/ # Archivos .scl TwinCAT
|
||||||
|
│ ├── GLOBAL_VARIABLES_IN_OUT.scl
|
||||||
|
│ ├── INPUT.scl
|
||||||
|
│ └── ... (otros archivos .scl)
|
||||||
|
├── TiaPortal/ # Archivos .md TIA Portal
|
||||||
|
│ ├── Input.md
|
||||||
|
│ ├── Output.md
|
||||||
|
│ └── ... (otros archivos .md)
|
||||||
|
└── resultados/ # Directorio creado automáticamente
|
||||||
|
├── IO_Detailed_Analysis_Report.md
|
||||||
|
├── io_adaptation_data.json
|
||||||
|
├── io_detailed_analysis.csv
|
||||||
|
├── IO_Code_Snippets_Report.md
|
||||||
|
└── IO_Usage_Statistics.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Funcionalidades Principales
|
||||||
|
|
||||||
|
### Script 1 - Análisis de Correlación
|
||||||
|
- ✅ Convierte direcciones TIA Portal a formato TwinCAT
|
||||||
|
- ✅ Busca variables por dirección exacta y similitud de nombres
|
||||||
|
- ✅ Calcula nivel de confianza de correlaciones
|
||||||
|
- ✅ Genera reportes en múltiples formatos (MD, JSON, CSV)
|
||||||
|
|
||||||
|
### Script 2 - Snippets de Código
|
||||||
|
- ✅ Muestra hasta 3 usos por variable por plataforma
|
||||||
|
- ✅ Contexto de 3 líneas (anterior, actual, siguiente)
|
||||||
|
- ✅ Links markdown a archivos fuente
|
||||||
|
- ✅ Estadísticas de uso y archivos más referenciados
|
||||||
|
|
||||||
|
## 📊 Resultados Típicos
|
||||||
|
|
||||||
|
- **Variables procesadas:** ~90-100 adaptaciones IO
|
||||||
|
- **Tasa de correlación:** ~70-80% de variables encontradas
|
||||||
|
- **Confianza alta:** Correlaciones por dirección exacta
|
||||||
|
- **Variable más usada:** Típicamente botones de reset/start/stop
|
||||||
|
|
||||||
|
## 🛠 Dependencias
|
||||||
|
|
||||||
|
```python
|
||||||
|
pandas
|
||||||
|
pathlib (incluida en Python 3.4+)
|
||||||
|
json (incluida en Python estándar)
|
||||||
|
re (incluida en Python estándar)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 Notas Importantes
|
||||||
|
|
||||||
|
1. **Orden de ejecución:** Ejecutar siempre el Script 1 antes que el Script 2
|
||||||
|
2. **Archivos fuente:** Verificar que existan los directorios TwinCat/ y TiaPortal/
|
||||||
|
3. **Codificación:** Los scripts manejan archivos con encoding UTF-8
|
||||||
|
4. **Rendimiento:** El Script 2 puede tardar algunos minutos procesando archivos grandes
|
||||||
|
|
||||||
|
## 👥 Proyecto
|
||||||
|
|
||||||
|
**Proyecto SIDEL:** E5.007560 - Modifica O&U - SAE235
|
||||||
|
**Automatización:** Migración TIA Portal → TwinCAT
|
|
@ -0,0 +1,315 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Script para generar snippets de código de uso de variables IO
|
||||||
|
entre TwinCAT y TIA Portal - Proyecto SIDEL
|
||||||
|
|
||||||
|
Autor: Generado automáticamente
|
||||||
|
Proyecto: E5.007560 - Modifica O&U - SAE235
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, List, Tuple, Optional
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
# Configurar el path al directorio raíz del proyecto
|
||||||
|
script_root = os.path.dirname(
|
||||||
|
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||||
|
)
|
||||||
|
sys.path.append(script_root)
|
||||||
|
|
||||||
|
# Importar la función de configuración
|
||||||
|
from backend.script_utils import load_configuration
|
||||||
|
|
||||||
|
|
||||||
|
def load_adaptation_data(working_directory, json_file='io_adaptation_data.json'):
|
||||||
|
"""Carga los datos de adaptación desde el archivo JSON"""
|
||||||
|
full_json_file = os.path.join(working_directory, 'resultados', json_file)
|
||||||
|
print(f"📖 Cargando datos de adaptación desde: {full_json_file}")
|
||||||
|
|
||||||
|
if not os.path.exists(full_json_file):
|
||||||
|
print(f"⚠️ Archivo {full_json_file} no encontrado")
|
||||||
|
return None
|
||||||
|
|
||||||
|
with open(full_json_file, 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
print(f"✅ Cargados datos de {data['metadata']['total_adaptations']} adaptaciones")
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def find_variable_usage_in_file(file_path, variable_name, max_occurrences=3):
|
||||||
|
"""Encuentra el uso de una variable en un archivo específico y retorna el contexto"""
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
return []
|
||||||
|
|
||||||
|
usages = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
# Buscar todas las líneas que contienen la variable
|
||||||
|
found_lines = []
|
||||||
|
for line_num, line in enumerate(lines):
|
||||||
|
# Buscar la variable como palabra completa (no como parte de otra palabra)
|
||||||
|
if re.search(rf'\b{re.escape(variable_name)}\b', line):
|
||||||
|
found_lines.append((line_num, line.strip()))
|
||||||
|
if len(found_lines) >= max_occurrences:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Para cada ocurrencia, obtener contexto (línea anterior, actual, siguiente)
|
||||||
|
for line_num, line_content in found_lines:
|
||||||
|
context = {
|
||||||
|
'line_number': line_num + 1, # Convertir a 1-indexado
|
||||||
|
'before': lines[line_num - 1].strip() if line_num > 0 else "",
|
||||||
|
'current': line_content,
|
||||||
|
'after': lines[line_num + 1].strip() if line_num < len(lines) - 1 else ""
|
||||||
|
}
|
||||||
|
usages.append(context)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ Error leyendo archivo {file_path}: {e}")
|
||||||
|
|
||||||
|
return usages
|
||||||
|
|
||||||
|
|
||||||
|
def find_tia_portal_usage(adaptation, working_directory):
|
||||||
|
"""Busca el uso de variables TIA Portal en archivos markdown"""
|
||||||
|
tia_address = adaptation['tia_portal']['address']
|
||||||
|
tia_tag = adaptation['tia_portal']['tag']
|
||||||
|
|
||||||
|
# Buscar en archivos TIA Portal (principalmente en archivos .md)
|
||||||
|
tia_usages = []
|
||||||
|
|
||||||
|
# Buscar en TiaPortal/ directory
|
||||||
|
tia_portal_dir = Path(working_directory) / 'TiaPortal'
|
||||||
|
if tia_portal_dir.exists():
|
||||||
|
for md_file in tia_portal_dir.glob('*.md'):
|
||||||
|
# Buscar por dirección TIA
|
||||||
|
address_usages = find_variable_usage_in_file(md_file, tia_address, 2)
|
||||||
|
for usage in address_usages:
|
||||||
|
usage['file'] = f"TiaPortal/{md_file.name}"
|
||||||
|
usage['search_term'] = tia_address
|
||||||
|
tia_usages.append(usage)
|
||||||
|
|
||||||
|
# Buscar por tag TIA si es diferente
|
||||||
|
if tia_tag != tia_address:
|
||||||
|
tag_usages = find_variable_usage_in_file(md_file, tia_tag, 1)
|
||||||
|
for usage in tag_usages:
|
||||||
|
usage['file'] = f"TiaPortal/{md_file.name}"
|
||||||
|
usage['search_term'] = tia_tag
|
||||||
|
tia_usages.append(usage)
|
||||||
|
|
||||||
|
# Limitar total de usos TIA
|
||||||
|
if len(tia_usages) >= 3:
|
||||||
|
break
|
||||||
|
|
||||||
|
return tia_usages[:3] # Máximo 3 usos TIA
|
||||||
|
|
||||||
|
|
||||||
|
def find_twincat_usage(adaptation, working_directory):
|
||||||
|
"""Busca el uso de variables TwinCAT en archivos .scl"""
|
||||||
|
if not adaptation['correlation']['found']:
|
||||||
|
return []
|
||||||
|
|
||||||
|
variable_name = adaptation['twincat']['variable']
|
||||||
|
usage_files = adaptation['usage']['usage_files']
|
||||||
|
|
||||||
|
twincat_usages = []
|
||||||
|
|
||||||
|
# Buscar en archivos TwinCAT
|
||||||
|
twincat_dir = Path(working_directory) / 'TwinCat'
|
||||||
|
if twincat_dir.exists():
|
||||||
|
for file_name in usage_files:
|
||||||
|
file_path = twincat_dir / file_name
|
||||||
|
if file_path.exists():
|
||||||
|
usages = find_variable_usage_in_file(file_path, variable_name, 2)
|
||||||
|
for usage in usages:
|
||||||
|
usage['file'] = f"TwinCat/{file_name}"
|
||||||
|
usage['search_term'] = variable_name
|
||||||
|
twincat_usages.append(usage)
|
||||||
|
|
||||||
|
# Limitar por archivo
|
||||||
|
if len(twincat_usages) >= 3:
|
||||||
|
break
|
||||||
|
|
||||||
|
return twincat_usages[:3] # Máximo 3 usos TwinCAT
|
||||||
|
|
||||||
|
|
||||||
|
def generate_code_snippets_report(data, working_directory, output_file='IO_Code_Snippets_Report.md'):
|
||||||
|
"""Genera el reporte con snippets de código"""
|
||||||
|
full_output_file = os.path.join(working_directory, 'resultados', output_file)
|
||||||
|
print(f"\n📄 Generando reporte de snippets: {full_output_file}")
|
||||||
|
|
||||||
|
matched_adaptations = [a for a in data['adaptations'] if a['correlation']['found']]
|
||||||
|
|
||||||
|
with open(full_output_file, 'w', encoding='utf-8') as f:
|
||||||
|
f.write("# Reporte de Snippets de Código - Adaptación IO\n\n")
|
||||||
|
f.write(f"**Fecha de generación:** {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
||||||
|
f.write(f"**Proyecto:** {data['metadata']['project']}\n\n")
|
||||||
|
|
||||||
|
f.write("## 📋 Resumen\n\n")
|
||||||
|
f.write(f"- **Variables analizadas:** {len(matched_adaptations)}\n")
|
||||||
|
f.write(f"- **Snippets generados:** Se muestran hasta 3 usos por plataforma\n")
|
||||||
|
f.write(f"- **Formato:** Contexto de 3 líneas (anterior, actual, siguiente)\n\n")
|
||||||
|
|
||||||
|
f.write("---\n\n")
|
||||||
|
|
||||||
|
# Procesar cada adaptación
|
||||||
|
for i, adaptation in enumerate(matched_adaptations, 1):
|
||||||
|
tia_address = adaptation['tia_portal']['address']
|
||||||
|
tia_tag = adaptation['tia_portal']['tag']
|
||||||
|
twincat_var = adaptation['twincat']['variable']
|
||||||
|
twincat_addr = adaptation['twincat']['address']
|
||||||
|
|
||||||
|
print(f" 📝 Procesando {i}/{len(matched_adaptations)}: {tia_address} → {twincat_var}")
|
||||||
|
|
||||||
|
f.write(f"## {i}. {tia_address} → {twincat_var}\n\n")
|
||||||
|
f.write(f"**TIA Portal:** `{tia_tag}` (`{tia_address}`)\n")
|
||||||
|
f.write(f"**TwinCAT:** `{twincat_var}` (`%{twincat_addr}`)\n")
|
||||||
|
f.write(f"**Tipo:** `{adaptation['twincat']['data_type']}`\n\n")
|
||||||
|
|
||||||
|
# Buscar usos en TIA Portal
|
||||||
|
f.write("### 🔵 Uso en TIA Portal\n\n")
|
||||||
|
tia_usages = find_tia_portal_usage(adaptation, working_directory)
|
||||||
|
|
||||||
|
if tia_usages:
|
||||||
|
for j, usage in enumerate(tia_usages):
|
||||||
|
f.write(f"**Uso {j+1}:** [{usage['file']}]({usage['file']}) - Línea {usage['line_number']}\n\n")
|
||||||
|
f.write("```scl\n")
|
||||||
|
if usage['before']:
|
||||||
|
f.write(f"{usage['before']}\n")
|
||||||
|
f.write(f">>> {usage['current']} // ← {usage['search_term']}\n")
|
||||||
|
if usage['after']:
|
||||||
|
f.write(f"{usage['after']}\n")
|
||||||
|
f.write("```\n\n")
|
||||||
|
else:
|
||||||
|
f.write("*No se encontraron usos específicos en archivos TIA Portal.*\n\n")
|
||||||
|
|
||||||
|
# Buscar usos en TwinCAT
|
||||||
|
f.write("### 🟢 Uso en TwinCAT\n\n")
|
||||||
|
twincat_usages = find_twincat_usage(adaptation, working_directory)
|
||||||
|
|
||||||
|
if twincat_usages:
|
||||||
|
for j, usage in enumerate(twincat_usages):
|
||||||
|
f.write(f"**Uso {j+1}:** [{usage['file']}]({usage['file']}) - Línea {usage['line_number']}\n\n")
|
||||||
|
f.write("```scl\n")
|
||||||
|
if usage['before']:
|
||||||
|
f.write(f"{usage['before']}\n")
|
||||||
|
f.write(f">>> {usage['current']} // ← {usage['search_term']}\n")
|
||||||
|
if usage['after']:
|
||||||
|
f.write(f"{usage['after']}\n")
|
||||||
|
f.write("```\n\n")
|
||||||
|
else:
|
||||||
|
f.write("*Variable definida pero no se encontraron usos específicos.*\n\n")
|
||||||
|
|
||||||
|
f.write("---\n\n")
|
||||||
|
|
||||||
|
print(f"✅ Reporte de snippets generado: {full_output_file}")
|
||||||
|
|
||||||
|
|
||||||
|
def generate_summary_statistics(data, working_directory, output_file='IO_Usage_Statistics.md'):
|
||||||
|
"""Genera estadísticas de uso de las variables"""
|
||||||
|
full_output_file = os.path.join(working_directory, 'resultados', output_file)
|
||||||
|
print(f"\n📊 Generando estadísticas de uso: {full_output_file}")
|
||||||
|
|
||||||
|
matched_adaptations = [a for a in data['adaptations'] if a['correlation']['found']]
|
||||||
|
|
||||||
|
# Calcular estadísticas
|
||||||
|
total_usage = sum(a['usage']['usage_count'] for a in matched_adaptations)
|
||||||
|
variables_with_usage = len([a for a in matched_adaptations if a['usage']['usage_count'] > 0])
|
||||||
|
|
||||||
|
# Variables más usadas
|
||||||
|
most_used = sorted(matched_adaptations, key=lambda x: x['usage']['usage_count'], reverse=True)[:10]
|
||||||
|
|
||||||
|
# Archivos más referenciados
|
||||||
|
file_usage = {}
|
||||||
|
for adaptation in matched_adaptations:
|
||||||
|
for file_name in adaptation['usage']['usage_files']:
|
||||||
|
file_usage[file_name] = file_usage.get(file_name, 0) + 1
|
||||||
|
|
||||||
|
top_files = sorted(file_usage.items(), key=lambda x: x[1], reverse=True)[:10]
|
||||||
|
|
||||||
|
with open(full_output_file, 'w', encoding='utf-8') as f:
|
||||||
|
f.write("# Estadísticas de Uso de Variables IO\n\n")
|
||||||
|
f.write(f"**Fecha de generación:** {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
|
||||||
|
|
||||||
|
f.write("## 📊 Resumen General\n\n")
|
||||||
|
f.write(f"- **Variables correlacionadas:** {len(matched_adaptations)}\n")
|
||||||
|
f.write(f"- **Variables con uso documentado:** {variables_with_usage}\n")
|
||||||
|
f.write(f"- **Total de usos encontrados:** {total_usage}\n")
|
||||||
|
f.write(f"- **Promedio de usos por variable:** {total_usage/len(matched_adaptations):.1f}\n\n")
|
||||||
|
|
||||||
|
f.write("## 🔥 Top 10 Variables Más Usadas\n\n")
|
||||||
|
f.write("| Ranking | TIA Address | TwinCAT Variable | Usos | Archivos |\n")
|
||||||
|
f.write("|---------|-------------|------------------|------|----------|\n")
|
||||||
|
|
||||||
|
for i, adaptation in enumerate(most_used, 1):
|
||||||
|
files_str = ', '.join(adaptation['usage']['usage_files'][:3])
|
||||||
|
if len(adaptation['usage']['usage_files']) > 3:
|
||||||
|
files_str += '...'
|
||||||
|
|
||||||
|
f.write(f"| {i} | {adaptation['tia_portal']['address']} | "
|
||||||
|
f"`{adaptation['twincat']['variable']}` | "
|
||||||
|
f"{adaptation['usage']['usage_count']} | {files_str} |\n")
|
||||||
|
|
||||||
|
f.write("\n## 📁 Top 10 Archivos Más Referenciados\n\n")
|
||||||
|
f.write("| Ranking | Archivo | Variables Usadas |\n")
|
||||||
|
f.write("|---------|---------|------------------|\n")
|
||||||
|
|
||||||
|
for i, (file_name, count) in enumerate(top_files, 1):
|
||||||
|
f.write(f"| {i} | `{file_name}` | {count} |\n")
|
||||||
|
|
||||||
|
print(f"✅ Estadísticas de uso generadas: {full_output_file}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("🚀 Iniciando generación de snippets de código para adaptación IO")
|
||||||
|
print("=" * 70)
|
||||||
|
|
||||||
|
# Cargar configuración
|
||||||
|
configs = load_configuration()
|
||||||
|
|
||||||
|
# Verificar que se cargó correctamente
|
||||||
|
if not configs:
|
||||||
|
print("Advertencia: No se pudo cargar la configuración, usando valores por defecto")
|
||||||
|
working_directory = "./"
|
||||||
|
else:
|
||||||
|
working_directory = configs.get("working_directory", "./")
|
||||||
|
|
||||||
|
# Verificar directorio de trabajo
|
||||||
|
if not os.path.exists(working_directory):
|
||||||
|
print(f"Error: El directorio de trabajo no existe: {working_directory}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"📁 Directorio de trabajo: {working_directory}")
|
||||||
|
|
||||||
|
# Crear directorio de resultados si no existe
|
||||||
|
results_dir = Path(working_directory) / 'resultados'
|
||||||
|
results_dir.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
# Cargar datos de adaptación
|
||||||
|
data = load_adaptation_data(working_directory)
|
||||||
|
if not data:
|
||||||
|
print("❌ No se pudieron cargar los datos de adaptación")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Generar reporte de snippets
|
||||||
|
generate_code_snippets_report(data, working_directory)
|
||||||
|
|
||||||
|
# Generar estadísticas de uso
|
||||||
|
generate_summary_statistics(data, working_directory)
|
||||||
|
|
||||||
|
print(f"\n🎉 Generación completada exitosamente!")
|
||||||
|
print(f"📁 Archivos generados en: {results_dir.absolute()}")
|
||||||
|
print(f" 📄 {results_dir / 'IO_Code_Snippets_Report.md'}")
|
||||||
|
print(f" 📄 {results_dir / 'IO_Usage_Statistics.md'}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
18675
data/log.txt
18675
data/log.txt
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue