Files
Std_Caisses/Caisses/GraphicalStore.cs

331 lines
12 KiB
C#

/*
* Rohmer Maxime
* STD Project
* 25/01/2023
* V1.0
* GraphicalStore.cs
* The model of the application that setups all the clients and the checkouts while communicating everything to the vue
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Caisses
{
internal class GraphicalStore
{
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 };
public int CrossoverTime = 10;
private List<GraphicalCheckout> _checkouts;
private List<GraphicalClient> _clients;
private int _timeOfTheDayInMinuts;
private Random rnd;
private int _clientsMultiplier;
/// Stats
private int _AverageWaitingTime;
private int _OpenCheckoutCount;
private int _PlacesLeftCount;
private List<GraphicalCheckout> _NotFullCheckouts;
private List<GraphicalClient> _WaitingClients;
public int AverageWaitingTime { get => _AverageWaitingTime; set => _AverageWaitingTime = value; }
public int OpenCheckoutCount { get => _OpenCheckoutCount; set => _OpenCheckoutCount = value; }
public int TotalPlacesLeftCount { get => _PlacesLeftCount; set => _PlacesLeftCount = value; }
internal List<GraphicalCheckout> NotFullCheckouts { get => _NotFullCheckouts; set => _NotFullCheckouts = value; }
public List<GraphicalClient> WaitingClients { get => _WaitingClients; set => _WaitingClients = value; }
/// Stats
public int TimeOfTheDayInMinuts { get => _timeOfTheDayInMinuts; set => _timeOfTheDayInMinuts = value; }
public List<GraphicalClient> Clients { get => _clients; set => _clients = value; }
internal List<GraphicalCheckout> Checkouts { get => _checkouts; set => _checkouts = value; }
public int TimeOfTheDayInHours
{
get { return _timeOfTheDayInMinuts / 60; }
}
public int ClientsMultiplier { get => _clientsMultiplier; set => _clientsMultiplier = value; }
public GraphicalStore(int startingHour, int checkoutNumber, Size checkoutsRoom)
{
TimeOfTheDayInMinuts = startingHour * 60;
Clients = new List<GraphicalClient>();
Checkouts = new List<GraphicalCheckout>();
rnd = new Random();
ClientsMultiplier = 1;
FillStore(ATTENDANCE[TimeOfTheDayInHours]);
populateCheckouts(checkoutsRoom, checkoutNumber);
Tick();
}
public void populateCheckouts(Size checkoutRoom, int checkoutNumber)
{
int checkoutWidth = checkoutRoom.Width / checkoutNumber + 1;
if (Checkouts.Count > 0)
{
//We are resizing
if (Checkouts.Count > checkoutNumber)
{
int checkoutsToRemove = Checkouts.Count - checkoutNumber;
for (int i = 0; i < checkoutsToRemove; i++)
{
Checkouts.RemoveAt(Checkouts.Count - 1);
}
}
else
{
int checkoutsToAdd = checkoutNumber - Checkouts.Count;
for (int i = 0; i < checkoutsToAdd; i++)
{
Checkouts.Add(new GraphicalCheckout());
}
}
}
else
{
//We are creating
for (int i = 0; i < checkoutNumber; i++)
{
Checkouts.Add(new GraphicalCheckout());
}
}
}
private void RefreshStoreFilling()
{
if (TimeOfTheDayInMinuts % 60 == 0)
{
if (TimeOfTheDayInMinuts >= 24 * 60)
{
TimeOfTheDayInMinuts = 0;
}
//Its a new Hour so we can send the new clients
int amountOfNewCLients = ATTENDANCE[TimeOfTheDayInHours];
FillStore(amountOfNewCLients * ClientsMultiplier);
}
}
public void Tick()
{
TimeOfTheDayInMinuts++;
RefreshStoreFilling();
int cumulatedWaitingTime = 0;
int waitingClients = 0;
AverageWaitingTime = 0;
WaitingClients = new List<GraphicalClient>();
if (NotFullCheckouts == null)
NotFullCheckouts = new List<GraphicalCheckout>();
//Clients that will leave the store
List<GraphicalClient> clientsToRemove = new List<GraphicalClient>();
foreach (GraphicalClient client in Clients)
{
//Tick
client.Tick();
// Calculating average waiting time
if (Clients.Count == 0 || waitingClients == 0)
{
AverageWaitingTime = 0;
}
else
{
AverageWaitingTime = cumulatedWaitingTime / waitingClients;
}
//Waiting time incrementation
if (Clients.Count != 0 && client.State == Client.ClientState.Waiting)
{
cumulatedWaitingTime += client.WaitingTime;
waitingClients += 1;
WaitingClients.Add(client);
//Checkout process
if (TotalPlacesLeftCount > 0 && NotFullCheckouts.Count > 0)
{
//Now we select a random one to put our waiting client
int index = 0;
int count = NotFullCheckouts.Count;
if (count > 0)
{
index = rnd.Next(0, count - 1);
}
else
{
index = 0;
}
if (NotFullCheckouts[index].Clients.Count < Checkout.MAX_CAPACITY)
{
//We need to check that because a client could have been already added and so the checkout could not have any places left even tho she is listed as not full
NotFullCheckouts[index].Clients.Add(client);
//Clients.Remove(client);
clientsToRemove.Add(client);
client.State = Client.ClientState.Inline;
}
}
}
}
foreach (GraphicalClient client in clientsToRemove)
{
Clients.Remove(client);
}
OpenCheckoutCount = 0;
TotalPlacesLeftCount = 0;
NotFullCheckouts = new List<GraphicalCheckout>();
foreach (GraphicalCheckout checkout in Checkouts)
{
//Tick
checkout.Tick(this);
if (checkout.Open)
{
//Calculate amount of open Checkouts
OpenCheckoutCount++;
//Calculate amount of places left
int CheckoutPlacesLeft = Checkout.MAX_CAPACITY - checkout.Clients.Count();
TotalPlacesLeftCount += CheckoutPlacesLeft;
//Collecting every non full checkout
if (CheckoutPlacesLeft > 0)
{
NotFullCheckouts.Add(checkout);
}
//Checkout behaviour
if (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<Bitmap> Draw(Size shelvesRoom, Size waitRoom, Size checkoutsRoom)
{
Bitmap shelvesImage = new Bitmap(shelvesRoom.Width, shelvesRoom.Height);
Bitmap waitingRoomImage = new Bitmap(waitRoom.Width, waitRoom.Height);
Bitmap checkoutsImage = new Bitmap(checkoutsRoom.Width, checkoutsRoom.Height);
foreach (GraphicalClient client in Clients)
{
client.Draw(shelvesImage, waitingRoomImage);
}
for (int i = 0; i < Checkouts.Count; i++)
{
Checkouts[i].Draw(checkoutsImage, Checkouts.Count, i);
foreach (GraphicalClient client in Checkouts[i].Clients)
{
client.Draw(shelvesImage, waitingRoomImage);
}
}
/*
foreach (GraphicalCheckout checkout in Checkouts)
{
checkout.Draw(checkoutsImage,Checkouts.Count, );
foreach (GraphicalClient client in checkout.Clients)
{
client.Draw(shelvesImage,waitingRoomImage);
}
}
*/
return new List<Bitmap> { shelvesImage, waitingRoomImage, checkoutsImage };
}
public virtual void FillStore(int amountOfNewClients)
{
for (int i = 0; i < amountOfNewClients; i++)
{
Clients.Add(new GraphicalClient(new Point(0, 0), rnd));
}
}
public int GetEmptyCheckoutCount()
{
int result = 0;
foreach (GraphicalCheckout checkout in Checkouts)
{
if (checkout.Open && checkout.Clients.Count == 0)
{
result += 1;
}
}
return result;
}
public void AddClients(int amount)
{
for (int i = 0; i < amount; i++)
{
Clients.Add(new GraphicalClient(new Point(0, 0), rnd));
}
}
public void ClearStore()
{
List<GraphicalClient> clientsToRemove = new List<GraphicalClient>();
foreach (GraphicalClient client in Clients)
{
if (client.State == Client.ClientState.Shopping)
{
clientsToRemove.Add(client);
}
}
foreach (GraphicalClient client in clientsToRemove)
{
Clients.Remove(client);
}
}
public void ClearWaitingRoom()
{
List<GraphicalClient> clientsToRemove = new List<GraphicalClient>();
foreach (GraphicalClient client in Clients)
{
if (client.State == Client.ClientState.Waiting)
{
clientsToRemove.Add(client);
}
}
foreach (GraphicalClient client in clientsToRemove)
{
Clients.Remove(client);
}
}
public void AddTime(int time)
{
TimeOfTheDayInMinuts += time;
}
public void UpdateCheckoutNumber(int newCheckoutNumber, Size checkoutRoom)
{
populateCheckouts(checkoutRoom, newCheckoutNumber);
}
public void ChangeClientMultiplier(int newMultiplier)
{
ClientsMultiplier = newMultiplier;
}
public void ChangeCrossoverTime(int newCrossoverTime)
{
CrossoverTime = newCrossoverTime;
}
}
}