Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Grocery Store Simulation Note: parts of this assignment were inspired by Deitel

ID: 3666181 • Letter: G

Question

Grocery Store Simulation

Note: parts of this assignment were inspired by Deitel and Deitel’s Supermarket Simulation problem. We’ve all had the pleasant experience of standing in line at the grocery store. As I’m standing in line I’m always trying to figure out if I chose the line with the fastest service. In most cases, I fail miserably. Let’s write a program to simulate two lines in a grocery store, which will allow us to better understand how to select the fastest line.

For this assignment you will need to simulate two lines using queues. This will require that you develop enqueue ( ) (insert), dequeue ( ) (delete), and printQueue ( ) operations for a queue. Although you will instantiate two queues, each one of these will consist of the same kind of queue nodes. Define a queue node in the following manner:

typedef struct queueNode

{

     int customerNumber; // Unique identifier; starts at 1; after 24 hours should be reset to 1

     int serviceTime;   // Random time; varies between express and normal lanes; units in minutes

     int totalTime;     // totalTime = serviceTime + sum of serviceTimes of customers in line before this customer; units in minutes

     struct queueNode *pNext;

} QueueNode;

One of your queues will represent the express lane and the other a normal lane. You will randomly generate arrival times and service times of customers into each lane. The express lane has customers arrive every one to five minutes, and customers arrive every three to eight minutes in the normal lane. Service times vary from one to five minutes, and three to eight minutes, for express and normal lane customers, respectively. As customers arrive into each line print out a message indicating in which line each customer arrives, along with the overall corresponding arrival time and customer number. When customers have finished checking out, print out a message indicating which line the customer was in, along the corresponding customer number and totalTime in the line. Allow for the simulation to run for n number of minutes, where n is inputted by the user.

The general program flow is as follows:

Generate a random number between 1 – 5 and 3 – 8 for express and normal lanes, respectively. This represents the arrival time of the first customer into each lane. Set the variable for total time elapsed to 0.

As customers arrive into each line, randomly generate a service time for each. Start processing the customers in the lanes based on service time. Randomly generate the arrival time of the next customer into each line. Elapsed time should be updated by one unit.

As each minute elapses, a new customer may arrive and/or another customer may be done checking out. Display the appropriate messages as described above.

For every 10 minutes, print out the entire queue for each line

Repeat steps 2 through 4 for n minutes of simulation.

Hints: since this is a simulation one minute is really one unit of time. Thus, the incrementing of an integer variable could represent one minute of time elapsing.

Written in C in a three file format

Explanation / Answer

groceryStore.c

#include "GroceryStore.h"

/*************************************************************************
* Removes node from from of queue and frees dynamic memory

*************************************************************************/
int dequeue(Queue *pQ)
{
   int custNum = 0;
   QueueNode *pTemp = NULL;
   GroceryNode *conductor = NULL, *pTempGroc = NULL;

   if(isEmpty(*pQ))
   {
       printf("Line is empty ");
   }
   else
   {
       pTemp = pQ->pHead;
       custNum = pTemp->customerNumber;
       conductor = pTemp->groceryList;
       pQ->pHead = pTemp->pNext;
       if(pQ->pHead == NULL)
       {
           pQ->pTail = NULL;
       }
       while(conductor !=NULL)
       {
           pTempGroc = conductor;
           conductor = conductor->pNext;
           free(pTempGroc);
       }
       free(pTemp);
   }
   return custNum;
}

/*************************************************************************
*
* Description: Adds node to end of queue
*
*************************************************************************/
void enqueue(Queue *pQ, int custNum, Boolean isExpress, int serviceNext)
{
   QueueNode *pMem = NULL;
   pMem = makeNode(pQ->pHead, custNum, isExpress, serviceNext);
   if(pQ->pHead == NULL) // If queue is empty
   {
       pQ->pHead = pMem;
       pQ->pTail = pMem;
   }
   else
   {
       pQ->pTail->pNext = pMem;
       pQ->pTail = pMem;
   }
}

/*************************************************************************
*
* Description: Creates a random service time for customer based on which line they are in
*
*************************************************************************/
int getServiceTime(Boolean isExpress)
{
   int time = 0;
   if(isExpress)
   {
       time = (rand() % 5) + 1;
   }
   else
   {
       time = (rand() % 6) + 3;
   }
   return time;
}

/*************************************************************************
*
* Description: Determines customers total time in line (individual service time plus service time of those ahead of them)
*
*************************************************************************/
int getTotalTime(QueueNode *pHead, int serviceTime, int serviceNext)
{
   int totalTime = 0;
   QueueNode *conductor = pHead, *pPrevious = NULL;
   while(conductor != NULL)
   {
       totalTime += conductor->serviceTime;
       pPrevious = conductor;
       conductor = conductor->pNext;
   }
   if(serviceNext != -1)
   {
       totalTime -= (pPrevious->serviceTime - serviceNext);
   }
   totalTime += serviceTime;
}

/*************************************************************************
*
* Description: Determines if list is empty or not
*
*************************************************************************/
Boolean isEmpty(Queue pQ)
{
   Boolean empty = FALSE;
   if(NULL == pQ.pHead)
   {
       empty = TRUE;
   }
   return empty;
}

/*************************************************************************
*
* Prints the entire queue including customer number, service time, and grocery list
*
*************************************************************************/
void printQueue(QueueNode *pHead)
{
   QueueNode *conductor = pHead;
   while(conductor != NULL)
   {
       printf("Customer Number: %d ", conductor->customerNumber);
       printGroceryList(conductor->groceryList);
       printf("Service Time: %d ", conductor->serviceTime);
       printf("Total Time: %d ", conductor->totalTime);
       conductor = conductor->pNext;
   }
}

/*************************************************************************
*
* Creates a new queue node (Memory dynamically allocated)
*
*************************************************************************/
QueueNode *makeNode(QueueNode *pHead, int custNum, Boolean isExpress, int serviceNext)
{
   QueueNode *pMem = NULL;
   pMem = (QueueNode*)malloc(sizeof(QueueNode));

   if(pMem != NULL)
   {
       pMem->customerNumber = custNum;
       pMem->serviceTime = getServiceTime(isExpress);
       pMem->totalTime = getTotalTime(pHead, pMem->serviceTime, serviceNext);
       pMem->groceryList = makeGroceryList(pMem->serviceTime);
       pMem->pNext = NULL;
   }
   return pMem;
}

/*************************************************************************
*
* Initializes the queue (head and tail pointers)
*
*************************************************************************/
Queue *initQueue(void)
{
   Queue *pMem = NULL;
   pMem = (Queue*)malloc(sizeof(Queue*));
   if(pMem != NULL)
   {
       pMem->pHead = NULL;
       pMem->pTail = NULL;
   }
   return pMem;
}

/*************************************************************************
* Gets simulation time from user and validates entry
*
*************************************************************************/
int getSimulationTime(void)
{
   int time = 0;
   while(time < 1)
   {
       printf(" Enter total simulation time in whole minutes: ");
       scanf("%d", &time);
       if(time < 1)
       {
           printf("Invalid entry, time must be a positive number. ");
       }
   }
   return time;
}

/*************************************************************************
*
* Makes a new grocery node (memory dynamically allocated)
*
*************************************************************************/
GroceryNode *makeGroceryNode(void)
{
   GroceryNode *pMem = NULL;
   int itemNum = 0;
   char *tempItem;
   char items[10][20] = {"Cereal", "Milk", "Carrots", "Bread", "Soda", "Steak", "Potatoes", "Jam", "Cookies", "Rice"};

   itemNum = rand()%10;
   pMem = (GroceryNode*)malloc(sizeof(GroceryNode));
   tempItem = (char*)malloc((sizeof(char)*strlen(items[itemNum])+1));
   strcpy(tempItem, items[itemNum]);
   pMem->item = tempItem;
   pMem->pNext = NULL;

   return pMem;
}

/*************************************************************************
*
* Adds a grocery node to front of grocery list
*
*************************************************************************/
void addGroceryToList(GroceryNode **pList)
{
   GroceryNode *pMem = NULL;
   pMem = makeGroceryNode();

   if(*pList == NULL)
   {
       *pList = pMem;
   }
   else
   {
       pMem->pNext = *pList;
       *pList = pMem;
   }
}

/*************************************************************************
Makes entire grocery list for one customer with length based on service time

*************************************************************************/
GroceryNode *makeGroceryList(int serviceTime)
{
   GroceryNode *pList = NULL;
   int i = 0;
   for(i = 0; i < serviceTime; i++)
   {
       addGroceryToList(&pList);
   }
   return pList;
}

/*************************************************************************

* Prints the entire grocery list for one customer
*
*************************************************************************/
void printGroceryList(GroceryNode *pList)
{
   GroceryNode *conductor = pList;
   printf("Grocery List: ");
   while(conductor != NULL)
   {
       printf("%s ", conductor->item);
       conductor = conductor->pNext;
   }
   printf(" ");
}

GroceryStore.h
#ifndef GROCERY_STORE_H
#define GROCERY_STORE_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

typedef struct queueNode
{
   int customerNumber;
   int serviceTime;
   int totalTime;
   struct groceryNode *groceryList;
   struct queueNode *pNext;
}QueueNode;

typedef struct queue
{
   QueueNode *pHead;
   QueueNode *pTail;
}Queue;

typedef enum
{
   FALSE, TRUE
}Boolean;

typedef struct groceryNode
{
   char *item;
   struct groceryNode *pNext;
}GroceryNode;

int dequeue(Queue *pQ);
void enqueue(Queue *pQ, int custNum, Boolean isExpress, int serviceNext);
int getServiceTime(Boolean isExpress);
int getTotalTime(QueueNode *pHead, int serviceTime, int serviceNext);
Boolean isEmpty(Queue pQ);
void printQueue(QueueNode *pHead);
QueueNode *makeNode(QueueNode *pHead, int custNum, Boolean isExpress, int serviceNext);
Queue *initQueue(void);
int getSimulationTime(void);
GroceryNode *makeGroceryNode(void);
void addGroceryToList(GroceryNode **pList);
GroceryNode *makeGroceryList(int serviceTime);
void printGroceryList(GroceryNode *pList);


#endif

main.c


#include "GroceryStore.h"

int main (void)
{
   int timeElapsed = 0, nextCustNum = 1, nextCustExpress = 0, nextCustNormal = 0,
       simulationTime = 0, serviceNextExpress = -1, serviceNextNormal = -1;
  
   Queue *pQExpress = NULL, *pQNormal = NULL;

   srand(time(NULL));
   nextCustExpress = getServiceTime(TRUE);
   nextCustNormal = getServiceTime(FALSE);

   pQExpress = initQueue();
   pQNormal = initQueue();

   simulationTime = getSimulationTime();
   while (timeElapsed <= simulationTime)
   {
       //If 24 hours has gone by reset customer number to 1
       if(timeElapsed % 1440 == 0)
       {
           nextCustNum = 1;
       }
       //Add customer to express line
       if(nextCustExpress == timeElapsed)
       {
           //Add customer to queue
           enqueue(pQExpress, nextCustNum, TRUE, serviceNextExpress);
          
           //Print customer info
           printf("Customer %d has entered express lane. Total Time elapsed: %d minutes ", nextCustNum, timeElapsed);
          
           //Increase customer number
           nextCustNum++;

           //Get time next customer will enter line
           nextCustExpress = getServiceTime(TRUE) + timeElapsed;

           //If line was empty get new time til next service
           if(serviceNextExpress == -1)
           {
               serviceNextExpress = pQExpress->pHead->serviceTime;
           }
       }

       //Add customer to normal line
       if(nextCustNormal == timeElapsed)
       {
           //Add customer to queue
           enqueue(pQNormal, nextCustNum, FALSE, serviceNextNormal);

           //Print customer info
           printf("Customer %d has entered normal lane. Total Time elapsed: %d minutes ", nextCustNum, timeElapsed);
          
           //Increase customer number
           nextCustNum++;

           //Get time next customer will enter line
           nextCustNormal = getServiceTime(FALSE) + timeElapsed;

           //If line was empty get new time til next service
           if(serviceNextNormal == -1)
           {
               serviceNextNormal = pQNormal->pHead->serviceTime;
           }
       }
       //Remove customer from express line
       if(serviceNextExpress == 0)
       {
           //Print customer info
           printf("Customer %d serviced from express lane. Total service time: %d minutes ", pQExpress->pHead->customerNumber, pQExpress->pHead->totalTime);
          
           //Remove customer
           dequeue(pQExpress);

           //Reset next service
           if(isEmpty(*pQExpress))
           {
               serviceNextExpress = -1;
           }
           else
           {
               serviceNextExpress = pQExpress->pHead->serviceTime;
           }
       }

       //Remove customer from normal line
       if(serviceNextNormal == 0)
       {
           //Print customer info
           printf("Customer %d serviced from normal lane. Total service time: %d minutes ", pQNormal->pHead->customerNumber, pQNormal->pHead->totalTime);

           //Remove customer
           dequeue(pQNormal);

           //Reset next service
           if(isEmpty(*pQNormal))
           {
               serviceNextNormal = -1;
           }
           else
           {
               serviceNextNormal = pQNormal->pHead->serviceTime;
           }
       }

       //If elapsed time is divisible by 10 print both queues
       if(timeElapsed != 0 && (timeElapsed % 10) == 0)
       {
           printf(" Express Lane: ");
           printQueue(pQExpress->pHead);
           printf(" Normal Lane: ");
           printQueue(pQNormal->pHead);
       }

       //Increment time & decrement next service time
       timeElapsed++;
       if(serviceNextExpress != -1)
       {
           serviceNextExpress--;
       }
       if(serviceNextNormal != -1)
       {
           serviceNextNormal--;
       }

      
   }

   return 0;
}