|

Restaurant Reservation System

Spread the love

Project Description

Develop a C++ console application for managing table reservations at a small restaurant. The system should handle customer registrations, table assignments, and reservation schedules. Required features:

  • Customer Representation: Model each diner with a Customer class containing:
    • CustomerID (std::string): a unique identifier for each customer.
    • Name (std::string): full name of the customer.
    • Contact (std::string): phone or email address for confirmations.
    • Method display(): outputs customer details.
  • Table Representation: Model each seating with a Table class containing:
    • TableID (int): unique numeric identifier.
    • Capacity (int): maximum number of seats.
    • isReserved (bool): current reservation status.
    • Methods:
      • reserve(): marks the table reserved if it’s free.
      • cancel(): frees a reserved table.
      • display(): prints table ID, capacity, and status.
  • Reservation Management: A ReservationManager class coordinating customers and tables:
    • addCustomer(shared_ptr): register a new customer.
    • removeCustomer(customerID): deregister by ID.
    • addTable(tableID, capacity): add a new table definition.
    • makeReservation(customerID, tableID, datetime): assign a table at a specific time if available.
    • cancelReservation(customerID, tableID): cancel an existing booking.
    • listReservations(): display all active reservations with customer and table details.
    • findAvailableTables(partySize): return list of tables with capacity ≥ partySize and not reserved.
  • Behavioral Requirements:
    • Prevent double-booking: a table may have at most one active reservation per time slot.
    • Validate inputs: customer and table IDs must exist; times must be future-dated.
    • Use std::shared_ptr for customers and std::unique_ptr for tables, stored in STL containers for automatic memory management.

Solution :

Customer Class
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
#include <string>
#include <map>
#include <ctime>

// Customer class
class Customer {
public:
    std::string customerID;
    std::string name;
    std::string contact;

    Customer(const std::string& id,
             const std::string& n,
             const std::string& c)
        : customerID(id), name(n), contact(c) {}

    void display() const {
        std::cout << "Customer " << customerID
                  << ": " << name
                  << " (" << contact << ")\n";
    }
};
Table Class :


// Table class
class Table {
public:
    int tableID;
    int capacity;
    bool isReserved;

    Table(int id, int cap)
        : tableID(id), capacity(cap), isReserved(false) {}

    bool reserve() {
        if (!isReserved) { isReserved = true; return true; }
        return false;
    }

    bool cancel() {
        if (isReserved) { isReserved = false; return true; }
        return false;
    }

    void display() const {
        std::cout << "Table " << tableID
                  << " (" << capacity << " seats)"
                  << " - " << (isReserved ? "Reserved" : "Free") << "\n";
    }
};

ReservationManager Class :
// ReservationManager class
class ReservationManager {
    std::map<std::string, std::shared_ptr<Customer>> customers;
    std::vector<std::unique_ptr<Table>> tables;
    std::vector<std::tuple<std::string, int, std::time_t>> reservations;

public:
    void addCustomer(const std::shared_ptr<Customer>& c) {
        customers[c->customerID] = c;
    }

    void removeCustomer(const std::string& cid) {
        customers.erase(cid);
    }

    void addTable(int id, int cap) {
        tables.push_back(std::make_unique<Table>(id, cap));
    }

    bool makeReservation(const std::string& cid, int tid, std::time_t when) {
        if (customers.find(cid) == customers.end()) return false;
        auto tableIt = std::find_if(tables.begin(), tables.end(),
            [&](const auto& t){ return t->tableID == tid; });
        if (tableIt == tables.end()) return false;
        if ((*tableIt)->isReserved) return false;
        if (when <= std::time(nullptr)) return false;
        (*tableIt)->reserve();
        reservations.emplace_back(cid, tid, when);
        return true;
    }

    bool cancelReservation(const std::string& cid, int tid) {
        auto it = std::find_if(reservations.begin(), reservations.end(),
            [&](const auto& r){ return std::get<0>(r)==cid && std::get<1>(r)==tid; });
        if (it == reservations.end()) return false;
        // free table
        for (auto& tptr : tables) {
            if (tptr->tableID == tid) { tptr->cancel(); break; }
        }
        reservations.erase(it);
        return true;
    }

    void listReservations() const {
        for (auto& r: reservations) {
            auto cid = std::get<0>(r);  int tid = std::get<1>(r);
            std::time_t when = std::get<2>(r);
            std::cout << "Reservation: Customer " << cid
                      << " at Table " << tid
                      << " on " << std::asctime(std::localtime(&when));
        }
    }

    std::vector<Table*> findAvailableTables(int party) {
        std::vector<Table*> result;
        for (auto& tptr : tables) {
            if (!tptr->isReserved && tptr->capacity >= party)
                result.push_back(tptr.get());
        }
        return result;
    }
};

Detailed Explanation of Logic

The ReservationManager uses a std::map of Customer pointers to allow fast lookup and ensure each Customer object is only stored once. Tables are owned by a std::vector<std::unique_ptr<Table>>, giving exclusive ownership and automatic cleanup. Reservations are stored as tuples (customerID, tableID, timestamp) in a std::vector, representing active bookings.

On makeReservation, the manager checks:

  1. That the provided customerID exists in the map.
  2. That the target Table (found via std::find_if) is not already reserved.
  3. That the requested time is in the future (compared against std::time(nullptr)).

If all conditions pass, it calls reserve() on the Table and adds a tuple to reservations.

To cancelReservation, it locates the matching tuple with std::find_if, frees the table by calling cancel(), and erases the tuple.

The method listReservations iterates over each tuple, dereferences the Customer and Table data for display (via asctime for human-readable dates).

Finally, findAvailableTables demonstrates non-owning access: it filters the table list by checking isReserved==false and sufficient capacity, then returns raw pointers (Table*) obtained with get().

This design cleanly separates ownership (smart pointers in containers) from access (raw pointers or tuple data) and enforces business rules via condition checks before state mutations.

If you have any questions , feel free to contact us at [email protected]

Similar Posts