diff --git a/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/AbstractCompany.cs b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/AbstractCompany.cs index 0753208..9bf100e 100644 --- a/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/AbstractCompany.cs +++ b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/AbstractCompany.cs @@ -59,7 +59,7 @@ public abstract class AbstractCompany /// public static bool operator +(AbstractCompany company, DrawningCar car) { - return company._collection?.Insert(car) ?? false; + return company._collection?.Insert(car, new DrawiningCarEqutables()) ?? false; } /// @@ -103,6 +103,12 @@ public abstract class AbstractCompany return bitmap; } + /// + /// Сортировка + /// + /// Сравнитель объектов + public void Sort(IComparer comparer) => _collection?.CollectionSort(comparer); + /// /// Вывод заднего фона /// diff --git a/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/CollectionInfo.cs b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/CollectionInfo.cs new file mode 100644 index 0000000..fea900d --- /dev/null +++ b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/CollectionInfo.cs @@ -0,0 +1,76 @@ +namespace ProjectSportCar.CollectionGenericObjects; + +/// +/// Класс, хранящиий информацию по коллекции +/// +public class CollectionInfo : IEquatable +{ + /// + /// Название + /// + public string Name { get; private set; } + + /// + /// Тип + /// + public CollectionType CollectionType { get; private set; } + + /// + /// Описание + /// + public string Description { get; private set; } + + /// + /// Разделитель для записи информации по объекту в файл + /// + private static readonly string _separator = "-"; + + /// + /// Конструктор + /// + /// Название + /// Тип + /// Описание + public CollectionInfo(string name, CollectionType collectionType, string description) + { + Name = name; + CollectionType = collectionType; + Description = description; + } + + /// + /// Создание объекта из строки + /// + /// Строка + /// Объект или null + public static CollectionInfo? GetCollectionInfo(string data) + { + string[] strs = data.Split(_separator, StringSplitOptions.RemoveEmptyEntries); + if (strs.Length < 1 || strs.Length > 3) + { + return null; + } + + return new CollectionInfo(strs[0], (CollectionType)Enum.Parse(typeof(CollectionType), strs[1]), strs.Length > 2 ? strs[2] : string.Empty); + } + + public override string ToString() + { + return Name + _separator + CollectionType + _separator + Description; + } + + public bool Equals(CollectionInfo? other) + { + return Name == other?.Name; + } + + public override bool Equals(object? obj) + { + return Equals(obj as CollectionInfo); + } + + public override int GetHashCode() + { + return Name.GetHashCode(); + } +} \ No newline at end of file diff --git a/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/ICollectionGenericObjects.cs b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/ICollectionGenericObjects.cs index 78668cf..35ae5c5 100644 --- a/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/ICollectionGenericObjects.cs +++ b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/ICollectionGenericObjects.cs @@ -1,4 +1,6 @@ -namespace ProjectSportCar.CollectionGenericObjects; +using ProjectSportCar.Drawnings; + +namespace ProjectSportCar.CollectionGenericObjects; /// /// Интерфейс описания действий для набора хранимых объектов @@ -21,16 +23,18 @@ public interface ICollectionGenericObjects /// Добавление объекта в коллекцию /// /// Добавляемый объект + /// Cравнение двух объектов /// true - вставка прошла удачно, false - вставка не удалась - bool Insert(T obj); + bool Insert(T obj, IEqualityComparer? comparer = null); /// /// Добавление объекта в коллекцию на конкретную позицию /// /// Добавляемый объект /// Позиция + /// Cравнение двух объектов /// true - вставка прошла удачно, false - вставка не удалась - bool Insert(T obj, int position); + bool Insert(T obj, int position, IEqualityComparer? comparer = null); /// /// Удаление объекта из коллекции с конкретной позиции @@ -56,4 +60,10 @@ public interface ICollectionGenericObjects /// /// Поэлементый вывод элементов коллекции IEnumerable GetItems(); + + /// + /// Сортировка коллекции + /// + /// Сравнитель объектов + void CollectionSort(IComparer comparer); } \ No newline at end of file diff --git a/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/ListGenericObjects.cs b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/ListGenericObjects.cs index cda6e04..a53135e 100644 --- a/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/ListGenericObjects.cs +++ b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/ListGenericObjects.cs @@ -1,5 +1,4 @@ - -namespace ProjectSportCar.CollectionGenericObjects; +namespace ProjectSportCar.CollectionGenericObjects; /// /// Параметризованный набор объектов @@ -50,7 +49,7 @@ public class ListGenericObjects : ICollectionGenericObjects return _collection[position]; } - public bool Insert(T obj) + public bool Insert(T obj, IEqualityComparer? comparer = null) { // TODO проверка, что не превышено максимальное количество элементов // TODO выброс ошибки, если переполнение @@ -58,7 +57,7 @@ public class ListGenericObjects : ICollectionGenericObjects return true; } - public bool Insert(T obj, int position) + public bool Insert(T obj, int position, IEqualityComparer? comparer = null) { // TODO проверка, что не превышено максимальное количество элементов // TODO выброс ошибки, если переполнение @@ -79,4 +78,9 @@ public class ListGenericObjects : ICollectionGenericObjects { throw new NotImplementedException(); } + + public void CollectionSort(IComparer comparer) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/MassiveGenericObjects.cs b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/MassiveGenericObjects.cs index 74111ea..071898e 100644 --- a/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/MassiveGenericObjects.cs +++ b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/MassiveGenericObjects.cs @@ -1,4 +1,6 @@  +using ProjectSportCar.Drawnings; + namespace ProjectSportCar.CollectionGenericObjects; /// @@ -55,15 +57,17 @@ public class MassiveGenericObjects : ICollectionGenericObjects return _collection[position]; } - public bool Insert(T obj) + public bool Insert(T obj, IEqualityComparer? comparer = null) { + // TODO выборс ошибки, если такой объект есть в коллекции // TODO вставка в свободное место набора // TODO выброс ошибки, если переполнение return false; } - public bool Insert(T obj, int position) + public bool Insert(T obj, int position, IEqualityComparer? comparer = null) { + // TODO выборс ошибки, если такой объект есть в коллекции // TODO проверка позиции // TODO выброс ошибки, если выход за границы массива // TODO проверка, что элемент массива по этой позиции пустой, если нет, то @@ -90,4 +94,9 @@ public class MassiveGenericObjects : ICollectionGenericObjects yield return _collection[i]; } } + + public void CollectionSort(IComparer comparer) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/StorageCollection.cs b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/StorageCollection.cs index 6ac1809..f222bd1 100644 --- a/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/StorageCollection.cs +++ b/ProjectSportCar/ProjectSportCar/CollectionGenericObjects/StorageCollection.cs @@ -14,12 +14,12 @@ public class StorageCollection /// /// Словарь (хранилище) с коллекциями /// - readonly Dictionary> _storages; + readonly Dictionary> _storages; /// /// Возвращение списка названий коллекций /// - public List Keys => _storages.Keys.ToList(); + public List Keys => _storages.Keys.ToList(); /// /// Ключевое слово, с которого должен начинаться файл @@ -41,7 +41,7 @@ public class StorageCollection /// public StorageCollection() { - _storages = new Dictionary>(); + _storages = new Dictionary>(); } /// @@ -97,7 +97,7 @@ public class StorageCollection StringBuilder sb = new(); sb.Append(_collectionKey); - foreach (KeyValuePair> value in _storages) + foreach (KeyValuePair> value in _storages) { sb.Append(Environment.NewLine); // не сохраняем пустые коллекции @@ -108,8 +108,6 @@ public class StorageCollection sb.Append(value.Key); sb.Append(_separatorForKeyValue); - sb.Append(value.Value.GetCollectionType); - sb.Append(_separatorForKeyValue); sb.Append(value.Value.MaxCount); sb.Append(_separatorForKeyValue); @@ -168,17 +166,18 @@ public class StorageCollection foreach (string data in strs) { string[] record = data.Split(_separatorForKeyValue, StringSplitOptions.RemoveEmptyEntries); - if (record.Length != 4) + if (record.Length != 3) { continue; } - CollectionType collectionType = (CollectionType)Enum.Parse(typeof(CollectionType), record[1]); - ICollectionGenericObjects? collection = StorageCollection.CreateCollection(collectionType) ?? + CollectionInfo? collectionInfo = CollectionInfo.GetCollectionInfo(record[0]) ?? + throw new Exception("Не удалось определить информацию коллекции:" + record[0]); + ICollectionGenericObjects? collection = StorageCollection.CreateCollection(collectionInfo.CollectionType) ?? throw new Exception("Не удалось определить тип коллекции:" + record[1]); - collection.MaxCount = Convert.ToInt32(record[2]); + collection.MaxCount = Convert.ToInt32(record[1]); - string[] set = record[3].Split(_separatorItems, StringSplitOptions.RemoveEmptyEntries); + string[] set = record[2].Split(_separatorItems, StringSplitOptions.RemoveEmptyEntries); foreach (string elem in set) { if (elem?.CreateDrawningCar() is T car) @@ -197,7 +196,7 @@ public class StorageCollection } } - _storages.Add(record[0], collection); + _storages.Add(collectionInfo, collection); } } diff --git a/ProjectSportCar/ProjectSportCar/Drawnings/DrawiningCarEqutables.cs b/ProjectSportCar/ProjectSportCar/Drawnings/DrawiningCarEqutables.cs new file mode 100644 index 0000000..192e6ff --- /dev/null +++ b/ProjectSportCar/ProjectSportCar/Drawnings/DrawiningCarEqutables.cs @@ -0,0 +1,54 @@ +using System.Diagnostics.CodeAnalysis; + +namespace ProjectSportCar.Drawnings; + +/// +/// Реализация сравнения двух объектов класса-прорисовки +/// +public class DrawiningCarEqutables : IEqualityComparer +{ + public bool Equals(DrawningCar? x, DrawningCar? y) + { + if (x == null || x.EntityCar == null) + { + return false; + } + + if (y == null || y.EntityCar == null) + { + return false; + } + + if (x.GetType().Name != y.GetType().Name) + { + return false; + } + + if (x.EntityCar.Speed != y.EntityCar.Speed) + { + return false; + } + + if (x.EntityCar.Weight != y.EntityCar.Weight) + { + return false; + } + + if (x.EntityCar.BodyColor != y.EntityCar.BodyColor) + { + return false; + } + + if (x is DrawningSportCar && y is DrawningSportCar) + { + // TODO доделать логику сравнения дополнительных параметров + } + + return true; + } + + public int GetHashCode([DisallowNull] DrawningCar obj) + { + return obj.GetHashCode(); + } +} \ No newline at end of file diff --git a/ProjectSportCar/ProjectSportCar/Drawnings/DrawningCarCompareByColor.cs b/ProjectSportCar/ProjectSportCar/Drawnings/DrawningCarCompareByColor.cs new file mode 100644 index 0000000..4b94077 --- /dev/null +++ b/ProjectSportCar/ProjectSportCar/Drawnings/DrawningCarCompareByColor.cs @@ -0,0 +1,13 @@ +namespace ProjectSportCar.Drawnings; + +/// +/// Сравнение по цвету, скорости, весу +/// +public class DrawningCarCompareByColor : IComparer +{ + public int Compare(DrawningCar? x, DrawningCar? y) + { + // TODO прописать логику сравения по цветам, скорости, весу + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/ProjectSportCar/ProjectSportCar/Drawnings/DrawningCarCompareByType.cs b/ProjectSportCar/ProjectSportCar/Drawnings/DrawningCarCompareByType.cs new file mode 100644 index 0000000..ad08707 --- /dev/null +++ b/ProjectSportCar/ProjectSportCar/Drawnings/DrawningCarCompareByType.cs @@ -0,0 +1,33 @@ +namespace ProjectSportCar.Drawnings; + +/// +/// Сравнение по типу, скорости, весу +/// +public class DrawningCarCompareByType : IComparer +{ + public int Compare(DrawningCar? x, DrawningCar? y) + { + if (x == null || x.EntityCar == null) + { + return -1; + } + + if (y == null || y.EntityCar == null) + { + return 1; + } + + if (x.GetType().Name != y.GetType().Name) + { + return x.GetType().Name.CompareTo(y.GetType().Name); + } + + var speedCompare = x.EntityCar.Speed.CompareTo(y.EntityCar.Speed); + if (speedCompare != 0) + { + return speedCompare; + } + + return x.EntityCar.Weight.CompareTo(y.EntityCar.Weight); + } +} \ No newline at end of file diff --git a/ProjectSportCar/ProjectSportCar/Exceptions/ObjectNotUniqueException.cs b/ProjectSportCar/ProjectSportCar/Exceptions/ObjectNotUniqueException.cs new file mode 100644 index 0000000..68fef40 --- /dev/null +++ b/ProjectSportCar/ProjectSportCar/Exceptions/ObjectNotUniqueException.cs @@ -0,0 +1,9 @@ +namespace ProjectSportCar.Exceptions; + +/// +/// Класс, описывающий ошибку наличия такого же объекта в коллекции +/// +[Serializable] +internal class ObjectNotUniqueException : ApplicationException +{ +} \ No newline at end of file diff --git a/ProjectSportCar/ProjectSportCar/FormCarCollection.Designer.cs b/ProjectSportCar/ProjectSportCar/FormCarCollection.Designer.cs index f204ff8..57457b1 100644 --- a/ProjectSportCar/ProjectSportCar/FormCarCollection.Designer.cs +++ b/ProjectSportCar/ProjectSportCar/FormCarCollection.Designer.cs @@ -30,6 +30,8 @@ { groupBoxTools = new GroupBox(); panelCompanyTools = new Panel(); + buttonSortByColor = new Button(); + buttonSortByType = new Button(); buttonAddCar = new Button(); maskedTextBoxPosition = new MaskedTextBox(); buttonRefresh = new Button(); @@ -68,13 +70,15 @@ groupBoxTools.Dock = DockStyle.Right; groupBoxTools.Location = new Point(783, 24); groupBoxTools.Name = "groupBoxTools"; - groupBoxTools.Size = new Size(179, 608); + groupBoxTools.Size = new Size(179, 657); groupBoxTools.TabIndex = 0; groupBoxTools.TabStop = false; groupBoxTools.Text = "Инструменты"; // // panelCompanyTools // + panelCompanyTools.Controls.Add(buttonSortByColor); + panelCompanyTools.Controls.Add(buttonSortByType); panelCompanyTools.Controls.Add(buttonAddCar); panelCompanyTools.Controls.Add(maskedTextBoxPosition); panelCompanyTools.Controls.Add(buttonRefresh); @@ -82,11 +86,33 @@ panelCompanyTools.Controls.Add(buttonGoToCheck); panelCompanyTools.Dock = DockStyle.Bottom; panelCompanyTools.Enabled = false; - panelCompanyTools.Location = new Point(3, 352); + panelCompanyTools.Location = new Point(3, 355); panelCompanyTools.Name = "panelCompanyTools"; - panelCompanyTools.Size = new Size(173, 253); + panelCompanyTools.Size = new Size(173, 299); panelCompanyTools.TabIndex = 9; // + // buttonSortByColor + // + buttonSortByColor.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + buttonSortByColor.Location = new Point(3, 250); + buttonSortByColor.Name = "buttonSortByColor"; + buttonSortByColor.Size = new Size(167, 40); + buttonSortByColor.TabIndex = 8; + buttonSortByColor.Text = "Сортировка по цвету"; + buttonSortByColor.UseVisualStyleBackColor = true; + buttonSortByColor.Click += ButtonSortByColor_Click; + // + // buttonSortByType + // + buttonSortByType.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + buttonSortByType.Location = new Point(3, 210); + buttonSortByType.Name = "buttonSortByType"; + buttonSortByType.Size = new Size(167, 40); + buttonSortByType.TabIndex = 7; + buttonSortByType.Text = "Сортировка по типу"; + buttonSortByType.UseVisualStyleBackColor = true; + buttonSortByType.Click += ButtonSortByType_Click; + // // buttonAddCar // buttonAddCar.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; @@ -100,7 +126,7 @@ // // maskedTextBoxPosition // - maskedTextBoxPosition.Location = new Point(3, 95); + maskedTextBoxPosition.Location = new Point(3, 49); maskedTextBoxPosition.Mask = "00"; maskedTextBoxPosition.Name = "maskedTextBoxPosition"; maskedTextBoxPosition.Size = new Size(167, 23); @@ -110,7 +136,7 @@ // buttonRefresh // buttonRefresh.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; - buttonRefresh.Location = new Point(3, 210); + buttonRefresh.Location = new Point(3, 164); buttonRefresh.Name = "buttonRefresh"; buttonRefresh.Size = new Size(167, 40); buttonRefresh.TabIndex = 6; @@ -121,7 +147,7 @@ // buttonRemoveCar // buttonRemoveCar.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; - buttonRemoveCar.Location = new Point(3, 124); + buttonRemoveCar.Location = new Point(3, 78); buttonRemoveCar.Name = "buttonRemoveCar"; buttonRemoveCar.Size = new Size(167, 40); buttonRemoveCar.TabIndex = 4; @@ -132,7 +158,7 @@ // buttonGoToCheck // buttonGoToCheck.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; - buttonGoToCheck.Location = new Point(3, 170); + buttonGoToCheck.Location = new Point(3, 124); buttonGoToCheck.Name = "buttonGoToCheck"; buttonGoToCheck.Size = new Size(167, 40); buttonGoToCheck.TabIndex = 5; @@ -249,7 +275,7 @@ pictureBox.Dock = DockStyle.Fill; pictureBox.Location = new Point(0, 24); pictureBox.Name = "pictureBox"; - pictureBox.Size = new Size(783, 608); + pictureBox.Size = new Size(783, 657); pictureBox.TabIndex = 1; pictureBox.TabStop = false; // @@ -297,7 +323,7 @@ // AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(962, 632); + ClientSize = new Size(962, 681); Controls.Add(pictureBox); Controls.Add(groupBoxTools); Controls.Add(menuStrip); @@ -342,5 +368,7 @@ private ToolStripMenuItem loadToolStripMenuItem; private SaveFileDialog saveFileDialog; private OpenFileDialog openFileDialog; + private Button buttonSortByColor; + private Button buttonSortByType; } } \ No newline at end of file diff --git a/ProjectSportCar/ProjectSportCar/FormCarCollection.cs b/ProjectSportCar/ProjectSportCar/FormCarCollection.cs index c7a3fde..10ca8fd 100644 --- a/ProjectSportCar/ProjectSportCar/FormCarCollection.cs +++ b/ProjectSportCar/ProjectSportCar/FormCarCollection.cs @@ -206,7 +206,7 @@ public partial class FormCarCollection : Form listBoxCollection.Items.Clear(); for (int i = 0; i < _storageCollection.Keys?.Count; ++i) { - string? colName = _storageCollection.Keys?[i]; + string? colName = _storageCollection.Keys?[i].Name; if (!string.IsNullOrEmpty(colName)) { listBoxCollection.Items.Add(colName); @@ -261,7 +261,7 @@ public partial class FormCarCollection : Form MessageBox.Show("Сохранение прошло успешно", "Результат", MessageBoxButtons.OK, MessageBoxIcon.Information); _logger.LogInformation("Сохранение в файл: {filename}", saveFileDialog.FileName); } - catch(Exception ex) + catch (Exception ex) { MessageBox.Show(ex.Message, "Результат", MessageBoxButtons.OK, MessageBoxIcon.Error); _logger.LogError("Ошибка: {Message}", ex.Message); @@ -278,4 +278,39 @@ public partial class FormCarCollection : Form { // TODO продумать логику } + + /// + /// Сортировка по типу + /// + /// + /// + private void ButtonSortByType_Click(object sender, EventArgs e) + { + CompareCars(new DrawningCarCompareByType()); + } + + /// + /// Сортировка по цвету + /// + /// + /// + private void ButtonSortByColor_Click(object sender, EventArgs e) + { + CompareCars(new DrawningCarCompareByColor()); + } + + /// + /// Сортировка по сравнителю + /// + /// Сравнитель объектов + private void CompareCars(IComparer comparer) + { + if (_company == null) + { + return; + } + + _company.Sort(comparer); + pictureBox.Image = _company.Show(); + } } \ No newline at end of file