From dc945c70b66c3d3302c71532840e00737d5ca2f3 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Fri, 7 Apr 2023 12:03:01 +0200 Subject: [PATCH 01/16] start implementation ItemCollection --- MCTG/MCTGLib/Class1.cs | 7 ------- MCTG/MCTGLib/ItemCollection.cs | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 MCTG/MCTGLib/Class1.cs create mode 100644 MCTG/MCTGLib/ItemCollection.cs diff --git a/MCTG/MCTGLib/Class1.cs b/MCTG/MCTGLib/Class1.cs deleted file mode 100644 index 5b51184..0000000 --- a/MCTG/MCTGLib/Class1.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace MCTGLib -{ - public class Class1 - { - - } -} \ No newline at end of file diff --git a/MCTG/MCTGLib/ItemCollection.cs b/MCTG/MCTGLib/ItemCollection.cs new file mode 100644 index 0000000..a3c7d4e --- /dev/null +++ b/MCTG/MCTGLib/ItemCollection.cs @@ -0,0 +1,7 @@ +namespace Model +{ + public class ItemCollection + { + + } +} \ No newline at end of file From cdb2628c5d6ef778c0074a98092a0be4f2b81a9a Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Fri, 7 Apr 2023 12:04:07 +0200 Subject: [PATCH 02/16] add unsaved modif --- MCTG/MCTGApp/MCTGApp.csproj | 4 ++++ MCTG/MCTGApp/Program.cs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/MCTG/MCTGApp/MCTGApp.csproj b/MCTG/MCTGApp/MCTGApp.csproj index f02677b..f184388 100644 --- a/MCTG/MCTGApp/MCTGApp.csproj +++ b/MCTG/MCTGApp/MCTGApp.csproj @@ -7,4 +7,8 @@ enable + + + + diff --git a/MCTG/MCTGApp/Program.cs b/MCTG/MCTGApp/Program.cs index 3751555..275a069 100644 --- a/MCTG/MCTGApp/Program.cs +++ b/MCTG/MCTGApp/Program.cs @@ -1,2 +1,4 @@ // See https://aka.ms/new-console-template for more information +using ; + Console.WriteLine("Hello, World!"); From 9b0015d3c4455dc1adb30d559c1e0b5bf6067917 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Fri, 7 Apr 2023 21:13:49 +0200 Subject: [PATCH 03/16] dev of the structure as decribed in #17. need some review before pr --- MCTG/MCTGApp/Program.cs | 40 ++++++++++++++- MCTG/MCTGLib/BaseItem.cs | 56 +++++++++++++++++++++ MCTG/MCTGLib/IDisplayable.cs | 23 +++++++++ MCTG/MCTGLib/ItemCollection.cs | 7 --- MCTG/MCTGLib/Recipe.cs | 47 +++++++++++++++++ MCTG/MCTGLib/RecipeCollection.cs | 86 ++++++++++++++++++++++++++++++++ 6 files changed, 250 insertions(+), 9 deletions(-) create mode 100644 MCTG/MCTGLib/BaseItem.cs create mode 100644 MCTG/MCTGLib/IDisplayable.cs delete mode 100644 MCTG/MCTGLib/ItemCollection.cs create mode 100644 MCTG/MCTGLib/Recipe.cs create mode 100644 MCTG/MCTGLib/RecipeCollection.cs diff --git a/MCTG/MCTGApp/Program.cs b/MCTG/MCTGApp/Program.cs index 275a069..eb783ba 100644 --- a/MCTG/MCTGApp/Program.cs +++ b/MCTG/MCTGApp/Program.cs @@ -1,4 +1,40 @@ // See https://aka.ms/new-console-template for more information -using ; -Console.WriteLine("Hello, World!"); +using Model; + + +Console.WriteLine("Hello, World!\n"); + + +// TESTS: + +BaseItem r1 = new Recipe("A recipe..."); + +r1.DisplayItem(); +r1.DisplayId(); +r1.DisplayDescription(); + +Console.WriteLine(); + +RecipeCollection rc = new RecipeCollection("A recipe collection..."); +for (uint i = 0; i < 10; i++) +{ + rc += new Recipe($"Recipe number {i} in the collection."); // test overload + operator +} + +try // test overload of [] operator +{ + rc[1003].DisplayItem(); + rc[2003].DisplayItem(); // incorrect index +} +catch (ArgumentNullException) +{ + Console.Error.WriteLine("An index are incorrect!\n"); +} + + +foreach (Recipe r in rc.Collection) +{ + r.DisplayId(); + r.DisplayDescription(); +} diff --git a/MCTG/MCTGLib/BaseItem.cs b/MCTG/MCTGLib/BaseItem.cs new file mode 100644 index 0000000..36a653c --- /dev/null +++ b/MCTG/MCTGLib/BaseItem.cs @@ -0,0 +1,56 @@ + +using System; + +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 + { + /// + /// The identifier of an Item.
+ /// The first number correspond to the typs of the Item. + ///
+ public uint Id { get; } + + /// + /// 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 = "") + { + Id = id; + Description = description; + } + + + public override string ToString() + { + return + $"[ Class -BaseItem- ]\n\n" + + $"\t.Id - {Id}\n" + + $"\t.Description - {Description}\n" + + $"______\n\n"; + } + + // IDisplayable Implementation + public void DisplayId() + { + Console.WriteLine($".Id - {Id}"); + } + + public void DisplayDescription() + { + Console.WriteLine($".Description - {Description}"); + } + + public void DisplayItem() + { + Console.WriteLine(this.ToString()); + } + } +} diff --git a/MCTG/MCTGLib/IDisplayable.cs b/MCTG/MCTGLib/IDisplayable.cs new file mode 100644 index 0000000..fed294c --- /dev/null +++ b/MCTG/MCTGLib/IDisplayable.cs @@ -0,0 +1,23 @@ +namespace Model +{ + /// + /// Define an Item that can be displayed. + /// + interface IDisplayable + { + /// + /// Display the Id of the Item + /// + void DisplayId(); + + /// + /// Display the Description of the Item + /// + void DisplayDescription(); + + /// + /// Display the entire Item (Id, Description and other...) + /// + void DisplayItem(); + } +} diff --git a/MCTG/MCTGLib/ItemCollection.cs b/MCTG/MCTGLib/ItemCollection.cs deleted file mode 100644 index a3c7d4e..0000000 --- a/MCTG/MCTGLib/ItemCollection.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Model -{ - public class ItemCollection - { - - } -} \ No newline at end of file diff --git a/MCTG/MCTGLib/Recipe.cs b/MCTG/MCTGLib/Recipe.cs new file mode 100644 index 0000000..0e6611f --- /dev/null +++ b/MCTG/MCTGLib/Recipe.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; + +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. + ///
+ 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; + + /// + /// The title of the recipe. + /// + public string Title { get; set; } + + /// + /// All the details about the preparation of the meal. + /// + public string Preparation { get; set; } + + + public Recipe(string description = "", string title = "", string preparation = "") + : base(idIterator+1000, description) + { + if (idIterator == 1000) throw new OverflowException("id has reach the maximum value."); + Title = title; + Preparation = preparation; + idIterator++; + } + + + public override string ToString() + { + return + $"[ Class -Recipe- ]\n\n" + + $"\t.Id - {Id}\n" + + $"\t.Description - {Description}\n" + + $"______\n\n"; + } + } +} diff --git a/MCTG/MCTGLib/RecipeCollection.cs b/MCTG/MCTGLib/RecipeCollection.cs new file mode 100644 index 0000000..594ae91 --- /dev/null +++ b/MCTG/MCTGLib/RecipeCollection.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; + +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. + ///
+ public class RecipeCollection : BaseItem + { + /// + /// 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; + + /// + /// The main composent of a RecipeCollection. This contain the Recipes included in this collection. + /// + public List Collection { get; set; } + + + public RecipeCollection(string description = "", List? collection = null) + : base(idIterator + 2000, description) + { + if (idIterator == 1000) throw new OverflowException("id has reach the maximum value."); + + if (collection == null) + Collection = new List(); + else + Collection = collection; + + idIterator++; + } + + + public override string ToString() + { + return + $"[ Class -RecipeCollection- ]\n\n" + + $"\t.Id - {Id}\n" + + $"\t.Description - {Description}\n" + + $"______\n\n"; + } + + /// + /// 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] + { + 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."); + } + } + + /// + /// Overload of + operator to add a Recipe to a RecipeCollection. + /// + /// The recipe collection where the recipe will be added + /// The recipe to add + /// The recipe collection where the recipe is added. + public static RecipeCollection operator + (RecipeCollection coll, Recipe ri) + { + coll.Collection.Add(ri); return coll; + } + + /// + /// Overload of - operator to remove a Recipe to a RecipeCollection. + /// + /// The recipe collection where the recipe will be removed + /// The recipe to remove + /// The recipe collection where the recipe is removed. + public static RecipeCollection operator - (RecipeCollection coll, Recipe ri) + { + coll.Collection.Remove(ri); return coll; + } + } +} From fa25dbf757302648a9f59228964e59bfacca3359 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Sun, 9 Apr 2023 22:02:25 +0200 Subject: [PATCH 04/16] :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 } } From e68a9ac48dfd84dc3dc35f38703c3387a376c785 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Mon, 10 Apr 2023 01:21:36 +0200 Subject: [PATCH 05/16] :bug: fix: ComputeId now compute correct ids --- MCTG/MCTGApp/MCTGApp.csproj | 4 --- MCTG/MCTGApp/Program.cs | 23 +++++++++------- MCTG/MCTGLib/BaseItem.cs | 45 +++++++++++++++++++------------- MCTG/MCTGLib/Recipe.cs | 9 ++++--- MCTG/MCTGLib/RecipeCollection.cs | 13 +++++---- 5 files changed, 55 insertions(+), 39 deletions(-) diff --git a/MCTG/MCTGApp/MCTGApp.csproj b/MCTG/MCTGApp/MCTGApp.csproj index 79a52db..f184388 100644 --- a/MCTG/MCTGApp/MCTGApp.csproj +++ b/MCTG/MCTGApp/MCTGApp.csproj @@ -7,10 +7,6 @@ enable - - - - diff --git a/MCTG/MCTGApp/Program.cs b/MCTG/MCTGApp/Program.cs index 021e938..57a3a18 100644 --- a/MCTG/MCTGApp/Program.cs +++ b/MCTG/MCTGApp/Program.cs @@ -8,7 +8,7 @@ Console.WriteLine("Hello, World!\n"); // TESTS: -// tests on Recipe class +Console.WriteLine("tests on Recipe class:"); BaseItem r1 = new Recipe("A recipe..."); r1.DisplayItem(); @@ -17,24 +17,30 @@ r1.DisplayDescription(); Console.WriteLine(); -// tests on RecipeCollection class +Console.WriteLine("tests on RecipeCollection class:"); RecipeCollection rc = new RecipeCollection("A recipe collection..."); for (uint i = 0; i < 10; i++) { - rc += new Recipe($"Recipe number {i} in the collection."); // test overload + operator + rc += new Recipe($"Recipe number {i} in the collection."); + Console.WriteLine("test overload + operator"); } -try // test overload of [] operator +Console.WriteLine("test overload of [] operator:"); +try { rc[2].DisplayId(); - rc.GetById(1002); + rc.GetById(14).DisplayId(); } catch (ArgumentNullException) { Console.Error.WriteLine("An index are incorrect!\n"); } +catch (Exception e) +{ + Console.Error.WriteLine("Exception thrown: {0}", e); +} -// test of multiple params constructor +Console.WriteLine("test of multiple params constructor:"); RecipeCollection rc2 = new RecipeCollection( new Recipe(), new Recipe(), @@ -42,9 +48,8 @@ RecipeCollection rc2 = new RecipeCollection( new Recipe(), new Recipe()); -// test of Enumerable property +Console.WriteLine("test of Enumerable property:"); foreach (Recipe r in rc2) { - r.DisplayId(); - r.DisplayDescription(); + r.DisplayId(); Console.Write(" - "); } diff --git a/MCTG/MCTGLib/BaseItem.cs b/MCTG/MCTGLib/BaseItem.cs index f031d66..8d8cd81 100644 --- a/MCTG/MCTGLib/BaseItem.cs +++ b/MCTG/MCTGLib/BaseItem.cs @@ -1,6 +1,7 @@  using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; namespace Model { @@ -10,6 +11,8 @@ namespace Model /// public abstract class BaseItem : IDisplayable, IEquatable { + #region Private Attributes + /// /// The identifier of an Item.
/// The first number correspond to the typs of the Item. @@ -20,19 +23,28 @@ namespace Model init => _id = value; } protected uint _id; - + + #endregion + + #region Public Properties /// /// A short description of the Item. Useful to know what this Item stand for. /// public string Description { get; set; } - + + #endregion + + #region Constructors protected BaseItem(uint id, string description="Any Item.") { Id = id; Description = description; } + #endregion + + #region Public Methods public override string ToString() { @@ -43,7 +55,8 @@ namespace Model $"______\n\n"; } - // IDisplayable Implementation + #region IDisplayable Implementation + public void DisplayId() { Console.WriteLine($".Id - {Id}"); @@ -59,27 +72,23 @@ namespace Model Console.WriteLine(this.ToString()); } - // IEquatable implementation - public bool Equals(BaseItem? other) - { - if (other != null) - return this.Id.Equals(other.Id); + #endregion - return false; - } + #region IEquatable implementation - public override bool Equals(object? obj) + public int GetHashCode([DisallowNull] BaseItem obj) { - BaseItem? baseItem = obj as BaseItem; - if (baseItem == null) return false; - if (baseItem == this) return true; - - return this.Id.Equals(baseItem.Id); + return obj.Id.GetHashCode() + obj.Description.GetHashCode(); } - public override int GetHashCode() + public bool Equals(BaseItem? other) { - return this.Id.GetHashCode(); + if (other == null) return false; + return (this.Id == other.Id) && (this.Description == other.Description); } + + #endregion + + #endregion } } diff --git a/MCTG/MCTGLib/Recipe.cs b/MCTG/MCTGLib/Recipe.cs index 2ab5420..f5cb00d 100644 --- a/MCTG/MCTGLib/Recipe.cs +++ b/MCTG/MCTGLib/Recipe.cs @@ -11,6 +11,7 @@ namespace Model { #region Private Attributes + private const int CAT_ITEM = 1; 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 = ""; @@ -57,9 +58,11 @@ namespace Model ///
private static uint ComputeId() { - uint dec = 0, id = _idCreator; - while ((_idCreator / (Math.Pow(10, dec)) > 10)) dec++; - id += 1 * (uint)(Math.Pow(10, dec)); + uint dec = 1; + while ((_idCreator / (Math.Pow(10, dec)) >= 1)) dec++; + + uint id = (CAT_ITEM * (uint)(Math.Pow(10, dec))) + _idCreator++; + Console.WriteLine("[recipe] new computed id: {0}", id); return id; } diff --git a/MCTG/MCTGLib/RecipeCollection.cs b/MCTG/MCTGLib/RecipeCollection.cs index f93227d..c9ed6be 100644 --- a/MCTG/MCTGLib/RecipeCollection.cs +++ b/MCTG/MCTGLib/RecipeCollection.cs @@ -19,14 +19,15 @@ namespace Model #endregion - #region Public Properties + #region ICollection Implementation public int Count => _recipes.Count; public bool IsReadOnly => false; #endregion + #endregion #region Constructors @@ -51,9 +52,11 @@ namespace Model ///
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)); + uint dec = 1; + while ((_idCreator / (Math.Pow(10, dec)) >= 1)) dec++; + + uint id = (CAT_ITEM * (uint)(Math.Pow(10, dec))) + _idCreator++; + Console.WriteLine("[recipe collection] new computed id: {0}", id); return id; } @@ -76,7 +79,7 @@ namespace Model 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)); + return (this._recipes as List).Find(x => x.Id.Equals(id)); } #region ICollection Implementation From 50f2cb43a48fd474f63f7e7380a7d9f07356e736 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Mon, 10 Apr 2023 01:39:30 +0200 Subject: [PATCH 06/16] :bug: fix: RecipeCollection is now correctly enumerable --- MCTG/MCTGApp/Program.cs | 4 ++-- MCTG/MCTGLib/RecipeCollection.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MCTG/MCTGApp/Program.cs b/MCTG/MCTGApp/Program.cs index 57a3a18..9998a9b 100644 --- a/MCTG/MCTGApp/Program.cs +++ b/MCTG/MCTGApp/Program.cs @@ -29,7 +29,7 @@ Console.WriteLine("test overload of [] operator:"); try { rc[2].DisplayId(); - rc.GetById(14).DisplayId(); + rc.GetById(110).DisplayId(); } catch (ArgumentNullException) { @@ -51,5 +51,5 @@ RecipeCollection rc2 = new RecipeCollection( Console.WriteLine("test of Enumerable property:"); foreach (Recipe r in rc2) { - r.DisplayId(); Console.Write(" - "); + r.DisplayId(); } diff --git a/MCTG/MCTGLib/RecipeCollection.cs b/MCTG/MCTGLib/RecipeCollection.cs index c9ed6be..0611a0f 100644 --- a/MCTG/MCTGLib/RecipeCollection.cs +++ b/MCTG/MCTGLib/RecipeCollection.cs @@ -39,7 +39,7 @@ namespace Model public RecipeCollection(params Recipe[] recipes) : base(ComputeId()) { - _recipes.CopyTo(recipes, 0); + _recipes = new List(recipes); } #endregion @@ -116,7 +116,7 @@ namespace Model IEnumerator IEnumerable.GetEnumerator() { - return _recipes.GetEnumerator(); + return this.GetEnumerator(); } #endregion From 522f16912800d6e4efbfd886834a3a36751374ee Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Mon, 10 Apr 2023 02:06:10 +0200 Subject: [PATCH 07/16] clean code and try to add some tests --- MCTG/MCTGApp/Program.cs | 2 +- MCTG/MCTGLib/BaseItem.cs | 2 +- MCTG/MCTGLib/IDisplayable.cs | 2 +- MCTG/MCTGLib/Recipe.cs | 2 +- MCTG/MCTGLib/RecipeCollection.cs | 4 +-- .../MCTGLib_UnitTests.csproj | 4 +++ MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs | 34 +++++++++++++++++++ MCTG/Tests/MCTGLib_UnitTests/UnitTest1.cs | 11 ------ 8 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs delete mode 100644 MCTG/Tests/MCTGLib_UnitTests/UnitTest1.cs diff --git a/MCTG/MCTGApp/Program.cs b/MCTG/MCTGApp/Program.cs index 9998a9b..9196a9a 100644 --- a/MCTG/MCTGApp/Program.cs +++ b/MCTG/MCTGApp/Program.cs @@ -1,6 +1,6 @@ // See https://aka.ms/new-console-template for more information -using Model; +using MCTGLib; Console.WriteLine("Hello, World!\n"); diff --git a/MCTG/MCTGLib/BaseItem.cs b/MCTG/MCTGLib/BaseItem.cs index 8d8cd81..9d60520 100644 --- a/MCTG/MCTGLib/BaseItem.cs +++ b/MCTG/MCTGLib/BaseItem.cs @@ -3,7 +3,7 @@ using System; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; -namespace Model +namespace MCTGLib { /// /// Define the base structure of any Items.
diff --git a/MCTG/MCTGLib/IDisplayable.cs b/MCTG/MCTGLib/IDisplayable.cs index fed294c..5de9319 100644 --- a/MCTG/MCTGLib/IDisplayable.cs +++ b/MCTG/MCTGLib/IDisplayable.cs @@ -1,4 +1,4 @@ -namespace Model +namespace MCTGLib { /// /// Define an Item that can be displayed. diff --git a/MCTG/MCTGLib/Recipe.cs b/MCTG/MCTGLib/Recipe.cs index f5cb00d..7e55030 100644 --- a/MCTG/MCTGLib/Recipe.cs +++ b/MCTG/MCTGLib/Recipe.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Model +namespace MCTGLib { /// /// A Recipe is a description of step and maybe some techniques, with an ingredient list to make a meal.
diff --git a/MCTG/MCTGLib/RecipeCollection.cs b/MCTG/MCTGLib/RecipeCollection.cs index 0611a0f..4e799d3 100644 --- a/MCTG/MCTGLib/RecipeCollection.cs +++ b/MCTG/MCTGLib/RecipeCollection.cs @@ -3,7 +3,7 @@ using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; -namespace Model +namespace MCTGLib { /// /// A Recipe collection is a group of recipe.
@@ -15,7 +15,7 @@ namespace Model 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. + private readonly ICollection _recipes = new List(); // main composent of this class. #endregion diff --git a/MCTG/Tests/MCTGLib_UnitTests/MCTGLib_UnitTests.csproj b/MCTG/Tests/MCTGLib_UnitTests/MCTGLib_UnitTests.csproj index 42ff44d..afc37b6 100644 --- a/MCTG/Tests/MCTGLib_UnitTests/MCTGLib_UnitTests.csproj +++ b/MCTG/Tests/MCTGLib_UnitTests/MCTGLib_UnitTests.csproj @@ -22,4 +22,8 @@ + + + + diff --git a/MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs b/MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs new file mode 100644 index 0000000..3196733 --- /dev/null +++ b/MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs @@ -0,0 +1,34 @@ +using MCTGLib; + +namespace MCTGLib_UnitTests +{ + public class Recipe_UT + { + [Fact] + public void TestConstructorNotNull() + { + Recipe r1 = new Recipe(); + Assert.NotNull(r1); + } + + [Fact] + public void TestConstructorWithValidDefaults() + { + Recipe r1 = new Recipe(); + Assert.Equal("Recipe n10", r1.Title); + Assert.Equal("A recipe.", r1.Description); + } + + [Fact] + public void TestComputeId() + { + List lr = new List(); + for (int i = 0; i < 11; i++) + lr.Add(new Recipe()); + + Assert.Equal((uint)18, lr.ElementAt(8).Id); + Assert.Equal((uint)19, lr.ElementAt(9).Id); + Assert.Equal((uint)110, lr.ElementAt(10).Id); + } + } +} \ No newline at end of file diff --git a/MCTG/Tests/MCTGLib_UnitTests/UnitTest1.cs b/MCTG/Tests/MCTGLib_UnitTests/UnitTest1.cs deleted file mode 100644 index 4d22b68..0000000 --- a/MCTG/Tests/MCTGLib_UnitTests/UnitTest1.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace MCTGLib_UnitTests -{ - public class UnitTest1 - { - [Fact] - public void Test1() - { - - } - } -} \ No newline at end of file From a38e35d1ed54fbe7a0c5df03792fd63248635181 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Thu, 27 Apr 2023 12:02:14 +0200 Subject: [PATCH 08/16] :recycle: changes on implementation. new structure described in #17 --- MCTG/MCTGApp/Program.cs | 47 +----- MCTG/MCTGLib/BaseItem.cs | 94 ------------ MCTG/MCTGLib/IDisplayable.cs | 23 --- MCTG/MCTGLib/PreparationStep.cs | 39 +++++ MCTG/MCTGLib/Recipe.cs | 106 ++++---------- MCTG/MCTGLib/RecipeCollection.cs | 242 ++++++++++++------------------- 6 files changed, 162 insertions(+), 389 deletions(-) delete mode 100644 MCTG/MCTGLib/BaseItem.cs delete mode 100644 MCTG/MCTGLib/IDisplayable.cs create mode 100644 MCTG/MCTGLib/PreparationStep.cs diff --git a/MCTG/MCTGApp/Program.cs b/MCTG/MCTGApp/Program.cs index 9196a9a..aa01b39 100644 --- a/MCTG/MCTGApp/Program.cs +++ b/MCTG/MCTGApp/Program.cs @@ -8,48 +8,5 @@ Console.WriteLine("Hello, World!\n"); // TESTS: -Console.WriteLine("tests on Recipe class:"); -BaseItem r1 = new Recipe("A recipe..."); - -r1.DisplayItem(); -r1.DisplayId(); -r1.DisplayDescription(); - -Console.WriteLine(); - -Console.WriteLine("tests on RecipeCollection class:"); -RecipeCollection rc = new RecipeCollection("A recipe collection..."); -for (uint i = 0; i < 10; i++) -{ - rc += new Recipe($"Recipe number {i} in the collection."); - Console.WriteLine("test overload + operator"); -} - -Console.WriteLine("test overload of [] operator:"); -try -{ - rc[2].DisplayId(); - rc.GetById(110).DisplayId(); -} -catch (ArgumentNullException) -{ - Console.Error.WriteLine("An index are incorrect!\n"); -} -catch (Exception e) -{ - Console.Error.WriteLine("Exception thrown: {0}", e); -} - -Console.WriteLine("test of multiple params constructor:"); -RecipeCollection rc2 = new RecipeCollection( - new Recipe(), - new Recipe(), - new Recipe(), - new Recipe(), - new Recipe()); - -Console.WriteLine("test of Enumerable property:"); -foreach (Recipe r in rc2) -{ - r.DisplayId(); -} +RecipeCollection rc = new RecipeCollection(); +Console.WriteLine($"rc.Description: {rc.Description}"); \ No newline at end of file diff --git a/MCTG/MCTGLib/BaseItem.cs b/MCTG/MCTGLib/BaseItem.cs deleted file mode 100644 index 9d60520..0000000 --- a/MCTG/MCTGLib/BaseItem.cs +++ /dev/null @@ -1,94 +0,0 @@ - -using System; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; - -namespace MCTGLib -{ - /// - /// 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, IEquatable - { - #region Private Attributes - - /// - /// The identifier of an Item.
- /// The first number correspond to the typs of the Item. - ///
- virtual public uint Id - { - get => _id; - init => _id = value; - } - protected uint _id; - - #endregion - - #region Public Properties - - /// - /// A short description of the Item. Useful to know what this Item stand for. - /// - public string Description { get; set; } - - #endregion - - #region Constructors - - protected BaseItem(uint id, string description="Any Item.") - { - Id = id; Description = description; - } - - #endregion - - #region Public Methods - - public override string ToString() - { - return - $"[ Class -BaseItem- ]\n\n" + - $"\t.Id - {Id}\n" + - $"\t.Description - {Description}\n" + - $"______\n\n"; - } - - #region IDisplayable Implementation - - public void DisplayId() - { - Console.WriteLine($".Id - {Id}"); - } - - public void DisplayDescription() - { - Console.WriteLine($".Description - {Description}"); - } - - public void DisplayItem() - { - Console.WriteLine(this.ToString()); - } - - #endregion - - #region IEquatable implementation - - public int GetHashCode([DisallowNull] BaseItem obj) - { - return obj.Id.GetHashCode() + obj.Description.GetHashCode(); - } - - public bool Equals(BaseItem? other) - { - if (other == null) return false; - return (this.Id == other.Id) && (this.Description == other.Description); - } - - #endregion - - #endregion - } -} diff --git a/MCTG/MCTGLib/IDisplayable.cs b/MCTG/MCTGLib/IDisplayable.cs deleted file mode 100644 index 5de9319..0000000 --- a/MCTG/MCTGLib/IDisplayable.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace MCTGLib -{ - /// - /// Define an Item that can be displayed. - /// - interface IDisplayable - { - /// - /// Display the Id of the Item - /// - void DisplayId(); - - /// - /// Display the Description of the Item - /// - void DisplayDescription(); - - /// - /// Display the entire Item (Id, Description and other...) - /// - void DisplayItem(); - } -} diff --git a/MCTG/MCTGLib/PreparationStep.cs b/MCTG/MCTGLib/PreparationStep.cs new file mode 100644 index 0000000..13a7d7a --- /dev/null +++ b/MCTG/MCTGLib/PreparationStep.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MCTGLib +{ + public class PreparationStep + { + #region Attributes + private string? _description; + #endregion + + #region Properties + public int Order { get; init; } + public string? Description + { + get => _description; + set + { + if (string.IsNullOrEmpty(value)) + { + _description = "No data."; return; + } + _description = value; + } + } + #endregion + + #region Constructors + public PreparationStep(int order, string? description) + { + Order = order; + Description = description; + } + #endregion + } +} diff --git a/MCTG/MCTGLib/Recipe.cs b/MCTG/MCTGLib/Recipe.cs index 7e55030..ebbdac6 100644 --- a/MCTG/MCTGLib/Recipe.cs +++ b/MCTG/MCTGLib/Recipe.cs @@ -1,85 +1,35 @@ using System; using System.Collections.Generic; - +using System.Runtime.CompilerServices; + namespace MCTGLib { - /// - /// 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 id, where the first number is 1. - ///
- public class Recipe : BaseItem - { - #region Private Attributes - - private const int CAT_ITEM = 1; - 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 => 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 - - #region Constructors - - public Recipe(string title="", string preparation="") - : base(ComputeId(), "A recipe.") - { - Title = title; - Preparation = preparation; - } - #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 = 1; - while ((_idCreator / (Math.Pow(10, dec)) >= 1)) dec++; - - uint id = (CAT_ITEM * (uint)(Math.Pow(10, dec))) + _idCreator++; - Console.WriteLine("[recipe] new computed id: {0}", id); - - return id; - } - - #endregion - - #region Public Methods - - public override string ToString() - { - return - $"[ Class -Recipe- ]\n\n" + - $"\t.Id - {Id}\n" + - $"\t.Description - {Description}\n" + - $"______\n\n"; - } - - #endregion + public class Recipe : IEquatable + { + private static int idCreator = 0; + + public int Id { get; init; } + public string Description { get; init; } + public string Title { get; set; } + + public Recipe(string title, string description = "No Description.") + { + Id = idCreator++; + Title = title; + Description = description; + } + + public bool Equals(Recipe? other) + { + if (other == null) return false; + if (other == this) return true; + return Title.Equals(other.Title) && Description.Equals(other.Description); + } + + public override int GetHashCode() + { + return Id.GetHashCode(); + } } } diff --git a/MCTG/MCTGLib/RecipeCollection.cs b/MCTG/MCTGLib/RecipeCollection.cs index 4e799d3..95b5ff5 100644 --- a/MCTG/MCTGLib/RecipeCollection.cs +++ b/MCTG/MCTGLib/RecipeCollection.cs @@ -5,159 +5,103 @@ using System.Collections.ObjectModel; namespace MCTGLib { - /// - /// A Recipe collection is a group of recipe.
- /// It is instantiated with a new unique id, where the first number is 2. - ///
- public class RecipeCollection : BaseItem, ICollection - { - #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 readonly ICollection _recipes = new List(); // main composent of this class. - - #endregion - - #region Public Properties - - #region ICollection Implementation - - 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()) - { - _recipes = new List(recipes); - } - - #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 = 1; - while ((_idCreator / (Math.Pow(10, dec)) >= 1)) dec++; - - uint id = (CAT_ITEM * (uint)(Math.Pow(10, dec))) + _idCreator++; - Console.WriteLine("[recipe collection] new computed id: {0}", id); - - return id; - } - - #endregion - - #region Public Methods - - public override string ToString() - { - return - $"[ Class -RecipeCollection- ]\n\n" + - $"\t.Id - {Id}\n" + - $"\t.Description - {Description}\n" + - $"______\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 this.GetEnumerator(); - } - - #endregion + public class RecipeCollection : IList, IEquatable + { + #region Attributes + private List _recipes; #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[Index id] - { - get => this.ElementAt(id); - } - - /// - /// Overload of + operator to add a Recipe to a RecipeCollection. - /// - /// The recipe collection where the recipe will be added - /// The recipe to add - /// The recipe collection where the recipe is added. - public static RecipeCollection operator + (RecipeCollection coll, Recipe ri) - { - coll.Add(ri); return coll; + #region Properties + public string Description { get; set; } + + #region IList Prperties + public int Count => _recipes.Count; + public bool IsReadOnly => false; + public Recipe this[int index] { get => _recipes[index]; set => _recipes[index] = value; } + #endregion + #endregion + + #region Constructors + public RecipeCollection(string description = "No Description.") + { + _recipes = new List(); + Description = description; } - /// - /// Overload of - operator to remove a Recipe to a RecipeCollection. - /// - /// The recipe collection where the recipe will be removed - /// The recipe to remove - /// The recipe collection where the recipe is removed. - public static RecipeCollection operator - (RecipeCollection coll, Recipe ri) - { - coll.Remove(ri); return coll; - } - - #endregion + public RecipeCollection(params Recipe[] recipes) + { + _recipes = new List(recipes); + Description = "No Description."; + } + #endregion + + #region Methods + #region IList Methods + public int IndexOf(Recipe item) + { + return _recipes.IndexOf(item); + } + + public void Insert(int index, Recipe item) + { + _recipes.Insert(index, item); + } + + public void RemoveAt(int index) + { + _recipes.RemoveAt(index); + } + + 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 + + #region IEquatable Mathods + public bool Equals(RecipeCollection? other) + { + if (other == null) return false; + if (other == this) return true; + return Description.Equals(other.Description) && _recipes.Equals(other._recipes); + } + #endregion + + public override int GetHashCode() + { + return Description.GetHashCode() + _recipes.GetHashCode(); + } + #endregion } } From f90a322f451a680698b59bfcb23d9bf9c758cb26 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Thu, 27 Apr 2023 13:28:57 +0200 Subject: [PATCH 09/16] correction on UT, simplified projects name --- .../{MCTGApp.csproj => ConsoleApp.csproj} | 4 +-- MCTG/MCTGApp/Program.cs | 2 +- MCTG/MCTGLib/{MCTGLib.csproj => Model.csproj} | 0 MCTG/MCTGLib/PreparationStep.cs | 2 +- MCTG/MCTGLib/Recipe.cs | 30 ++++++++--------- MCTG/MCTGLib/RecipeCollection.cs | 32 +++++++++---------- ...nitTests.csproj => Model_UnitTests.csproj} | 0 MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs | 26 +++++++-------- 8 files changed, 47 insertions(+), 49 deletions(-) rename MCTG/MCTGApp/{MCTGApp.csproj => ConsoleApp.csproj} (99%) rename MCTG/MCTGLib/{MCTGLib.csproj => Model.csproj} (100%) rename MCTG/Tests/MCTGLib_UnitTests/{MCTGLib_UnitTests.csproj => Model_UnitTests.csproj} (100%) diff --git a/MCTG/MCTGApp/MCTGApp.csproj b/MCTG/MCTGApp/ConsoleApp.csproj similarity index 99% rename from MCTG/MCTGApp/MCTGApp.csproj rename to MCTG/MCTGApp/ConsoleApp.csproj index f184388..6dd3df4 100644 --- a/MCTG/MCTGApp/MCTGApp.csproj +++ b/MCTG/MCTGApp/ConsoleApp.csproj @@ -7,8 +7,8 @@ enable - - + + diff --git a/MCTG/MCTGApp/Program.cs b/MCTG/MCTGApp/Program.cs index aa01b39..c677863 100644 --- a/MCTG/MCTGApp/Program.cs +++ b/MCTG/MCTGApp/Program.cs @@ -1,6 +1,6 @@ // See https://aka.ms/new-console-template for more information -using MCTGLib; +using Model; Console.WriteLine("Hello, World!\n"); diff --git a/MCTG/MCTGLib/MCTGLib.csproj b/MCTG/MCTGLib/Model.csproj similarity index 100% rename from MCTG/MCTGLib/MCTGLib.csproj rename to MCTG/MCTGLib/Model.csproj diff --git a/MCTG/MCTGLib/PreparationStep.cs b/MCTG/MCTGLib/PreparationStep.cs index 13a7d7a..ad549b6 100644 --- a/MCTG/MCTGLib/PreparationStep.cs +++ b/MCTG/MCTGLib/PreparationStep.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace MCTGLib +namespace Model { public class PreparationStep { diff --git a/MCTG/MCTGLib/Recipe.cs b/MCTG/MCTGLib/Recipe.cs index ebbdac6..eca21b2 100644 --- a/MCTG/MCTGLib/Recipe.cs +++ b/MCTG/MCTGLib/Recipe.cs @@ -1,18 +1,18 @@ -using System; -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Runtime.CompilerServices; -namespace MCTGLib -{ - - public class Recipe : IEquatable - { - private static int idCreator = 0; - - public int Id { get; init; } - public string Description { get; init; } - public string Title { get; set; } - +namespace Model +{ + + public class Recipe : IEquatable + { + private static int idCreator = 0; + + public int Id { get; init; } + public string Description { get; init; } + public string Title { get; set; } + public Recipe(string title, string description = "No Description.") { Id = idCreator++; @@ -31,5 +31,5 @@ namespace MCTGLib { return Id.GetHashCode(); } - } -} + } +} diff --git a/MCTG/MCTGLib/RecipeCollection.cs b/MCTG/MCTGLib/RecipeCollection.cs index 95b5ff5..de3503e 100644 --- a/MCTG/MCTGLib/RecipeCollection.cs +++ b/MCTG/MCTGLib/RecipeCollection.cs @@ -1,17 +1,17 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; - -namespace MCTGLib -{ - - public class RecipeCollection : IList, IEquatable +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Model +{ + + public class RecipeCollection : IList, IEquatable { - #region Attributes + #region Attributes private List _recipes; - #endregion - + #endregion + #region Properties public string Description { get; set; } @@ -27,8 +27,8 @@ namespace MCTGLib { _recipes = new List(); Description = description; - } - + } + public RecipeCollection(params Recipe[] recipes) { _recipes = new List(recipes); @@ -103,5 +103,5 @@ namespace MCTGLib return Description.GetHashCode() + _recipes.GetHashCode(); } #endregion - } -} + } +} diff --git a/MCTG/Tests/MCTGLib_UnitTests/MCTGLib_UnitTests.csproj b/MCTG/Tests/MCTGLib_UnitTests/Model_UnitTests.csproj similarity index 100% rename from MCTG/Tests/MCTGLib_UnitTests/MCTGLib_UnitTests.csproj rename to MCTG/Tests/MCTGLib_UnitTests/Model_UnitTests.csproj diff --git a/MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs b/MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs index 3196733..40d8504 100644 --- a/MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs +++ b/MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs @@ -1,34 +1,32 @@ -using MCTGLib; +using Model; -namespace MCTGLib_UnitTests +namespace Model_UnitTests { public class Recipe_UT { [Fact] public void TestConstructorNotNull() { - Recipe r1 = new Recipe(); + Recipe r1 = new Recipe("R1"); Assert.NotNull(r1); } [Fact] public void TestConstructorWithValidDefaults() { - Recipe r1 = new Recipe(); - Assert.Equal("Recipe n10", r1.Title); - Assert.Equal("A recipe.", r1.Description); + Recipe r2 = new Recipe("Recipe n2"); + Assert.Equal("Recipe n2", r2.Title); + Assert.Equal("No Description.", r2.Description); } [Fact] - public void TestComputeId() + public void TestRecipeId() { - List lr = new List(); - for (int i = 0; i < 11; i++) - lr.Add(new Recipe()); + Recipe r3 = new Recipe("R3"); + Recipe r4 = new Recipe("R4"); - Assert.Equal((uint)18, lr.ElementAt(8).Id); - Assert.Equal((uint)19, lr.ElementAt(9).Id); - Assert.Equal((uint)110, lr.ElementAt(10).Id); + Assert.Equal(2, r3.Id); + Assert.Equal(3, r4.Id); } } -} \ No newline at end of file +} From ffae251bda49d82e76d5a27ba3a0c52f231d0b1b Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Thu, 27 Apr 2023 13:36:50 +0200 Subject: [PATCH 10/16] :truck: renaming ok --- .../{MCTGApp => ConsoleApp}/ConsoleApp.csproj | 2 +- MCTG/{MCTGApp => ConsoleApp}/Program.cs | 0 MCTG/{MCTGLib => Model}/Model.csproj | 0 MCTG/{MCTGLib => Model}/PreparationStep.cs | 78 +++---- MCTG/{MCTGLib => Model}/Recipe.cs | 70 +++--- MCTG/{MCTGLib => Model}/RecipeCollection.cs | 214 +++++++++--------- MCTG/SAE-2.01.sln | 6 +- .../Model_UnitTests.csproj | 2 +- .../Recipe_UT.cs | 0 .../Usings.cs | 0 10 files changed, 186 insertions(+), 186 deletions(-) rename MCTG/{MCTGApp => ConsoleApp}/ConsoleApp.csproj (81%) rename MCTG/{MCTGApp => ConsoleApp}/Program.cs (100%) rename MCTG/{MCTGLib => Model}/Model.csproj (100%) rename MCTG/{MCTGLib => Model}/PreparationStep.cs (95%) rename MCTG/{MCTGLib => Model}/Recipe.cs (96%) rename MCTG/{MCTGLib => Model}/RecipeCollection.cs (96%) rename MCTG/Tests/{MCTGLib_UnitTests => Model_UnitTests}/Model_UnitTests.csproj (93%) rename MCTG/Tests/{MCTGLib_UnitTests => Model_UnitTests}/Recipe_UT.cs (100%) rename MCTG/Tests/{MCTGLib_UnitTests => Model_UnitTests}/Usings.cs (100%) diff --git a/MCTG/MCTGApp/ConsoleApp.csproj b/MCTG/ConsoleApp/ConsoleApp.csproj similarity index 81% rename from MCTG/MCTGApp/ConsoleApp.csproj rename to MCTG/ConsoleApp/ConsoleApp.csproj index 6dd3df4..c7f3ecd 100644 --- a/MCTG/MCTGApp/ConsoleApp.csproj +++ b/MCTG/ConsoleApp/ConsoleApp.csproj @@ -8,7 +8,7 @@ - + diff --git a/MCTG/MCTGApp/Program.cs b/MCTG/ConsoleApp/Program.cs similarity index 100% rename from MCTG/MCTGApp/Program.cs rename to MCTG/ConsoleApp/Program.cs diff --git a/MCTG/MCTGLib/Model.csproj b/MCTG/Model/Model.csproj similarity index 100% rename from MCTG/MCTGLib/Model.csproj rename to MCTG/Model/Model.csproj diff --git a/MCTG/MCTGLib/PreparationStep.cs b/MCTG/Model/PreparationStep.cs similarity index 95% rename from MCTG/MCTGLib/PreparationStep.cs rename to MCTG/Model/PreparationStep.cs index ad549b6..8fe4071 100644 --- a/MCTG/MCTGLib/PreparationStep.cs +++ b/MCTG/Model/PreparationStep.cs @@ -1,39 +1,39 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Model -{ - public class PreparationStep - { - #region Attributes - private string? _description; - #endregion - - #region Properties - public int Order { get; init; } - public string? Description - { - get => _description; - set - { - if (string.IsNullOrEmpty(value)) - { - _description = "No data."; return; - } - _description = value; - } - } - #endregion - - #region Constructors - public PreparationStep(int order, string? description) - { - Order = order; - Description = description; - } - #endregion - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Model +{ + public class PreparationStep + { + #region Attributes + private string? _description; + #endregion + + #region Properties + public int Order { get; init; } + public string? Description + { + get => _description; + set + { + if (string.IsNullOrEmpty(value)) + { + _description = "No data."; return; + } + _description = value; + } + } + #endregion + + #region Constructors + public PreparationStep(int order, string? description) + { + Order = order; + Description = description; + } + #endregion + } +} diff --git a/MCTG/MCTGLib/Recipe.cs b/MCTG/Model/Recipe.cs similarity index 96% rename from MCTG/MCTGLib/Recipe.cs rename to MCTG/Model/Recipe.cs index eca21b2..c253ef4 100644 --- a/MCTG/MCTGLib/Recipe.cs +++ b/MCTG/Model/Recipe.cs @@ -1,35 +1,35 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace Model -{ - - public class Recipe : IEquatable - { - private static int idCreator = 0; - - public int Id { get; init; } - public string Description { get; init; } - public string Title { get; set; } - - public Recipe(string title, string description = "No Description.") - { - Id = idCreator++; - Title = title; - Description = description; - } - - public bool Equals(Recipe? other) - { - if (other == null) return false; - if (other == this) return true; - return Title.Equals(other.Title) && Description.Equals(other.Description); - } - - public override int GetHashCode() - { - return Id.GetHashCode(); - } - } -} +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace Model +{ + + public class Recipe : IEquatable + { + private static int idCreator = 0; + + public int Id { get; init; } + public string Description { get; init; } + public string Title { get; set; } + + public Recipe(string title, string description = "No Description.") + { + Id = idCreator++; + Title = title; + Description = description; + } + + public bool Equals(Recipe? other) + { + if (other == null) return false; + if (other == this) return true; + return Title.Equals(other.Title) && Description.Equals(other.Description); + } + + public override int GetHashCode() + { + return Id.GetHashCode(); + } + } +} diff --git a/MCTG/MCTGLib/RecipeCollection.cs b/MCTG/Model/RecipeCollection.cs similarity index 96% rename from MCTG/MCTGLib/RecipeCollection.cs rename to MCTG/Model/RecipeCollection.cs index de3503e..bde57ba 100644 --- a/MCTG/MCTGLib/RecipeCollection.cs +++ b/MCTG/Model/RecipeCollection.cs @@ -1,107 +1,107 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; - -namespace Model -{ - - public class RecipeCollection : IList, IEquatable - { - #region Attributes - private List _recipes; - #endregion - - #region Properties - public string Description { get; set; } - - #region IList Prperties - public int Count => _recipes.Count; - public bool IsReadOnly => false; - public Recipe this[int index] { get => _recipes[index]; set => _recipes[index] = value; } - #endregion - #endregion - - #region Constructors - public RecipeCollection(string description = "No Description.") - { - _recipes = new List(); - Description = description; - } - - public RecipeCollection(params Recipe[] recipes) - { - _recipes = new List(recipes); - Description = "No Description."; - } - #endregion - - #region Methods - #region IList Methods - public int IndexOf(Recipe item) - { - return _recipes.IndexOf(item); - } - - public void Insert(int index, Recipe item) - { - _recipes.Insert(index, item); - } - - public void RemoveAt(int index) - { - _recipes.RemoveAt(index); - } - - 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 - - #region IEquatable Mathods - public bool Equals(RecipeCollection? other) - { - if (other == null) return false; - if (other == this) return true; - return Description.Equals(other.Description) && _recipes.Equals(other._recipes); - } - #endregion - - public override int GetHashCode() - { - return Description.GetHashCode() + _recipes.GetHashCode(); - } - #endregion - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Model +{ + + public class RecipeCollection : IList, IEquatable + { + #region Attributes + private List _recipes; + #endregion + + #region Properties + public string Description { get; set; } + + #region IList Prperties + public int Count => _recipes.Count; + public bool IsReadOnly => false; + public Recipe this[int index] { get => _recipes[index]; set => _recipes[index] = value; } + #endregion + #endregion + + #region Constructors + public RecipeCollection(string description = "No Description.") + { + _recipes = new List(); + Description = description; + } + + public RecipeCollection(params Recipe[] recipes) + { + _recipes = new List(recipes); + Description = "No Description."; + } + #endregion + + #region Methods + #region IList Methods + public int IndexOf(Recipe item) + { + return _recipes.IndexOf(item); + } + + public void Insert(int index, Recipe item) + { + _recipes.Insert(index, item); + } + + public void RemoveAt(int index) + { + _recipes.RemoveAt(index); + } + + 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 + + #region IEquatable Mathods + public bool Equals(RecipeCollection? other) + { + if (other == null) return false; + if (other == this) return true; + return Description.Equals(other.Description) && _recipes.Equals(other._recipes); + } + #endregion + + public override int GetHashCode() + { + return Description.GetHashCode() + _recipes.GetHashCode(); + } + #endregion + } +} diff --git a/MCTG/SAE-2.01.sln b/MCTG/SAE-2.01.sln index ab7e910..81242a9 100644 --- a/MCTG/SAE-2.01.sln +++ b/MCTG/SAE-2.01.sln @@ -3,11 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.33516.290 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MCTGApp", "MCTGApp\MCTGApp.csproj", "{666C2211-8EBB-4FC8-9484-CB93BC854153}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp", "ConsoleApp\ConsoleApp.csproj", "{666C2211-8EBB-4FC8-9484-CB93BC854153}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MCTGLib", "MCTGLib\MCTGLib.csproj", "{42FF86BD-92F9-4A32-A938-68515905378F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Model", "Model\Model.csproj", "{42FF86BD-92F9-4A32-A938-68515905378F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MCTGLib_UnitTests", "Tests\MCTGLib_UnitTests\MCTGLib_UnitTests.csproj", "{45AB746A-194B-4E43-81EB-83B06F35AA33}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Model_UnitTests", "Tests\Model_UnitTests\Model_UnitTests.csproj", "{45AB746A-194B-4E43-81EB-83B06F35AA33}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{08B80CE8-A01D-4D86-8989-AF225D5DA48C}" EndProject diff --git a/MCTG/Tests/MCTGLib_UnitTests/Model_UnitTests.csproj b/MCTG/Tests/Model_UnitTests/Model_UnitTests.csproj similarity index 93% rename from MCTG/Tests/MCTGLib_UnitTests/Model_UnitTests.csproj rename to MCTG/Tests/Model_UnitTests/Model_UnitTests.csproj index afc37b6..dc31a95 100644 --- a/MCTG/Tests/MCTGLib_UnitTests/Model_UnitTests.csproj +++ b/MCTG/Tests/Model_UnitTests/Model_UnitTests.csproj @@ -23,7 +23,7 @@ - + diff --git a/MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs similarity index 100% rename from MCTG/Tests/MCTGLib_UnitTests/Recipe_UT.cs rename to MCTG/Tests/Model_UnitTests/Recipe_UT.cs diff --git a/MCTG/Tests/MCTGLib_UnitTests/Usings.cs b/MCTG/Tests/Model_UnitTests/Usings.cs similarity index 100% rename from MCTG/Tests/MCTGLib_UnitTests/Usings.cs rename to MCTG/Tests/Model_UnitTests/Usings.cs From 316cb66c74b7c3cd41e12bd46e94dfd8421c7f90 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Thu, 27 Apr 2023 14:53:41 +0200 Subject: [PATCH 11/16] add unit test for recipe + ToString() method for all --- MCTG/ConsoleApp/Program.cs | 15 ++++-- MCTG/Model/PreparationStep.cs | 16 ++++-- MCTG/Model/Recipe.cs | 53 ++++++++++++++++++-- MCTG/Model/RecipeCollection.cs | 66 +++++++++++++++---------- MCTG/Tests/Model_UnitTests/Recipe_UT.cs | 37 +++++++------- 5 files changed, 131 insertions(+), 56 deletions(-) diff --git a/MCTG/ConsoleApp/Program.cs b/MCTG/ConsoleApp/Program.cs index c677863..ac6bfb0 100644 --- a/MCTG/ConsoleApp/Program.cs +++ b/MCTG/ConsoleApp/Program.cs @@ -3,10 +3,19 @@ using Model; -Console.WriteLine("Hello, World!\n"); +Console.WriteLine("Hello, World!\n\n"); // TESTS: -RecipeCollection rc = new RecipeCollection(); -Console.WriteLine($"rc.Description: {rc.Description}"); \ No newline at end of file +RecipeCollection rc = new RecipeCollection("Desserts", + new Recipe("Cookies", "Cookies au chocolats", null, + new PreparationStep(1, "Faire cuire le truc."), + new PreparationStep(2, "Elaboré un autre truc"), + new PreparationStep(3, null)), + new Recipe(null, null, 99, + new PreparationStep(1, null), + new PreparationStep(1, null)), + new Recipe()); + +Console.WriteLine(rc.ToString()); diff --git a/MCTG/Model/PreparationStep.cs b/MCTG/Model/PreparationStep.cs index 8fe4071..6057273 100644 --- a/MCTG/Model/PreparationStep.cs +++ b/MCTG/Model/PreparationStep.cs @@ -19,11 +19,10 @@ namespace Model get => _description; set { - if (string.IsNullOrEmpty(value)) - { - _description = "No data."; return; - } - _description = value; + if (string.IsNullOrWhiteSpace(value)) + _description = "No description."; + else + _description = value; } } #endregion @@ -35,5 +34,12 @@ namespace Model Description = description; } #endregion + + #region Methods + public override string ToString() + { + return $"{Order}- {Description}"; + } + #endregion } } diff --git a/MCTG/Model/Recipe.cs b/MCTG/Model/Recipe.cs index c253ef4..e493212 100644 --- a/MCTG/Model/Recipe.cs +++ b/MCTG/Model/Recipe.cs @@ -1,25 +1,59 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Text; namespace Model { public class Recipe : IEquatable { + #region Attributes private static int idCreator = 0; + private string? _title; + private string? _description; + #endregion + #region Properties public int Id { get; init; } - public string Description { get; init; } - public string Title { get; set; } + public string? Title + { + get => _title; + set + { + if (string.IsNullOrWhiteSpace(value)) + _title = "No title."; + else + _title = value; + } + } + public string? Description + { + get => _description; + set + { + if (string.IsNullOrWhiteSpace(value)) + _description = "No description."; + else + _description = value; + } + } + public List? PreparationSteps { get; private set; } + #endregion - public Recipe(string title, string description = "No Description.") + #region Constructors + public Recipe(string? title = null, string? description = null, int? id = null, + params PreparationStep[] preparationSteps) { - Id = idCreator++; + if (id == null) Id = idCreator++; + else Id = (int)id; Title = title; Description = description; + PreparationSteps = new List(preparationSteps); } + #endregion + #region Methods public bool Equals(Recipe? other) { if (other == null) return false; @@ -31,5 +65,16 @@ namespace Model { return Id.GetHashCode(); } + + public override string ToString() + { + StringBuilder sb = new StringBuilder($"[Recipe] - {Title}: {Description}\n"); + foreach (PreparationStep ps in PreparationSteps) + { + sb.AppendFormat("\t* {0}\n", ps.ToString()); + } + return sb.ToString(); + } + #endregion } } diff --git a/MCTG/Model/RecipeCollection.cs b/MCTG/Model/RecipeCollection.cs index bde57ba..283af8e 100644 --- a/MCTG/Model/RecipeCollection.cs +++ b/MCTG/Model/RecipeCollection.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Text; namespace Model { @@ -9,98 +10,111 @@ namespace Model public class RecipeCollection : IList, IEquatable { #region Attributes - private List _recipes; + private List recipes; + private string? _description; #endregion #region Properties - public string Description { get; set; } + public string? Description + { + get => _description; + set + { + if (string.IsNullOrWhiteSpace(value)) + _description = "No description."; + else + _description = value; + } + } #region IList Prperties - public int Count => _recipes.Count; + public int Count => recipes.Count; public bool IsReadOnly => false; - public Recipe this[int index] { get => _recipes[index]; set => _recipes[index] = value; } + public Recipe this[int index] { get => recipes[index]; set => recipes[index] = value; } #endregion #endregion #region Constructors - public RecipeCollection(string description = "No Description.") + public RecipeCollection(string? description = null, params Recipe[] recipes) { - _recipes = new List(); + this.recipes = new List(recipes); Description = description; } - - public RecipeCollection(params Recipe[] recipes) - { - _recipes = new List(recipes); - Description = "No Description."; - } #endregion #region Methods #region IList Methods public int IndexOf(Recipe item) { - return _recipes.IndexOf(item); + return recipes.IndexOf(item); } public void Insert(int index, Recipe item) { - _recipes.Insert(index, item); + recipes.Insert(index, item); } public void RemoveAt(int index) { - _recipes.RemoveAt(index); + recipes.RemoveAt(index); } public void Add(Recipe item) { - _recipes.Add(item); + recipes.Add(item); } public void Clear() { - _recipes.Clear(); + recipes.Clear(); } public bool Contains(Recipe item) { - return _recipes.Contains(item); + return recipes.Contains(item); } public void CopyTo(Recipe[] array, int arrayIndex) { - _recipes.CopyTo(array, arrayIndex); + recipes.CopyTo(array, arrayIndex); } public bool Remove(Recipe item) { - return _recipes.Remove(item); + return recipes.Remove(item); } public IEnumerator GetEnumerator() { - return _recipes.GetEnumerator(); + return recipes.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { - return _recipes.GetEnumerator(); + return recipes.GetEnumerator(); } #endregion - #region IEquatable Mathods public bool Equals(RecipeCollection? other) { if (other == null) return false; if (other == this) return true; - return Description.Equals(other.Description) && _recipes.Equals(other._recipes); + return Description.Equals(other.Description) && recipes.Equals(other.recipes); } - #endregion public override int GetHashCode() { - return Description.GetHashCode() + _recipes.GetHashCode(); + return Description.GetHashCode() + recipes.GetHashCode(); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder($"[RecipeCollection] - {Description}:\n"); + foreach (Recipe r in recipes) + { + sb.AppendFormat("\t - {0}\n", r.ToString()); + } + return sb.ToString(); } #endregion } diff --git a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs index 40d8504..e1d6720 100644 --- a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs +++ b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs @@ -5,28 +5,29 @@ namespace Model_UnitTests public class Recipe_UT { [Fact] - public void TestConstructorNotNull() + public void TestVoidConstructor() { - Recipe r1 = new Recipe("R1"); - Assert.NotNull(r1); + Recipe r = new Recipe(id: 999); // id is given to avoid tests errors with the static atrribute 'idCreator'. + Assert.NotNull(r.Title); + Assert.NotNull(r.Description); } - [Fact] - public void TestConstructorWithValidDefaults() - { - Recipe r2 = new Recipe("Recipe n2"); - Assert.Equal("Recipe n2", r2.Title); - Assert.Equal("No Description.", r2.Description); - } - - [Fact] - public void TestRecipeId() + [Theory] + [InlineData("Cookies", "Choco Cookies", 23, "Cookies", "Choco Cookies", 23)] + [InlineData("Cookies", "No description.", 1, "Cookies", "", 1)] + [InlineData("No title.", "Choco Cookies", 1, "", "Choco Cookies", 1)] + [InlineData("Cookies", "Choco Cookies", 0, "Cookies", "Choco Cookies", null)] + [InlineData("Cookies", "No description.", 1, "Cookies", null, 1)] + [InlineData("No title.", "Choco Cookies", 1, null, "Choco Cookies", 1)] + public void TestConstructor(string expectedTitle, string expectedDescription, int expectedId, + string title, string description, int? id) { - Recipe r3 = new Recipe("R3"); - Recipe r4 = new Recipe("R4"); - - Assert.Equal(2, r3.Id); - Assert.Equal(3, r4.Id); + Recipe r = new Recipe(title, description, id); + Assert.NotNull(r.Title); + Assert.NotNull(r.Description); + Assert.Equal(expectedId, r.Id); + Assert.Equal(expectedTitle, r.Title); + Assert.Equal(expectedDescription, r.Description); } } } From 531cf092b98dc545618aceed6460dc5600cac995 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Thu, 27 Apr 2023 19:56:40 +0200 Subject: [PATCH 12/16] :memo: add comments for the doc --- MCTG/ConsoleApp/Program.cs | 15 ++++++++-- MCTG/Model/PreparationStep.cs | 23 +++++++++++++- MCTG/Model/Recipe.cs | 40 +++++++++++++++---------- MCTG/Model/RecipeCollection.cs | 27 ++++++++++++++++- MCTG/Tests/Model_UnitTests/Recipe_UT.cs | 19 +++++------- 5 files changed, 92 insertions(+), 32 deletions(-) diff --git a/MCTG/ConsoleApp/Program.cs b/MCTG/ConsoleApp/Program.cs index ac6bfb0..4a2aedd 100644 --- a/MCTG/ConsoleApp/Program.cs +++ b/MCTG/ConsoleApp/Program.cs @@ -9,13 +9,24 @@ Console.WriteLine("Hello, World!\n\n"); // TESTS: RecipeCollection rc = new RecipeCollection("Desserts", - new Recipe("Cookies", "Cookies au chocolats", null, + new Recipe("Cookies", null, new PreparationStep(1, "Faire cuire le truc."), new PreparationStep(2, "Elaboré un autre truc"), new PreparationStep(3, null)), - new Recipe(null, null, 99, + new Recipe(null, 99, new PreparationStep(1, null), new PreparationStep(1, null)), new Recipe()); Console.WriteLine(rc.ToString()); + +Console.WriteLine(rc.GetRecipeById(99).ToString()); + +try +{ + Console.WriteLine(rc.GetRecipeById(23).ToString()); +} +catch (ArgumentException e) +{ + Console.Error.WriteLine(e.Message); +} diff --git a/MCTG/Model/PreparationStep.cs b/MCTG/Model/PreparationStep.cs index 6057273..1301dac 100644 --- a/MCTG/Model/PreparationStep.cs +++ b/MCTG/Model/PreparationStep.cs @@ -6,14 +6,25 @@ using System.Threading.Tasks; namespace Model { - public class PreparationStep + /// + /// Define a step of the preparation of a recipe. + /// + public class PreparationStep : IEquatable { #region Attributes private string? _description; #endregion #region Properties + /// + /// The order of this step in the preparation of the meal. + /// public int Order { get; init; } + + /// + /// The description of the task the user need to do for this step of the preparation.
+ /// Set to "No description." when the value passed is null, empty or contain white spaces. + ///
public string? Description { get => _description; @@ -28,6 +39,11 @@ namespace Model #endregion #region Constructors + /// + /// Construct a new step of preparation. + /// + /// The number of the order in preparation + /// The description of the task public PreparationStep(int order, string? description) { Order = order; @@ -36,6 +52,11 @@ namespace Model #endregion #region Methods + public bool Equals(PreparationStep? other) + { + return Order.Equals(other.Order) && Description.Equals(other.Description); + } + public override string ToString() { return $"{Order}- {Description}"; diff --git a/MCTG/Model/Recipe.cs b/MCTG/Model/Recipe.cs index e493212..b575c6a 100644 --- a/MCTG/Model/Recipe.cs +++ b/MCTG/Model/Recipe.cs @@ -5,7 +5,9 @@ using System.Text; namespace Model { - + /// + /// Define a Recipe for the preparation of a meal. + /// public class Recipe : IEquatable { #region Attributes @@ -15,7 +17,15 @@ namespace Model #endregion #region Properties + /// + /// The ID of the recipe - allows you to compare and/or get this item in an easier way. + /// public int Id { get; init; } + + /// + /// The Title of the recipe.
+ /// Set to "No title." when the value passed is null, empty or contain white spaces. + ///
public string? Title { get => _title; @@ -27,28 +37,26 @@ namespace Model _title = value; } } - public string? Description - { - get => _description; - set - { - if (string.IsNullOrWhiteSpace(value)) - _description = "No description."; - else - _description = value; - } - } + + /// + /// The steps of the preparation. See: . + /// public List? PreparationSteps { get; private set; } #endregion #region Constructors - public Recipe(string? title = null, string? description = null, int? id = null, + /// + /// Construct a new recipe. + /// + /// The title of the recipe + /// The id of the recipe. If not given, get a new id. + /// The steps of the preparation of the meal + public Recipe(string? title = null, int? id = null, params PreparationStep[] preparationSteps) { if (id == null) Id = idCreator++; else Id = (int)id; Title = title; - Description = description; PreparationSteps = new List(preparationSteps); } #endregion @@ -58,7 +66,7 @@ namespace Model { if (other == null) return false; if (other == this) return true; - return Title.Equals(other.Title) && Description.Equals(other.Description); + return Title.Equals(other.Title) && PreparationSteps.Equals(other.PreparationSteps); } public override int GetHashCode() @@ -68,7 +76,7 @@ namespace Model public override string ToString() { - StringBuilder sb = new StringBuilder($"[Recipe] - {Title}: {Description}\n"); + StringBuilder sb = new StringBuilder($"[Recipe n°{Id}] - {Title}\n"); foreach (PreparationStep ps in PreparationSteps) { sb.AppendFormat("\t* {0}\n", ps.ToString()); diff --git a/MCTG/Model/RecipeCollection.cs b/MCTG/Model/RecipeCollection.cs index 283af8e..2de66d6 100644 --- a/MCTG/Model/RecipeCollection.cs +++ b/MCTG/Model/RecipeCollection.cs @@ -6,7 +6,10 @@ using System.Text; namespace Model { - + /// + /// Define a collection of . + ///
This class implement and . + ///
public class RecipeCollection : IList, IEquatable { #region Attributes @@ -15,6 +18,10 @@ namespace Model #endregion #region Properties + /// + /// A short description of what this collection contain.
+ /// Set to "No description." when the value passed is null, empty or contain white spaces. + ///
public string? Description { get => _description; @@ -35,6 +42,11 @@ namespace Model #endregion #region Constructors + /// + /// Construct a new collection of recipes. + /// + /// A short description of what this list will contain + /// Recipes to add in this new collection public RecipeCollection(string? description = null, params Recipe[] recipes) { this.recipes = new List(recipes); @@ -43,6 +55,19 @@ namespace Model #endregion #region Methods + /// + /// Find a recipe in this list by giving the id. + /// + /// The id of the list we are looking for + /// The recipe of the id given + /// + public Recipe? GetRecipeById(int id) + { + Recipe? recipe = recipes.Find(r => r.Id == id); + if (recipe == null) throw new ArgumentException("No recipes match the given id."); + return recipe; + } + #region IList Methods public int IndexOf(Recipe item) { diff --git a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs index e1d6720..205d6cd 100644 --- a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs +++ b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs @@ -9,25 +9,20 @@ namespace Model_UnitTests { Recipe r = new Recipe(id: 999); // id is given to avoid tests errors with the static atrribute 'idCreator'. Assert.NotNull(r.Title); - Assert.NotNull(r.Description); } [Theory] - [InlineData("Cookies", "Choco Cookies", 23, "Cookies", "Choco Cookies", 23)] - [InlineData("Cookies", "No description.", 1, "Cookies", "", 1)] - [InlineData("No title.", "Choco Cookies", 1, "", "Choco Cookies", 1)] - [InlineData("Cookies", "Choco Cookies", 0, "Cookies", "Choco Cookies", null)] - [InlineData("Cookies", "No description.", 1, "Cookies", null, 1)] - [InlineData("No title.", "Choco Cookies", 1, null, "Choco Cookies", 1)] - public void TestConstructor(string expectedTitle, string expectedDescription, int expectedId, - string title, string description, int? id) + [InlineData("Cookies", 23, "Cookies", 23)] + [InlineData("Cookies", 1, "Cookies", 1)] + [InlineData("No title.", 1, "", 1)] + [InlineData("Cookies", 0, "Cookies", null)] + [InlineData("No title.", 1, null, 1)] + public void TestConstructor(string expectedTitle, int expectedId, string title, int? id) { - Recipe r = new Recipe(title, description, id); + Recipe r = new Recipe(title, id); Assert.NotNull(r.Title); - Assert.NotNull(r.Description); Assert.Equal(expectedId, r.Id); Assert.Equal(expectedTitle, r.Title); - Assert.Equal(expectedDescription, r.Description); } } } From 5fa9dd62dbfe2646d978964cefdc1a6617564341 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Thu, 27 Apr 2023 21:31:54 +0200 Subject: [PATCH 13/16] :adhesive_bandage: try to correct sonar issues --- MCTG/ConsoleApp/Program.cs | 3 +++ MCTG/Model/PreparationStep.cs | 7 ++++++- MCTG/Model/Recipe.cs | 9 ++++----- MCTG/Model/RecipeCollection.cs | 6 +++--- MCTG/Tests/Model_UnitTests/Recipe_UT.cs | 1 - 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/MCTG/ConsoleApp/Program.cs b/MCTG/ConsoleApp/Program.cs index 4a2aedd..e015ab7 100644 --- a/MCTG/ConsoleApp/Program.cs +++ b/MCTG/ConsoleApp/Program.cs @@ -20,6 +20,9 @@ RecipeCollection rc = new RecipeCollection("Desserts", Console.WriteLine(rc.ToString()); +rc.Add(new Recipe("Cookies", null)); +Console.WriteLine(rc.Last()); + Console.WriteLine(rc.GetRecipeById(99).ToString()); try diff --git a/MCTG/Model/PreparationStep.cs b/MCTG/Model/PreparationStep.cs index 1301dac..54a9f14 100644 --- a/MCTG/Model/PreparationStep.cs +++ b/MCTG/Model/PreparationStep.cs @@ -28,7 +28,7 @@ namespace Model public string? Description { get => _description; - set + private set { if (string.IsNullOrWhiteSpace(value)) _description = "No description."; @@ -57,6 +57,11 @@ namespace Model return Order.Equals(other.Order) && Description.Equals(other.Description); } + public override int GetHashCode() + { + return Order.GetHashCode() + Description.GetHashCode(); + } + public override string ToString() { return $"{Order}- {Description}"; diff --git a/MCTG/Model/Recipe.cs b/MCTG/Model/Recipe.cs index b575c6a..d99da31 100644 --- a/MCTG/Model/Recipe.cs +++ b/MCTG/Model/Recipe.cs @@ -11,9 +11,7 @@ namespace Model public class Recipe : IEquatable { #region Attributes - private static int idCreator = 0; private string? _title; - private string? _description; #endregion #region Properties @@ -54,15 +52,16 @@ namespace Model public Recipe(string? title = null, int? id = null, params PreparationStep[] preparationSteps) { - if (id == null) Id = idCreator++; - else Id = (int)id; Title = title; PreparationSteps = new List(preparationSteps); + + if (id == null) Id = new Random().Next(); + else Id = (int)id; } #endregion #region Methods - public bool Equals(Recipe? other) + public virtual bool Equals(Recipe? other) { if (other == null) return false; if (other == this) return true; diff --git a/MCTG/Model/RecipeCollection.cs b/MCTG/Model/RecipeCollection.cs index 2de66d6..546d2aa 100644 --- a/MCTG/Model/RecipeCollection.cs +++ b/MCTG/Model/RecipeCollection.cs @@ -13,7 +13,7 @@ namespace Model public class RecipeCollection : IList, IEquatable { #region Attributes - private List recipes; + private readonly List recipes; private string? _description; #endregion @@ -120,7 +120,7 @@ namespace Model } #endregion - public bool Equals(RecipeCollection? other) + public virtual bool Equals(RecipeCollection? other) { if (other == null) return false; if (other == this) return true; @@ -129,7 +129,7 @@ namespace Model public override int GetHashCode() { - return Description.GetHashCode() + recipes.GetHashCode(); + return recipes.GetHashCode(); } public override string ToString() diff --git a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs index 205d6cd..55df465 100644 --- a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs +++ b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs @@ -15,7 +15,6 @@ namespace Model_UnitTests [InlineData("Cookies", 23, "Cookies", 23)] [InlineData("Cookies", 1, "Cookies", 1)] [InlineData("No title.", 1, "", 1)] - [InlineData("Cookies", 0, "Cookies", null)] [InlineData("No title.", 1, null, 1)] public void TestConstructor(string expectedTitle, int expectedId, string title, int? id) { From 2e4c8fa29f106543575fbe3ad7b4dcd643bf837b Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Fri, 28 Apr 2023 14:20:24 +0200 Subject: [PATCH 14/16] add some stubs --- MCTG/ConsoleApp/Program.cs | 36 ++++++++++-------------------- MCTG/ConsoleApp/Stub.cs | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 25 deletions(-) create mode 100644 MCTG/ConsoleApp/Stub.cs diff --git a/MCTG/ConsoleApp/Program.cs b/MCTG/ConsoleApp/Program.cs index e015ab7..773f61b 100644 --- a/MCTG/ConsoleApp/Program.cs +++ b/MCTG/ConsoleApp/Program.cs @@ -1,5 +1,6 @@ // See https://aka.ms/new-console-template for more information +using ConsoleApp; using Model; @@ -8,28 +9,13 @@ Console.WriteLine("Hello, World!\n\n"); // TESTS: -RecipeCollection rc = new RecipeCollection("Desserts", - new Recipe("Cookies", null, - new PreparationStep(1, "Faire cuire le truc."), - new PreparationStep(2, "Elaboré un autre truc"), - new PreparationStep(3, null)), - new Recipe(null, 99, - new PreparationStep(1, null), - new PreparationStep(1, null)), - new Recipe()); - -Console.WriteLine(rc.ToString()); - -rc.Add(new Recipe("Cookies", null)); -Console.WriteLine(rc.Last()); - -Console.WriteLine(rc.GetRecipeById(99).ToString()); - -try -{ - Console.WriteLine(rc.GetRecipeById(23).ToString()); -} -catch (ArgumentException e) -{ - Console.Error.WriteLine(e.Message); -} +Stub stub = new Stub(); + +List recipes = stub.LoadRecipes(); +List recipeCollections = stub.LoadRecipeCollection(); + +foreach (Recipe r in recipes) + Console.WriteLine(r); + +foreach (RecipeCollection r in recipeCollections) + Console.WriteLine(r); diff --git a/MCTG/ConsoleApp/Stub.cs b/MCTG/ConsoleApp/Stub.cs new file mode 100644 index 0000000..87c5a72 --- /dev/null +++ b/MCTG/ConsoleApp/Stub.cs @@ -0,0 +1,45 @@ +using Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ConsoleApp +{ + internal struct Stub + { + public List LoadRecipes() + { + List stub = new List(); + stub.AddRange(new[] + { + new Recipe(), + new Recipe("Cookies"), + new Recipe("Cookies", 23), + new Recipe("Cookies", null), + new Recipe(null, null), + new Recipe(null, 24), + new Recipe("Cookies", 24, + new PreparationStep(1, null)), + new Recipe("Cookies", 26, + new PreparationStep(1, null), + new PreparationStep(2, "Faire cuire.")) + }); + return stub; + } + + public List LoadRecipeCollection() + { + List stub = new List(); + stub.AddRange(new[] + { + new RecipeCollection("All", LoadRecipes().ToArray()), + new RecipeCollection("Starters", LoadRecipes().FindAll(x => x.Id.Equals(23)).ToArray()), + new RecipeCollection("Dishies", LoadRecipes().FindAll(x => x.Id.Equals(24)).ToArray()), + new RecipeCollection("Desserts", LoadRecipes().FindAll(x => x.Id.Equals(26)).ToArray()), + }); + return stub; + } + } +} From 7d6cf0bb56a1360c3ad58b9cc97a3e1d52d11e30 Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Fri, 28 Apr 2023 14:59:14 +0200 Subject: [PATCH 15/16] :rotating_light: null ref fix --- MCTG/ConsoleApp/Stub.cs | 8 ++--- MCTG/Model/PreparationStep.cs | 10 +++--- MCTG/Model/Recipe.cs | 10 +++--- MCTG/Model/RecipeCollection.cs | 47 +++++++++++++------------ MCTG/Tests/Model_UnitTests/Recipe_UT.cs | 1 - 5 files changed, 39 insertions(+), 37 deletions(-) diff --git a/MCTG/ConsoleApp/Stub.cs b/MCTG/ConsoleApp/Stub.cs index 87c5a72..a6fc02a 100644 --- a/MCTG/ConsoleApp/Stub.cs +++ b/MCTG/ConsoleApp/Stub.cs @@ -18,12 +18,12 @@ namespace ConsoleApp new Recipe("Cookies"), new Recipe("Cookies", 23), new Recipe("Cookies", null), - new Recipe(null, null), - new Recipe(null, 24), + new Recipe("", null), + new Recipe("", 24), new Recipe("Cookies", 24, - new PreparationStep(1, null)), + new PreparationStep(1)), new Recipe("Cookies", 26, - new PreparationStep(1, null), + new PreparationStep(1), new PreparationStep(2, "Faire cuire.")) }); return stub; diff --git a/MCTG/Model/PreparationStep.cs b/MCTG/Model/PreparationStep.cs index 54a9f14..55336d2 100644 --- a/MCTG/Model/PreparationStep.cs +++ b/MCTG/Model/PreparationStep.cs @@ -12,7 +12,7 @@ namespace Model public class PreparationStep : IEquatable { #region Attributes - private string? _description; + private string _description = ""; #endregion #region Properties @@ -25,7 +25,7 @@ namespace Model /// The description of the task the user need to do for this step of the preparation.
/// Set to "No description." when the value passed is null, empty or contain white spaces. ///
- public string? Description + public string Description { get => _description; private set @@ -44,7 +44,7 @@ namespace Model ///
/// The number of the order in preparation /// The description of the task - public PreparationStep(int order, string? description) + public PreparationStep(int order, string description = "") { Order = order; Description = description; @@ -52,8 +52,10 @@ namespace Model #endregion #region Methods - public bool Equals(PreparationStep? other) + public virtual bool Equals(PreparationStep? other) { + if (other == null) return false; + if (other == this) return true; return Order.Equals(other.Order) && Description.Equals(other.Description); } diff --git a/MCTG/Model/Recipe.cs b/MCTG/Model/Recipe.cs index d99da31..8f69fb9 100644 --- a/MCTG/Model/Recipe.cs +++ b/MCTG/Model/Recipe.cs @@ -11,9 +11,9 @@ namespace Model public class Recipe : IEquatable { #region Attributes - private string? _title; + private string _title = ""; #endregion - + #region Properties /// /// The ID of the recipe - allows you to compare and/or get this item in an easier way. @@ -24,7 +24,7 @@ namespace Model /// The Title of the recipe.
/// Set to "No title." when the value passed is null, empty or contain white spaces. ///
- public string? Title + public string Title { get => _title; set @@ -39,7 +39,7 @@ namespace Model /// /// The steps of the preparation. See: . /// - public List? PreparationSteps { get; private set; } + public List PreparationSteps { get; set; } #endregion #region Constructors @@ -49,7 +49,7 @@ namespace Model /// The title of the recipe /// The id of the recipe. If not given, get a new id. /// The steps of the preparation of the meal - public Recipe(string? title = null, int? id = null, + public Recipe(string title = "", int? id = null, params PreparationStep[] preparationSteps) { Title = title; diff --git a/MCTG/Model/RecipeCollection.cs b/MCTG/Model/RecipeCollection.cs index 546d2aa..6575729 100644 --- a/MCTG/Model/RecipeCollection.cs +++ b/MCTG/Model/RecipeCollection.cs @@ -13,8 +13,8 @@ namespace Model public class RecipeCollection : IList, IEquatable { #region Attributes - private readonly List recipes; - private string? _description; + private readonly List _recipes; + private string _description = ""; #endregion #region Properties @@ -22,7 +22,7 @@ namespace Model /// A short description of what this collection contain.
/// Set to "No description." when the value passed is null, empty or contain white spaces. ///
- public string? Description + public string Description { get => _description; set @@ -35,21 +35,21 @@ namespace Model } #region IList Prperties - public int Count => recipes.Count; + public int Count => _recipes.Count; public bool IsReadOnly => false; - public Recipe this[int index] { get => recipes[index]; set => recipes[index] = value; } + public Recipe this[int index] { get => _recipes[index]; set => _recipes[index] = value; } #endregion #endregion #region Constructors /// - /// Construct a new collection of recipes. + /// Construct a new collection of _recipes. /// /// A short description of what this list will contain /// Recipes to add in this new collection - public RecipeCollection(string? description = null, params Recipe[] recipes) + public RecipeCollection(string description, params Recipe[] recipes) { - this.recipes = new List(recipes); + _recipes = new List(recipes); Description = description; } #endregion @@ -63,79 +63,80 @@ namespace Model /// public Recipe? GetRecipeById(int id) { - Recipe? recipe = recipes.Find(r => r.Id == id); - if (recipe == null) throw new ArgumentException("No recipes match the given id."); + Recipe? recipe = _recipes.Find(r => r.Id == id); + if (recipe == null) throw new ArgumentException("No _recipes match the given id."); return recipe; } #region IList Methods public int IndexOf(Recipe item) { - return recipes.IndexOf(item); + return _recipes.IndexOf(item); } public void Insert(int index, Recipe item) { - recipes.Insert(index, item); + _recipes.Insert(index, item); } public void RemoveAt(int index) { - recipes.RemoveAt(index); + _recipes.RemoveAt(index); } public void Add(Recipe item) { - recipes.Add(item); + _recipes.Add(item); } public void Clear() { - recipes.Clear(); + _recipes.Clear(); } public bool Contains(Recipe item) { - return recipes.Contains(item); + return _recipes.Contains(item); } public void CopyTo(Recipe[] array, int arrayIndex) { - recipes.CopyTo(array, arrayIndex); + _recipes.CopyTo(array, arrayIndex); } public bool Remove(Recipe item) { - return recipes.Remove(item); + return _recipes.Remove(item); } public IEnumerator GetEnumerator() { - return recipes.GetEnumerator(); + return _recipes.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { - return recipes.GetEnumerator(); + return _recipes.GetEnumerator(); } #endregion public virtual bool Equals(RecipeCollection? other) { + if (other == null) return false; if (other == this) return true; - return Description.Equals(other.Description) && recipes.Equals(other.recipes); + return _description.Equals(other.Description) && _recipes.Equals(other._recipes); } public override int GetHashCode() { - return recipes.GetHashCode(); + return _recipes.GetHashCode(); } public override string ToString() { StringBuilder sb = new StringBuilder($"[RecipeCollection] - {Description}:\n"); - foreach (Recipe r in recipes) + foreach (Recipe r in _recipes) { sb.AppendFormat("\t - {0}\n", r.ToString()); } diff --git a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs index 55df465..e8593a5 100644 --- a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs +++ b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs @@ -15,7 +15,6 @@ namespace Model_UnitTests [InlineData("Cookies", 23, "Cookies", 23)] [InlineData("Cookies", 1, "Cookies", 1)] [InlineData("No title.", 1, "", 1)] - [InlineData("No title.", 1, null, 1)] public void TestConstructor(string expectedTitle, int expectedId, string title, int? id) { Recipe r = new Recipe(title, id); From e3dbd2ab17e6ae0c93a81300f2e13878ba6d1b4a Mon Sep 17 00:00:00 2001 From: Alexandre Agostinho Date: Fri, 28 Apr 2023 15:12:50 +0200 Subject: [PATCH 16/16] fix code security issues (sonar) --- MCTG/Model/PreparationStep.cs | 7 +++++++ MCTG/Model/Recipe.cs | 18 ++++++++++++++++-- MCTG/Model/RecipeCollection.cs | 7 +++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/MCTG/Model/PreparationStep.cs b/MCTG/Model/PreparationStep.cs index 55336d2..95d15ca 100644 --- a/MCTG/Model/PreparationStep.cs +++ b/MCTG/Model/PreparationStep.cs @@ -59,6 +59,13 @@ namespace Model return Order.Equals(other.Order) && Description.Equals(other.Description); } + public override bool Equals(object? obj) + { + var item = obj as PreparationStep; + if (item == null) return false; + return Equals(obj); + } + public override int GetHashCode() { return Order.GetHashCode() + Description.GetHashCode(); diff --git a/MCTG/Model/Recipe.cs b/MCTG/Model/Recipe.cs index 8f69fb9..9d65bf9 100644 --- a/MCTG/Model/Recipe.cs +++ b/MCTG/Model/Recipe.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Security.Cryptography; using System.Text; namespace Model @@ -54,8 +55,14 @@ namespace Model { Title = title; PreparationSteps = new List(preparationSteps); - - if (id == null) Id = new Random().Next(); + + if (id == null) + { + var randomGenerator = RandomNumberGenerator.Create(); + byte[] data = new byte[16]; + randomGenerator.GetBytes(data); + Id = Math.Abs(BitConverter.ToInt16(data)); + } else Id = (int)id; } #endregion @@ -68,6 +75,13 @@ namespace Model return Title.Equals(other.Title) && PreparationSteps.Equals(other.PreparationSteps); } + public override bool Equals(object? obj) + { + var item = obj as Recipe; + if (item == null) return false; + return Equals(obj); + } + public override int GetHashCode() { return Id.GetHashCode(); diff --git a/MCTG/Model/RecipeCollection.cs b/MCTG/Model/RecipeCollection.cs index 6575729..3592bb8 100644 --- a/MCTG/Model/RecipeCollection.cs +++ b/MCTG/Model/RecipeCollection.cs @@ -128,6 +128,13 @@ namespace Model return _description.Equals(other.Description) && _recipes.Equals(other._recipes); } + public override bool Equals(object? obj) + { + var item = obj as RecipeCollection; + if (item == null) return false; + return Equals(obj); + } + public override int GetHashCode() { return _recipes.GetHashCode();