fix merge conflict
continuous-integration/drone/push Build is passing Details

pull/39/head
Alexandre AGOSTINHO 2 years ago
commit d8d58997f9

@ -100,7 +100,7 @@ steps:
dockerfile: MCTG/Dockerfile dockerfile: MCTG/Dockerfile
context: MCTG/ context: MCTG/
registry: hub.codefirst.iut.uca.fr registry: hub.codefirst.iut.uca.fr
repo: hub.codefirst.iut.uca.fr/alexandre.agostinho/cli-mctg repo: hub.codefirst.iut.uca.fr/alexandre.agostinho/console-mctg
username: username:
from_secret: SECRET_REGISTRY_USERNAME from_secret: SECRET_REGISTRY_USERNAME
password: password:
@ -111,7 +111,7 @@ steps:
# image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest # image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
# environment: # environment:
# IMAGENAME: hub.codefirst.iut.uca.fr/alexandre.agostinho/sae-2.01:latest # IMAGENAME: hub.codefirst.iut.uca.fr/alexandre.agostinho/sae-2.01:latest
# CONTAINERNAME: cli-mctg # CONTAINERNAME: console-mctg
# COMMAND: create # COMMAND: create
# OVERWRITE: true # OVERWRITE: true
# depends_on: [ docker-build-and-push ] # depends_on: [ docker-build-and-push ]

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp.Menu
{
internal class ConnectionMenu : Entry
{
public ConnectionMenu()
: base("Connection",
new Entry.EntryStep("Username: ", typeof(string)),
new Entry.EntryStep("Password: ", typeof(string)))
{ }
public override IMenu? Return()
{
string username = _selectList[0].Item.Input;
string password = _selectList[1].Item.Input;
return new PlainText($"User: {username} connected with password: {password}");
}
}
}

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp.Menu
{
internal abstract partial class Entry
{
/// <summary>
/// Define a step of the Entry menu, or in other word, an entry itself.
/// </summary>
public class EntryStep
{
#region Attributes & Properties
private readonly Type _entryType;
/// <summary>
/// The entry description. This text is generally placed before the input field.
/// </summary>
public string Description { get; private set; }
/// <summary>
/// Contain the input gave by the menu.
/// </summary>
public string Input { get; internal set; }
#endregion
#region Constructors
/// <summary>
/// Constructor of the entry step.
/// </summary>
/// <param name="description">The text generally placed before the input in the menu.</param>
/// <param name="type">The type of the returned input.</param>
public EntryStep(string description, Type type)
{
Description = description;
Input = "";
_entryType = type;
}
#endregion
#region Methods
/// <summary>
/// Get the inputed string converted on this entry type.
/// </summary>
/// <returns>The converted string on the entry type.</returns>
/// <exception cref="NotImplementedException">Throw when the entry type converter does not exist here.</exception>
public object GetEntry()
{
try
{
if (_entryType == typeof(string))
return Input;
if (_entryType == typeof(int))
return Int32.Parse(Input);
if (_entryType == typeof(DateTime))
return DateTime.Parse(Input);
}
catch (FormatException fe)
{
Console.Error.WriteLine(fe);
}
throw new NotImplementedException("Error: parse of this type is not implemented.");
}
#endregion
}
}
}

@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp.Menu
{
/// <summary>
/// Define an Entry menu.
/// <br/>It allows you to navigate through the entries and completes them with a console input.
/// </summary>
internal abstract partial class Entry : Menu<Entry.EntryStep>
{
#region Attributes & Properties
private List<EntryStep> _steps;
#endregion
#region Constructors
/// <summary>
/// Constructor of the entry menu, based on the Menu constructor.
/// </summary>
/// <param name="title">The title of this menu.</param>
/// <param name="entrySteps">All the entries of this menu.</param>
protected Entry(string title, params EntryStep[] entrySteps) : base(title)
{
_steps = entrySteps.ToList();
_allSelectors = ConvertEntryStepsInSelector();
_selectList = _allSelectors;
}
#endregion
#region Methods
private List<Selector<EntryStep>> ConvertEntryStepsInSelector()
{
List<Selector<EntryStep>> newSelectors = new List<Selector<EntryStep>>();
foreach (EntryStep step in _steps)
{
newSelectors.Add(new Selector<EntryStep>(step, step.Description));
}
return newSelectors;
}
#endregion
#region IMenu implementation
public override void WriteMenuMode(ConsoleKeyInfo cki)
{
if (!WriteMode && cki.Key == ConsoleKey.R)
{
EnableWriteMode();
return;
}
if (WriteMode)
{
if (cki.Key == ConsoleKey.Escape)
{
if (CurrentSelected is null)
throw new ArgumentNullException("CurrentSelected");
CurrentSelected.Input = InputStr.ToString();
DisableWriteMode();
InputStr.Clear();
return;
}
if (cki.Key == ConsoleKey.Backspace && InputStr.Length > 0)
{
InputStr.Remove(InputStr.Length - 1, 1);
return;
}
InputStr.Append(cki.KeyChar);
}
}
public override void Update()
{
if (_selectList.Count == 0)
{
CurrentSelected = default;
return;
}
CurrentSelected = _selectList[CurrentLine].Item;
}
public override void Display()
{
_screenDisplay.Clear();
Console.Clear();
_screenDisplay.AppendLine($"[ {Title} ]");
_screenDisplay.AppendLine("-------------------------------------------");
for (int i = 0; i < _selectList.Count; i++)
{
if (CurrentLine == i)
_screenDisplay.Append($"> ");
else
_screenDisplay.Append($" ");
_screenDisplay.Append($"{_selectList[i].Line} {_selectList[i].Item.Input}");
if (CurrentLine == i && WriteMode)
_screenDisplay.Append(InputStr);
_screenDisplay.AppendLine();
}
if (_selectList.Count == 0)
_screenDisplay.AppendLine("Empty...");
_screenDisplay.AppendLine(
"\n\nHint:\n^:previous, v:next, <:ret, -enter-:return, r:write, -escape-:exit search mode");
Console.WriteLine(_screenDisplay);
}
#endregion
}
}

@ -0,0 +1,72 @@
using Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp.Menu
{
/// <summary>
/// Define a console menu with element selection.
/// </summary>
internal interface IMenu
{
/// <summary>
/// True when enable, False otherwise.
/// </summary>
bool WriteMode { get; set; }
/// <summary>
/// A string input. Used for search string or entry input.
/// </summary>
StringBuilder InputStr { get; set; }
/// <summary>
/// Refresh the console with the updated display. This function dose not call Update().
/// </summary>
void Display();
/// <summary>
/// Update the parameters of the menu. Generally called before Display() to refresh the informations.
/// </summary>
void Update();
/// <summary>
/// Select the next element in the selection list.
/// </summary>
void SelectNext();
/// <summary>
/// Select the previous element in the selection list.
/// </summary>
void SelectPrevious();
/// <summary>
/// Enable the write mode.
/// </summary>
void EnableWriteMode();
/// <summary>
/// Disable the write mode.
/// </summary>
void DisableWriteMode();
/// <summary>
/// Toogle the write mode.
/// </summary>
void ToggleWriteMode();
/// <summary>
/// Define the comportement of the write mode. For instence: in the standard menu, it is used for the research of a line.
/// </summary>
/// <param name="cki">The key to deal with.</param>
void WriteMenuMode(ConsoleKeyInfo cki);
/// <summary>
/// Execute some actions and then return.
/// </summary>
/// <returns>'null' when there is no menu after this selection. Otherwise the next menu.</returns>
IMenu? Return();
}
}

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp.Menu
{
internal interface IMenuDisplay
{
/// <summary>
/// Update the menu display in the Console.
/// </summary>
void UpdateDisplay();
/// <summary>
/// Select the next line in the menu
/// </summary>
/// <returns>The current number of the new selected line</returns>
int SelectNextLine();
/// <summary>
/// Select the previous line in the menu
/// </summary>
/// <returns>The current number of the new selected line</returns>
int SelectPrevioustLine();
}
}

@ -0,0 +1,24 @@
using Model;
using DataPersistence;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp.Menu
{
/// <summary>
/// Main menu of the console. Contain the first interaction menus.
/// </summary>
internal class MainMenu : Menu<IMenu>
{
public MainMenu(DataManager dataMgr)
: base("Main menu",
new Selector<IMenu>(
new SearcherRecipe(new RecipeCollection("search", dataMgr.Data[nameof(Recipe)].Cast<Recipe>().ToArray())), "Recipe search"),
new Selector<IMenu>(
new ConnectionMenu(), "Connection"))
{ }
}
}

@ -0,0 +1,201 @@
using System.Data;
using Model;
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp.Menu
{
/// <summary>
/// Define a selection menu.
/// <br/>It allows you to navigate through the selections and search with a console input.
/// </summary>
/// <typeparam name="T">The type (or the implementation) of the selection.</typeparam>
internal abstract class Menu<T> : IMenu
where T : notnull
{
#region Attributes & Properties
protected StringBuilder _screenDisplay;
protected List<Selector<T>> _allSelectors = new List<Selector<T>>();
protected List<Selector<T>> _selectList = new List<Selector<T>>();
private int _currentLine;
/// <summary>
/// Title of the menu.
/// </summary>
public string Title { get; private set; }
/// <summary>
/// The current line of the selection list.
/// </summary>
public int CurrentLine
{
get
{
if (_currentLine >= _selectList.Count) _currentLine = _selectList.Count - 1;
return _currentLine;
}
protected set
{
_currentLine = value;
if (_currentLine <= 0) _currentLine = 0;
else if (_currentLine >= _selectList.Count) _currentLine = _selectList.Count-1;
}
}
/// <summary>
/// The currently selected object.
/// </summary>
public T? CurrentSelected { get; protected set; }
#endregion
#region Constructors
/// <summary>
/// Base constructor of the Menu class.
/// <br/>This one is incomplete and need to be completed in the inherited class constructors.
/// <br/>Basically, the '_allSelection' and '_selectList' attribute initialization are missing.
/// </summary>
/// <param name="title">The title of the Menu.</param>
protected Menu(string title)
{
Title = title;
CurrentLine = 0;
WriteMode = false;
_screenDisplay = new StringBuilder();
InputStr = new StringBuilder();
}
/// <summary>
/// Constructor of the Menu class. This constructor allows you to directly pass the selections.
/// </summary>
/// <param name="title">The title of the menu.</param>
/// <param name="selections">The selections of the menu.</param>
protected Menu(string title, params Selector<T>[] selections ) : this(title)
{
if (selections == null || selections.Length == 0)
{
Console.WriteLine("Empty menu...");
return;
}
_allSelectors = selections.ToList();
_selectList = _allSelectors;
CurrentSelected = _allSelectors[0].Item;
}
#endregion
#region IMenu implementation
public StringBuilder InputStr { get; set; }
public bool WriteMode { get; set; }
public virtual IMenu? Return()
{
if (CurrentSelected is null)
throw new ArgumentNullException("CurrentSelected");
return (IMenu)CurrentSelected;
}
protected virtual List<Selector<T>> SearchInSelection()
{
if (_allSelectors is null)
throw new ArgumentNullException("_allSelectors");
return _allSelectors.FindAll(x =>
x.Line.ToLower().Contains(InputStr.ToString().ToLower()));
}
public virtual void WriteMenuMode(ConsoleKeyInfo cki)
{
if (!WriteMode && cki.Key == ConsoleKey.R)
{
EnableWriteMode();
return;
}
if (WriteMode)
{
if (cki.Key == ConsoleKey.Escape)
{
DisableWriteMode();
InputStr.Clear();
return;
}
if (cki.Key == ConsoleKey.Backspace && InputStr.Length > 0)
{
InputStr.Remove(InputStr.Length - 1, 1);
return;
}
InputStr.Append(cki.KeyChar);
}
}
public virtual void Update()
{
_selectList = SearchInSelection();
if (_selectList.Count == 0)
{
CurrentSelected = default;
return;
}
CurrentSelected = _selectList[CurrentLine].Item;
}
public virtual void Display()
{
_screenDisplay.Clear();
Console.Clear();
_screenDisplay.AppendLine($"[ {Title} ]");
_screenDisplay.AppendLine("-------------------------------------------");
if (WriteMode)
{
_screenDisplay.Append("Search: ");
_screenDisplay.AppendLine(InputStr.ToString());
}
for (int i = 0; i < _selectList.Count; i++)
{
if (CurrentLine == i)
_screenDisplay.Append($"> ");
else
_screenDisplay.Append($" ");
_screenDisplay.AppendLine($"{_selectList[i].Line}");
}
if (_selectList.Count == 0)
_screenDisplay.AppendLine("Empty...");
_screenDisplay.AppendLine(
"\n\nHint:\n^:previous, v:next, <:ret, -enter-:select, r:search, -escape-:exit search mode");
Console.WriteLine(_screenDisplay);
}
public void SelectNext() => ++CurrentLine;
public void SelectPrevious() => --CurrentLine;
public void EnableWriteMode() => WriteMode = true;
public void DisableWriteMode() => WriteMode = false;
public void ToggleWriteMode()
{
if (WriteMode)
DisableWriteMode();
else
EnableWriteMode();
}
#endregion
}
}

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp.Menu
{
/// <summary>
/// Define a Plain text menu.
/// <br/>This menu is a bit special. It display some text, and then, the only action that can be performed is the back return. Usefull for testing.
/// </summary>
internal class PlainText : IMenu
{
#region Constructors
/// <summary>
/// Constructor of the Plain text menu.
/// </summary>
/// <param name="text">The text buffer to display.</param>
public PlainText(string text)
{
InputStr = new StringBuilder(text);
WriteMode = false;
}
#endregion
#region IMenu implementation
public IMenu? Return() { return null; }
public void Display()
{
Console.Clear();
Console.WriteLine(InputStr);
}
public bool WriteMode { get; set; }
public StringBuilder InputStr { get; set; }
public void DisableWriteMode()
{
// Plain text does not need to do anything for this.
}
public void EnableWriteMode()
{
// Plain text does not need to do anything for this.
}
public void SelectNext()
{
// Plain text does not need to do anything for this.
}
public void SelectPrevious()
{
// Plain text does not need to do anything for this.
}
public void ToggleWriteMode()
{
// Plain text does not need to do anything for this.
}
public void Update()
{
// Plain text does not need to do anything for this.
}
public void WriteMenuMode(ConsoleKeyInfo cki)
{
// Plain text does not need to do anything for this.
}
#endregion
}
}

@ -1,125 +1,46 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Model; using Model;
namespace ConsoleApp.Menu namespace ConsoleApp.Menu
{ {
/// <summary> /// <summary>
/// An utility to find a recipe. /// An utility to find a recipe.
/// </summary> /// </summary>
public class SearcherRecipe : SelectMenu<Recipe> internal class SearcherRecipe : Menu<Recipe>
{ {
#region Attribute private readonly RecipeCollection _recipeCollectionOnSearch;
private RecipeCollection _recipeOnSearch;
#endregion public SearcherRecipe(RecipeCollection recipeCollection) : base("Search recipe")
{
#region Properties _recipeCollectionOnSearch = recipeCollection;
/// <summary> _allSelectors = ConvertRecipeCollectionInSelectors();
/// A collection of recipe where the title contain the search string _selectList = _allSelectors;
/// </summary> }
public RecipeCollection SearchResult { get; private set; }
#region Methods
/// <summary> private List<Selector<Recipe>> ConvertRecipeCollectionInSelectors()
/// The search string {
/// </summary> List<Selector<Recipe>> newSelectors = new List<Selector<Recipe>>();
public string ResearchStr { get; set; } foreach (Recipe recipe in _recipeCollectionOnSearch)
#endregion {
newSelectors.Add(new Selector<Recipe>(recipe, $"[{recipe.Id}]: {recipe.Title}"));
/// <summary> }
/// Constructor of the SearcherRecipe utility. return newSelectors;
/// </summary> }
/// <param name="recipeOnSearch">The collection of recipe where to search</param>
public SearcherRecipe(RecipeCollection recipeOnSearch) public override IMenu? Return()
{ {
_recipeOnSearch = recipeOnSearch; if (CurrentSelected == null)
SearchResult = _recipeOnSearch; throw new ArgumentNullException("CurrentSelected");
ResearchStr = "";
} return new PlainText(CurrentSelected.ToString());
}
#region Methodes #endregion
/// <summary> }
/// Launch a search by name request in the collection of Recipe with with a string. }
/// </summary>
/// <param name="researchStr">The string for search</param>
/// <returns>True if the result of the search gave at least 1 element. False otherwise.</returns>
public bool ComputeSearch(string researchStr = "")
{
ResearchStr = researchStr;
SearchResult = _recipeOnSearch.ResearchByName(ResearchStr.ToLower());
_maxLines = SearchResult.Count - 1;
return SearchResult.Count > 0;
}
public override void UpdateDisplay()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("---------------------------------------------------------");
sb.AppendLine($" Research: {ResearchStr}");
sb.AppendLine("---------------------------------------------------------");
for (int i = 0; i < SearchResult.Count; i++)
{
if (i == CurrentLine)
{
CurrentSelected = SearchResult[i];
sb.Append($">");
}
sb.AppendLine($" [ {SearchResult[i].Id} ]:\t{SearchResult[i].Title} ");
}
Console.Clear();
Console.WriteLine(sb);
}
/// <summary>
/// Launch and pilot the search menu.
/// </summary>
/// <param name="recipeOnSearch">The collection of recipe where to search</param>
/// <returns>The recipe selected</returns>
public static Recipe? ResearchOn(RecipeCollection recipeOnSearch)
{
SearcherRecipe sr = new SearcherRecipe(recipeOnSearch);
StringBuilder sb = new StringBuilder();
sr.ComputeSearch();
sr.UpdateDisplay();
ConsoleKeyInfo cki;
do
{
cki = Console.ReadKey(true);
switch (cki.Key)
{
case ConsoleKey.UpArrow:
sr.SelectPrevioustLine();
break;
case ConsoleKey.DownArrow:
sr.SelectNextLine();
break;
case ConsoleKey.Backspace:
if (sb.Length > 0)
{
sb.Remove(sb.Length - 1, 1);
sr.ComputeSearch(sb.ToString());
}
break;
default:
sb.Append(cki.KeyChar);
sr.ComputeSearch(sb.ToString());
break;
}
sr.UpdateDisplay();
} while (cki.Key != ConsoleKey.Enter);
return sr.CurrentSelected;
}
#endregion
}
}

@ -1,52 +0,0 @@
using ConsoleApp;
using Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp.Menu
{
/// <summary>
/// An abstract class that define the components of a selection-type menu.
/// </summary>
/// <typeparam name="T">The return type of the currently selected item</typeparam>
public abstract class SelectMenu<T> : IMenuDisplay
{
protected int _currentLine = 0;
protected int _maxLines = 0;
/// <summary>
/// The currently selected item.
/// </summary>
public T? CurrentSelected { get; protected set; }
/// <summary>
/// The current line selected in the menu.
/// </summary>
public int CurrentLine
{
get => _currentLine;
protected set
{
_currentLine = value;
if (_currentLine > _maxLines)
{
_currentLine = _maxLines;
}
if (_currentLine < 0)
{
_currentLine = 0;
}
return;
}
}
public int SelectNextLine() { return ++CurrentLine; }
public int SelectPrevioustLine() { return --CurrentLine; }
public abstract void UpdateDisplay();
}
}

@ -0,0 +1,76 @@
using Model;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp.Menu
{
/// <summary>
/// The selector of a menu.
/// </summary>
/// <typeparam name="T">The type of the selector.</typeparam>
internal class Selector<T> : IEquatable<Selector<T>>
where T : notnull
{
#region Attributes & Properties
private string _line = "";
/// <summary>
/// The string that are displayed on the menu.
/// </summary>
public string Line {
get => _line;
private set
{
if (string.IsNullOrEmpty(value))
_line = "no data";
else
_line = value;
}
}
/// <summary>
/// The item contained in the selector.
/// </summary>
public T Item { get; private set; }
#endregion
#region Constructors
/// <summary>
/// The constructor of the selector.
/// </summary>
/// <param name="item">The item to place inside.</param>
/// <param name="line">The string to display in the menu.</param>
public Selector(T item, string line = "")
{
Line = line;
Item = item;
}
#endregion
#region IEquatable implementation
public virtual bool Equals(Selector<T>? other)
{
if (other == null) return false;
if (other == this) return true;
return other.Line.Equals(this.Line);
}
public override bool Equals(object? obj)
{
var item = obj as Selector<T>;
if (item == null) return false;
return Equals(obj);
}
public override int GetHashCode()
{
return Line.GetHashCode();
}
#endregion
}
}

@ -0,0 +1,90 @@
using ConsoleApp.Menu;
using Model;
using DataPersistence;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp
{
/// <summary>
/// Manage the menus of the console application.
/// </summary>
internal class MenuManager
{
#region Attributes & Properties
/// <summary>
/// The manager that contains usefull data taken from the model.
/// </summary>
public DataManager DataManager { get; private set; }
/// <summary>
/// Each menu called are push in this stack. Then, to return back, we pop this stack to retrive the previous menu.
/// </summary>
public Stack<Menu.IMenu> MenuCallStack { get; set; }
#endregion
#region Constructors
/// <summary>
/// Constructor of the MenuManager class. This constructor allows you to give the first menu of the call stack, wich is usefull for testing.
/// </summary>
/// <param name="dataManager">The data manager needed by the menus inside.</param>
/// <param name="firstMenu">The starting menu, the first that will be push on the call stack.</param>
public MenuManager(DataManager dataManager, Menu.IMenu firstMenu)
{
DataManager = dataManager;
MenuCallStack = new Stack<Menu.IMenu>();
MenuCallStack.Push(firstMenu);
}
/// <summary>
/// Constructor of the MenuManager class.
/// </summary>
/// <param name="dataManager">The data manager needed by the menus inside.</param>
public MenuManager(DataManager dataManager) : this(dataManager, new MainMenu(dataManager))
{ }
#endregion
#region Methods
/// <summary>
/// Main loop. Loop while the menu call stack is not empty.
/// </summary>
public void Loop()
{
ConsoleKeyInfo cki;
Menu.IMenu menuOnHead;
do
{
menuOnHead = MenuCallStack.Peek();
menuOnHead.Update();
menuOnHead.Display();
cki = Console.ReadKey(true);
switch (cki.Key)
{
case ConsoleKey.DownArrow:
menuOnHead.SelectNext();
break;
case ConsoleKey.UpArrow:
menuOnHead.SelectPrevious();
break;
case ConsoleKey.Enter:
Menu.IMenu? retMenu = menuOnHead.Return();
if (retMenu is null) MenuCallStack.Pop();
else MenuCallStack.Push(retMenu);
break;
case ConsoleKey.LeftArrow:
MenuCallStack.Pop();
break;
default:
menuOnHead.WriteMenuMode(cki);
break;
}
} while (MenuCallStack.Count > 0);
}
#endregion
}
}

@ -11,12 +11,12 @@ Console.WriteLine("Hello, World!\n\n");
// TESTS: // TESTS:
//DataManager dataMgr = new DataManager(new Stubs()); DataManager dataMgr = new DataManager(new Stubs());
//DataManager dataMgr = new DataManager(new DataContractXML(xmlFolderPath: "../../../../DataPersistence/data")); //DataManager dataMgr = new DataManager(new DataContractXML(xmlFolderPath: "../../../../DataPersistence/data"));
DataManager dataMgr = new DataManager(new DataContractJSON(jsonFolderPath: "../../../../DataPersistence/data")); //DataManager dataMgr = new DataManager(new DataContractJSON());
//dataMgr.Serializer = new DataContractXML(xmlFolderPath: "../../../../DataPersistence/data"); //dataMgr.Serializer = new DataContractXML(xmlFolderPath: "../../../../DataPersistence/data");
//dataMgr.Serializer = new DataContractJSON(jsonFolderPath: "../../../../DataPersistence/data"); dataMgr.Serializer = new DataContractJSON();
// /!\ here is an absolute path I put for testing purpose. It will only work on my computer so don't forget to change it whene you test. // /!\ here is an absolute path I put for testing purpose. It will only work on my computer so don't forget to change it whene you test.
@ -25,10 +25,11 @@ DataManager dataMgr = new DataManager(new DataContractJSON(jsonFolderPath: "../.
RecipeCollection rc = new RecipeCollection("All recipes", dataMgr.Data[nameof(Recipe)].Cast<Recipe>().ToArray()); RecipeCollection rc = new RecipeCollection("All recipes", dataMgr.Data[nameof(Recipe)].Cast<Recipe>().ToArray());
Recipe? ret = SearcherRecipe.ResearchOn(rc);
Console.WriteLine(ret);
dataMgr.Save(); dataMgr.Save();
MenuManager menuMgr = new MenuManager(dataMgr);
menuMgr.Loop();
// press any key to quit // press any key to quit
Console.ReadKey(); //Console.ReadKey();

@ -1,38 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
/// <summary>
/// Manager of the model. Here is stoked all the recipes, the users, etc...
/// </summary>
public class Manager
{
/// <summary>
/// A collection of all the recipe loaded in the app.
/// </summary>
public RecipeCollection AllRecipes { get; protected set; }
/// <summary>
/// The constructor of the manager.
/// </summary>
public Manager()
{
AllRecipes = new RecipeCollection(description: "All Recipes");
}
/// <summary>
/// The constructor of the manager.
/// </summary>
/// <param name="allRecipes">A list of loaded recipes</param>
public Manager(RecipeCollection allRecipes)
{
AllRecipes = new RecipeCollection(
description: "All Recipes",
recipes: allRecipes.ToArray());
}
}
}

@ -10,10 +10,9 @@ namespace Model
/// Define a collection of <see cref="Recipe"/>. /// Define a collection of <see cref="Recipe"/>.
/// <br/>This class implement <see cref="IList"/> and <see cref="IEquatable{T}"/>. /// <br/>This class implement <see cref="IList"/> and <see cref="IEquatable{T}"/>.
/// </summary> /// </summary>
public class RecipeCollection : IList<Recipe>, IEquatable<RecipeCollection> public class RecipeCollection : List<Recipe>, IEquatable<RecipeCollection>
{ {
#region Attributes #region Attributes
private readonly List<Recipe> _recipes;
private string _description = ""; private string _description = "";
#endregion #endregion
@ -33,12 +32,6 @@ namespace Model
_description = value; _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 #endregion
#region Constructors #region Constructors
@ -48,8 +41,8 @@ namespace Model
/// <param name="description">A short description of what this list will contain</param> /// <param name="description">A short description of what this list will contain</param>
/// <param name="recipes">Recipes to add in this new collection</param> /// <param name="recipes">Recipes to add in this new collection</param>
public RecipeCollection(string description, params Recipe[] recipes) public RecipeCollection(string description, params Recipe[] recipes)
: base(recipes)
{ {
_recipes = new List<Recipe>(recipes);
Description = description; Description = description;
} }
#endregion #endregion
@ -63,7 +56,7 @@ namespace Model
/// <exception cref="ArgumentException"/> /// <exception cref="ArgumentException"/>
public Recipe? GetRecipeById(int id) public Recipe? GetRecipeById(int id)
{ {
Recipe? recipe = _recipes.Find(r => r.Id == id); Recipe? recipe = this.Find(r => r.Id == id);
if (recipe == null) throw new ArgumentException("No _recipes match the given id."); if (recipe == null) throw new ArgumentException("No _recipes match the given id.");
return recipe; return recipe;
} }
@ -77,66 +70,14 @@ namespace Model
{ {
return new RecipeCollection( return new RecipeCollection(
description: $"Results of the research: {str}", description: $"Results of the research: {str}",
recipes: _recipes.FindAll(x => x.Title.ToLower().Contains(str.ToLower())).ToArray()); recipes: this.FindAll(x => x.Title.ToLower().Contains(str.ToLower())).ToArray());
}
#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<Recipe> GetEnumerator()
{
return _recipes.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _recipes.GetEnumerator();
}
#endregion
public virtual bool Equals(RecipeCollection? other) public virtual bool Equals(RecipeCollection? other)
{ {
if (other == null) return false; if (other == null) return false;
if (other == this) return true; if (other == this) return true;
return _description.Equals(other.Description) && _recipes.Equals(other._recipes); return this.Description.Equals(other.Description);
} }
public override bool Equals(object? obj) public override bool Equals(object? obj)
@ -148,13 +89,13 @@ namespace Model
public override int GetHashCode() public override int GetHashCode()
{ {
return _recipes.GetHashCode(); return Description.GetHashCode();
} }
public override string ToString() public override string ToString()
{ {
StringBuilder sb = new StringBuilder($"[RecipeCollection] - {Description}:\n"); StringBuilder sb = new StringBuilder($"[RecipeCollection] - {Description}:\n");
foreach (Recipe r in _recipes) foreach (Recipe r in this)
{ {
sb.AppendFormat("\t - {0}\n", r.ToString()); sb.AppendFormat("\t - {0}\n", r.ToString());
} }

@ -21,5 +21,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Model\Model.csproj" /> <ProjectReference Include="..\..\Model\Model.csproj" />
<ProjectReference Include="..\..\DataPersistence\DataPersistence.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -22,7 +22,10 @@ namespace Model_UnitTests
new Recipe(title: "Gateau aux cerises", id: 3) new Recipe(title: "Gateau aux cerises", id: 3)
}); });
Assert.Equal(2, recipes.ResearchByName("chocolat").FirstOrDefault().Id); Recipe? recipe = recipes.ResearchByName("chocolat").FirstOrDefault();
Assert.NotNull(recipe);
Assert.Equal(2, recipe.Id);
} }
} }
} }

@ -12,8 +12,8 @@ namespace Model_UnitTests
[Fact] [Fact]
public void TestConstructUser() public void TestConstructUser()
{ {
User user = new User("Bob","Dylan", "bd@gmail.com"); User? user = new User("Bob","Dylan", "bd@gmail.com");
//Assert. Assert.NotNull(user);
} }
} }
} }

Loading…
Cancel
Save