⚗️ try making the RecipeCollection act like a real collection
continuous-integration/drone/push Build is passing Details

pull/24/head
Alexandre Agostinho 2 years ago
parent 9b0015d3c4
commit fa25dbf757

3
.gitignore vendored

@ -4,6 +4,9 @@
## ##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-spacific editor config
.editorconfig
# User-specific files # User-specific files
*.rsuser *.rsuser
*.suo *.suo

@ -7,6 +7,10 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\MCTGLib\MCTGLib.csproj" /> <ProjectReference Include="..\MCTGLib\MCTGLib.csproj" />
</ItemGroup> </ItemGroup>

@ -8,6 +8,7 @@ Console.WriteLine("Hello, World!\n");
// TESTS: // TESTS:
// tests on Recipe class
BaseItem r1 = new Recipe("A recipe..."); BaseItem r1 = new Recipe("A recipe...");
r1.DisplayItem(); r1.DisplayItem();
@ -16,6 +17,7 @@ r1.DisplayDescription();
Console.WriteLine(); Console.WriteLine();
// tests on RecipeCollection class
RecipeCollection rc = new RecipeCollection("A recipe collection..."); RecipeCollection rc = new RecipeCollection("A recipe collection...");
for (uint i = 0; i < 10; i++) for (uint i = 0; i < 10; i++)
{ {
@ -24,16 +26,24 @@ for (uint i = 0; i < 10; i++)
try // test overload of [] operator try // test overload of [] operator
{ {
rc[1003].DisplayItem(); rc[2].DisplayId();
rc[2003].DisplayItem(); // incorrect index rc.GetById(1002);
} }
catch (ArgumentNullException) catch (ArgumentNullException)
{ {
Console.Error.WriteLine("An index are incorrect!\n"); 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.DisplayId();
r.DisplayDescription(); r.DisplayDescription();

@ -1,5 +1,6 @@
 
using System; using System;
using System.ComponentModel;
namespace Model namespace Model
{ {
@ -7,24 +8,29 @@ namespace Model
/// Define the base structure of any Items.<br/> /// Define the base structure of any Items.<br/>
/// An Item can be identifed and have a short description. It can also be displayed. /// An Item can be identifed and have a short description. It can also be displayed.
/// </summary> /// </summary>
public abstract class BaseItem : IDisplayable public abstract class BaseItem : IDisplayable, IEquatable<BaseItem>
{ {
/// <summary> /// <summary>
/// The identifier of an Item.<br/> /// The identifier of an Item.<br/>
/// The first number correspond to the typs of the Item. /// The first number correspond to the typs of the Item.
/// </summary> /// </summary>
public uint Id { get; } virtual public uint Id
{
get => _id;
init => _id = value;
}
protected uint _id;
/// <summary> /// <summary>
/// A short description of the Item. Useful to know what this Item stand for. /// A short description of the Item. Useful to know what this Item stand for.
/// </summary> /// </summary>
public string Description { get; set; } public string Description { get; set; }
protected BaseItem(uint id, string description="Any Item.")
protected BaseItem(uint id, string description = "")
{ {
Id = id; Id = id; Description = description;
Description = description;
} }
@ -52,5 +58,28 @@ namespace Model
{ {
Console.WriteLine(this.ToString()); Console.WriteLine(this.ToString());
} }
// IEquatable<BaseItem> 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();
}
} }
} }

@ -5,35 +5,68 @@ namespace Model
{ {
/// <summary> /// <summary>
/// A Recipe is a description of step and maybe some techniques, with an ingredient list to make a meal.<br/> /// A Recipe is a description of step and maybe some techniques, with an ingredient list to make a meal.<br/>
/// 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.
/// </summary> /// </summary>
public class Recipe : BaseItem public class Recipe : BaseItem
{ {
/// <summary> #region Private Attributes
/// This static atrribute stand for the creation of a new id. It is incremented each time a new Recipe is instantiated.
/// </summary> private static uint _idCreator = 0; // stand for the creation of a new id. It is incremented each time a new Recipe is instantiated.
public static uint idIterator = 0; private string title = "";
#endregion
#region Public Properties
/// <summary> /// <summary>
/// The title of the recipe. /// The title of the recipe.
/// </summary> /// </summary>
public string Title { get; set; } public string Title
{
get => title;
set
{
title = value;
if (string.IsNullOrEmpty(title)) title = $"Recipe n{this.Id}";
}
}
/// <summary> /// <summary>
/// All the details about the preparation of the meal. /// All the details about the preparation of the meal.
/// </summary> /// </summary>
public string Preparation { get; set; } public string Preparation { get; set; }
#endregion
public Recipe(string description = "", string title = "", string preparation = "") #region Constructors
: base(idIterator+1000, description)
public Recipe(string title="", string preparation="")
: base(ComputeId(), "A recipe.")
{ {
if (idIterator == 1000) throw new OverflowException("id has reach the maximum value.");
Title = title; Title = title;
Preparation = preparation; Preparation = preparation;
idIterator++;
} }
#endregion
#region Private Methods
/// <summary>
/// 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.
/// </summary>
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() public override string ToString()
{ {
@ -43,5 +76,7 @@ namespace Model
$"\t.Description - {Description}\n" + $"\t.Description - {Description}\n" +
$"______\n\n"; $"______\n\n";
} }
#endregion
} }
} }

@ -1,38 +1,66 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace Model namespace Model
{ {
/// <summary> /// <summary>
/// A Recipe collection is a group of recipe.<br/> /// A Recipe collection is a group of recipe.<br/>
/// 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.
/// </summary> /// </summary>
public class RecipeCollection : BaseItem public class RecipeCollection : BaseItem, ICollection<Recipe>
{ {
/// <summary> #region Private Attributes
/// This static atrribute stand for the creation of a new id. It is incremented each time a new RecipeCollection is instantiated.
/// </summary> private const int CAT_ITEM = 2; // the first number of the item full id : the item category.
private static uint idIterator = 0; 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<Recipe> _recipes = new List<Recipe>(); // main composent of this class.
#endregion
/// <summary>
/// The main composent of a RecipeCollection. This contain the Recipes included in this collection.
/// </summary>
public List<Recipe> Collection { get; set; }
#region Public Properties
#region ICollection Implementation
public RecipeCollection(string description = "", List<Recipe>? collection = null) public int Count => _recipes.Count;
: base(idIterator + 2000, description) 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) #region Private Methods
Collection = new List<Recipe>();
else
Collection = collection;
idIterator++; /// <summary>
/// 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.
/// </summary>
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() public override string ToString()
{ {
@ -43,22 +71,66 @@ namespace Model
$"______\n\n"; $"______\n\n";
} }
public Recipe GetById(uint id)
{
if (this._recipes is not List<Recipe>)
throw new InvalidCastException("Need to verify the type of the private attribute '_recipes'.");
return (this._recipes as List<Recipe>).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<Recipe> GetEnumerator()
{
return _recipes.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _recipes.GetEnumerator();
}
#endregion
#endregion
#region Operators Overloading
/// <summary> /// <summary>
/// Overload the [] operator to access the Recipe directly without passing by the Collection.<br/> /// Overload the [] operator to access the Recipe directly without passing by the Collection.<br/>
/// It use the identifier of the Recipe to get the item. /// It use the identifier of the Recipe to get the item.
/// </summary> /// </summary>
/// <param name="id">The id of the Recipe</param> /// <param name="id">The id of the Recipe</param>
/// <returns></returns> /// <returns></returns>
public Recipe this[uint id] public Recipe this[Index id]
{ {
get get => this.ElementAt(id);
{
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.");
}
} }
/// <summary> /// <summary>
@ -69,7 +141,7 @@ namespace Model
/// <returns>The recipe collection where the recipe is added.</returns> /// <returns>The recipe collection where the recipe is added.</returns>
public static RecipeCollection operator + (RecipeCollection coll, Recipe ri) public static RecipeCollection operator + (RecipeCollection coll, Recipe ri)
{ {
coll.Collection.Add(ri); return coll; coll.Add(ri); return coll;
} }
/// <summary> /// <summary>
@ -80,7 +152,9 @@ namespace Model
/// <returns>The recipe collection where the recipe is removed.</returns> /// <returns>The recipe collection where the recipe is removed.</returns>
public static RecipeCollection operator - (RecipeCollection coll, Recipe ri) public static RecipeCollection operator - (RecipeCollection coll, Recipe ri)
{ {
coll.Collection.Remove(ri); return coll; coll.Remove(ri); return coll;
} }
#endregion
} }
} }

Loading…
Cancel
Save