2025-02-14 10:04:29 -03:00
|
|
|
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;
|
2025-02-15 18:38:12 -03:00
|
|
|
using System.Windows.Threading; // Add this line
|
2025-02-14 10:04:29 -03:00
|
|
|
using System.Linq;
|
2025-02-15 18:38:12 -03:00
|
|
|
using ClosedXML.Excel;
|
|
|
|
using System.Diagnostics;
|
2025-02-14 10:04:29 -03:00
|
|
|
|
|
|
|
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; }
|
2025-02-15 18:38:12 -03:00
|
|
|
public UniqueId Id { get; set; }
|
|
|
|
public string Source_Image { get; set; }
|
|
|
|
public int Copy_Number { get; set; } // Add this property
|
2025-02-14 10:04:29 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
public partial class MatrixPreviewViewModel : ObservableObject
|
|
|
|
{
|
|
|
|
private Window _window;
|
|
|
|
private MainViewModel _mainViewModel;
|
|
|
|
private DataGrid _dataGrid;
|
2025-02-15 18:38:12 -03:00
|
|
|
private readonly Services.LLMService _llmService;
|
|
|
|
|
|
|
|
public MatrixPreviewViewModel()
|
|
|
|
{
|
|
|
|
_llmService = new Services.LLMService();
|
|
|
|
}
|
2025-02-14 10:04:29 -03:00
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
private ObservableCollection<MatrixItem> matrixItems;
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
private ObservableCollection<Dictionary<string, string>> matrixRows;
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
private GridLength detailsHeight = new GridLength(150);
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
private double detailsHeightValue = 150;
|
|
|
|
|
2025-02-15 18:38:12 -03:00
|
|
|
private ObservableCollection<string> selectedImages;
|
|
|
|
|
2025-02-14 10:04:29 -03:00
|
|
|
partial void OnDetailsHeightValueChanged(double value)
|
|
|
|
{
|
|
|
|
DetailsHeight = new GridLength(value);
|
|
|
|
}
|
|
|
|
|
2025-02-15 18:38:12 -03:00
|
|
|
public void Initialize(MainViewModel mainViewModel, Window window, ObservableCollection<string> images = null)
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
|
|
|
_mainViewModel = mainViewModel;
|
|
|
|
_window = window;
|
|
|
|
_dataGrid = (_window as MatrixPreviewWindow)?.MatrixPreview;
|
2025-02-15 18:38:12 -03:00
|
|
|
selectedImages = images ?? new ObservableCollection<string> { mainViewModel.SelectedImage };
|
2025-02-14 10:04:29 -03:00
|
|
|
|
|
|
|
MatrixItems = new ObservableCollection<MatrixItem>();
|
|
|
|
MatrixRows = new ObservableCollection<Dictionary<string, string>>();
|
|
|
|
|
2025-02-15 18:38:12 -03:00
|
|
|
AnalyzeMatrixMultiPage();
|
2025-02-14 10:04:29 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2025-02-15 18:38:12 -03:00
|
|
|
// Group items by source image and then by column number
|
|
|
|
var itemsByImage = MatrixItems.GroupBy(x => x.Source_Image);
|
|
|
|
|
2025-02-14 10:04:29 -03:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2025-02-15 18:38:12 -03:00
|
|
|
// Process each image's data
|
|
|
|
foreach (var imageGroup in itemsByImage)
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
2025-02-15 18:38:12 -03:00
|
|
|
// Calculate max rows needed for this image
|
|
|
|
int maxRows = 1;
|
|
|
|
var clonedItems = imageGroup.Where(x => x.IsCloned).ToList();
|
|
|
|
if (clonedItems.Any())
|
|
|
|
{
|
|
|
|
maxRows = clonedItems.Max(x => x.Copy_Number) + 1;
|
|
|
|
}
|
2025-02-14 10:04:29 -03:00
|
|
|
|
2025-02-15 18:38:12 -03:00
|
|
|
// Create rows for this image
|
|
|
|
for (int row = 0; row < maxRows; row++)
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
2025-02-15 18:38:12 -03:00
|
|
|
var rowData = new Dictionary<string, string>();
|
|
|
|
|
|
|
|
// Add image identifier
|
|
|
|
rowData["Image"] = imageGroup.Key;
|
|
|
|
|
|
|
|
// Add fixed (non-cloned) values in all rows
|
|
|
|
foreach (var item in imageGroup.Where(x => !x.IsCloned))
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
2025-02-15 18:38:12 -03:00
|
|
|
if (item.ColumnNumber > 0)
|
|
|
|
{
|
|
|
|
rowData[item.ColumnNumber.ToString()] = item.Value ?? string.Empty;
|
|
|
|
}
|
2025-02-14 10:04:29 -03:00
|
|
|
}
|
|
|
|
|
2025-02-15 18:38:12 -03:00
|
|
|
// Add cloned values only in their corresponding row
|
|
|
|
foreach (var item in imageGroup.Where(x => x.IsCloned))
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
2025-02-15 18:38:12 -03:00
|
|
|
if (item.ColumnNumber > 0 && item.Copy_Number == row)
|
|
|
|
{
|
|
|
|
rowData[item.ColumnNumber.ToString()] = item.Value ?? string.Empty;
|
|
|
|
}
|
2025-02-14 10:04:29 -03:00
|
|
|
}
|
|
|
|
|
2025-02-15 18:38:12 -03:00
|
|
|
MatrixRows.Add(rowData);
|
|
|
|
}
|
2025-02-14 10:04:29 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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}";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-15 18:38:12 -03:00
|
|
|
private async void AnalyzeMatrixMultiPage()
|
|
|
|
{
|
|
|
|
MatrixItems.Clear();
|
|
|
|
bool originalHasUnsavedChanges = _mainViewModel.HasUnsavedChanges;
|
|
|
|
_mainViewModel.HasUnsavedChanges = false;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
foreach (var imageName in selectedImages)
|
|
|
|
{
|
|
|
|
// Store current image
|
|
|
|
var currentImage = _mainViewModel.SelectedImage;
|
|
|
|
|
|
|
|
// Change to target image and wait for UI update
|
|
|
|
_mainViewModel.SelectedImage = imageName;
|
|
|
|
await _mainViewModel.WaitForUIUpdateAsync();
|
|
|
|
|
|
|
|
// Analyze current page
|
|
|
|
var items = AnalyzePage();
|
|
|
|
foreach (var item in items)
|
|
|
|
{
|
|
|
|
item.Source_Image = imageName;
|
|
|
|
MatrixItems.Add(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Restore original image if needed
|
|
|
|
if (currentImage != imageName)
|
|
|
|
{
|
|
|
|
_mainViewModel.SelectedImage = currentImage;
|
|
|
|
await _mainViewModel.WaitForUIUpdateAsync();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
_mainViewModel.HasUnsavedChanges = originalHasUnsavedChanges;
|
|
|
|
}
|
|
|
|
|
|
|
|
ResolveColumnConflicts();
|
|
|
|
UpdateMatrixPreview();
|
|
|
|
}
|
|
|
|
|
|
|
|
private List<MatrixItem> AnalyzePage()
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
2025-02-15 18:38:12 -03:00
|
|
|
var items = new List<MatrixItem>();
|
|
|
|
|
2025-02-14 10:04:29 -03:00
|
|
|
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();
|
2025-02-15 18:38:12 -03:00
|
|
|
items.Add(new MatrixItem
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
|
|
|
TagName = tag.Nombre,
|
|
|
|
ColumnName = tag.Collumn_name,
|
|
|
|
ColumnNumber = tag.Collumn_number,
|
|
|
|
Value = tag.Tag_extract,
|
|
|
|
Type = "Fixed",
|
|
|
|
IsCloned = false,
|
2025-02-15 18:38:12 -03:00
|
|
|
Id = tag.Id
|
2025-02-14 10:04:29 -03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add grouped tags
|
|
|
|
foreach (var tag in osExtraccionTagBaseGrouped_List)
|
|
|
|
{
|
|
|
|
tag.CaptureImageAreaAndDoOCR();
|
2025-02-15 18:38:12 -03:00
|
|
|
items.Add(new MatrixItem
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
|
|
|
TagName = tag.Nombre,
|
|
|
|
ColumnName = tag.Collumn_name,
|
|
|
|
ColumnNumber = tag.Collumn_number,
|
|
|
|
Value = tag.Tag_extract,
|
|
|
|
Type = $"Grouped ({tag.Id_Search_Templates})",
|
|
|
|
IsCloned = false,
|
2025-02-15 18:38:12 -03:00
|
|
|
Id = tag.Id
|
2025-02-14 10:04:29 -03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add cloned tags
|
|
|
|
foreach (var tag in osExtraccionTagCloned_List)
|
|
|
|
{
|
|
|
|
tag.CaptureImageAreaAndDoOCR();
|
2025-02-15 18:38:12 -03:00
|
|
|
items.Add(new MatrixItem
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
|
|
|
TagName = tag.Nombre,
|
|
|
|
ColumnName = tag.Collumn_name,
|
|
|
|
ColumnNumber = tag.Collumn_number,
|
|
|
|
Value = tag.Tag_extract,
|
|
|
|
Type = "Cloned",
|
|
|
|
IsCloned = true,
|
2025-02-15 18:38:12 -03:00
|
|
|
Id = tag.Id,
|
|
|
|
Copy_Number = tag.Copy_Number // Add this line
|
2025-02-14 10:04:29 -03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2025-02-15 18:38:12 -03:00
|
|
|
return items;
|
2025-02-14 10:04:29 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
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]
|
2025-02-15 18:38:12 -03:00
|
|
|
private async void ApplyChanges()
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-15 18:38:12 -03:00
|
|
|
bool originalHasUnsavedChanges = _mainViewModel.HasUnsavedChanges;
|
|
|
|
_mainViewModel.HasUnsavedChanges = false;
|
|
|
|
|
|
|
|
try
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
2025-02-15 18:38:12 -03:00
|
|
|
foreach (var imageName in selectedImages)
|
2025-02-14 10:04:29 -03:00
|
|
|
{
|
2025-02-15 18:38:12 -03:00
|
|
|
// Store current image
|
|
|
|
var currentImage = _mainViewModel.SelectedImage;
|
|
|
|
|
|
|
|
// Change to target image and wait for UI update
|
|
|
|
_mainViewModel.SelectedImage = imageName;
|
|
|
|
await Task.Yield();
|
|
|
|
Application.Current.Dispatcher.Invoke(() => { }, DispatcherPriority.ApplicationIdle);
|
|
|
|
|
|
|
|
// Apply changes for current page
|
|
|
|
var pageItems = MatrixItems.Where(x => x.Source_Image == imageName);
|
|
|
|
foreach (var item in pageItems)
|
|
|
|
{
|
|
|
|
// Find the tag by Id instead of direct reference
|
|
|
|
var tag = _mainViewModel.ObjetosSimulables
|
|
|
|
.OfType<osExtraccionTag>()
|
|
|
|
.FirstOrDefault(t => t.Id == item.Id);
|
|
|
|
|
|
|
|
if (tag != null)
|
|
|
|
{
|
|
|
|
tag.Collumn_name = item.ColumnName;
|
|
|
|
tag.Collumn_number = item.ColumnNumber;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Restore original image if needed
|
|
|
|
if (currentImage != imageName)
|
|
|
|
{
|
|
|
|
_mainViewModel.SelectedImage = currentImage;
|
|
|
|
await Task.Yield();
|
|
|
|
Application.Current.Dispatcher.Invoke(() => { }, DispatcherPriority.ApplicationIdle);
|
|
|
|
}
|
|
|
|
|
|
|
|
_mainViewModel.SaveStateObjetosSimulables();
|
2025-02-14 10:04:29 -03:00
|
|
|
}
|
|
|
|
}
|
2025-02-15 18:38:12 -03:00
|
|
|
finally
|
|
|
|
{
|
|
|
|
_mainViewModel.HasUnsavedChanges = originalHasUnsavedChanges;
|
|
|
|
}
|
|
|
|
|
2025-02-14 10:04:29 -03:00
|
|
|
_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;
|
|
|
|
}
|
2025-02-15 18:38:12 -03:00
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
private void ExportToExcel()
|
|
|
|
{
|
|
|
|
var saveDialog = new Microsoft.Win32.SaveFileDialog
|
|
|
|
{
|
|
|
|
DefaultExt = ".xlsx",
|
|
|
|
Filter = "Excel files (*.xlsx)|*.xlsx",
|
|
|
|
InitialDirectory = EstadoPersistente.Instance.directorio,
|
|
|
|
FileName = "MatrixExport.xlsx"
|
|
|
|
};
|
|
|
|
|
|
|
|
if (saveDialog.ShowDialog() == true)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
using (var workbook = new XLWorkbook())
|
|
|
|
{
|
|
|
|
var worksheet = workbook.Worksheets.Add("Matrix");
|
|
|
|
|
|
|
|
// Write headers
|
|
|
|
int colIndex = 1;
|
|
|
|
worksheet.Cell(1, colIndex++).Value = "Image";
|
|
|
|
|
|
|
|
var columns = MatrixItems
|
|
|
|
.GroupBy(x => x.ColumnNumber)
|
|
|
|
.OrderBy(g => g.Key)
|
|
|
|
.Select(g => g.First())
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
foreach (var col in columns)
|
|
|
|
{
|
|
|
|
worksheet.Cell(1, colIndex++).Value = col.ColumnName;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write data
|
|
|
|
int rowIndex = 2;
|
|
|
|
foreach (var row in MatrixRows)
|
|
|
|
{
|
|
|
|
colIndex = 1;
|
|
|
|
worksheet.Cell(rowIndex, colIndex++).Value = row["Image"];
|
|
|
|
|
|
|
|
foreach (var col in columns)
|
|
|
|
{
|
|
|
|
var value = row.ContainsKey(col.ColumnNumber.ToString())
|
|
|
|
? row[col.ColumnNumber.ToString()]
|
|
|
|
: string.Empty;
|
|
|
|
worksheet.Cell(rowIndex, colIndex++).Value = value;
|
|
|
|
}
|
|
|
|
rowIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Format headers
|
|
|
|
var headerRow = worksheet.Row(1);
|
|
|
|
headerRow.Style.Font.Bold = true;
|
|
|
|
headerRow.Style.Fill.BackgroundColor = XLColor.LightGray;
|
|
|
|
headerRow.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
|
|
|
|
|
|
|
|
// Auto-fit columns
|
|
|
|
worksheet.Columns().AdjustToContents();
|
|
|
|
|
|
|
|
workbook.SaveAs(saveDialog.FileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
MessageBox.Show("Export completed successfully", "Success", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
MessageBox.Show($"Error exporting to Excel: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
private async Task AICorrectMatrix()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (_llmService == null)
|
|
|
|
{
|
|
|
|
MessageBox.Show("LLM Service not initialized", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var columnNames = MatrixItems
|
|
|
|
.Select(x => x.ColumnName)
|
|
|
|
.Distinct()
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
var dialog = new ColumnSelectionDialog(columnNames);
|
|
|
|
if (dialog.ShowDialog() != true) return;
|
|
|
|
|
|
|
|
var sourceColumn = dialog.SelectedSourceColumn;
|
|
|
|
var targetColumn = dialog.SelectedTargetColumn;
|
|
|
|
var sourceLanguage = dialog.SelectedSourceLanguage;
|
|
|
|
var targetLanguage = dialog.SelectedTargetLanguage;
|
|
|
|
|
|
|
|
// Group items by image and process each row
|
|
|
|
var itemsByImage = MatrixItems.GroupBy(x => x.Source_Image);
|
|
|
|
int batchSize = 10;
|
|
|
|
int processedCount = 0;
|
|
|
|
|
|
|
|
foreach (var imageGroup in itemsByImage)
|
|
|
|
{
|
|
|
|
var textPairs = new List<(string Source, string Target)>();
|
|
|
|
var itemsToUpdate = new List<(MatrixItem SourceItem, MatrixItem TargetItem)>();
|
|
|
|
|
|
|
|
// Create pairs for each row
|
|
|
|
var sourceItems = imageGroup
|
|
|
|
.Where(x => x.ColumnName == sourceColumn)
|
|
|
|
.OrderBy(x => x.Copy_Number);
|
|
|
|
|
|
|
|
var targetItems = imageGroup
|
|
|
|
.Where(x => x.ColumnName == targetColumn)
|
|
|
|
.OrderBy(x => x.Copy_Number);
|
|
|
|
|
|
|
|
foreach (var (source, target) in sourceItems.Zip(targetItems, (s, t) => (s, t)))
|
|
|
|
{
|
|
|
|
if (!string.IsNullOrWhiteSpace(source.Value) && !string.IsNullOrWhiteSpace(target.Value))
|
|
|
|
{
|
|
|
|
textPairs.Add((source.Value, target.Value));
|
|
|
|
itemsToUpdate.Add((source, target));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Process in batches
|
|
|
|
for (int i = 0; i < textPairs.Count; i += batchSize)
|
|
|
|
{
|
|
|
|
var batchPairs = textPairs.Skip(i).Take(batchSize).ToList();
|
|
|
|
var batchItems = itemsToUpdate.Skip(i).Take(batchSize).ToList();
|
|
|
|
|
|
|
|
var correctedPairs = await _llmService.ProcessTextBatch(batchPairs, sourceLanguage, targetLanguage);
|
|
|
|
|
|
|
|
// Update values
|
|
|
|
for (int j = 0; j < correctedPairs.Count; j++)
|
|
|
|
{
|
|
|
|
batchItems[j].SourceItem.Value = correctedPairs[j].Source;
|
|
|
|
batchItems[j].TargetItem.Value = correctedPairs[j].Target;
|
|
|
|
processedCount += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateMatrixPreview();
|
|
|
|
MessageBox.Show($"AI Correction completed. Processed {processedCount} items.",
|
|
|
|
"Success", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
MessageBox.Show($"Error during AI correction: {ex.Message}",
|
|
|
|
"Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~MatrixPreviewViewModel()
|
|
|
|
{
|
|
|
|
_llmService?.Dispose();
|
|
|
|
}
|
2025-02-14 10:04:29 -03:00
|
|
|
}
|
|
|
|
}
|