diff --git a/EmptyDataCollectionException.cpp b/EmptyDataCollectionException.cpp new file mode 100644 index 0000000..dcb1abe --- /dev/null +++ b/EmptyDataCollectionException.cpp @@ -0,0 +1,19 @@ +/* + * EmptyDataCollectionException.cpp + * + * Class Description: Defines the exception that is thrown when the + * data collection ADT class is empty. + * + * Author: Inspired from our textbook's authors Frank M. Carrano and Tim Henry. + * Copyright (c) 2013 __Pearson Education__. All rights reserved. + */ + + +#include "EmptyDataCollectionException.h" + +EmptyDataCollectionException::EmptyDataCollectionException(const string& message): +logic_error("Empty Data Collection ADT Class Exception: " + message) +{ +} // end constructor + +// End of implementation file. \ No newline at end of file diff --git a/EmptyDataCollectionException.h b/EmptyDataCollectionException.h new file mode 100644 index 0000000..316cf02 --- /dev/null +++ b/EmptyDataCollectionException.h @@ -0,0 +1,23 @@ +/* + * EmptyDataCollectionException.h + * + * Class Description: Defines the exception that is thrown when the + * data collection ADT class is empty. + * + * Author: Inspired from our textbook's authors Frank M. Carrano and Tim Henry. + * Copyright (c) 2013 __Pearson Education__. All rights reserved. + */ + +#pragma once + +#include +#include + +using namespace std; + +class EmptyDataCollectionException : public logic_error +{ +public: + EmptyDataCollectionException(const string& message = ""); + +}; // end EmptyDataCollectionException \ No newline at end of file diff --git a/Event.cpp b/Event.cpp new file mode 100644 index 0000000..609730e --- /dev/null +++ b/Event.cpp @@ -0,0 +1,79 @@ +/* + * Event.cpp + * + * Class Definition: Stores a type (arrival/departure), + * arrival/departure time, and the durature of an event + * + * Created on: July 4th, 2017 + * Author: Jacky Lee & Joey Zhu + */ + + +#pragma once +#include +#include +#include +#include "Event.h" + +using namespace std; + +Event::Event(){ + Type = 'A'; + Time = 0; + Length = 0; +} + +Event::Event(char aType, int aTime){ + Type = aType; + Time = aTime; + Length = 0; +} + +Event::Event(char aType, int aTime, int aLength){ + Type = aType; + Time = aTime; + Length = aLength; +} + +Event::~Event(){ + // not needed +} + +char Event::getType() const{ + return Type; +} + +int Event::getTime() const{ + return Time; +} + +int Event::getLength() const{ + return Length; +} + +void Event::setType(char aType){ + Type = aType; +} + +void Event::setTime(int aTime){ + Time = aTime; +} + +void Event::setLength(int aLength){ + Length = aLength; +} + +bool Event::operator > (const Event &rhs){ + return (Time > rhs.Time); +} + +bool Event::operator == (const Event &rhs){ + return (Time == rhs.Time && Type == rhs.Type); +} + +ostream & operator<<(ostream & os, const Event & rhs){ + os << "Type = " << rhs.getType(); + os << " Time = " << rhs.getTime(); + os << " Length = " << rhs.getLength() << " "; + return os; +} diff --git a/Event.h b/Event.h new file mode 100644 index 0000000..7b3625d --- /dev/null +++ b/Event.h @@ -0,0 +1,41 @@ +/* + * Event.h + * + * Class Definition: Stores a type (arrival/departure), + * arrival/departure time, and the durature of an event + * + * Created on: July 4th, 2017 + * Author: Jacky Lee & Joey Zhu + */ + +#pragma once +#include +#include + +using namespace std; + +class Event{ +private: + char Type; + int Time; + int Length; + +public: + // constructors and destructor + Event(); + Event(char aType, int aTime); + Event(char aType, int aTime, int aLength); + ~Event(); + // getters + char getType() const; + int getTime() const; + int getLength() const; + // setters + void setType(char aType); + void setTime(int aTime); + void setLength(int aLength); + // operator overloads + bool operator > (const Event &rhs); + bool operator == (const Event &rhs); + friend ostream & operator<<(ostream & os, const Event& rhs); +}; diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7d1ccbc --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +all: sApp + +sApp: SimulationApp.cpp Queue.h PriorityQueue.h Node.h Event.o EmptyDataCollectionException.o + g++ -Wall -std=c++11 -o sApp SimulationApp.cpp Event.o EmptyDataCollectionException.o + +Event.o: Event.cpp Event.h + g++ -c Event.cpp + +EmptyDataCollectionException.o: EmptyDataCollectionException.cpp EmptyDataCollectionException.h + g++ -c EmptyDataCollectionException.cpp + +clean: + rm -f sApp *.o diff --git a/Node.h b/Node.h new file mode 100644 index 0000000..d47e8c4 --- /dev/null +++ b/Node.h @@ -0,0 +1,54 @@ +/* + * Node.h + * + * Class Definition: Node of a singly linked list + * in which the data is of "int" data type. + * Designed and implemented as a non-ADT. + * + * Created on: July 4th, 2017 + * Author: Jacky Lee & Joey Zhu + */ + +// #pragma once is shorthand for the 2 #include guards we've seen before: +// #ifndef _NODE and #define _NODE +// and it means: do not include me more than once. +#pragma once +#include + +template +class Node +{ +public: + // Public attributes - Why are the attributes public? + ElementType data; // The data in the node + Node *next; // Pointer to next node + + // Constructors (why no destructor?) + Node(); + Node(ElementType theData); + Node(ElementType theData, Node* theNextNode); + +}; // end Node + +// implementation +template +Node::Node() +{ + next = NULL; +} + +template +Node::Node(ElementType theData) +{ + data = theData; + next = NULL; +} + +template +Node::Node(ElementType theData, Node* theNextNode) +{ + data = theData; + next = theNextNode; +} + +// end Node.cpp diff --git a/PriorityQueue.h b/PriorityQueue.h new file mode 100644 index 0000000..009f5ed --- /dev/null +++ b/PriorityQueue.h @@ -0,0 +1,145 @@ +/* + * PriorityQueue.h + * + * Class Definition: PriorityQueue using array implementation + * + * Created on: July 4th, 2017 + * Author: Jacky Lee & Joey Zhu + */ + +#pragma once +#include +#include +#include "Event.h" +#include "EmptyDataCollectionException.h" + +using namespace std; + +template +class PriorityQueue { + +private: + static const int MAX_CAPACITY = 100; + ElementType array[100]; + int front; + int back; + int capacity; + +public: +// Let's put our constructor(s) and destructor (if any) ***here***. + PriorityQueue(); + + ~PriorityQueue(); + +/******* Public Interface - START - *******/ + + // Description: Returns the number of elements in the Priority Queue. + // (This method eases testing.) + // Time Efficiency: O(1) + int getElementCount() const; + + // Description: Returns "true" is this Priority Queue is empty, otherwise "false". + // Time Efficiency: O(1) + bool isEmpty() const; + + // Description: Inserts newElement in sort order. + // It returns "true" if successful, otherwise "false". + // Precondition: This Priority Queue is sorted. + // Postcondition: Once newElement is inserted, this Priority Queue remains sorted. + // Time Efficiency: O(n) + bool enqueue(const ElementType& newElement); + + // Description: Removes the element with the "highest" priority. + // It returns "true" if successful, otherwise "false". + // Precondition: This Priority Queue is not empty. + // Time Efficiency: O(1) + bool dequeue(); + + // Description: Returns (a copy of) the element with the "highest" priority. + // Precondition: This Priority Queue is not empty. + // Postcondition: This Priority Queue is unchanged. + // Exceptions: Thows EmptyDataCollectionException if this Priority Queue is empty. + // Time Efficiency: O(1) + ElementType peek() const throw(EmptyDataCollectionException); + + +/******* Public Interface - END - *******/ + +// Let's feel free to add other private helper methods to our Priority Queue class. + +}; // end PriorityQueue + +template +PriorityQueue::PriorityQueue(){ + front = -1; + back = -1; + capacity = MAX_CAPACITY; +} + +template +PriorityQueue::~PriorityQueue(){ + // not needed +} + +template +int PriorityQueue::getElementCount() const{ + if (front == -1){ + return 0; + } + if (front == back){ + return 1; + } + return (back-front+1); +} + +template +bool PriorityQueue::isEmpty() const{ + return (front == -1); +} + +template +bool PriorityQueue::enqueue(const ElementType& newElement){ + if ((back+1) % capacity == front){ + return false; + } + if (isEmpty()){ + front = 0; + back = 0; + array[front] = newElement; + } + else{ + int i = front; + while (i <= back && (!(array[i] > newElement))){ + i++; + } + for (int j = back+1; j > i; j--){ + array[j] = array[j-1]; + } + array[i] = newElement; + back = (back+1) % capacity; + } + return true; +} + +template +bool PriorityQueue::dequeue(){ + if (isEmpty()){ + return false; + } + if (front == back){ + front = -1; + back = -1; + } + else{ + front++; + } + return true; +} + +template +ElementType PriorityQueue::peek() const throw(EmptyDataCollectionException){ + if (isEmpty()){ + throw EmptyDataCollectionException("Queue is currently empty."); + } + return array[front]; +} diff --git a/Queue.h b/Queue.h new file mode 100644 index 0000000..8f40d7d --- /dev/null +++ b/Queue.h @@ -0,0 +1,143 @@ +/* + * Queue.h + * + * Class Definition: Queue ADT using linked linked implementation + * + * Created on: July 4th, 2017 + * Author: Jacky Lee & Joey Zhu + */ + +#pragma once +#include +#include "Node.h" +#include "Event.h" +#include "EmptyDataCollectionException.h" + +template +class Queue { + +private: + static const int MAX_CAPACITY = 100; + int elementCount; + int capacity; + Node *head; + Node *tail; + +public: +// Let's put our constructor(s) and destructor (if any) ***here***. + Queue(); + + ~Queue(); + +/******* Public Interface - START - *******/ + + // Description: Returns the number of elements in the Queue. + // (This method eases testing.) + // Time Efficiency: O(1) + int getElementCount() const; + + // Description: Returns "true" is this Queue is empty, otherwise "false". + // Time Efficiency: O(1) + bool isEmpty() const; + + // Description: Adds newElement to the "back" of this Queue + // (not necessarily the "back" of its data structure) and + // returns "true" if successful, otherwise "false". + // Time Efficiency: O(1) + bool enqueue(const ElementType& newElement); + + // Description: Removes the element at the "front" of this Queue + // (not necessarily the "front" of its data structure) and + // returns "true" if successful, otherwise "false". + // Precondition: This Queue is not empty. + // Time Efficiency: O(1) + bool dequeue(); + + // Description: Returns (a copy of) the element located at the "front" of this Queue. + // Precondition: This Queue is not empty. + // Postcondition: This Queue is unchanged. + // Exceptions: Throws EmptyDataCollectionException if this Queue is empty. + // Time Efficiency: O(1) + ElementType peek() const throw(EmptyDataCollectionException); + +/******* Public Interface - END - *******/ + +// Let's feel free to add other private helper methods to our Queue class. + +}; // end Queue + + +template +Queue::Queue(){ + head = NULL; + tail = NULL; + elementCount = 0; + capacity = MAX_CAPACITY; +} + +template +Queue::~Queue(){ + Node *current = head; + while (current != NULL){ + head = head->next; + delete current; + current = head; + } + head = NULL; +} + +template +int Queue::getElementCount() const{ + return elementCount; +} + +template +bool Queue::isEmpty() const{ + return (elementCount == 0); +} + +template +bool Queue::enqueue(const ElementType& newElement){ + if (elementCount == capacity){ + return false; + } + Node *newNode= new Node; + newNode->data = newElement; + newNode->next = NULL; + if (isEmpty()){ + head = newNode; + tail = newNode; + } + else{ + tail->next = newNode; + tail = tail->next; + } + elementCount++; + return true; +} + +template +bool Queue::dequeue(){ + if (isEmpty()){ + return false; + } + Node *current = head; + if (elementCount == 1){ + head = NULL; + tail = NULL; + } + else{ + head = head->next; + } + delete current; + elementCount--; + return true; +} + +template +ElementType Queue::peek() const throw(EmptyDataCollectionException){ + if (isEmpty()){ + throw EmptyDataCollectionException("Queue is currently empty."); + } + return head->data; +} diff --git a/SimulationApp.cpp b/SimulationApp.cpp new file mode 100644 index 0000000..249a756 --- /dev/null +++ b/SimulationApp.cpp @@ -0,0 +1,107 @@ +/* + * SimulationApp.cpp + * + * Created on: July 4th, 2017 + * Author: Jacky Lee & Joey Zhu + */ + +#pragma once +#include +#include +#include "Queue.h" +#include "PriorityQueue.h" +#include "Event.h" + +using namespace std; + +static int processed; +static int currentTime; +static bool tellerAvailable; +Queue bankLine; +PriorityQueue eventPriorityQueue; +static double totalWaitTime = 0.0; + +void processArrival(Event arrivalEvent){ + cout << "Processing an arrival event at time: " << currentTime << endl; + //cout << eventPriorityQueue.peek() << "removed from PriorityQueue" << endl; + eventPriorityQueue.dequeue(); + if (bankLine.isEmpty() && tellerAvailable){ + int transactionTime = arrivalEvent.getLength(); + int departureTime = currentTime + transactionTime; + Event newDepartureEvent = Event('D', departureTime); + //cout << newDepartureEvent << "added to PriorityQueue1" << endl; + eventPriorityQueue.enqueue(newDepartureEvent); + tellerAvailable = false; + } + else{ + //cout << arrivalEvent << "added to bankLine" << endl; + bankLine.enqueue(arrivalEvent); + } +} + +void processDeparture(Event departureEvent){ + cout << "Processing a departure event at time: " << currentTime << endl; + //cout << eventPriorityQueue.peek() << "removed from PriorityQueue" << endl << endl; + eventPriorityQueue.dequeue(); + if (!bankLine.isEmpty()){ + Event customer = bankLine.peek(); + bankLine.dequeue(); + double waitTime = currentTime - customer.getTime(); + totalWaitTime += waitTime; + int transactionTime = customer.getLength(); + int departureTime = currentTime + transactionTime; + Event newDepartureEvent = Event('D', departureTime); + //cout << newDepartureEvent << "added to PriorityQueue2" << endl << endl; + eventPriorityQueue.enqueue(newDepartureEvent); + } + else{ + tellerAvailable = true; + } +} + +void simulate(){ + tellerAvailable = true; + int aTime, aLength; + int result = scanf("%d", &aTime); + scanf("%d", &aLength); + while (result != EOF){ + Event newArrivalEvent = Event('A', aTime, aLength); + //cout << newArrivalEvent << "added to PriorityQueue" << endl << endl; + eventPriorityQueue.enqueue(newArrivalEvent); + result = scanf("%d", &aTime); + scanf("%d", &aLength); + } + int i = 0; + while (!eventPriorityQueue.isEmpty()){ + //eventPriorityQueue.printQueue(); + Event newEvent; + try{ + newEvent = eventPriorityQueue.peek(); + } + catch ( EmptyDataCollectionException&anException ) { + cout << "peeking() unsuccessful because " << anException.what() << endl; + } + currentTime = newEvent.getTime(); + if (newEvent.getType() == 'A'){ + processArrival(newEvent); + processed++; + } + else{ + processDeparture(newEvent); + } + i++; + } +} + + +int main(int argc, char* argv[]){ + currentTime = 0; + cout << "Simulation Begins" << endl; + simulate(); + cout << "Simulation Ends" << endl << endl; + cout << "Final Statistics:" << endl; + cout << " Total number of people processed: " << processed << endl; + float averageWaitTime = totalWaitTime / processed; + cout << " Average amount of time spent waiting: " << averageWaitTime << endl; + return 0; +} diff --git a/simulationShuffled1.in b/simulationShuffled1.in new file mode 100644 index 0000000..851a719 --- /dev/null +++ b/simulationShuffled1.in @@ -0,0 +1,10 @@ +26 5 +1 5 +28 5 +2 5 +20 5 +4 5 +22 5 +88 3 +24 5 +30 5 diff --git a/simulationShuffled2.in b/simulationShuffled2.in new file mode 100644 index 0000000..f18e2c3 --- /dev/null +++ b/simulationShuffled2.in @@ -0,0 +1,4 @@ +30 3 +23 2 +22 4 +20 6 diff --git a/simulationShuffled3.in b/simulationShuffled3.in new file mode 100644 index 0000000..fc2f848 --- /dev/null +++ b/simulationShuffled3.in @@ -0,0 +1,6 @@ +14 5 +5 9 +30 5 +7 5 +34 5 +32 5