CtrEditor/ViewModels/MatrixPreviewViewModel.cs

364 lines
12 KiB
C#
Raw Normal View History

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CtrEditor.ObjetosSim;
using CtrEditor.ObjetosSim.Extraccion_Datos;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Linq;
namespace CtrEditor.PopUps
{
public class MatrixItem : ObservableObject
{
public string TagName { get; set; }
private string columnName;
public string ColumnName
{
get => columnName;
set => SetProperty(ref columnName, value);
}
private int columnNumber;
public int ColumnNumber
{
get => columnNumber;
set => SetProperty(ref columnNumber, value);
}
public string Value { get; set; }
public string Type { get; set; }
public bool IsCloned { get; set; }
public osBase SourceObject { get; set; }
}
public partial class MatrixPreviewViewModel : ObservableObject
{
private Window _window;
private MainViewModel _mainViewModel;
private DataGrid _dataGrid;
[ObservableProperty]
private ObservableCollection<MatrixItem> matrixItems;
[ObservableProperty]
private ObservableCollection<Dictionary<string, string>> matrixRows;
[ObservableProperty]
private GridLength detailsHeight = new GridLength(150);
[ObservableProperty]
private double detailsHeightValue = 150;
partial void OnDetailsHeightValueChanged(double value)
{
DetailsHeight = new GridLength(value);
}
public void Initialize(MainViewModel mainViewModel, Window window)
{
_mainViewModel = mainViewModel;
_window = window;
_dataGrid = (_window as MatrixPreviewWindow)?.MatrixPreview;
MatrixItems = new ObservableCollection<MatrixItem>();
MatrixRows = new ObservableCollection<Dictionary<string, string>>();
AnalyzeMatrix();
}
private void UpdateMatrixPreview()
{
if (_dataGrid == null) return;
if (MatrixRows == null) MatrixRows = new ObservableCollection<Dictionary<string, string>>();
MatrixRows.Clear();
_dataGrid.Columns.Clear();
if (!MatrixItems.Any()) return;
// Ordenar items por número de columna
var orderedItems = MatrixItems
.GroupBy(x => x.ColumnNumber)
.OrderBy(g => g.Key)
.Select(g => g.First())
.ToList();
// Crear columnas
foreach (var item in orderedItems)
{
var column = new DataGridTextColumn
{
Header = $"{item.ColumnNumber}:{item.ColumnName}",
Binding = new Binding($"[{item.ColumnNumber}]"),
Width = DataGridLength.Auto
};
_dataGrid.Columns.Add(column);
}
// Calcular número de filas necesarias
int maxRows = 1;
var clonedItems = MatrixItems.Where(x => x.IsCloned).ToList();
if (clonedItems.Any())
{
maxRows = clonedItems.Max(x => x.SourceObject is osExtraccionTag tag ? tag.Copy_Number : 0) + 1;
}
// Crear filas con valores
for (int row = 0; row < maxRows; row++)
{
var rowData = new Dictionary<string, string>();
// Agregar valores fijos (no clonados) en todas las filas
foreach (var item in MatrixItems.Where(x => !x.IsCloned))
{
if (item.ColumnNumber > 0)
{
rowData[item.ColumnNumber.ToString()] = item.Value ?? string.Empty;
}
}
// Agregar valores clonados solo en su fila correspondiente
foreach (var item in MatrixItems.Where(x => x.IsCloned))
{
if (item.ColumnNumber > 0 && item.SourceObject is osExtraccionTag tag && tag.Copy_Number == row)
{
rowData[item.ColumnNumber.ToString()] = item.Value ?? string.Empty;
}
}
MatrixRows.Add(rowData);
}
}
private void UpdateColumnHeaders()
{
if (_dataGrid == null) return;
foreach (var col in _dataGrid.Columns.Cast<DataGridColumn>())
{
if (col is DataGridTextColumn textCol)
{
var item = MatrixItems.FirstOrDefault(x => x.ColumnName == (textCol.Header?.ToString() ?? "").Split(':').Last());
if (item != null)
{
textCol.Header = $"{item.ColumnNumber}:{item.ColumnName}";
}
}
}
}
private void AnalyzeMatrix()
{
var osBuscarCoincidencias_List = _mainViewModel.ObjetosSimulables
.OfType<osBuscarCoincidencias>()
.Where(tag => tag.Show_On_This_Page)
.ToList();
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();
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();
var osExtraccionTagCloned_List = _mainViewModel.ObjetosSimulables
.OfType<osExtraccionTag>()
.Where(tag => tag.Show_On_This_Page && tag.Cloned)
.ToList();
// Add fixed tags
foreach (var tag in osExtraccionTagBaseFix_List)
{
tag.CaptureImageAreaAndDoOCR();
MatrixItems.Add(new MatrixItem
{
TagName = tag.Nombre,
ColumnName = tag.Collumn_name,
ColumnNumber = tag.Collumn_number,
Value = tag.Tag_extract,
Type = "Fixed",
IsCloned = false,
SourceObject = tag
});
}
// Add grouped tags
foreach (var tag in osExtraccionTagBaseGrouped_List)
{
tag.CaptureImageAreaAndDoOCR();
MatrixItems.Add(new MatrixItem
{
TagName = tag.Nombre,
ColumnName = tag.Collumn_name,
ColumnNumber = tag.Collumn_number,
Value = tag.Tag_extract,
Type = $"Grouped ({tag.Id_Search_Templates})",
IsCloned = false,
SourceObject = tag
});
}
// Add cloned tags
foreach (var tag in osExtraccionTagCloned_List)
{
tag.CaptureImageAreaAndDoOCR();
MatrixItems.Add(new MatrixItem
{
TagName = tag.Nombre,
ColumnName = tag.Collumn_name,
ColumnNumber = tag.Collumn_number,
Value = tag.Tag_extract,
Type = "Cloned",
IsCloned = true,
SourceObject = tag
});
}
// Ordenar los items por número de columna
var items = MatrixItems.OrderBy(x => x.ColumnNumber).ToList();
MatrixItems.Clear();
foreach (var item in items)
{
MatrixItems.Add(item);
}
ResolveColumnConflicts(); // Analizar y resolver conflictos al cargar
UpdateMatrixPreview();
}
partial void OnMatrixItemsChanged(ObservableCollection<MatrixItem> value)
{
if (value != null)
{
foreach (var item in value)
{
item.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(MatrixItem.ColumnNumber) ||
e.PropertyName == nameof(MatrixItem.ColumnName))
{
UpdateColumnHeaders();
}
};
}
}
UpdateMatrixPreview();
}
[RelayCommand]
private void ApplyChanges()
{
// Resolver solo los conflictos reales, mantener el orden existente
var conflicts = MatrixItems
.GroupBy(x => x.ColumnNumber)
.Where(g => g.Select(x => x.ColumnName).Distinct().Count() > 1)
.Any();
if (conflicts)
{
ResolveColumnConflicts();
}
// Validar números de columna
var columnNumbers = MatrixItems.Select(x => x.ColumnNumber).OrderBy(x => x).ToList();
for (int i = 0; i < columnNumbers.Count; i++)
{
if (columnNumbers[i] <= 0)
{
MessageBox.Show("Column numbers must be greater than 0", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
}
// Aplicar cambios a los objetos
foreach (var item in MatrixItems)
{
if (item.SourceObject is osExtraccionTag tag)
{
tag.Collumn_name = item.ColumnName;
tag.Collumn_number = item.ColumnNumber;
}
}
_mainViewModel.HasUnsavedChanges = true;
_window.Close();
}
[RelayCommand]
private void Close()
{
_window.Close();
}
[RelayCommand]
private void RegenerateMatrix()
{
ResolveColumnConflicts();
UpdateMatrixPreview();
}
private void ResolveColumnConflicts()
{
// Paso 1: Mantener el orden actual y resolver solo los conflictos reales
var columnGroups = MatrixItems
.GroupBy(x => x.ColumnNumber)
.Where(g => g.Select(x => x.ColumnName).Distinct().Count() > 1)
.ToList();
foreach (var group in columnGroups)
{
var nameGroups = group
.GroupBy(x => x.ColumnName)
.OrderByDescending(g => g.Count())
.ToList();
// El grupo más grande mantiene su número
var largestGroup = nameGroups.First();
// Solo reasignar números para grupos que tengan conflicto
for (int i = 1; i < nameGroups.Count; i++)
{
var newColumnNumber = GetNextAvailableColumnNumber();
foreach (var item in nameGroups[i])
{
item.ColumnNumber = newColumnNumber;
}
}
}
// Paso 2: Asegurarse de que los números son consecutivos sin alterar el orden relativo
var orderedItems = MatrixItems
.OrderBy(x => x.ColumnNumber)
.GroupBy(x => x.ColumnName)
.ToList();
int currentNumber = 1;
foreach (var group in orderedItems)
{
foreach (var item in group)
{
item.ColumnNumber = currentNumber;
}
currentNumber++;
}
}
private int GetNextAvailableColumnNumber()
{
var usedNumbers = MatrixItems.Select(x => x.ColumnNumber).Distinct().OrderBy(x => x).ToList();
int nextNumber = 1;
foreach (var number in usedNumbers)
{
if (number > nextNumber)
return nextNumber;
nextNumber = number + 1;
}
return nextNumber;
}
}
}