1
0
Files
OAiP-Presnyakov_Ilya-Labora…/MainWindow.xaml.cs
Debug_pro b74b40209b upload
2026-06-07 18:14:39 +03:00

311 lines
11 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.Win32;
using Lab9.Models;
using Lab9.Services;
using Lab9.Strategies;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using System.IO;
using System.Text.RegularExpressions;
namespace Lab9
{
public partial class MainWindow : Window
{
private readonly SortingContext _context = new();
private readonly IReadOnlyList<ISortStrategy> _strategies;
private int[] _currentArray = Array.Empty<int>();
private SortResult? _lastResult;
public MainWindow()
{
InitializeComponent();
_strategies = new List<ISortStrategy>
{
new TimSortStrategy(),
new MsdRadixSortStrategy(),
new CommunistSortStrategy()
};
UpdatePreview("Массив ещё не сформирован.");
ResetMetrics();
}
private void ElementCountSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!IsLoaded)
{
return;
}
ElementCountTextBox.Text = ((int)ElementCountSlider.Value).ToString(CultureInfo.InvariantCulture);
}
private void ElementCountTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
if (!IsLoaded)
{
return;
}
if (int.TryParse(ElementCountTextBox.Text, out var value))
{
value = Math.Clamp(value, (int)ElementCountSlider.Minimum, (int)ElementCountSlider.Maximum);
ElementCountSlider.Value = value;
}
}
private void GenerateArray_Click(object sender, RoutedEventArgs e)
{
var count = (int)ElementCountSlider.Value;
var random = new Random();
_currentArray = Enumerable.Range(0, count)
.Select(_ => random.Next(-250, 1000))
.ToArray();
_lastResult = null;
ClearLog();
ResetMetrics();
UpdatePreview($"Исходный массив:{Environment.NewLine}{FormatArray(_currentArray)}");
}
private void LoadFromFile_Click(object sender, RoutedEventArgs e)
{
var dialog = new OpenFileDialog
{
Filter = "Текстовые файлы (*.txt)|*.txt|Все файлы (*.*)|*.*"
};
if (dialog.ShowDialog() != true)
{
return;
}
try
{
_currentArray = ArrayIoService.ReadArrayFromFile(dialog.FileName);
_lastResult = null;
ClearLog();
ResetMetrics();
UpdatePreview($"Массив из файла:{Environment.NewLine}{FormatArray(_currentArray)}");
}
catch (Exception ex)
{
MessageBox.Show(
$"Не удалось прочитать файл.\n{ex.Message}",
"Ошибка",
MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
private void StartSorting_Click(object sender, RoutedEventArgs e)
{
if (_currentArray.Length == 0)
{
MessageBox.Show(
"Сначала сгенерируй массив или загрузи его из файла. Машина без данных сортирует только воздух.",
"Ошибка",
MessageBoxButton.OK,
MessageBoxImage.Warning);
return;
}
var strategy = GetSelectedStrategy();
var ascending = DescendingCheckBox.IsChecked != true;
_context.ContextStrategy = strategy;
_lastResult = _context.Execute(_currentArray, ascending, enableLogging: true);
ComparisonsTextBlock.Text = _lastResult.Metrics.Comparisons.ToString(CultureInfo.InvariantCulture);
MovesTextBlock.Text = _lastResult.Metrics.Moves.ToString(CultureInfo.InvariantCulture);
ElapsedTextBlock.Text = $"{_lastResult.Elapsed.TotalMilliseconds:F6} мс";
RenderLog(_lastResult.Log);
UpdatePreview(
$"Исходный массив:{Environment.NewLine}{FormatArray(_currentArray)}{Environment.NewLine}{Environment.NewLine}" +
$"Результат ({_lastResult.AlgorithmName}):{Environment.NewLine}{FormatArray(_lastResult.SortedArray)}");
}
private void SaveToFile_Click(object sender, RoutedEventArgs e)
{
if (_currentArray.Length == 0)
{
MessageBox.Show(
"Сохранять пока нечего. Даже файл не любит пустые жесты.",
"Ошибка",
MessageBoxButton.OK,
MessageBoxImage.Warning);
return;
}
var dialog = new SaveFileDialog
{
Filter = "Текстовые файлы (*.txt)|*.txt",
FileName = "sorting_result.txt"
};
if (dialog.ShowDialog() != true)
{
return;
}
try
{
var content = BuildExportContent();
File.WriteAllText(dialog.FileName, content, Encoding.UTF8);
MessageBox.Show(
"Результаты сохранены в файл.",
"Готово",
MessageBoxButton.OK,
MessageBoxImage.Information);
}
catch (Exception ex)
{
MessageBox.Show(
$"Не удалось сохранить файл.\n{ex.Message}",
"Ошибка",
MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
private void Clear_Click(object sender, RoutedEventArgs e)
{
_currentArray = Array.Empty<int>();
_lastResult = null;
ClearLog();
ResetMetrics();
UpdatePreview("Массив очищен.");
}
private void OpenAnalysis_Click(object sender, RoutedEventArgs e)
{
var analysisWindow = new AnalysisWindow(_strategies, DescendingCheckBox.IsChecked == true)
{
Owner = this
};
analysisWindow.ShowDialog();
}
private ISortStrategy GetSelectedStrategy()
{
if (MsdRadioButton.IsChecked == true)
{
return _strategies.OfType<MsdRadixSortStrategy>().First();
}
if (CommunistRadioButton.IsChecked == true)
{
return _strategies.OfType<CommunistSortStrategy>().First();
}
return _strategies.OfType<TimSortStrategy>().First();
}
private void ResetMetrics()
{
ComparisonsTextBlock.Text = "0";
MovesTextBlock.Text = "0";
ElapsedTextBlock.Text = "0.000000 мс";
}
private void UpdatePreview(string text)
{
ArrayPreviewTextBlock.Text = text;
}
private void ClearLog()
{
LogRichTextBox.Document.Blocks.Clear();
}
private static string FormatArray(int[] array)
{
if (array.Length == 0)
{
return "Пустой массив.";
}
return string.Join(" ", array);
}
private void RenderLog(string log)
{
LogRichTextBox.Document.Blocks.Clear();
var regex = new Regex(@"\[-?\d+\]", RegexOptions.Compiled);
var lines = log.Replace("\r\n", "\n").Split('\n');
foreach (var line in lines)
{
var paragraph = new Paragraph
{
Margin = new Thickness(0)
};
if (string.IsNullOrWhiteSpace(line))
{
paragraph.Inlines.Add(new Run(" "));
LogRichTextBox.Document.Blocks.Add(paragraph);
continue;
}
var lastIndex = 0;
foreach (Match match in regex.Matches(line))
{
if (match.Index > lastIndex)
{
paragraph.Inlines.Add(new Run(line.Substring(lastIndex, match.Index - lastIndex)));
}
paragraph.Inlines.Add(new Run(match.Value)
{
Background = Brushes.LightSkyBlue,
FontWeight = FontWeights.Bold
});
lastIndex = match.Index + match.Length;
}
if (lastIndex < line.Length)
{
paragraph.Inlines.Add(new Run(line.Substring(lastIndex)));
}
LogRichTextBox.Document.Blocks.Add(paragraph);
}
}
private string BuildExportContent()
{
var builder = new StringBuilder();
builder.AppendLine("Лабораторная работа №9. Внутренняя сортировка данных");
builder.AppendLine($"Исходный массив: {string.Join(", ", _currentArray)}");
builder.AppendLine($"Режим сортировки: {(DescendingCheckBox.IsChecked == true ? "По убыванию" : "По возрастанию")}");
if (_lastResult is null)
{
builder.AppendLine("Сортировка ещё не запускалась.");
return builder.ToString();
}
builder.AppendLine($"Алгоритм: {_lastResult.AlgorithmName}");
builder.AppendLine($"Отсортированный массив: {string.Join(", ", _lastResult.SortedArray)}");
builder.AppendLine($"Количество сравнений: {_lastResult.Metrics.Comparisons}");
builder.AppendLine($"Количество пересылок: {_lastResult.Metrics.Moves}");
builder.AppendLine($"Время сортировки: {_lastResult.Elapsed.TotalMilliseconds:F6} мс");
builder.AppendLine();
builder.AppendLine("Пошаговый журнал:");
builder.AppendLine(_lastResult.Log);
return builder.ToString();
}
}
}