1
0
This commit is contained in:
Debug_pro
2026-06-07 18:14:39 +03:00
commit b74b40209b
24 changed files with 2528 additions and 0 deletions

311
MainWindow.xaml.cs Normal file
View File

@@ -0,0 +1,311 @@
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();
}
}
}