Mejorado la descripcion de las extracciones de Tag con Patrones
This commit is contained in:
parent
8573d942c4
commit
633cd71d00
|
@ -44,6 +44,8 @@
|
|||
<None Remove="Icons\duplicate.png" />
|
||||
<None Remove="Icons\extract.png" />
|
||||
<None Remove="Icons\fotocelula.png" />
|
||||
<None Remove="Icons\match.png" />
|
||||
<None Remove="Icons\ocr.png" />
|
||||
<None Remove="Icons\rotation.cur" />
|
||||
<None Remove="Icons\rotation32x32.cur" />
|
||||
<None Remove="Icons\rotationRx.cur" />
|
||||
|
@ -121,6 +123,8 @@
|
|||
<CopyToOutputDirectory></CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Icons\fotocelula.png" />
|
||||
<Resource Include="Icons\match.png" />
|
||||
<Resource Include="Icons\ocr.png" />
|
||||
<Resource Include="Icons\rotationRx.cur" />
|
||||
<Resource Include="Icons\rotationSx.cur" />
|
||||
<Resource Include="Icons\save.png" />
|
||||
|
|
|
@ -0,0 +1,383 @@
|
|||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows;
|
||||
using CtrEditor.ObjetosSim;
|
||||
using LibS7Adv;
|
||||
|
||||
namespace CtrEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata de una página, incluyendo información sobre la imagen y configuración
|
||||
/// </summary>
|
||||
public class PageMetadata
|
||||
{
|
||||
public string PageId { get; set; }
|
||||
public string PageName { get; set; }
|
||||
public string ImagePath { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
public Dictionary<string, object> CustomMetadata { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estado de un objeto dentro de una página específica
|
||||
/// </summary>
|
||||
public class PageObjectState
|
||||
{
|
||||
public string GlobalObjectId { get; set; }
|
||||
public bool IsVisible { get; set; } = true;
|
||||
public float Left { get; set; }
|
||||
public float Top { get; set; }
|
||||
public float Rotation { get; set; }
|
||||
public Dictionary<string, object> CustomProperties { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estado de una página específica
|
||||
/// </summary>
|
||||
public class PageState
|
||||
{
|
||||
public string PageId { get; set; }
|
||||
public string PageName { get; set; }
|
||||
public List<osBase> LocalObjects { get; set; } = new();
|
||||
public Dictionary<string, PageObjectState> GlobalObjectStates { get; set; } = new();
|
||||
public Dictionary<string, object> PageMetadata { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estado global de la aplicación
|
||||
/// </summary>
|
||||
public class GlobalState
|
||||
{
|
||||
public List<osBase> SharedObjects { get; set; } = new();
|
||||
public Dictionary<string, PageMetadata> PagesMetadata { get; set; } = new();
|
||||
public PLCViewModel PLCConfiguration { get; set; }
|
||||
public UnitConverter UnitConverter { get; set; }
|
||||
public int LastUsedId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gestor principal de estados de la aplicación
|
||||
/// </summary>
|
||||
public class StateManager : IDisposable
|
||||
{
|
||||
private readonly string _basePath;
|
||||
private GlobalState _globalState;
|
||||
private Dictionary<string, PageState> _loadedPages;
|
||||
private string _currentPageId;
|
||||
private readonly object _lockObject = new();
|
||||
private bool _hasUnsavedChanges;
|
||||
private MainViewModel _mainViewModel;
|
||||
|
||||
public event EventHandler<string> PageStateChanged;
|
||||
public event EventHandler GlobalStateChanged;
|
||||
|
||||
public StateManager(string basePath, MainViewModel mainViewModel)
|
||||
{
|
||||
_basePath = basePath;
|
||||
_mainViewModel = mainViewModel;
|
||||
_loadedPages = new Dictionary<string, PageState>();
|
||||
Directory.CreateDirectory(basePath);
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
await LoadGlobalStateAsync();
|
||||
if (_mainViewModel.SelectedImage != null)
|
||||
{
|
||||
await LoadPageStateAsync(_mainViewModel.SelectedImage);
|
||||
}
|
||||
}
|
||||
|
||||
private JsonSerializerSettings GetSerializerSettings()
|
||||
{
|
||||
return new JsonSerializerSettings
|
||||
{
|
||||
TypeNameHandling = TypeNameHandling.Auto,
|
||||
ObjectCreationHandling = ObjectCreationHandling.Replace,
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
};
|
||||
}
|
||||
|
||||
public async Task LoadGlobalStateAsync()
|
||||
{
|
||||
var path = Path.Combine(_basePath, "global.json");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(path);
|
||||
_globalState = JsonConvert.DeserializeObject<GlobalState>(json, GetSerializerSettings());
|
||||
|
||||
// Restaurar configuración global
|
||||
_mainViewModel.PLCViewModel = _globalState.PLCConfiguration ?? new PLCViewModel();
|
||||
if (_globalState.UnitConverter != null)
|
||||
PixelToMeter.Instance.calc = _globalState.UnitConverter;
|
||||
else
|
||||
PixelToMeter.Instance.calc = new UnitConverter(1.0f); // Valor por defecto
|
||||
|
||||
// Restaurar objetos globales
|
||||
foreach (var obj in _globalState.SharedObjects)
|
||||
{
|
||||
await RestoreObjectAsync(obj);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log error y crear nuevo estado global
|
||||
_globalState = new GlobalState();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_globalState = new GlobalState();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SaveGlobalStateAsync()
|
||||
{
|
||||
var path = Path.Combine(_basePath, "global.json");
|
||||
var backupPath = Path.ChangeExtension(path, ".bak");
|
||||
|
||||
// Actualizar estado global
|
||||
_globalState.PLCConfiguration = _mainViewModel.PLCViewModel;
|
||||
_globalState.UnitConverter = PixelToMeter.Instance.calc;
|
||||
|
||||
// Crear backup
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Copy(path, backupPath, true);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Preparar objetos para serialización
|
||||
foreach (var obj in _globalState.SharedObjects)
|
||||
{
|
||||
obj.SalvarDatosNoSerializables();
|
||||
}
|
||||
|
||||
var json = JsonConvert.SerializeObject(_globalState, GetSerializerSettings());
|
||||
await File.WriteAllTextAsync(path, json);
|
||||
_hasUnsavedChanges = false;
|
||||
GlobalStateChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Restaurar estado de objetos
|
||||
foreach (var obj in _globalState.SharedObjects)
|
||||
{
|
||||
obj.RestaurarDatosNoSerializables();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<PageState> LoadPageStateAsync(string pageId)
|
||||
{
|
||||
// Retornar página cacheada si existe
|
||||
if (_loadedPages.TryGetValue(pageId, out var cachedState))
|
||||
{
|
||||
return cachedState;
|
||||
}
|
||||
|
||||
var path = Path.Combine(_basePath, $"page_{pageId}.json");
|
||||
try
|
||||
{
|
||||
PageState pageState;
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(path);
|
||||
pageState = JsonConvert.DeserializeObject<PageState>(json, GetSerializerSettings());
|
||||
}
|
||||
else
|
||||
{
|
||||
pageState = new PageState
|
||||
{
|
||||
PageId = pageId,
|
||||
PageName = _globalState.PagesMetadata.GetValueOrDefault(pageId)?.PageName ?? pageId
|
||||
};
|
||||
}
|
||||
|
||||
_loadedPages[pageId] = pageState;
|
||||
|
||||
// Restaurar objetos locales
|
||||
foreach (var obj in pageState.LocalObjects)
|
||||
{
|
||||
await RestoreObjectAsync(obj);
|
||||
}
|
||||
|
||||
// Aplicar estados de objetos globales
|
||||
ApplyGlobalObjectStates(pageState);
|
||||
|
||||
return pageState;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log error
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyGlobalObjectStates(PageState pageState)
|
||||
{
|
||||
foreach (var kvp in pageState.GlobalObjectStates)
|
||||
{
|
||||
var globalObj = _globalState.SharedObjects.FirstOrDefault(o => o.Id.Value.ToString() == kvp.Key);
|
||||
if (globalObj != null)
|
||||
{
|
||||
var state = kvp.Value;
|
||||
globalObj.Left = state.Left;
|
||||
globalObj.Top = state.Top;
|
||||
globalObj.Angulo = state.Rotation;
|
||||
|
||||
// Actualizar Show_On_This_Page que ahora maneja internamente showOnThisPagesList
|
||||
if (state.IsVisible && !globalObj.Show_On_This_Page)
|
||||
globalObj.Show_On_This_Page = true;
|
||||
else if (!state.IsVisible && globalObj.Show_On_This_Page)
|
||||
globalObj.Show_On_This_Page = false;
|
||||
|
||||
// Aplicar propiedades personalizadas
|
||||
foreach (var prop in state.CustomProperties)
|
||||
{
|
||||
var property = globalObj.GetType().GetProperty(prop.Key);
|
||||
if (property != null && property.CanWrite)
|
||||
{
|
||||
property.SetValue(globalObj, prop.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RestoreObjectAsync(osBase obj)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
obj.CheckData();
|
||||
await Task.Run(() =>
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
CrearUserControlDesdeObjetoSimulable(obj);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private bool CrearUserControlDesdeObjetoSimulable(osBase osObjeto)
|
||||
{
|
||||
Type tipoObjeto = osObjeto.GetType();
|
||||
UserControl userControl = UserControlFactory.GetControlForType(tipoObjeto);
|
||||
|
||||
if (userControl != null)
|
||||
{
|
||||
UserControlFactory.AssignDatos(userControl, osObjeto, _mainViewModel.simulationManager);
|
||||
osObjeto._mainViewModel = _mainViewModel;
|
||||
|
||||
if (osObjeto.Id == null)
|
||||
{
|
||||
osObjeto.Id = new UniqueId().ObtenerNuevaID();
|
||||
}
|
||||
|
||||
_mainViewModel.MainWindow.AgregarRegistrarUserControlCanvas(userControl);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task SavePageStateAsync(string pageId)
|
||||
{
|
||||
if (!_loadedPages.TryGetValue(pageId, out var pageState))
|
||||
return;
|
||||
|
||||
var path = Path.Combine(_basePath, $"page_{pageId}.json");
|
||||
var backupPath = Path.ChangeExtension(path, ".bak");
|
||||
|
||||
// Crear backup
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Copy(path, backupPath, true);
|
||||
}
|
||||
|
||||
// Actualizar estado de objetos globales
|
||||
pageState.GlobalObjectStates.Clear();
|
||||
foreach (var obj in _mainViewModel.ObjetosSimulables.Where(o => o.Enable_On_All_Pages))
|
||||
{
|
||||
var currentPageId = _mainViewModel.SelectedImage;
|
||||
pageState.GlobalObjectStates[obj.Id.Value.ToString()] = new PageObjectState
|
||||
{
|
||||
GlobalObjectId = obj.Id.Value.ToString(),
|
||||
IsVisible = obj.Show_On_This_Page,
|
||||
Left = obj.Left,
|
||||
Top = obj.Top,
|
||||
Rotation = obj.Angulo,
|
||||
CustomProperties = CaptureCustomProperties(obj)
|
||||
};
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Preparar objetos para serialización
|
||||
foreach (var obj in pageState.LocalObjects)
|
||||
{
|
||||
obj.SalvarDatosNoSerializables();
|
||||
}
|
||||
|
||||
var json = JsonConvert.SerializeObject(pageState, GetSerializerSettings());
|
||||
await File.WriteAllTextAsync(path, json);
|
||||
_hasUnsavedChanges = false;
|
||||
PageStateChanged?.Invoke(this, pageId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Restaurar estado de objetos
|
||||
foreach (var obj in pageState.LocalObjects)
|
||||
{
|
||||
obj.RestaurarDatosNoSerializables();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, object> CaptureCustomProperties(osBase obj)
|
||||
{
|
||||
var customProps = new Dictionary<string, object>();
|
||||
var properties = obj.GetType().GetProperties()
|
||||
.Where(p => p.GetCustomAttributes(typeof(SerializeAttribute), true).Any());
|
||||
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
customProps[prop.Name] = prop.GetValue(obj);
|
||||
}
|
||||
|
||||
return customProps;
|
||||
}
|
||||
|
||||
public async Task SaveAllAsync()
|
||||
{
|
||||
foreach (var pageId in _loadedPages.Keys)
|
||||
{
|
||||
await SavePageStateAsync(pageId);
|
||||
}
|
||||
await SaveGlobalStateAsync();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_hasUnsavedChanges)
|
||||
{
|
||||
SaveAllAsync().Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Atributo para marcar propiedades que deben ser serializadas como propiedades personalizadas
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class SerializeAttribute : Attribute { }
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
using LanguageDetection;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
|
||||
|
||||
namespace CtrEditor.FuncionesBase
|
||||
{
|
||||
public class Idiomas
|
||||
{
|
||||
public const string DEFAULT_LANGUAGE = "English";
|
||||
|
||||
private static readonly Dictionary<string, string> _languageMap = new Dictionary<string, string>
|
||||
{
|
||||
{ "en", "English" },
|
||||
{ "es", "Spanish" },
|
||||
{ "it", "Italian" },
|
||||
{ "pt", "Portuguese" },
|
||||
{ "fr", "French" },
|
||||
{ "de", "German" }
|
||||
};
|
||||
|
||||
private static readonly LanguageDetector _languageDetector;
|
||||
|
||||
static Idiomas()
|
||||
{
|
||||
_languageDetector = new LanguageDetector();
|
||||
_languageDetector.AddLanguages("en", "es", "it", "pt", "fr", "de");
|
||||
}
|
||||
|
||||
public static List<string> GetLanguageList()
|
||||
{
|
||||
return new List<string>(_languageMap.Values);
|
||||
}
|
||||
|
||||
public static string DetectarIdioma(string texto)
|
||||
{
|
||||
if (string.IsNullOrEmpty(texto)) return DEFAULT_LANGUAGE;
|
||||
|
||||
try
|
||||
{
|
||||
string detectedLanguageCode = _languageDetector.Detect(texto);
|
||||
return _languageMap.GetValueOrDefault(detectedLanguageCode, DEFAULT_LANGUAGE);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return DEFAULT_LANGUAGE;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetLanguageCode(string languageName)
|
||||
{
|
||||
return _languageMap.FirstOrDefault(x => x.Value == languageName).Key ?? "en";
|
||||
}
|
||||
}
|
||||
|
||||
public class IdiomasItemsSource<T> : IItemsSource
|
||||
{
|
||||
public ItemCollection GetValues()
|
||||
{
|
||||
ItemCollection items = new ItemCollection();
|
||||
foreach (string language in Idiomas.GetLanguageList())
|
||||
{
|
||||
items.Add(language);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
|
||||
|
||||
namespace CtrEditor.FuncionesBase
|
||||
{
|
||||
public class TagPattern
|
||||
{
|
||||
public const string DEFAULT_PATTERN = "DESCRIPCION";
|
||||
|
||||
private static readonly Dictionary<string, string> _patternDescriptions = new Dictionary<string, string>
|
||||
{
|
||||
{ "Descripcion", "First letter capitalized" },
|
||||
{ "DESCRIPCION", "All uppercase text" },
|
||||
{ "Siemens IO Input", "Format: Exxxxx.y (x: 0-65535, y: 0-7)" },
|
||||
{ "Siemens IO Output", "Format: Axxxxx.y (x: 0-65535, y: 0-7)" },
|
||||
{ "LETRASNUMEROS", "Format: ABC...123... (1-10 letters + numbers)" },
|
||||
{ "Numero", "Numeric value" }
|
||||
};
|
||||
|
||||
public static List<string> GetPatternList()
|
||||
{
|
||||
return new List<string>(_patternDescriptions.Keys);
|
||||
}
|
||||
|
||||
public static string ApplyPattern(string text, string pattern)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) return text;
|
||||
|
||||
return pattern switch
|
||||
{
|
||||
"Descripcion" => ApplyDescripcionPattern(text),
|
||||
"DESCRIPCION" => text.ToUpper(),
|
||||
"Siemens IO Input" => ApplySiemensPattern(text, "E"),
|
||||
"Siemens IO Output" => ApplySiemensPattern(text, "A"),
|
||||
"LETRASNUMEROS" => ApplyLetrasNumerosPattern(text),
|
||||
"Numero" => ApplyNumberPattern(text),
|
||||
_ => text
|
||||
};
|
||||
}
|
||||
|
||||
private static string ApplyDescripcionPattern(string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) return text;
|
||||
return char.ToUpper(text[0]) + (text.Length > 1 ? text.Substring(1).ToLower() : "");
|
||||
}
|
||||
|
||||
private static string ApplySiemensPattern(string text, string prefix)
|
||||
{
|
||||
var match = Regex.Match(text, $"{prefix}?(\\d{{1,5}})\\.?(\\d)?", RegexOptions.IgnoreCase);
|
||||
if (match.Success)
|
||||
{
|
||||
int address = Math.Min(int.Parse(match.Groups[1].Value), 65535);
|
||||
int bit = match.Groups[2].Success ?
|
||||
Math.Min(int.Parse(match.Groups[2].Value), 7) : 0;
|
||||
return $"{prefix}{address}.{bit}";
|
||||
}
|
||||
return $"{prefix}0.0"; // Default value if pattern doesn't match
|
||||
}
|
||||
|
||||
private static string ApplyLetrasNumerosPattern(string text)
|
||||
{
|
||||
// Extract letters and numbers from the text
|
||||
var letters = new string(text.Where(c => char.IsLetter(c)).Take(10).ToArray());
|
||||
var numbers = new string(text.Where(c => char.IsDigit(c)).ToArray());
|
||||
|
||||
// If no letters found, return "A" as default
|
||||
if (string.IsNullOrEmpty(letters))
|
||||
letters = "A";
|
||||
|
||||
// If no numbers found, return "0" as default
|
||||
if (string.IsNullOrEmpty(numbers))
|
||||
numbers = "0";
|
||||
|
||||
// Combine letters (uppercase) and numbers
|
||||
return $"{letters.ToUpper()}{numbers}";
|
||||
}
|
||||
|
||||
private static string ApplyNumberPattern(string text)
|
||||
{
|
||||
var match = Regex.Match(text, @"-?\d+\.?\d*");
|
||||
return match.Success ? match.Value : "0";
|
||||
}
|
||||
}
|
||||
|
||||
public class TagPatternItemsSource<T> : IItemsSource
|
||||
{
|
||||
public ItemCollection GetValues()
|
||||
{
|
||||
ItemCollection items = new ItemCollection();
|
||||
foreach (string pattern in TagPattern.GetPatternList())
|
||||
{
|
||||
items.Add(pattern);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
}
|
23
IA/gtpask.cs
23
IA/gtpask.cs
|
@ -9,6 +9,7 @@ using LanguageDetection;
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Diagnostics;
|
||||
using CtrEditor.FuncionesBase;
|
||||
|
||||
namespace GTPCorrgir
|
||||
{
|
||||
|
@ -70,15 +71,6 @@ namespace GTPCorrgir
|
|||
private string _grokApiKey;
|
||||
private readonly HttpClient _httpClient;
|
||||
private bool _disposed;
|
||||
private readonly LanguageDetector _languageDetector;
|
||||
|
||||
private readonly Dictionary<string, string> _languageMap = new Dictionary<string, string>
|
||||
{
|
||||
{ "en", "English" },
|
||||
{ "es", "Spanish" },
|
||||
{ "it", "Italian" },
|
||||
{ "pt", "Portuguese" }
|
||||
};
|
||||
|
||||
public string IdiomaDetectado { get; private set; }
|
||||
public string TextoACorregir { get; set; }
|
||||
|
@ -90,8 +82,6 @@ namespace GTPCorrgir
|
|||
try
|
||||
{
|
||||
_httpClient = new HttpClient();
|
||||
_languageDetector = new LanguageDetector();
|
||||
_languageDetector.AddLanguages("en", "es", "it", "pt");
|
||||
|
||||
LoadApiKeys();
|
||||
InitializeHttpClient();
|
||||
|
@ -153,20 +143,15 @@ namespace GTPCorrgir
|
|||
{
|
||||
try
|
||||
{
|
||||
|
||||
string detectedLanguageCode = _languageDetector.Detect(TextoACorregir);
|
||||
IdiomaDetectado = _languageMap.GetValueOrDefault(detectedLanguageCode, "Desconocido");
|
||||
|
||||
return IdiomaDetectado != "Desconocido";
|
||||
IdiomaDetectado = Idiomas.DetectarIdioma(TextoACorregir);
|
||||
return IdiomaDetectado != "Unknown";
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task ProcesarTextoConLLM( Opciones Modelo)
|
||||
{
|
||||
try
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
258
MainViewModel.cs
258
MainViewModel.cs
|
@ -43,9 +43,24 @@ namespace CtrEditor
|
|||
|
||||
public Canvas MainCanvas;
|
||||
|
||||
public bool IsConnected
|
||||
[ObservableProperty]
|
||||
private bool isConnected;
|
||||
|
||||
partial void OnPLCViewModelChanged(PLCViewModel value)
|
||||
{
|
||||
get => PLCViewModel.IsConnected;
|
||||
if (value != null)
|
||||
{
|
||||
value.PropertyChanged += PLCViewModel_PropertyChanged;
|
||||
IsConnected = value.IsConnected;
|
||||
}
|
||||
}
|
||||
|
||||
private void PLCViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(PLCViewModel.IsConnected))
|
||||
{
|
||||
IsConnected = PLCViewModel.IsConnected;
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
|
@ -64,8 +79,6 @@ namespace CtrEditor
|
|||
public ICommand TBStartSimulationCommand { get; }
|
||||
public ICommand TBStopSimulationCommand { get; }
|
||||
public ICommand TBSaveCommand { get; }
|
||||
public ICommand TBConnectPLCCommand { get; }
|
||||
public ICommand TBDisconnectPLCCommand { get; }
|
||||
public ICommand TBExtractTagsCommand { get; }
|
||||
|
||||
public ICommand TBEliminarUserControlCommand { get; }
|
||||
|
@ -79,9 +92,17 @@ namespace CtrEditor
|
|||
public ICommand TBAssingPagesCommand { get; }
|
||||
public ICommand TBMultiPageExtractTagsCommand { get; }
|
||||
public ICommand TBMultiPageAnalizeCommand { get; }
|
||||
public ICommand TBAnalyzeMatrixCommand { get; }
|
||||
public ICommand TBMultiPageMatrixCommand { get; }
|
||||
|
||||
|
||||
public ICommand TBTogglePLCConnectionCommand => new RelayCommand(() =>
|
||||
{
|
||||
if (IsConnected)
|
||||
DisconnectPLC();
|
||||
else
|
||||
ConnectPLC();
|
||||
});
|
||||
|
||||
// Evento que se dispara cuando se selecciona una nueva imagen
|
||||
public event EventHandler<string> ImageSelected;
|
||||
public event EventHandler<TickSimulacionEventArgs> TickSimulacion;
|
||||
|
@ -202,27 +223,24 @@ namespace CtrEditor
|
|||
[ObservableProperty]
|
||||
private string selectedImage;
|
||||
|
||||
partial void OnSelectedImageChanged(string value)
|
||||
{
|
||||
if (value != null)
|
||||
partial void OnSelectedImageChanging(string? oldValue, string newValue)
|
||||
{
|
||||
if (HasUnsavedChanges && !inhibitSaveChangesControl)
|
||||
{
|
||||
var result = MessageBox.Show("There are unsaved changes. Do you want to save them?",
|
||||
"Save Changes",
|
||||
MessageBoxButton.YesNoCancel);
|
||||
MessageBoxButton.YesNo);
|
||||
|
||||
if (result == MessageBoxResult.Cancel)
|
||||
{
|
||||
OnPropertyChanged(nameof(SelectedImage)); // Restore previous selection
|
||||
return;
|
||||
}
|
||||
else if (result == MessageBoxResult.Yes)
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
SaveStateObjetosSimulables();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
partial void OnSelectedImageChanged(string value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
StopSimulation();
|
||||
ImageSelected?.Invoke(this, datosDeTrabajo.Imagenes[value]);
|
||||
LoadStateObjetosSimulables();
|
||||
|
@ -271,6 +289,8 @@ namespace CtrEditor
|
|||
// Constructor
|
||||
//
|
||||
|
||||
private StateManager _stateManager;
|
||||
|
||||
public MainViewModel()
|
||||
{
|
||||
OpenWorkDirectoryCommand = new RelayCommand(OpenWorkDirectory);
|
||||
|
@ -289,7 +309,7 @@ namespace CtrEditor
|
|||
PLCViewModel = new PLCViewModel();
|
||||
|
||||
_timerPLCUpdate = new DispatcherTimer();
|
||||
_timerPLCUpdate.Interval = TimeSpan.FromMilliseconds(50); // ajusta el intervalo según sea necesario
|
||||
_timerPLCUpdate.Interval = TimeSpan.FromMilliseconds(10); // ajusta el intervalo según sea necesario
|
||||
_timerPLCUpdate.Tick += OnRefreshEvent;
|
||||
|
||||
InitializeTipoSimulableList();
|
||||
|
@ -306,21 +326,15 @@ namespace CtrEditor
|
|||
TBStartSimulationCommand = new RelayCommand(StartSimulation, () => !IsSimulationRunning);
|
||||
TBStopSimulationCommand = new RelayCommand(StopSimulation, () => IsSimulationRunning);
|
||||
TBSaveCommand = new RelayCommand(Save);
|
||||
TBConnectPLCCommand = new RelayCommand(ConnectPLC, () => !PLCViewModel.IsConnected);
|
||||
TBDisconnectPLCCommand = new RelayCommand(DisconnectPLC, () => PLCViewModel.IsConnected);
|
||||
|
||||
TBEliminarUserControlCommand = new RelayCommand(EliminarUserControl, () => habilitarEliminarUserControl);
|
||||
TBDuplicarUserControlCommand = new RelayCommand(DuplicarUserControl, () => habilitarEliminarUserControl);
|
||||
|
||||
TBExtractTagsCommand = new RelayCommand(ExtraerTags);
|
||||
|
||||
TBEliminarTodosCommand = new RelayCommand(EliminarTodosCommand);
|
||||
TBEliminarAutoCreatedCommand = new RelayCommand(EliminarAutoCreatedCommand);
|
||||
TBEliminarClonedCommand = new RelayCommand(EliminarClonedCommand);
|
||||
TBAssingPagesCommand = new RelayCommand(AssingPagesCommand);
|
||||
TBMultiPageExtractTagsCommand = new RelayCommand(MultiPageExtractTagsCommand);
|
||||
TBMultiPageAnalizeCommand = new RelayCommand(MultiPageAnalizeCommand);
|
||||
TBAnalyzeMatrixCommand = new RelayCommand(AnalyzeMatrixCommand);
|
||||
TBMultiPageMatrixCommand = new RelayCommand(MultiPageMatrixCommand);
|
||||
|
||||
stopwatch_Sim = new Stopwatch();
|
||||
|
@ -334,6 +348,8 @@ namespace CtrEditor
|
|||
|
||||
recentDirectories = new ObservableCollection<string>(EstadoPersistente.Instance.RecentDirectories);
|
||||
OpenRecentDirectoryCommand = new RelayCommand<string>(OpenRecentDirectory);
|
||||
|
||||
_stateManager = new StateManager(EstadoPersistente.Instance.directorio, this);
|
||||
}
|
||||
|
||||
private void OsListFilter_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
|
@ -544,51 +560,6 @@ namespace CtrEditor
|
|||
Application.Current.Dispatcher.Invoke(() => { }, DispatcherPriority.ApplicationIdle);
|
||||
}
|
||||
|
||||
|
||||
private async void MultiPageExtractTagsCommand()
|
||||
{
|
||||
if (HasUnsavedChanges)
|
||||
{
|
||||
var result = MessageBox.Show("There are unsaved changes. Do you want to save them?",
|
||||
"Save Changes",
|
||||
MessageBoxButton.YesNoCancel);
|
||||
|
||||
if (result == MessageBoxResult.Cancel)
|
||||
return;
|
||||
else if (result == MessageBoxResult.Yes)
|
||||
SaveStateObjetosSimulables();
|
||||
}
|
||||
|
||||
var ImagenesSeleccionadas = new ObservableCollection<string>
|
||||
{
|
||||
SelectedImage
|
||||
};
|
||||
|
||||
StopSimulation();
|
||||
|
||||
var selectPagesWindow = new SelectPages();
|
||||
var selectPagesViewModel = new SelectPagesViewModel();
|
||||
selectPagesViewModel.Initialize(this, selectPagesWindow, ref ImagenesSeleccionadas);
|
||||
selectPagesWindow.DataContext = selectPagesViewModel;
|
||||
selectPagesWindow.ShowDialog();
|
||||
|
||||
inhibitSaveChangesControl = true;
|
||||
try
|
||||
{
|
||||
if (selectPagesWindow.DataContext is SelectPagesViewModel dialog && dialog.CloseOK)
|
||||
foreach (var page in ImagenesSeleccionadas)
|
||||
{
|
||||
SelectedImage = page;
|
||||
await WaitForUIUpdateAsync(); // Espera a que la UI se actualice
|
||||
ExtraerTags();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
inhibitSaveChangesControl = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async void MultiPageAnalizeCommand()
|
||||
{
|
||||
var ImagenesSeleccionadas = new ObservableCollection<string>
|
||||
|
@ -641,148 +612,6 @@ namespace CtrEditor
|
|||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Extrae y formatea las etiquetas de los objetos simulables y las guarda en un archivo Excel.
|
||||
/// </summary>
|
||||
private void ExtraerTags()
|
||||
{
|
||||
// Obtiene la ruta del archivo Excel donde se guardarán los datos.
|
||||
var filePath = DatosDeTrabajo.ObtenerPathAllPages(".xlsx");
|
||||
|
||||
try
|
||||
{
|
||||
// Crea o abre un libro de Excel.
|
||||
XLWorkbook workbook = File.Exists(filePath) ? new XLWorkbook(filePath) : new XLWorkbook();
|
||||
var sheetName = "TagsExtracted";
|
||||
// Obtiene o crea la hoja de trabajo "TagsExtracted".
|
||||
var worksheet = workbook.Worksheets.Contains(sheetName) ? workbook.Worksheet(sheetName) : workbook.Worksheets.Add(sheetName);
|
||||
var lastRowUsed = worksheet.LastRowUsed();
|
||||
// Determina la fila en la que se empezarán a escribir los datos.
|
||||
int rowOffset = lastRowUsed == null ? 2 : lastRowUsed.RowNumber() + 1;
|
||||
|
||||
// Determina la columna fija más alta.
|
||||
List<int> columnasOcupadas = new List<int>();
|
||||
int actualMaxCol = 0;
|
||||
int col = 0;
|
||||
|
||||
// Filtrar los objetos de tipo osExtraccionTag y crear una nueva lista
|
||||
var osBuscarCoincidencias_List = ObjetosSimulables
|
||||
.OfType<osBuscarCoincidencias>()
|
||||
.Where(tag => tag.Show_On_This_Page)
|
||||
.ToList();
|
||||
var osExtraccionTagBaseGrouped_List = ObjetosSimulables
|
||||
.OfType<osExtraccionTag>()
|
||||
.Where(tag => tag.Show_On_This_Page && !tag.Cloned && tag.Id_Search_Templates != null && tag.Id_Search_Templates != "")
|
||||
.ToList();
|
||||
var osExtraccionTagBaseFix_List = ObjetosSimulables
|
||||
.OfType<osExtraccionTag>()
|
||||
.Where(tag => tag.Show_On_This_Page && !tag.Cloned && (tag.Id_Search_Templates == null || tag.Id_Search_Templates == ""))
|
||||
.ToList();
|
||||
|
||||
var osExtraccionTagCloned_List = ObjetosSimulables
|
||||
.OfType<osExtraccionTag>()
|
||||
.Where(tag => tag.Show_On_This_Page && tag.Cloned)
|
||||
.ToList();
|
||||
|
||||
// Columnas Fijas para los Tags no agrupados que no son clonados
|
||||
foreach (var objExtraccionTag in osExtraccionTagBaseFix_List)
|
||||
if ((string.IsNullOrEmpty(objExtraccionTag.Id_Search_Templates)) && !objExtraccionTag.Cloned)
|
||||
{
|
||||
col = objExtraccionTag.Collumn_number;
|
||||
if (col == 0 || columnasOcupadas.Contains(col))
|
||||
col = ++actualMaxCol;
|
||||
else
|
||||
actualMaxCol = Math.Max(actualMaxCol, col);
|
||||
|
||||
columnasOcupadas.Add(col);
|
||||
objExtraccionTag.Collumn_number = col;
|
||||
}
|
||||
|
||||
// Tags Agrupados no Clonados
|
||||
foreach (var objBC in osBuscarCoincidencias_List)
|
||||
foreach (var objExtraccionTag in osExtraccionTagBaseGrouped_List)
|
||||
if (objExtraccionTag.Id_Search_Templates == objBC.Nombre && !objExtraccionTag.Cloned)
|
||||
{
|
||||
col = objExtraccionTag.Collumn_number;
|
||||
if (col == 0 || columnasOcupadas.Contains(col))
|
||||
col = ++actualMaxCol;
|
||||
else
|
||||
actualMaxCol = Math.Max(actualMaxCol, col);
|
||||
|
||||
columnasOcupadas.Add(col);
|
||||
objExtraccionTag.Collumn_number = col;
|
||||
}
|
||||
|
||||
int RowToRender = 0;
|
||||
// Cloned Tag - Asignar las mismas columnas
|
||||
foreach (var oFrom in osExtraccionTagBaseGrouped_List)
|
||||
foreach (var oCloned in osExtraccionTagCloned_List)
|
||||
{
|
||||
if (oCloned.Cloned_from == oFrom.Id)
|
||||
oCloned.Collumn_number = oFrom.Collumn_number;
|
||||
RowToRender = Math.Max(RowToRender, oCloned.Copy_Number);
|
||||
}
|
||||
|
||||
// Render Rows
|
||||
for (int row = 0; row < RowToRender; row++)
|
||||
{
|
||||
// Render Fix tags
|
||||
foreach (var TagFixs in osExtraccionTagBaseFix_List)
|
||||
{
|
||||
col = TagFixs.Collumn_number;
|
||||
if (worksheet.Cell(1, col).IsEmpty())
|
||||
worksheet.Cell(1, col).Value = TagFixs.Collumn_name;
|
||||
TagFixs.CaptureImageAreaAndDoOCR();
|
||||
worksheet.Cell(row + rowOffset, col).Value = TagFixs.Tag_extract;
|
||||
}
|
||||
// Render Cloned tags
|
||||
foreach (var TagCloned in osExtraccionTagCloned_List)
|
||||
{
|
||||
if (TagCloned.Copy_Number == row) // Estamos en la fila correcta
|
||||
{
|
||||
col = TagCloned.Collumn_number;
|
||||
if (worksheet.Cell(1, col).IsEmpty())
|
||||
worksheet.Cell(1, col).Value = TagCloned.Collumn_name;
|
||||
|
||||
TagCloned.CaptureImageAreaAndDoOCR();
|
||||
worksheet.Cell(row + rowOffset, col).Value = TagCloned.Tag_extract;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Formatear los títulos en la fila 1
|
||||
var titleRow = worksheet.Row(1);
|
||||
titleRow.Style.Font.Bold = true;
|
||||
titleRow.Style.Fill.BackgroundColor = XLColor.LightGray;
|
||||
titleRow.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
|
||||
|
||||
// Auto dimensionado de las columnas utilizadas
|
||||
worksheet.Columns().AdjustToContents();
|
||||
|
||||
// Guarda el libro de Excel.
|
||||
workbook.SaveAs(filePath);
|
||||
HasUnsavedChanges = false;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// Muestra un diálogo de error si ocurre una excepción de IO.
|
||||
var dialog = new TaskDialog
|
||||
{
|
||||
WindowTitle = "IOException",
|
||||
MainInstruction = "Error al acceder al archivo",
|
||||
Content = $"El proceso no puede acceder al archivo '{filePath}' porque está siendo utilizado por otro proceso.",
|
||||
ExpandedInformation = ex.ToString(),
|
||||
MainIcon = TaskDialogIcon.Error,
|
||||
ButtonStyle = TaskDialogButtonStyle.Standard
|
||||
};
|
||||
dialog.Buttons.Add(new TaskDialogButton(ButtonType.Ok));
|
||||
dialog.ShowDialog();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void InitializeTipoSimulableList()
|
||||
{
|
||||
var baseType = typeof(osBase);
|
||||
|
@ -1142,15 +971,6 @@ namespace CtrEditor
|
|||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
private void AnalyzeMatrixCommand()
|
||||
{
|
||||
var matrixPreviewWindow = new MatrixPreviewWindow();
|
||||
var matrixPreviewViewModel = new MatrixPreviewViewModel();
|
||||
matrixPreviewViewModel.Initialize(this, matrixPreviewWindow);
|
||||
matrixPreviewWindow.DataContext = matrixPreviewViewModel;
|
||||
matrixPreviewWindow.ShowDialog();
|
||||
}
|
||||
|
||||
private async void MultiPageMatrixCommand()
|
||||
{
|
||||
if (HasUnsavedChanges)
|
||||
|
|
|
@ -27,13 +27,21 @@
|
|||
<!-- Style for Connect/Disconnect Button -->
|
||||
<Style x:Key="ConnectDisconnectButtonStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Padding" Value="5" />
|
||||
<Setter Property="MinWidth" Value="80" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsConnected}" Value="True">
|
||||
<Setter Property="Background" Value="LightGreen" />
|
||||
<Setter Property="Background" Value="#90EE90" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<!-- Converter for PLC Connect/Disconnect button text -->
|
||||
<local:ConnectStateToBtnTextConverter x:Key="ConnectStateToBtnTextConverter" />
|
||||
|
||||
<!-- Converter for PLC Connect/Disconnect image -->
|
||||
<local:ConnectStateToImageConverter x:Key="ConnectStateToImageConverter" />
|
||||
|
||||
</Window.Resources>
|
||||
|
||||
<Grid>
|
||||
|
@ -116,42 +124,29 @@
|
|||
<TextBlock Text="Guardar" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Command="{Binding TBConnectPLCCommand}" ToolTip="Conectar PLC"
|
||||
<Button Command="{Binding TBTogglePLCConnectionCommand}"
|
||||
ToolTip="{Binding IsConnected, Converter={StaticResource ConnectStateToBtnTextConverter}}"
|
||||
Style="{StaticResource ConnectDisconnectButtonStyle}">
|
||||
<StackPanel>
|
||||
<Image Source="Icons/connect.png" Width="24" Height="24" />
|
||||
<TextBlock Text="Conectar" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Command="{Binding TBDisconnectPLCCommand}" ToolTip="Desconectar PLC">
|
||||
<StackPanel>
|
||||
<Image Source="Icons/disconnect.png" Width="24" Height="24" />
|
||||
<TextBlock Text="Desconectar" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Command="{Binding TBExtractTagsCommand}" ToolTip="Extraer Tags">
|
||||
<StackPanel>
|
||||
<Image Source="Icons/extract.png" Width="24" Height="24" />
|
||||
<TextBlock Text="Extraer Tags" />
|
||||
<Image
|
||||
Source="{Binding IsConnected, Converter={StaticResource ConnectStateToImageConverter}}"
|
||||
Width="24" Height="24" />
|
||||
<TextBlock
|
||||
Text="{Binding IsConnected, Converter={StaticResource ConnectStateToBtnTextConverter}}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Command="{Binding TBMultiPageAnalizeCommand}"
|
||||
ToolTip="Analyze Tags in multiple pages.">
|
||||
<StackPanel>
|
||||
<Image Source="Icons/analyze.png" Width="24" Height="24" />
|
||||
<Image Source="Icons/match.png" Width="24" Height="24" />
|
||||
<TextBlock Text="Multi Page Analyze" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Command="{Binding TBAnalyzeMatrixCommand}" ToolTip="Analyze Export Matrix">
|
||||
<StackPanel>
|
||||
<Image Source="Icons/analyze.png" Width="24" Height="24" />
|
||||
<TextBlock Text="Analyze Matrix" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<Button Command="{Binding TBMultiPageMatrixCommand}" ToolTip="Analyze Matrix (Multiple Pages)">
|
||||
<StackPanel>
|
||||
<Image Source="Icons/analyze.png" Width="24" Height="24" />
|
||||
<TextBlock Text="Multi Page Matrix" />
|
||||
<Image Source="Icons/ocr.png" Width="24" Height="24" />
|
||||
<TextBlock Text="Exportar Tags a Excel" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
|
|
|
@ -288,6 +288,15 @@ namespace CtrEditor
|
|||
new Tuple<Point, string>(new Point(rectBox.Right, rectBox.Top + rectBox.Height / 2), "CenterRight")
|
||||
};
|
||||
|
||||
// Add validation before setting Canvas position
|
||||
void SetCanvasPosition(UIElement element, double left, double top)
|
||||
{
|
||||
if (!double.IsInfinity(left) && !double.IsNaN(left))
|
||||
Canvas.SetLeft(element, left);
|
||||
if (!double.IsInfinity(top) && !double.IsNaN(top))
|
||||
Canvas.SetTop(element, top);
|
||||
}
|
||||
|
||||
foreach (var position in positions)
|
||||
{
|
||||
Rectangle rect = new Rectangle
|
||||
|
@ -337,8 +346,8 @@ namespace CtrEditor
|
|||
break;
|
||||
}
|
||||
|
||||
Canvas.SetLeft(rect, position.Item1.X - rectSize / 2);
|
||||
Canvas.SetTop(rect, position.Item1.Y - rectSize / 2);
|
||||
// Replace direct Canvas.Set calls with the validation method
|
||||
SetCanvasPosition(rect, position.Item1.X - rectSize / 2, position.Item1.Y - rectSize / 2);
|
||||
|
||||
rect.MouseLeftButtonDown += UserControl_MouseLeftButtonDown;
|
||||
rect.MouseMove += UserControl_MouseMove;
|
||||
|
|
|
@ -123,8 +123,6 @@ namespace CtrEditor.ObjetosSim
|
|||
|
||||
public override void UpdatePLC(PLCViewModel plc, int TotalMilliseconds)
|
||||
{
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
elapsedTimeAccumulator += TotalMilliseconds;
|
||||
float randomFactor = (float)(new Random().NextDouble() * 0.1); // 10% random factor
|
||||
|
@ -135,12 +133,9 @@ namespace CtrEditor.ObjetosSim
|
|||
motState.UpdatePLC(plc, this, TotalMilliseconds);
|
||||
elapsedTimeAccumulator = 0;
|
||||
}
|
||||
|
||||
Velocidad = (Proporcional_Speed / 100) * (motState.STATUS_VFD_ACT_Speed_Hz / 10);
|
||||
Sentido_contrario = motState.OUT_Reversal;
|
||||
|
||||
stopwatch.Stop();
|
||||
Debug.WriteLine($" osVMmotorSim : {Nombre} : {stopwatch.Elapsed.TotalMilliseconds} ms");
|
||||
}
|
||||
|
||||
public override void UpdateControl(int TotalMilliseconds)
|
||||
|
|
|
@ -27,9 +27,40 @@ using Emgu.CV.Structure;
|
|||
namespace CtrEditor.ObjetosSim.Extraccion_Datos
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ucBuscarCoincidencias.xaml
|
||||
/// Represents a template search control that identifies similar patterns in images and creates tag extraction clones.
|
||||
/// This class is designed to work with OCR extraction by finding visual patterns and creating copies of extraction tags
|
||||
/// at each matching location.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Key functionalities:
|
||||
/// - Template matching using OpenCV
|
||||
/// - Automatic tag cloning at found locations
|
||||
/// - OCR text extraction from matched regions
|
||||
/// - Export capabilities to Excel
|
||||
///
|
||||
/// Workflow:
|
||||
/// 1. User creates a search template by positioning and sizing the control over a pattern
|
||||
/// 2. Links extraction tags to this template using Id_Search_Templates
|
||||
/// 3. Activates search_templates to find similar patterns
|
||||
/// 4. The system automatically:
|
||||
/// - Searches for visual matches in the image
|
||||
/// - Creates clones of linked extraction tags at each match
|
||||
/// - Assigns incremental copy_Number to organize rows in exports
|
||||
/// - Performs OCR on each cloned tag location
|
||||
///
|
||||
/// Properties:
|
||||
/// - search_templates: Triggers the pattern search process
|
||||
/// - threshold: Minimum similarity threshold for pattern matching
|
||||
/// - coincidencias: Number of matches found (readonly)
|
||||
/// - show_debug_ocr: Shows debug windows during OCR process
|
||||
/// - export_ocr: Triggers OCR text export for all matches
|
||||
///
|
||||
/// Usage example:
|
||||
/// 1. Position the search template over a repeating pattern
|
||||
/// 2. Create extraction tags and link them to this template
|
||||
/// 3. Set threshold value (default usually works well)
|
||||
/// 4. Activate search_templates to find matches and create clones
|
||||
/// </remarks>
|
||||
|
||||
public partial class osBuscarCoincidencias : osBase, IosBase
|
||||
{
|
||||
|
@ -362,9 +393,6 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
|
|||
}
|
||||
}
|
||||
Row++;
|
||||
if (newObj != null)
|
||||
newObj.New_Row = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,18 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
|
|||
bool extraer;
|
||||
|
||||
[ObservableProperty]
|
||||
bool new_Row;
|
||||
[property: Category("Tag Extraction:")]
|
||||
bool eliminar_enters;
|
||||
|
||||
[ObservableProperty]
|
||||
[property: Category("Tag Extraction:")]
|
||||
[property: ItemsSource(typeof(IdiomasItemsSource<Idiomas>))]
|
||||
string idioma_Extraccion;
|
||||
|
||||
[ObservableProperty]
|
||||
[property: Category("Tag Extraction:")]
|
||||
[property: ItemsSource(typeof(TagPatternItemsSource<TagPattern>))]
|
||||
string pattern_Type;
|
||||
|
||||
public override void TopChanged(float value)
|
||||
{
|
||||
|
@ -147,11 +158,39 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
|
|||
Alto = 1;
|
||||
Angulo = 0;
|
||||
Opacity_oculto = 0.1f;
|
||||
Idioma_Extraccion = Idiomas.DEFAULT_LANGUAGE;
|
||||
Pattern_Type = TagPattern.DEFAULT_PATTERN;
|
||||
}
|
||||
|
||||
public void CaptureImageAreaAndDoOCR()
|
||||
{
|
||||
Tag_extract = CaptureImageAreaAndDoOCR(Left, Top, Ancho, Alto, Angulo, Show_Debug_Window);
|
||||
string extractedText = CaptureImageAreaAndDoOCR(Left, Top, Ancho, Alto, Angulo, Show_Debug_Window);
|
||||
|
||||
// Clean up the extracted text if eliminar_enters is true
|
||||
if (Eliminar_enters && !string.IsNullOrEmpty(extractedText))
|
||||
{
|
||||
// Replace all types of line endings with spaces
|
||||
extractedText = extractedText.Replace("\r\n", " ")
|
||||
.Replace("\n", " ")
|
||||
.Replace("\r", " ");
|
||||
|
||||
// Replace multiple consecutive spaces with a single space
|
||||
extractedText = System.Text.RegularExpressions.Regex.Replace(extractedText, @"\s+", " ");
|
||||
|
||||
// Trim spaces at the beginning and end
|
||||
extractedText = extractedText.Trim();
|
||||
}
|
||||
|
||||
// Apply the selected pattern
|
||||
extractedText = TagPattern.ApplyPattern(extractedText, Pattern_Type);
|
||||
|
||||
Tag_extract = extractedText;
|
||||
|
||||
// Set default language to English if not set
|
||||
if (string.IsNullOrEmpty(Idioma_Extraccion))
|
||||
{
|
||||
Idioma_Extraccion = Idiomas.DEFAULT_LANGUAGE;
|
||||
}
|
||||
}
|
||||
|
||||
public int ExportToExcel(IXLWorksheet worksheet, int row, int colBase)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using CtrEditor.FuncionesBase;
|
||||
|
||||
namespace CtrEditor.PopUps
|
||||
{
|
||||
|
@ -12,15 +13,7 @@ namespace CtrEditor.PopUps
|
|||
public string SelectedSourceLanguage { get; private set; }
|
||||
public string SelectedTargetLanguage { get; private set; }
|
||||
|
||||
private static readonly List<string> SupportedLanguages = new List<string>
|
||||
{
|
||||
"English",
|
||||
"Spanish",
|
||||
"Italian",
|
||||
"French",
|
||||
"German",
|
||||
"Portuguese"
|
||||
};
|
||||
private static readonly List<string> SupportedLanguages = Idiomas.GetLanguageList();
|
||||
|
||||
private string _sourceColumnLabel = "Idioma 1";
|
||||
private string _targetColumnLabel = "Idioma 2";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Window x:Class="CtrEditor.PopUps.MatrixPreviewWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Export Matrix Preview" Height="600" Width="800">
|
||||
Title="Exportar Tags Extraidos" Height="600" Width="800">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
|
@ -70,23 +70,23 @@
|
|||
HorizontalAlignment="Right"
|
||||
Margin="5"
|
||||
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
|
||||
<Button Content="AI Correction"
|
||||
<Button Content="Correccion de Descripcion"
|
||||
Command="{Binding AICorrectMatrixCommand}"
|
||||
Margin="5"
|
||||
Padding="10,5"/>
|
||||
<Button Content="Export to Excel"
|
||||
<Button Content="Exportar a Excel"
|
||||
Command="{Binding ExportToExcelCommand}"
|
||||
Margin="5"
|
||||
Padding="10,5"/>
|
||||
<Button Content="Regenerate Matrix"
|
||||
<Button Content="Regenerar Matriz"
|
||||
Command="{Binding RegenerateMatrixCommand}"
|
||||
Margin="5"
|
||||
Padding="10,5"/>
|
||||
<Button Content="Apply Changes"
|
||||
<Button Content="Salvar Cambios"
|
||||
Command="{Binding ApplyChangesCommand}"
|
||||
Margin="5"
|
||||
Padding="10,5"/>
|
||||
<Button Content="Close"
|
||||
<Button Content="Cerrar"
|
||||
Command="{Binding CloseCommand}"
|
||||
Margin="5"
|
||||
Padding="10,5"/>
|
||||
|
|
|
@ -41,8 +41,8 @@ namespace CtrEditor.Services
|
|||
|
||||
public async Task<List<(string Source, string Target)>> ProcessTextBatch(
|
||||
List<(string Source, string Target)> textPairs,
|
||||
string sourceLanguage = "Unknown",
|
||||
string targetLanguage = "Unknown")
|
||||
string sourceLanguage = "English",
|
||||
string targetLanguage = "English")
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -213,31 +213,60 @@ namespace CtrEditor.PopUps
|
|||
UpdateMatrixPreview();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Analyzes the current page and collects all extraction tags data for matrix preview.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The method processes three types of extraction tags:
|
||||
/// 1. Fixed Tags: Tags without Search Templates association
|
||||
/// 2. Grouped Tags: Tags linked to Search Templates but not cloned
|
||||
/// 3. Cloned Tags: Tags created by Search Templates pattern matching
|
||||
///
|
||||
/// Workflow:
|
||||
/// 1. Filters objects by visibility on current page
|
||||
/// 2. Groups tags by their type (fixed, grouped, cloned)
|
||||
/// 3. Performs OCR extraction on each tag
|
||||
/// 4. Creates MatrixItems with extracted data
|
||||
///
|
||||
/// Data Organization:
|
||||
/// - Fixed tags maintain their original position and values
|
||||
/// - Grouped tags are associated with their Search Templates
|
||||
/// - Cloned tags inherit Copy_Number from their creation order in pattern matching
|
||||
///
|
||||
/// Related Classes:
|
||||
/// - osExtraccionTag: Contains OCR extraction logic and tag properties
|
||||
/// - osBuscarCoincidencias: Handles pattern matching and tag cloning
|
||||
/// </remarks>
|
||||
/// <returns>A list of MatrixItems containing all processed tag data for the current page</returns>
|
||||
private List<MatrixItem> AnalyzePage()
|
||||
{
|
||||
var items = new List<MatrixItem>();
|
||||
|
||||
// Filter visible objects by type
|
||||
var osBuscarCoincidencias_List = _mainViewModel.ObjetosSimulables
|
||||
.OfType<osBuscarCoincidencias>()
|
||||
.Where(tag => tag.Show_On_This_Page)
|
||||
.ToList();
|
||||
|
||||
// Get base tags that are linked to Search Templates
|
||||
var osExtraccionTagBaseGrouped_List = _mainViewModel.ObjetosSimulables
|
||||
.OfType<osExtraccionTag>()
|
||||
.Where(tag => tag.Show_On_This_Page && !tag.Cloned && tag.Id_Search_Templates != null && tag.Id_Search_Templates != "")
|
||||
.ToList();
|
||||
|
||||
// Get fixed tags (not linked to Search Templates)
|
||||
var osExtraccionTagBaseFix_List = _mainViewModel.ObjetosSimulables
|
||||
.OfType<osExtraccionTag>()
|
||||
.Where(tag => tag.Show_On_This_Page && !tag.Cloned && (tag.Id_Search_Templates == null || tag.Id_Search_Templates == ""))
|
||||
.ToList();
|
||||
|
||||
// Get cloned tags (created by Search Templates)
|
||||
var osExtraccionTagCloned_List = _mainViewModel.ObjetosSimulables
|
||||
.OfType<osExtraccionTag>()
|
||||
.Where(tag => tag.Show_On_This_Page && tag.Cloned)
|
||||
.ToList();
|
||||
|
||||
// Add fixed tags
|
||||
// Process fixed tags
|
||||
foreach (var tag in osExtraccionTagBaseFix_List)
|
||||
{
|
||||
tag.CaptureImageAreaAndDoOCR();
|
||||
|
@ -253,7 +282,7 @@ namespace CtrEditor.PopUps
|
|||
});
|
||||
}
|
||||
|
||||
// Add grouped tags
|
||||
// Process grouped tags
|
||||
foreach (var tag in osExtraccionTagBaseGrouped_List)
|
||||
{
|
||||
tag.CaptureImageAreaAndDoOCR();
|
||||
|
@ -269,7 +298,7 @@ namespace CtrEditor.PopUps
|
|||
});
|
||||
}
|
||||
|
||||
// Add cloned tags
|
||||
// Process cloned tags
|
||||
foreach (var tag in osExtraccionTagCloned_List)
|
||||
{
|
||||
tag.CaptureImageAreaAndDoOCR();
|
||||
|
@ -282,7 +311,7 @@ namespace CtrEditor.PopUps
|
|||
Type = "Cloned",
|
||||
IsCloned = true,
|
||||
Id = tag.Id,
|
||||
Copy_Number = tag.Copy_Number // Add this line
|
||||
Copy_Number = tag.Copy_Number
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,33 @@ namespace CtrEditor
|
|||
|
||||
}
|
||||
|
||||
public class ConnectStateToBtnTextConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return (bool)value ? "Desconectar PLC" : "Conectar PLC";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class ConnectStateToImageConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return (bool)value ? "Icons/disconnect.png" : "Icons/connect.png";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ListItemPropertyDescriptor<T> : PropertyDescriptor
|
||||
{
|
||||
private readonly IList<T> owner;
|
||||
|
|
Loading…
Reference in New Issue