Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // //
- // Project: Project 4 - Queues //
- // File Name: SimulationForm.cs //
- // Description: Form that handles simulating a given run of supermarket registers in a day. //
- // Course: CSCI 2210-001 - Data Structures //
- // Author: Dillon Buchanan, buchananjd2@etsu.edu, Department of Computing, East Tennessee State University //
- // Created: Saturday Apr 13 2019 //
- // Copyright: Dillon Buchanan 2019 //
- // //
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- namespace Project4 {
- /// <summary>Form that handles simulating a given run of supermarket registers in a day.</summary>
- public partial class SimulationForm : Form {
- /// <summary>Gets or sets the store.</summary>
- /// <value>The store.</value>
- public Supermarket Store {get; set;}
- public List<Queue<Customer>> RegisterQueues {get; set;}
- /// <summary>Initializes a new instance of the <see cref="SimulationForm"/> class.</summary>
- public SimulationForm() {
- InitializeComponent();
- }
- #region RegBox placeholder text handling
- /// <summary> Removes default text if the user enters focus on this field.</summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
- private void RegBox_Enter(object sender, EventArgs e) {
- if(RegBox.Text == "(Max 15)") { //if default text
- RegBox.Text = ""; //clear the field
- }
- }
- /// <summary> Replaces the default text when the user leaves focus on this field, if the field is left empty or invalid.</summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
- private void RegBox_Leave(object sender, EventArgs e) {
- if(RegBox.Text == "" || int.Parse(RegBox.Text) > 15) { //if the field is blank or invalid
- RegBox.Text = "(Max 15)"; //replace the default text
- }
- }
- #endregion
- #region CheckBox placeholder text handling
- /// <summary> Removes default text if the user enters focus on this field.</summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
- private void CheckBox_Enter(object sender, EventArgs e) {
- if (CheckBox.Text == "(Min 120)") { //if default text
- CheckBox.Text = ""; //clear the field
- }
- }
- /// <summary> Replaces the default text when the user leaves focus on this field, if the field is left empty or invalid.</summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
- private void CheckBox_Leave(object sender, EventArgs e) {
- if (CheckBox.Text == "" || int.Parse(CheckBox.Text) < 120) { //if the field is blank or invalid
- CheckBox.Text = "(Min 120)"; //replace the default text
- }
- }
- #endregion
- #region invalid key press handlers
- /// <summary> Prevents a key press that is not a digit.</summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="KeyPressEventArgs"/> instance containing the event data.</param>
- private void CustBox_KeyPress(object sender, KeyPressEventArgs e) {
- string acceptedKeys = "0123456789";
- if (!acceptedKeys.Contains(e.KeyChar) && !char.IsControl(e.KeyChar)) { //if the accepted keys string does not contain the key pressed
- //or if the key is a control key (i.e. Backspace)
- e.Handled = true; //The event is ignored.
- }
- }
- /// <summary> Prevents a key press that is not a digit.</summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="KeyPressEventArgs"/> instance containing the event data.</param>
- private void HoursBox_KeyPress(object sender, KeyPressEventArgs e) {
- string acceptedKeys = "0123456789";
- if (!acceptedKeys.Contains(e.KeyChar) && !char.IsControl(e.KeyChar)) { //if the accepted keys string does not contain the key pressed
- //or if the key is a control key (i.e. Backspace)
- e.Handled = true; //The event is ignored.
- }
- }
- /// <summary> Prevents a key press that is not a digit.</summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="KeyPressEventArgs"/> instance containing the event data.</param>
- private void RegBox_KeyPress(object sender, KeyPressEventArgs e) {
- string acceptedKeys = "0123456789";
- if (!acceptedKeys.Contains(e.KeyChar) && !char.IsControl(e.KeyChar)) { //if the accepted keys string does not contain the key pressed
- //or if the key is a control key (i.e. Backspace)
- e.Handled = true; //The event is ignored.
- }
- }
- /// <summary> Prevents a key press that is not a digit.</summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="KeyPressEventArgs"/> instance containing the event data.</param>
- private void CheckBox_KeyPress(object sender, KeyPressEventArgs e) {
- string acceptedKeys = "0123456789";
- if (!acceptedKeys.Contains(e.KeyChar) && !char.IsControl(e.KeyChar)) { //if the accepted keys string does not contain the key pressed
- //or if the key is a control key (i.e. Backspace)
- e.Handled = true; //The event is ignored.
- }
- }
- #endregion
- #region Run Button -> simulation handling
- /// <summary> Starts the simulation.</summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
- private async void RunBtn_Click(object sender, EventArgs e) {
- //bad input handling
- if(CustBox.Text == "" || HoursBox.Text == "") {
- MessageBox.Show("Error: Empty field.", "Empty Field Error");
- return;
- }
- else if (RegBox.Text == "(Max 15)") {
- MessageBox.Show("Error: Too Many Registers.", "Argument Exception Error");
- return;
- }
- else if (CheckBox.Text == "(Min 120)") {
- MessageBox.Show("Error: Average Checkout Time too short.", "Argument Exception Error");
- return;
- }
- else if(int.Parse(CustBox.Text) < 0 || int.Parse(HoursBox.Text) < 0 || int.Parse(RegBox.Text) < 0) {
- MessageBox.Show("Error: Negative Value entered.", "Negative Value Error");
- return;
- }
- //disable all registers and clear them (in case this is not the first run)
- Register1.Visible = false;
- Register2.Visible = false;
- Register3.Visible = false;
- Register4.Visible = false;
- Register5.Visible = false;
- Register6.Visible = false;
- Register7.Visible = false;
- Register8.Visible = false;
- Register9.Visible = false;
- Register10.Visible = false;
- Register11.Visible = false;
- Register12.Visible = false;
- Register13.Visible = false;
- Register14.Visible = false;
- Register15.Visible = false;
- Register1.Items.Clear();
- Register2.Items.Clear();
- Register3.Items.Clear();
- Register4.Items.Clear();
- Register5.Items.Clear();
- Register6.Items.Clear();
- Register7.Items.Clear();
- Register8.Items.Clear();
- Register9.Items.Clear();
- Register10.Items.Clear();
- Register11.Items.Clear();
- Register12.Items.Clear();
- Register13.Items.Clear();
- Register14.Items.Clear();
- Register15.Items.Clear();
- Store = new Supermarket(int.Parse(CustBox.Text), int.Parse(HoursBox.Text), int.Parse(RegBox.Text), int.Parse(CheckBox.Text));
- //enable registers
- switch (Store.Registers) {
- case 15:
- Register15.Visible = true;
- goto case 14;
- case 14:
- Register14.Visible = true;
- goto case 13;
- case 13:
- Register13.Visible = true;
- goto case 12;
- case 12:
- Register12.Visible = true;
- goto case 11;
- case 11:
- Register11.Visible = true;
- goto case 10;
- case 10:
- Register10.Visible = true;
- goto case 9;
- case 9:
- Register9.Visible = true;
- goto case 8;
- case 8:
- Register8.Visible = true;
- goto case 7;
- case 7:
- Register7.Visible = true;
- goto case 6;
- case 6:
- Register6.Visible = true;
- goto case 5;
- case 5:
- Register5.Visible = true;
- goto case 4;
- case 4:
- Register4.Visible = true;
- goto case 3;
- case 3:
- Register3.Visible = true;
- goto case 2;
- case 2:
- Register2.Visible = true;
- goto case 1;
- case 1:
- Register1.Visible = true;
- break;
- }
- //add Queues to the list of registers for each register enabled.
- RegisterQueues = new List<Queue<Customer>>();
- for(int i = 0; i < Store.Registers; i++) {
- RegisterQueues.Add(new Queue<Customer>());
- }
- //dequeue the events one by one and display them to the GUI while keeping track of important values
- int Longest = 0;
- int Arrived = 0;
- int Departed = 0;
- List<int> serveTimes = new List<int>();
- int Average = 0;
- int Minimum = 0;
- int Maximum = 0;
- for(int i = Store.Events.Count; i > 0; i--) {
- Customer temp = Store.Customers[Store.Events.Peek().ID - 1]; //gets the customer related to the event from the List
- if (!Store.Events.Peek().Leave) { //if this is an enter event
- //we need to find the smallest line.
- List<int> regSizes = new List<int>();
- switch (Store.Registers) {
- case 15:
- regSizes.Insert(0, Register15.Items.Count);
- goto case 14;
- case 14:
- regSizes.Insert(0, Register14.Items.Count);
- goto case 13;
- case 13:
- regSizes.Insert(0, Register13.Items.Count);
- goto case 12;
- case 12:
- regSizes.Insert(0, Register12.Items.Count);
- goto case 11;
- case 11:
- regSizes.Insert(0, Register11.Items.Count);
- goto case 10;
- case 10:
- regSizes.Insert(0, Register10.Items.Count);
- goto case 9;
- case 9:
- regSizes.Insert(0, Register9.Items.Count);
- goto case 8;
- case 8:
- regSizes.Insert(0, Register8.Items.Count);
- goto case 7;
- case 7:
- regSizes.Insert(0, Register7.Items.Count);
- goto case 6;
- case 6:
- regSizes.Insert(0, Register6.Items.Count);
- goto case 5;
- case 5:
- regSizes.Insert(0, Register5.Items.Count);
- goto case 4;
- case 4:
- regSizes.Insert(0, Register4.Items.Count);
- goto case 3;
- case 3:
- regSizes.Insert(0, Register3.Items.Count);
- goto case 2;
- case 2:
- regSizes.Insert(0, Register2.Items.Count);
- goto case 1;
- case 1:
- regSizes.Insert(0, Register1.Items.Count);
- break;
- }
- int smallestLine = Min(regSizes, regSizes.Count); //the Register Index with the smallest line
- //now we need to enter the customer into the smallest line
- RegisterQueues[smallestLine].Enqueue(temp);
- regSizes[smallestLine]++; //increment the size of the line we just added to
- //find the longest line at the moment (this is one of the data points we are tracking
- int currentLQueue = regSizes[Max(regSizes, regSizes.Count)];
- if(currentLQueue > Longest) { //only change the tracked data point if a longer queue than already tracked is found
- Longest = currentLQueue;
- LQueue.Text = Longest.ToString();
- }
- //and now we need to add the customer to the GUI element representing this
- switch (smallestLine + 1) {
- case 15:
- Register15.Items.Add(temp.ID);
- break;
- case 14:
- Register14.Items.Add(temp.ID);
- break;
- case 13:
- Register13.Items.Add(temp.ID);
- break;
- case 12:
- Register12.Items.Add(temp.ID);
- break;
- case 11:
- Register11.Items.Add(temp.ID);
- break;
- case 10:
- Register10.Items.Add(temp.ID);
- break;
- case 9:
- Register9.Items.Add(temp.ID);
- break;
- case 8:
- Register8.Items.Add(temp.ID);
- break;
- case 7:
- Register7.Items.Add(temp.ID);
- break;
- case 6:
- Register6.Items.Add(temp.ID);
- break;
- case 5:
- Register5.Items.Add(temp.ID);
- break;
- case 4:
- Register4.Items.Add(temp.ID);
- break;
- case 3:
- Register3.Items.Add(temp.ID);
- break;
- case 2:
- Register2.Items.Add(temp.ID);
- break;
- case 1:
- Register1.Items.Add(temp.ID);
- break;
- }
- //now, enqueue a leave event for the customer.
- //their service time does not start until the customer in front of them leaves.
- //so, we can only enter a leave event now in this part of the logic if the customer just entered an empty queue
- //if we don't do it here, we will do it after the customer in front of this one's leave event
- if(RegisterQueues[smallestLine].Count == 1) { //if the register queue only contains this customer
- Event Leave = new Event(temp.ID, true, temp.RegArrival + temp.RegDuration);
- Store.Events.Enqueue(Leave);
- i++; //if we add an event we need to increment i so that the loop continues
- }
- //finally, increment CArrived and dequeue the event
- Store.Events.Dequeue();
- Arrived++;
- CArrived.Text = Arrived.ToString();
- }
- else { //if this is a leave event
- //first, we need to find out which line the customer is in.
- bool found = false;
- int count = 0;
- int queueIndex = -1;
- while(!found) {
- if(RegisterQueues[count].Count == 0) {
- found = false;
- }
- else if(RegisterQueues[count].Peek().ID == temp.ID) {
- queueIndex = count;
- found = true;
- }
- count++;
- }
- //second, we need to add the Service Time of this customer to serveTimes
- serveTimes.Add(temp.RegDuration);
- //third, we need to remove this customer from RegisterQueues
- RegisterQueues[queueIndex].Dequeue();
- //next, we need to add the leave event for the next customer in line, if there is one.
- if (RegisterQueues[queueIndex].Count != 0) {
- Customer next = RegisterQueues[queueIndex].Peek();
- //OccurTime calculated by taking the time of this leave event and adding the next customer's RegDuration to it.
- Event Leave = new Event(next.ID, true, Store.Events.Peek().OccurTime + next.RegDuration);
- Store.Events.Enqueue(Leave);
- i++; //if we add an event we need to increment i so that the loop continues
- }
- //now we need to update the UI to reflect these changes
- switch (queueIndex + 1) {
- case 15:
- Register15.Items.RemoveAt(0);
- break;
- case 14:
- Register14.Items.RemoveAt(0);
- break;
- case 13:
- Register13.Items.RemoveAt(0);
- break;
- case 12:
- Register12.Items.RemoveAt(0);
- break;
- case 11:
- Register11.Items.RemoveAt(0);
- break;
- case 10:
- Register10.Items.RemoveAt(0);
- break;
- case 9:
- Register9.Items.RemoveAt(0);
- break;
- case 8:
- Register8.Items.RemoveAt(0);
- break;
- case 7:
- Register7.Items.RemoveAt(0);
- break;
- case 6:
- Register6.Items.RemoveAt(0);
- break;
- case 5:
- Register5.Items.RemoveAt(0);
- break;
- case 4:
- Register4.Items.RemoveAt(0);
- break;
- case 3:
- Register3.Items.RemoveAt(0);
- break;
- case 2:
- Register2.Items.RemoveAt(0);
- break;
- case 1:
- Register1.Items.RemoveAt(0);
- break;
- }
- //update the average/min/max service time values
- int sum = 0;
- foreach (int time in serveTimes) {
- sum += time;
- }
- Average = sum / serveTimes.Count;
- AvgTime.Text = Average.ToString();
- AvgTime.Text += " Seconds";
- Minimum = serveTimes[Min(serveTimes, serveTimes.Count)];
- Maximum = serveTimes[Max(serveTimes, serveTimes.Count)];
- MinTime.Text = Minimum.ToString();
- MinTime.Text += " Seconds";
- MaxTime.Text = Maximum.ToString();
- MaxTime.Text += " Seconds";
- //finally, increment CDeparted and dequeue the event
- Store.Events.Dequeue();
- Departed++;
- CDeparted.Text = Departed.ToString();
- }
- //add a small delay so that the simulation can be seen
- await Task.Delay(25);
- }
- }
- #endregion
- #region simulation handling helper methods
- /// <summary>Determines the minimum of the parameters.</summary>
- /// <param name="list">The list.</param>
- /// <param name="n">The size of the list.</param>
- /// <returns>the index of the minimum in the list.</returns>
- private static int Min(List<int> list, int n) {
- int min = 0;
- for (int i = 0; i < n; i++) {
- if (list[min] > list[i]) {
- min = i;
- }
- }
- return min;
- }
- /// <summary>Determines the maximum of the parameters.</summary>
- /// <param name="list">The list.</param>
- /// <param name="n">The size of the list.</param>
- /// <returns>the index of the maximum in the list.</returns>
- private static int Max(List<int> list, int n) {
- int max = 0;
- for (int i = 0; i < n; i++) {
- if (list[max] < list[i]) {
- max = i;
- }
- }
- return max;
- }
- #endregion
- /// <summary> Exits the Application</summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
- private void ExitBtn_Click(object sender, EventArgs e) {
- Application.Exit();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement