From fa25dbf757302648a9f59228964e59bfacca3359 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Sun, 9 Apr 2023 22:02:25 +0200 Subject: [PATCH] :alembic: try making the RecipeCollection act like a real collection --- .gitignore | 3 + MCTG/MCTGApp/MCTGApp.csproj | 4 + MCTG/MCTGApp/Program.cs | 16 +++- MCTG/MCTGLib/BaseItem.cs | 41 ++++++++-- MCTG/MCTGLib/Recipe.cs | 55 ++++++++++--- MCTG/MCTGLib/RecipeCollection.cs | 132 ++++++++++++++++++++++++------- 6 files changed, 203 insertions(+), 48 deletions(-) diff --git a/.gitignore b/.gitignore index 4a3a6d3..6c1ac87 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ ## ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore +# User-spacific editor config +.editorconfig + # User-specific files *.rsuser *.suo diff --git a/MCTG/MCTGApp/MCTGApp.csproj b/MCTG/MCTGApp/MCTGApp.csproj index f184388..79a52db 100644 --- a/MCTG/MCTGApp/MCTGApp.csproj +++ b/MCTG/MCTGApp/MCTGApp.csproj @@ -7,6 +7,10 @@ enable + + + + diff --git a/MCTG/MCTGApp/Program.cs b/MCTG/MCTGApp/Program.cs index eb783ba..021e938 100644 --- a/MCTG/MCTGApp/Program.cs +++ b/MCTG/MCTGApp/Program.cs @@ -8,6 +8,7 @@ Console.WriteLine("Hello, World!\n"); // TESTS: +// tests on Recipe class BaseItem r1 = new Recipe("A recipe..."); r1.DisplayItem(); @@ -16,6 +17,7 @@ r1.DisplayDescription(); Console.WriteLine(); +// tests on RecipeCollection class RecipeCollection rc = new RecipeCollection("A recipe collection..."); for (uint i = 0; i < 10; i++) { @@ -24,16 +26,24 @@ for (uint i = 0; i < 10; i++) try // test overload of [] operator { - rc[1003].DisplayItem(); - rc[2003].DisplayItem(); // incorrect index + rc[2].DisplayId(); + rc.GetById(1002); } catch (ArgumentNullException) { Console.Error.WriteLine("An index are incorrect!\n"); } +// test of multiple params constructor +RecipeCollection rc2 = new RecipeCollection( + new Recipe(), + new Recipe(), + new Recipe(), + new Recipe(), + new Recipe()); -foreach (Recipe r in rc.Collection) +// test of Enumerable property +foreach (Recipe r in rc2) { r.DisplayId(); r.DisplayDescription(); diff --git a/MCTG/MCTGLib/BaseItem.cs b/MCTG/MCTGLib/BaseItem.cs index 36a653c..f031d66 100644 --- a/MCTG/MCTGLib/BaseItem.cs +++ b/MCTG/MCTGLib/BaseItem.cs @@ -1,5 +1,6 @@  using System; +using System.ComponentModel; namespace Model { @@ -7,24 +8,29 @@ namespace Model /// Define the base structure of any Items.
/// An Item can be identifed and have a short description. It can also be displayed. /// - public abstract class BaseItem : IDisplayable + public abstract class BaseItem : IDisplayable, IEquatable { /// /// The identifier of an Item.
/// The first number correspond to the typs of the Item. ///
- public uint Id { get; } + virtual public uint Id + { + get => _id; + init => _id = value; + } + protected uint _id; + /// /// A short description of the Item. Useful to know what this Item stand for. /// public string Description { get; set; } + - - protected BaseItem(uint id, string description = "") + protected BaseItem(uint id, string description="Any Item.") { - Id = id; - Description = description; + Id = id; Description = description; } @@ -52,5 +58,28 @@ namespace Model { Console.WriteLine(this.ToString()); } + + // IEquatable implementation + public bool Equals(BaseItem? other) + { + if (other != null) + return this.Id.Equals(other.Id); + + return false; + } + + public override bool Equals(object? obj) + { + BaseItem? baseItem = obj as BaseItem; + if (baseItem == null) return false; + if (baseItem == this) return true; + + return this.Id.Equals(baseItem.Id); + } + + public override int GetHashCode() + { + return this.Id.GetHashCode(); + } } } diff --git a/MCTG/MCTGLib/Recipe.cs b/MCTG/MCTGLib/Recipe.cs index 0e6611f..2ab5420 100644 --- a/MCTG/MCTGLib/Recipe.cs +++ b/MCTG/MCTGLib/Recipe.cs @@ -5,35 +5,68 @@ namespace Model { /// /// A Recipe is a description of step and maybe some techniques, with an ingredient list to make a meal.
- /// It is instantiated with a new unique four digit id, where the first one is 1. + /// It is instantiated with a new unique id, where the first number is 1. ///
public class Recipe : BaseItem { - /// - /// This static atrribute stand for the creation of a new id. It is incremented each time a new Recipe is instantiated. - /// - public static uint idIterator = 0; + #region Private Attributes + + private static uint _idCreator = 0; // stand for the creation of a new id. It is incremented each time a new Recipe is instantiated. + private string title = ""; + + #endregion + + #region Public Properties /// /// The title of the recipe. /// - public string Title { get; set; } + public string Title + { + get => title; + set + { + title = value; + if (string.IsNullOrEmpty(title)) title = $"Recipe n{this.Id}"; + } + } /// /// All the details about the preparation of the meal. /// public string Preparation { get; set; } + #endregion - public Recipe(string description = "", string title = "", string preparation = "") - : base(idIterator+1000, description) + #region Constructors + + public Recipe(string title="", string preparation="") + : base(ComputeId(), "A recipe.") { - if (idIterator == 1000) throw new OverflowException("id has reach the maximum value."); Title = title; Preparation = preparation; - idIterator++; } + #endregion + + #region Private Methods + + /// + /// Processi the unique identificator of an Item. The identificator is calculated to put the number representing + /// the type of item before the number of its number in its type. + /// + private static uint ComputeId() + { + uint dec = 0, id = _idCreator; + while ((_idCreator / (Math.Pow(10, dec)) > 10)) dec++; + id += 1 * (uint)(Math.Pow(10, dec)); + + return id; + } + + #endregion + + #region Public Methods public override string ToString() { @@ -43,5 +76,7 @@ namespace Model $"\t.Description - {Description}\n" + $"______\n\n"; } + + #endregion } } diff --git a/MCTG/MCTGLib/RecipeCollection.cs b/MCTG/MCTGLib/RecipeCollection.cs index 594ae91..f93227d 100644 --- a/MCTG/MCTGLib/RecipeCollection.cs +++ b/MCTG/MCTGLib/RecipeCollection.cs @@ -1,38 +1,66 @@ using System; +using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; namespace Model { /// /// A Recipe collection is a group of recipe.
- /// It is instantiated with a new unique four digit id, where the first one is 2. + /// It is instantiated with a new unique id, where the first number is 2. ///
- public class RecipeCollection : BaseItem + public class RecipeCollection : BaseItem, ICollection { - /// - /// This static atrribute stand for the creation of a new id. It is incremented each time a new RecipeCollection is instantiated. - /// - private static uint idIterator = 0; + #region Private Attributes + + private const int CAT_ITEM = 2; // the first number of the item full id : the item category. + private static uint _idCreator = 0; // stand for the creation of a new id. It is incremented each time a new Recipe is instantiated. + private ICollection _recipes = new List(); // main composent of this class. + + #endregion - /// - /// The main composent of a RecipeCollection. This contain the Recipes included in this collection. - /// - public List Collection { get; set; } + #region Public Properties + #region ICollection Implementation - public RecipeCollection(string description = "", List? collection = null) - : base(idIterator + 2000, description) + public int Count => _recipes.Count; + public bool IsReadOnly => false; + + #endregion + #endregion + + #region Constructors + + public RecipeCollection(string description="A recipe collection.") + : base(ComputeId(), description) + { } + + public RecipeCollection(params Recipe[] recipes) + : base(ComputeId()) { - if (idIterator == 1000) throw new OverflowException("id has reach the maximum value."); + _recipes.CopyTo(recipes, 0); + } + + #endregion - if (collection == null) - Collection = new List(); - else - Collection = collection; + #region Private Methods - idIterator++; + /// + /// Processi the unique identificator of an Item. The identificator is calculated to put the number representing + /// the type of item before the number of its number in its type. + /// + private static uint ComputeId() + { + uint dec = 0, id = _idCreator; + while ((_idCreator / (Math.Pow(10, dec)) > 10)) dec++; + id += CAT_ITEM * (uint)(Math.Pow(10, dec)); + + return id; } + #endregion + + #region Public Methods public override string ToString() { @@ -43,22 +71,66 @@ namespace Model $"______\n\n"; } + public Recipe GetById(uint id) + { + if (this._recipes is not List) + throw new InvalidCastException("Need to verify the type of the private attribute '_recipes'."); + + return (this._recipes as List).Find(x => x.Id.Equals(Id)); + } + + #region ICollection Implementation + + public void Add(Recipe item) + { + _recipes.Add(item); + } + + public void Clear() + { + _recipes.Clear(); + } + + public bool Contains(Recipe item) + { + return _recipes.Contains(item); + } + + public void CopyTo(Recipe[] array, int arrayIndex) + { + _recipes.CopyTo(array, arrayIndex); + } + + public bool Remove(Recipe item) + { + return _recipes.Remove(item); + } + + public IEnumerator GetEnumerator() + { + return _recipes.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return _recipes.GetEnumerator(); + } + + #endregion + + #endregion + + #region Operators Overloading + /// /// Overload the [] operator to access the Recipe directly without passing by the Collection.
/// It use the identifier of the Recipe to get the item. ///
/// The id of the Recipe /// - public Recipe this[uint id] + public Recipe this[Index id] { - get - { - foreach (Recipe r in this.Collection) - { - if (r.Id == id) return r; - } - throw new ArgumentNullException("The id given dosen't correspond to any recipes in the collection."); - } + get => this.ElementAt(id); } /// @@ -69,7 +141,7 @@ namespace Model /// The recipe collection where the recipe is added. public static RecipeCollection operator + (RecipeCollection coll, Recipe ri) { - coll.Collection.Add(ri); return coll; + coll.Add(ri); return coll; } /// @@ -80,7 +152,9 @@ namespace Model /// The recipe collection where the recipe is removed. public static RecipeCollection operator - (RecipeCollection coll, Recipe ri) { - coll.Collection.Remove(ri); return coll; + coll.Remove(ri); return coll; } + + #endregion } }