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/ConsoleApp/ConsoleApp.csproj similarity index 73% rename from MCTG/MCTGApp/MCTGApp.csproj rename to MCTG/ConsoleApp/ConsoleApp.csproj index f02677b..c7f3ecd 100644 --- a/MCTG/MCTGApp/MCTGApp.csproj +++ b/MCTG/ConsoleApp/ConsoleApp.csproj @@ -7,4 +7,8 @@ enable + + + + diff --git a/MCTG/ConsoleApp/Program.cs b/MCTG/ConsoleApp/Program.cs new file mode 100644 index 0000000..773f61b --- /dev/null +++ b/MCTG/ConsoleApp/Program.cs @@ -0,0 +1,21 @@ +// See https://aka.ms/new-console-template for more information + +using ConsoleApp; +using Model; + + +Console.WriteLine("Hello, World!\n\n"); + + +// TESTS: + +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..a6fc02a --- /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), + new Recipe("", 24), + new Recipe("Cookies", 24, + new PreparationStep(1)), + new Recipe("Cookies", 26, + new PreparationStep(1), + 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; + } + } +} diff --git a/MCTG/MCTGApp/Program.cs b/MCTG/MCTGApp/Program.cs deleted file mode 100644 index 3751555..0000000 --- a/MCTG/MCTGApp/Program.cs +++ /dev/null @@ -1,2 +0,0 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); 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/MCTGLib.csproj b/MCTG/Model/Model.csproj similarity index 100% rename from MCTG/MCTGLib/MCTGLib.csproj rename to MCTG/Model/Model.csproj diff --git a/MCTG/Model/PreparationStep.cs b/MCTG/Model/PreparationStep.cs new file mode 100644 index 0000000..95d15ca --- /dev/null +++ b/MCTG/Model/PreparationStep.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Model +{ + /// + /// 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; + private set + { + if (string.IsNullOrWhiteSpace(value)) + _description = "No description."; + else + _description = value; + } + } + #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; + Description = description; + } + #endregion + + #region Methods + 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); + } + + 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(); + } + + public override string ToString() + { + return $"{Order}- {Description}"; + } + #endregion + } +} diff --git a/MCTG/Model/Recipe.cs b/MCTG/Model/Recipe.cs new file mode 100644 index 0000000..9d65bf9 --- /dev/null +++ b/MCTG/Model/Recipe.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Security.Cryptography; +using System.Text; + +namespace Model +{ + /// + /// Define a Recipe for the preparation of a meal. + /// + public class Recipe : IEquatable + { + #region Attributes + private string _title = ""; + #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; + set + { + if (string.IsNullOrWhiteSpace(value)) + _title = "No title."; + else + _title = value; + } + } + + /// + /// The steps of the preparation. See: . + /// + public List PreparationSteps { get; set; } + #endregion + + #region Constructors + /// + /// 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 = "", int? id = null, + params PreparationStep[] preparationSteps) + { + Title = title; + PreparationSteps = new List(preparationSteps); + + 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 + + #region Methods + public virtual bool Equals(Recipe? other) + { + if (other == null) return false; + if (other == this) return true; + 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(); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder($"[Recipe n°{Id}] - {Title}\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 new file mode 100644 index 0000000..3592bb8 --- /dev/null +++ b/MCTG/Model/RecipeCollection.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text; + +namespace Model +{ + /// + /// Define a collection of . + ///
This class implement and . + ///
+ public class RecipeCollection : IList, IEquatable + { + #region Attributes + private readonly List _recipes; + private string _description = ""; + #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; + set + { + if (string.IsNullOrWhiteSpace(value)) + _description = "No description."; + else + _description = value; + } + } + + #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 + /// + /// 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, params Recipe[] recipes) + { + _recipes = new List(recipes); + Description = description; + } + #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) + { + 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 + + 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); + } + + 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(); + } + + 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/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/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 diff --git a/MCTG/Tests/MCTGLib_UnitTests/MCTGLib_UnitTests.csproj b/MCTG/Tests/Model_UnitTests/Model_UnitTests.csproj similarity index 91% rename from MCTG/Tests/MCTGLib_UnitTests/MCTGLib_UnitTests.csproj rename to MCTG/Tests/Model_UnitTests/Model_UnitTests.csproj index 42ff44d..dc31a95 100644 --- a/MCTG/Tests/MCTGLib_UnitTests/MCTGLib_UnitTests.csproj +++ b/MCTG/Tests/Model_UnitTests/Model_UnitTests.csproj @@ -22,4 +22,8 @@ + + + + diff --git a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs new file mode 100644 index 0000000..e8593a5 --- /dev/null +++ b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs @@ -0,0 +1,26 @@ +using Model; + +namespace Model_UnitTests +{ + public class Recipe_UT + { + [Fact] + public void TestVoidConstructor() + { + Recipe r = new Recipe(id: 999); // id is given to avoid tests errors with the static atrribute 'idCreator'. + Assert.NotNull(r.Title); + } + + [Theory] + [InlineData("Cookies", 23, "Cookies", 23)] + [InlineData("Cookies", 1, "Cookies", 1)] + [InlineData("No title.", 1, "", 1)] + public void TestConstructor(string expectedTitle, int expectedId, string title, int? id) + { + Recipe r = new Recipe(title, id); + Assert.NotNull(r.Title); + Assert.Equal(expectedId, r.Id); + Assert.Equal(expectedTitle, r.Title); + } + } +} 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