using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Caisses { internal class GraphicalStore { private List _checkouts; private List _clients; private int _timeOfTheDayInMinuts; private Bitmap _shelvesCorner; private Bitmap _checkoutCorner; private Random rnd; public static readonly int[] ATTENDANCE = { 0, 0, 0, 0, 0, 0, 0, 30, 30, 40, 50, 60, 100, 80, 50, 30, 80, 100, 50, 50, 80, 0, 0, 0 }; const int CROSSOVER_TIME = 10; public int TimeOfTheDayInMinuts { get => _timeOfTheDayInMinuts; set => _timeOfTheDayInMinuts = value; } public List Clients { get => _clients; set => _clients = value; } internal List Checkouts { get => _checkouts; set => _checkouts = value; } public Bitmap ShelvesCorner { get => _shelvesCorner; set => _shelvesCorner = value; } public Bitmap CheckoutCorner { get => _checkoutCorner; set => _checkoutCorner = value; } public int TimeOfTheDayInHours { get { return _timeOfTheDayInMinuts / 60; } } public GraphicalStore(int startingHour,int checkoutNumber, Size shelvesCornerSize,Size checkoutCornerSize) { TimeOfTheDayInMinuts = startingHour * 60; Clients = new List(); Checkouts = new List(); CheckoutCorner = new Bitmap(checkoutCornerSize.Width,checkoutCornerSize.Height); ShelvesCorner = new Bitmap(shelvesCornerSize.Width,shelvesCornerSize.Height); rnd = new Random(); FillStore(ATTENDANCE[TimeOfTheDayInHours]); populateCheckouts(checkoutNumber); Tick(); } public void populateCheckouts(int numberOfCheckouts) { int checkoutWidth = CheckoutCorner.Width / numberOfCheckouts + 1; for (int i = 0; i < numberOfCheckouts; i++) { Point position = new Point(i * checkoutWidth + checkoutWidth / numberOfCheckouts, 0); Checkouts.Add(new GraphicalCheckout(position, new Rectangle(new Point(0, 0), new Size(CheckoutCorner.Width, CheckoutCorner.Height)), numberOfCheckouts)); } } public void Tick() { TimeOfTheDayInMinuts++; if (TimeOfTheDayInMinuts % 60 == 0) { //Its a new Hour so we can send the new clients int amountOfNewCLients = ATTENDANCE[TimeOfTheDayInHours]; FillStore(amountOfNewCLients); } int cumulatedWaitingTime = 0; int averageWaitingTime = 0; foreach (GraphicalClient client in Clients) { client.Tick(); cumulatedWaitingTime += client.WaitingTime; } if (Clients.Count == 0) { averageWaitingTime = 0; } else { averageWaitingTime = cumulatedWaitingTime / Clients.Count; } foreach (GraphicalCheckout checkout in Checkouts) { checkout.Tick(averageWaitingTime,CROSSOVER_TIME); } //Processing the checkout mechanism int openPlacesAmount = GetAmountOfPlacesLeft(); List clientsToRemove = new List(); foreach (GraphicalClient client in Clients) { if (client.State == Client.ClientState.Waiting) { if (openPlacesAmount > 0) { List checkoutsWithFreeSpace = GetNotFullCheckouts(); if (checkoutsWithFreeSpace.Count > 0) { //Now we select a random one to put our waiting client int index = 0; int count = checkoutsWithFreeSpace.Count - 1; if (count > 0) { index = rnd.Next(0, checkoutsWithFreeSpace.Count - 1); } else { index = 0; } checkoutsWithFreeSpace[index].Clients.Add(client); //Clients.Remove(client); clientsToRemove.Add(client); client.State = Client.ClientState.Inline; } } } } foreach (GraphicalClient client in clientsToRemove) { Clients.Remove(client); } foreach (GraphicalCheckout checkout in Checkouts) { if (checkout.Open && checkout.Clients.Count > 0) { Client cClient = checkout.Clients[0]; if (cClient.State != Client.ClientState.Checkout) cClient.State = Client.ClientState.Checkout; if (cClient.CheckoutTime <= 0) { checkout.Clients.Remove(cClient); //We dont load the next because he should be loaded the next time this function is loaded } foreach (GraphicalClient ccClient in checkout.Clients) { ccClient.Tick(); } } } } public List Draw() { ShelvesCorner = new Bitmap(ShelvesCorner.Width,ShelvesCorner.Height); CheckoutCorner = new Bitmap(CheckoutCorner.Width,CheckoutCorner.Height); foreach (GraphicalClient client in Clients) { client.Draw(ShelvesCorner); } foreach (GraphicalCheckout checkout in Checkouts) { checkout.Draw(CheckoutCorner); foreach (GraphicalClient client in checkout.Clients) { client.Draw(ShelvesCorner); } } return new List { ShelvesCorner, CheckoutCorner }; } public virtual void FillStore(int amountOfNewClients) { for (int i = 0; i < amountOfNewClients; i++) { Clients.Add(new GraphicalClient(new Point(0,0),rnd)); } } public List GetClientsWithoutCheckout() { List result = new List(); foreach (GraphicalClient client in Clients) { if (client.State == Client.ClientState.Waiting) result.Add(client); } return result; } public List GetNotFullCheckouts() { List result = new List(); foreach (GraphicalCheckout checkout in Checkouts) { if (checkout.Clients.Count < Checkout.MAX_CAPACITY && checkout.Open) { result.Add(checkout); } } return result; } public int GetAmountOfPlacesLeft() { int result = 0; foreach(GraphicalCheckout checkout in Checkouts) { if (checkout.Open) { result += Checkout.MAX_CAPACITY - checkout.Clients.Count(); } } return result; } public int GetAverageWaitingTime() { int cumulatedWaitingTime = 0; int averageWaitingTime = 0; foreach (GraphicalClient client in Clients) { cumulatedWaitingTime += client.WaitingTime; } if (Clients.Count == 0) { averageWaitingTime = 0; } else { averageWaitingTime = cumulatedWaitingTime / Clients.Count; } return averageWaitingTime; } } }