Postanowiłem przećwiczyć pe podejscie:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SmartMenu
{
internal class Context
{
public Cafe cafe { get; set; }
public Order order { get; set; }
public Dish dish { get; set; }
public Context combine(Context extra)
{
return (extra == null) ? this : new Context
{
cafe = (extra.cafe ?? cafe),
order = (extra.order ?? order),
dish = (extra.dish ?? dish)
};
}
public Context combine(Order order)
{
return new Context
{
cafe = cafe,
order = (order ?? this.order),
dish = dish
};
}
public Context combine(Dish dish)
{
return new Context
{
cafe = cafe,
order = order,
dish = (dish ?? this.dish)
};
}
}
internal class Cafe
{
private static readonly UserMenu[] orderMenu = new UserMenu[]
{
new UserMenu("Pokaż zamówienie",Order.ShowOrder),
new UserMenu("Dodaj danie",Dish.makeCategoryMenu(Order.AddDish)),
new UserMenu("Rozlicz",Cafe.CompleteOrder),
UserMenu.returnMenu,
};
public static readonly UserMenu[] mainMenu = new UserMenu[]
{
new UserMenu("Nowe zamówienie",Cafe.MakeOrder),
new UserMenu("Wybierz zamówienie",Cafe.ChoiseOrder),
new UserMenu("Koniec programu"),
};
private readonly List<Order> orders = new List<Order>();
public static bool MakeOrder(string title, Context context)
{
Console.WriteLine(title);
Console.Write("Podaj id: ");
string id = Console.ReadLine();
string subtitle = $"{title} / zamówienie {id}";
foreach (Order ord in context.cafe.orders)
{
if (ord.id == id)
{
Console.WriteLine($"Znaleziono zamówienie {id}");
Console.WriteLine();
UserMenu.Run(subtitle, orderMenu, context.combine(ord));
return true;
}
}
Console.WriteLine($"Utworzono zamówienie {id}");
Console.WriteLine();
Order order = new Order(id);
context.cafe.orders.Add(order);
UserMenu.Run(subtitle, orderMenu, context.combine(order));
return true;
}
public static bool ChoiseOrder(string title, Context context)
{
UserMenu[] menu =
context.cafe.orders
.OrderBy(order => order.id)
.Select(order => new UserMenu(order.id, orderMenu, context.combine(order)))
.Append(UserMenu.returnMenu)
.ToArray()
;
UserMenu.Run(title, menu.ToArray(), context);
return true;
}
public static bool CompleteOrder(string title, Context context)
{
Console.WriteLine(title);
Order.ShowOrder($"Zamówienie {context.order.id}", context);
context.cafe.orders.Remove(context.order);
return false;
}
public static string ShowPrice(int price)
{
return string.Format("{0:###0.00}", price / 100.0);
}
}
internal class Order
{
private readonly List<Dish> dishes = new List<Dish>();
public string id { get; private set; }
public Order(string id) { this.id = id; }
public static bool AddDish(string Title, Context context)
{
Console.WriteLine(Title);
context.order.dishes.Add(context.dish);
Console.WriteLine($"Do zamówienia {context.order.id} dodano danie {context.dish.category}:{context.dish.title} - {Cafe.ShowPrice(context.dish.price)}");
return true;
}
public static bool ShowOrder(string title, Context context)
{
Console.WriteLine(title);
if(context.order.dishes.Count <= 0) Console.WriteLine("Zamówienie puste");
else
{
foreach(Dish dish in context.order.dishes)
{
Console.WriteLine(dish.Show());
}
Console.WriteLine($"razem: {Cafe.ShowPrice(context.order.Sum()).Trim()}");
}
return true;
}
public int Sum()
{
return
dishes
.Aggregate(0, (curr, dish) => (curr + dish.price))
;
}
}
internal class Dish
{
private static readonly List<Dish> dishes = new List<Dish>()
{
new Dish("Przystawki","Pajda",999),
new Dish("Przystawki","Koreczki",1199),
new Dish("Zupy","Ogórkowa",2399),
new Dish("Zupy","Pomidorowa",2199),
new Dish("Dania główne","Schabowy",3499),
new Dish("Dania główne","Pierogi",1799),
};
public static UserMenu[] makeCategoryMenu(UserMenuExecuter executer)
{
return
dishes
.Select(dish => dish.category)
.Distinct()
.OrderBy(category => category)
.Select(category => new UserMenu(category, makeDishMenu(category, executer)))
.Append(UserMenu.returnMenu)
.ToArray()
;
}
private static UserMenu[] makeDishMenu(string category, UserMenuExecuter executer)
{
return
dishes
.Where(dish => (dish.category == category))
.OrderBy(dish => dish.title)
.Select(dish => new UserMenu(dish.title, executer, new Context { dish = dish }))
.Append(UserMenu.returnMenu)
.ToArray()
;
}
public string category { get; private set; }
public string title { get; private set; }
public int price { get; private set; }
private Dish(string category, string title, int price)
{
this.category = category;
this.title = title;
this.price = price;
}
public string Show()
{
return $"{Cafe.ShowPrice(price)} \t{category}:{title}";
}
}
internal delegate bool UserMenuExecuter(string title, Context context);
internal class UserMenu
{
public static readonly UserMenu returnMenu = new UserMenu("Powrót");
private readonly String name;
private readonly UserMenuExecuter executer;
private readonly UserMenu[] submenu;
private readonly Context context;
private UserMenu(String name, UserMenuExecuter executer, UserMenu[] submenu, Context context)
{
this.name = name;
this.executer = executer;
this.submenu = submenu;
this.context = context;
}
public UserMenu(String name, UserMenuExecuter executer, Context context = null) : this(name, executer, null, context) { }
public UserMenu(String name, UserMenu[] submenu, Context context = null) : this(name, null, submenu, context) { }
public UserMenu(String name) : this(name, null, null, null) { }
public static void Run(String title, UserMenu[] submenu, Context context = null)
{
while (true)
{
Console.WriteLine($"* {title}:");
for (int i = 0; i < submenu.Length; ++i) Console.WriteLine($"{i + 1}. {submenu[i].name}");
Console.Write("Wybierz opcję: ");
if (!int.TryParse(Console.ReadLine(), out int pos)) pos = -1;
if ((1 <= pos) && (pos <= submenu.Length))
{
UserMenu sub = submenu[pos - 1];
string subtitle = $"{title} * {sub.name}";
Context subcontext = context.combine(sub.context);
if (sub.submenu != null)
{
Run(subtitle, sub.submenu, subcontext);
}
else if (sub.executer != null)
{
if(!sub.executer(subtitle, subcontext)) break;
}
else break;
}
else Console.WriteLine("Nie ma takiej opcji");
Console.WriteLine();
}
}
}
internal class Program
{
static void Main()
{
UserMenu.Run("Menu główne", Cafe.mainMenu, new Context { cafe = new Cafe() });
}
}
}