Tables: table #, max seats 1 2 2 4 3 2 4 2 5 2 6 4 7 6 8 10 9 2 10 4 11 4 12 4 1
ID: 3817703 • Letter: T
Question
Tables: table #, max seats
1 2
2 4
3 2
4 2
5 2
6 4
7 6
8 10
9 2
10 4
11 4
12 4
13 4
14 2
15 2
16 2
17 2
18 2
Menu: listing of the full menu: item code, name, price
A1 Bruschetta 5.29
A2 Caprese_Flatbread 6.10
A3 Artichoke-Spinach_Dip 3.99
A4 Lasagna_Fritta 4.99
A5 Mozzarella_Fonduta 5.99
E1 Lasagna_Classico 6.99
E2 Capellini_Pomodoro 7.99
E3 Eggplant_Parmigiana 8.99
E4 Fettuccine_Alfredo 7.49
E5 Tour_of_Italy 14.99
D1 Tiramisu 2.99
D2 Zeppoli 2.49
D3 Dolcini 3.49
S1 Soda 1.99
S2 Bella_Limonata 0.99
S3 Berry_Acqua_Fresca 2.88
Sample activity file (activity.txt):
1 P2 // Party of 2 is assigned to Table 1
2 P4
4 P2
1 O A1 A1 E1 E2 // Party at table 1 orders these items
8 P10
1 S // Food arrives at table 1
3 P2
1 C // T1 gets the check, pays and leaves & table is cleaned too.
5 P2
1 P1 // Party of 1 is assigned to table 1
In addition to processing these commands, when a table is closed, display the check as well. Include table #, # of customers in the party, name and price of each ordered item and the total. No need to worry about tax or tips.
Error checking:
- Do not allow orders from table with no party assigned to it.
- Do not allow assigning new party to a table when another party is already there.
- Do not allow check-out from empty table or a table in which food has not been served.
- Do not allow delivery of food to an empty table!
- Do not assign a party to a table with insufficient # of chairs.
- Reject any request that does not match with sample formats.
* Load config.txt and setup an array of Table objects and the array of MenuItem objects.
*Complete the remaining functionality (reading the commands from activity.txt & processing them).
Tip: (please try to follow this)
Order *order = new Order(...); ...
This assignment mimics the configuration and activities happen at a typical restaurant. Input is provided in 2 files: config.txt and activity txt. Configuration file contains how many tables, table waiter relationship & full menu list. Activity file mimics the actual activities that happen in restaurant. After setting up the necessary objects using the configuration file, you can read the activity file and process them. Do not use vector or any other template in this assignment. We will use the following classes to complete this assignment. Feel free to add more variables if needed. Avoid making drastic changes to existing variables. You need to define the classes and implement all the .cpp files including class implementation and overall application functionality. Table status, of max seats, of guests if a party is seated, order if the party has ordered Menu Item: itemCode, name, price Menu array of MenuItems Order a list of menu items ordered at a tableExplanation / Answer
I have written the program and posting each class file here.
Main.cpp
--------------
#include "List.h"
#include "Menu.h"
#include "MenuItem.h"
#include "Order.h"
#include "Payment.h"
#include "Table.h"
#include "Waiter.h"
#include <fstream>
#include <sstream>
#include <iostream>
#include <iomanip>
using namespace std;
Table *tables;
int numTables;
Waiter **waiters;
int numWaiters;
Menu menu;
void loadConfig(){
ifstream config("config.txt");
string line;
getline(config, line); //skip the "Table: ..."" line
getline(config, line);
//Use a List to create the Table array
List<Table> tableList;
int tableNum, maxSeats;
while(line != ""){
istringstream convert(line);
convert >> tableNum >> maxSeats;
tableList << Table(tableNum, maxSeats);
getline(config, line);
}
tables = tableList.getArray();
numTables = tableList.getLength();
// // Time for the waiter
getline(config, line); // Skip the "Waiters: ..." line
getline(config, line);
// List<Waiter> waiterList;
List<string> nameList;
List<string> tableIdList;
while(line != ""){
istringstream convert(line);
string name, tableIds;
convert >> name >> tableIds;
nameList << name;
tableIdList << tableIds;
getline(config, line);
}
numWaiters = nameList.getLength();
waiters = new Waiter*[numWaiters];
for(int k=0;k<numWaiters;k++){
waiters[k] = new Waiter(nameList[k], tableIdList[k], tables);
}
getline(config, line); // Skip the "Menu: ..." line
getline(config, line);
// Menu menu;
while(line != ""){
string code, name;
double price;
istringstream convert(line);
convert >> code >> name >> price;
menu.addItem(MenuItem(code, name, price));
getline(config, line);
}
}
Table* findTable(int tableId){
for(int k = 0; k < numTables; k++){
if(tables[k].getTableId() == tableId)
return tables+k;
}
return NULL;
}
void destroy(){
delete [] tables;
for(int k=0;k<numWaiters;k++)
delete waiters[k];
delete [] waiters;
}
int main(){
loadConfig();
ifstream activity("activity.txt");
string line;
getline(activity, line);
while(line != ""){
istringstream convert(line);
char trash, action;
int tableId;
convert >> trash >> tableId >> action;
Table* table = findTable(tableId);
switch(action){
case 'P':
int numPeople;
convert >> numPeople;
if(table->getStatus() != IDLE)
{cout << "ERROR: Table " << tableId << " is not available. ";
break;
}
if(table->getWaiter() == NULL)
{cout << "ERROR: Table " << tableId << " does not have a waiter assigned to it. ";
break;
}
table->partySeated(numPeople);
cout << "Seating " << numPeople << " at Table " << tableId << endl;
break;
case 'O':{
string orderStr;
getline(convert, orderStr); // gets the rest of the line
Order *order = new Order(orderStr, &menu);
if(table->getStatus() != SEATED){
cout << "Error: Table" << tableId << " is not seated, so it cannot receive order " << orderStr << endl;
break;}
table->partyOrdered(order);
cout << "Party at Table " << tableId << " ordered " << orderStr << endl;
}
break;
case 'S':
if(table->getStatus() != ORDERED)
{cout << "Error: Table " << tableId << " cannot be served, because it does not have an order." << endl;
break;
}
table->partyServed();
cout << "Party at Table " << tableId << " has been served." << endl;
break;
case 'C':
if(table->getStatus() != SERVED){
cout << "Error: Table " << tableId << " cannot be checkout, because it has not been served yet." << endl;
break;
}
// Get order before checkout because it will be gone
Order *order = table->getOrder();
table->partyCheckout();
cout << "Party at Table " << tableId << " has checked out." << endl;
cout << " CHECKOUT RECEIPT" << endl;
cout << " Table #: " << tableId << endl;
cout << " # of customers in party: " << table->getNumPeople() << endl;
double total = 0.0;
for(int k = 0; k < order->getNumItems(); k++){
string name = order->getItem(k)->getName();
double price = order->getItem(k)->getPrice();
total += price;
cout << " " << name << " $" << fixed << setprecision(2) << price << endl;
}
cout << " Total: $" << fixed << setprecision(2) << total << endl;
delete order; // We won't need this anymore.
break;
}
getline(activity, line);
}
destroy();
return 0;
}
--------------------
Menu.cpp
-------------------
#include "Menu.h"
#include <string>
using namespace std;
Menu::Menu(int items){
menup = new MenuItem[items];
maxItems = items;
numItems = 0;
}
Menu::~Menu(){
delete [] menup;
menup = NULL;
}
void Menu::addItem(MenuItem item){
menup[numItems++] = item;
}
MenuItem* Menu::findItem(const string code){
for(int k = 0; k < numItems; k++){
if(menup[k].getCode() == code)
return menup+k;
}
return NULL;
}
-----------------
MenuItem.cpp
-----------------
#include "MenuItem.h"
#include <string>
using namespace std;
MenuItem::MenuItem(string mcode, string mname, double mprice) : code(mcode), name(mname), price(mprice){
}
// MenuItem& MenuItem::operator=(const MenuItem &other)
// {
// code = other.code;
// name = other.name;
// price = other.price;
// }
string MenuItem::getCode(){
return code;
}
string MenuItem::getName(){
return name;
}
double MenuItem::getPrice(){
return price;
}
-------------
Order.cpp
----------------
#include "List.h"
#include "Order.h"
#include <string>
#include "Tokenizer.h"
using namespace std;
Order::Order(int count){
itemsp = new MenuItem*[count];
maxItems = count;
numItems = 0;
}
Order::~Order(){
delete [] itemsp;
}
int Order::addItem(MenuItem *itemp){
itemsp[numItems++] = itemp;
}
MenuItem* Order::getItem(const int index){
return itemsp[index];
}
int Order::getNumItems(){
return numItems;
}
Order::Order(string orderList, Menu *menu){
Tokenizer tokenizedList(orderList);
List<string> list;
string token = tokenizedList.next();
while(token != ""){
list.add(token);
token = tokenizedList.next();
}
itemsp = new MenuItem*[list.getLength()];
maxItems = numItems = list.getLength();
for(int k = 0; k < numItems; k++){
itemsp[k] = menu->findItem(list.get(k));
}
// // Go through the list once to figure out the size
// Tokenizer *list = new Tokenizer(orderList);
// int count = 0;
// while(list->next() != "")
// {
// count++;
// }
// delete list;
// // Create the right sized list
// itemsp = new MenuItem*[count];
// maxItems = numItems = count;
// // Now go through the orderList again to do stuff
// list = new Tokenizer(orderList);
// string itemCode = list->next();
// while(itemCode != "")
// {
// MenuItem* item = menu->findItem(itemCode);
// }
// delete list;
}
-------------
Payment.cpp
-------------------
#include "Payment.h"
// Payment::Payment()
// {
// }
Payment::Payment(int tblId, int npersons, Order *order, double total, Waiter *waiter) : tableId(tblId), numPeople(npersons), orderp(order), total(total), waiterp(waiter){
}
--------------------------
Table.cpp
---------------------
#include "Table.h"
Table::Table(int tblid, int mseats) : tableId(tblid), maxSeats(mseats), numPeople(0), status(IDLE), waiter(NULL), order(NULL){
}
Table::~Table(){
if(order != NULL)
delete order;
}
// Table::Table(const Table &other) : tableId(other.tableId), maxSeats(other.maxSeats), numPeople(other.numPeople), status(other.status), order(other.order), waiter(other.waiter)
// {
// }
// Table& Table::operator=(const Table &other)
// {
// tableId = other.tableId;
// maxSeats = other.maxSeats;
// status = other.status;
// numPeople = other.numPeople;
// order = other.order;
// waiter = other.waiter;
// return *this;
// }
void Table::assignWaiter(Waiter *person){
waiter = person;
}
void Table::partySeated(int npeople){
int numPeople = npeople;
status = SEATED;}
void Table::partyOrdered(Order *order){
this->order = order;
status = ORDERED;
}
void Table::partyServed(){
status = SERVED;
}
void Table::partyCheckout(){
status = IDLE;
// If table checked out, main function will take care of delete
// But if it never gets checked out, the destructor can compare
// it to NULL to know it wasn't checked out, and order was
// never deleted.
order = NULL;
}
int Table::getTableId(){
return tableId;
}
int Table::getMaxSeats(){
return maxSeats;
}
int Table::getNumPeople(){
return numPeople;
}
TableStatus Table::getStatus(){
return status;
}
Waiter* Table::getWaiter(){
return waiter;
}
Order* Table::getOrder()
{return order;
}
---------------------
Tokenizer.cpp
-------------------------
#include "Tokenizer.h"
// constructor
Tokenizer::Tokenizer() : buffer(""), token(""), delimiter(DEFAULT_DELIMITER){
currPos = buffer.begin();
}
Tokenizer::Tokenizer(const std::string& str, const std::string& delimiter) : buffer(str), token(""), delimiter(delimiter){
currPos = buffer.begin();
}
// destructor
Tokenizer::~Tokenizer(){
}
// reset string buffer, delimiter and the currsor position
void Tokenizer::set(const std::string& str, const std::string& delimiter){
this->buffer = str;
this->delimiter = delimiter;
this->currPos = buffer.begin();
}
void Tokenizer::setString(const std::string& str){
this->buffer = str;
this->currPos = buffer.begin();
}
void Tokenizer::setDelimiter(const std::string& delimiter){
this->delimiter = delimiter;
this->currPos = buffer.begin();
}
// return the next token
// If cannot find a token anymore, return "".
std::string Tokenizer::next(){
if(buffer.size() <= 0) return ""; // skip if buffer is empty
token.clear(); // reset token string
this->skipDelimiter(); // skip leading delimiters
// append each char to token string until it meets delimiter
while(currPos != buffer.end() && !isDelimiter(*currPos)){
token += *currPos;
++currPos;
}
return token;
}
// skip ang leading delimiters
void Tokenizer::skipDelimiter()
{
while(currPos != buffer.end() && isDelimiter(*currPos))
++currPos;
}
// return true if the current character is delimiter
bool Tokenizer::isDelimiter(char c){
return (delimiter.find(c) != std::string::npos);
}
----------------------------
Waiter.cpp
----------------------------
#include "List.h"
#include "Waiter.h"
#include "Tokenizer.h"
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
Table* findTable(string tableCode, Table *table){
istringstream stream(tableCode);
int tableId;
stream >> tableId;
while(table->getTableId() != tableId){
table++;
}
return table;
}
Waiter::Waiter(string mname, string tableList, Table *table) : name(mname), numTables(0), tables(NULL){
if(name == "" && tableList == ""){
return; //the List of waiters will initialize empty waiters when expanding
}
Tokenizer tokenizedList(tableList,",");
List<string> list;
string token = tokenizedList.next();
while(token != ""){
list.add(token);
token = tokenizedList.next();
}
numTables = list.getLength();
tables = new Table*[numTables];
for(int k = 0; k < numTables; k++){
tables[k] = findTable(list.get(k), table);
tables[k]->assignWaiter(this);
}
// // Count how many tables are in the list
// Tokenizer *list = new Tokenizer(tableList);
// numTables = 0;
// while(list->next() != "")
// {
// numTables++;
// }
// delete list;
// // Create the list of tables for the waiter
// tables = new Table*[numTables];
// // Find and add all the tables
// list = new Tokenizer(tableList);
// string tableCode;
// for(int k = 0; k < numTables; k++)
// {
// tableCode = list->next();
// tables[k] = findTable(tableCode, table);
// }
// delete list;
}
Waiter::~Waiter(){
if(tables != NULL)
delete [] tables;
}
string Waiter::getName(){
return name;
}
--------------
activity.txt
--------------
T1 P2
T2 P4
T4 P2
T4 O A2 E3 S2
T1 O A1 A1 E1 E2
T4 S
T8 P10
T2 O S2 S3 A2 A3 A2 E2 E1 E2
T1 S
T3 P2
T1 C
T2 S
T3 O A1 E4 E5 S2
T5 P2
T1 P1
T3 S
T4 C
T2 C
T1 O A4 E5
----------------
config.txt
----------------
Tables: table #, max seats
1 2
2 4
3 2
4 2
5 2
6 4
7 6
8 10
9 2
10 4
11 4
12 4
13 4
14 2
15 2
16 2
17 2
18 2
Waiters: first name followed by table list
John 1,2,5,9,11,15
Maria 3,4,6,7,17,18
Mike 8,10,12,13,14,16
Menu: listing of the full menu: item code, name, price
A1 Bruschetta 5.29
A2 Caprese_Flatbread 6.10
A3 Artichoke-Spinach_Dip 3.99
A4 Lasagna_Fritta 4.99
A5 Mozzarella_Fonduta 5.99
E1 Lasagna_Classico 6.99
E2 Capellini_Pomodoro 7.99
E3 Eggplant_Parmigiana 8.99
E4 Fettuccine_Alfredo 7.49
E5 Tour_of_Italy 14.99
D1 Tiramisu 2.99
D2 Zeppoli 2.49
D3 Dolcini 3.49
S1 Soda 1.99
S2 Bella_Limonata 0.99
S3 Berry_Acqua_Fresca 2.88
-----------------------------
testTokenizer.cpp
-----------------------------
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
#include "Tokenizer.h"
using namespace std;
int main(){
double x, y, z;
while (1) {
string line;
/*
int xx = 5;
if (xx)
// xx is not 0
else
// xx is 0
*/
x = y = z = -1;
cout << "Enter input (3 numbers):";
getline(cin, line);
//
// parse the input line
istringstream input(line);
if (input >> x >> y >> z)
cout << "input is good." << endl;
else
cout << "input read error." << endl;
cout << x << " " << y << " " << z << endl;
// tokenizing example
Tokenizer str(line, " ,");
// str.setDelimiter(" ,");
// Tokenizer str(line, " ,");
string token;
while ((token = str.next()) != "")
cout << token << endl;
// identifying empty lines
Tokenizer str2(line);
str2.setDelimiter(" ");
if (str2.next() == "")
cout << "That was empty line." << endl;}
}
Menu.h
--------------
#ifndef MENU_H
#define MENU_H
#include "MenuItem.h"
class Menu {
private:
int maxItems; // MAX capacity
int numItems; // current # of items in menu
MenuItem *menup;
public:
Menu(int items = 100); //constructor to allocate memory
void addItem(MenuItem item); //add one menu item at a time
MenuItem* findItem(const string code); //lookup operation
~Menu(); //destructor
};
// Usage:
// Menu menu;
// MenuItem *ip = menu.findItem(code);
// IMPLEMENTATION:
// MenuItem* Menu::findItem(string code) CORRECT
// MenuItem Menu::*findItem(string code) WRONG
#endif
MenuItem.h
-----------------
#ifndef MENUITEM_H
#define MENUITEM_H
#include <iostream>
#include <string>
using namespace std;
class MenuItem{
private:
string code; // See sample codes in config.txt
string name; // Full name of the entry
double price; // price of the item
public:
MenuItem(string mcode = "", string mname= "", double mprice = 0);
// MenuItem& operator=(const MenuItem &other);
string getCode();
string getName();
double getPrice();
};
#endif
Order.h
--------------
#ifndef ORDER_H
#define ORDER_H
#include "MenuItem.h"
#include "Menu.h"
class Order{
private:
int maxItems; // # of items in the order
int numItems; // current # of items in the order
MenuItem **itemsp;
public:
Order(int count); //allocates array of pointers to "selected" menu items
int addItem(MenuItem *itemp); // add one item at a time to the order
MenuItem* getItem(const int index);
int getNumItems();
Order(string orderList, Menu *menu); // alternate way to setup the order
~Order();
};
#endif
Payment.h
-------
#ifndef PAYMENT_H
#define PAYMENT_H
#include "Order.h"
#include "Menu.h"
#include "Waiter.h"
class Payment {
private:
int tableId; // table number
int numPeople; // number of people in the party
Order *orderp; // order information
double total; // total bill
Waiter *waiterp; // pointer to waiter
public:
// Payment();
Payment(int tblId, int npersons, Order *order, double total, Waiter *waiter);
};
#endif
Table.h
----------
#ifndef TABLE_H
#define TABLE_H
#include "Order.h"
#include "Waiter.h"
enum TableStatus { IDLE, SEATED, ORDERED, SERVED };
class Waiter; // to take care of circular reference.
class Table {
private:
int tableId; // table number
// This used to be const but i can't use the assignment operator if it's const,
int maxSeats; // table seat capacity
TableStatus status; // current status, you can use assign like
// status = IDLE;
int numPeople; // number of people in current party
Order *order; // current party's order
Waiter *waiter; // pointer to waiter for this table
public:
Table(int tblid =0, int mseats = 0); // initialization, IDLE
~Table();
// Table(const Table &other);
// Table& operator= (const Table &other);
void assignWaiter(Waiter *person); // initially no waiter
void partySeated(int npeople); // process IDLE --> SEATED
void partyOrdered(Order *order); // process SEATED --> ORDERED
void partyServed(void); // process ORDERED --> SERVED
void partyCheckout(void); // process SERVED --> IDLE
int getTableId();
int getMaxSeats();
int getNumPeople();
TableStatus getStatus();
Waiter* getWaiter();
Order* getOrder();
};
#endif
Tokenizer.h
-----------------
#ifndef TOKENIZER_H
#define TOKENIZER_H
#include <string>
// default delimiter string (space, tab, newline, carriage return, form feed)
const std::string DEFAULT_DELIMITER = " ";
class Tokenizer{
public:
// ctor/dtor
Tokenizer();
Tokenizer(const std::string& str, const std::string& delimiter=DEFAULT_DELIMITER);
~Tokenizer();
// set string and delimiter
void set(const std::string& str, const std::string& delimiter=DEFAULT_DELIMITER);
void setString(const std::string& str); // set source string only
void setDelimiter(const std::string& delimiter); // set delimiter string only
std::string next(); // return the next token, return "" if it ends
protected:
private:
void skipDelimiter(); // ignore leading delimiters
bool isDelimiter(char c); // check if the current char is delimiter
std::string buffer; // input string
std::string token; // output string
std::string delimiter; // delimiter string
std::string::const_iterator currPos; // string iterator pointing the current position
};
#endif // TOKENIZER_H
Waiter.h
--------------
#ifndef WAITER_H
#define WAITER_H
#include <string>
#include "Table.h"
class Table; // to take care of circular reference.
class Waiter{
private:
string name; // waiter's name
int numTables; // number of tables waiter is in-charge for
Table **tables; // waiter's table list
public:
~Waiter();
Waiter(string mname = "", string tableList = "", Table *table = NULL);
// waiter's name, his table list as a string, table array pointer
string getName();
};
#endif
List.h
--------------
#include <cmath>
template <class T>
class List{
private:
T *data;
int length;
int capacityExponent; // capacity is measured by 2^capacityExponent
void increaseCapacity(){
int newSize = pow(2,++capacityExponent);
T *newdata = new T[newSize];
for(int k = 0; k < getLength(); k++){
newdata[k] = data[k];}
delete [] data;
data = newdata;}
public:
List(){
length = 0;
capacityExponent = 0;
int size = pow(2,capacityExponent);
data = new T[size];
}
~List(){
delete [] data;
}
int getLength(){
return length;
}
int getCapacity(){
return pow(2,capacityExponent);
}
void add(const T& value){
if(getLength()==getCapacity())
increaseCapacity();
data[length++] = value;
}
T* getArray(){
T *copy = new T[length];
for(int k = 0; k < getLength(); k++) {
copy[k] = data[k];
}
return copy;
}
T** getPointerArray()
{ T **copy = new T*[length];
for(int k = 0; k < getLength(); k++)
{
copy[k] = new T(data[k]);
}
return copy;
}
T get(const int index) {
return data[index];
}
T operator[](const int index) {
return data[index];
}
List<T>& operator<<(const T& value) {
add(value);
return *this;
}
};
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.