YNO

 avatar
unknown
c_cpp
5 months ago
56 kB
4
Indexable
#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <cmath>
#include <limits>
#include <algorithm>
#include <set>
#include <sstream>
#include <fstream>

 // Required for std::find_if and std::remove

using namespace std;

struct Book {
    int id;
    string title;
    int copies;

    // Define an equality operator to compare books by their ID
    bool operator == (const Book& other) const {
        return id == other.id;
    }
};

struct BorrowedBookDetails {
    int id;
    string dateBorrow;
    string dateReturn;
};

struct Borrower {
    int id;
    string lastName, firstName, middleInitial;
    vector<BorrowedBookDetails> borrowedBooks; // Stores multiple borrowed books
    int overdueFee = 0;
};


vector<Book> fictionBooks;
vector<Book> nonFictionBooks;
vector<Book> scienceBooks;
vector<Book> mysteryBooks;
vector<Book> romanceBooks;
vector<Book> biographyBooks;
vector<Book> historyBooks;
vector<Book> technologyBooks;
vector<Book> childrenBooks;
vector<Book> artBooks;
vector<Borrower> borrowers;
set<int> uniqueBookIDs;
set<int> uniqueBorrowerIDs;

const string BOOKS_FILE = "books.txt";
const string BORROWERS_FILE = "borrowers.txt";

void displayMainMenu();
void displayAddMenu();
void addBook();
void displayMenu();
void displayBooks();
void displaySearchMenu();
void searchBook();
void addBorrower();
void viewBorrowers();
void searchBorrower();
void borrowBook();
void displayBorrowedDetails(const Borrower& borrower);
void returnBook();
void displayTableHeader();
void displayTable(const vector<Book>& books, const string& header);
void displayBorrowerTableHeader();
void displayBorrowerTable(const Borrower& borrower);
int calculateOverdueFee(const string& borrowDate, const string& returnDate);
void saveBooks();
void loadBooks();
void saveBorrowers();
void loadBorrowers();

bool isValidDate(const string& date) {
    if (date.size() != 10 || date[4] != '-' || date[7] != '-') {
        return false;
    }

    int year, month, day;
    if (sscanf(date.c_str(), "%d-%d-%d", &year, &month, &day) != 3) {
        return false;
    }

    if (year < 1900 || year > 2100 || month < 1 || month > 12 || day < 1 || day > 31) {
        return false;
    }

    if ((month == 4 || month == 6 || month == 9 || month == 11) && day > 30) {
        return false;
    }

    if (month == 2) {
        bool isLeap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
        if (day > (isLeap ? 29 : 28)) {
            return false;
        }
    }
    return true;
}

int main() {
    loadBooks();      // Load books at the start
    loadBorrowers();
    displayMainMenu();
    borrowBook();
    return 0;
}

void saveBooks() {
    ofstream outFile(BOOKS_FILE);
    if (outFile.is_open()) {
        for (const auto& book : fictionBooks) {
            outFile << "Fiction," << book.id << "," << book.title << "," << book.copies << endl;
        }
        for (const auto& book : nonFictionBooks) {
            outFile << "NonFiction," << book.id << "," << book.title << "," << book.copies << endl;
        }
        for (const auto& book : scienceBooks) {
            outFile << "Science Fiction & Fantasy," << book.id << "," << book.title << "," << book.copies << endl;
        }
        for (const auto& book : mysteryBooks) {
            outFile << "Mystery & Thriller," << book.id << "," << book.title << "," << book.copies << endl;
        }
        for (const auto& book : romanceBooks) {
            outFile << "Romance," << book.id << "," << book.title << "," << book.copies << endl;
        }
        for (const auto& book : biographyBooks) {
            outFile << "Biography & Autobiography," << book.id << "," << book.title << "," << book.copies << endl;
        }
        for (const auto& book : historyBooks) {
            outFile << "History," << book.id << "," << book.title << "," << book.copies << endl;
        }
        for (const auto& book : technologyBooks) {
            outFile << "Science & Technology," << book.id << "," << book.title << "," << book.copies << endl;
        }
        for (const auto& book : childrenBooks) {
            outFile << "Children's Book," << book.id << "," << book.title << "," << book.copies << endl;
        }
        for (const auto& book : artBooks) {
            outFile << "Art & Design," << book.id << "," << book.title << "," << book.copies << endl;
        }

        outFile.close();
    } else {
        cout << "Error opening books file for writing.\n";
    }
}

void loadBooks() {
    ifstream inFile(BOOKS_FILE);
    if (inFile.is_open()) {
        string line;
        while (getline(inFile, line)) {
            stringstream ss(line);
            string category;
            Book book;
            getline(ss, category, ',');
            ss >> book.id;
            ss.ignore();  // Ignore the comma
            getline(ss, book.title, ',');
            ss >> book.copies;

            // Add book to the appropriate category
            if (category == "Fiction") fictionBooks.push_back(book);
            else if (category == "NonFiction") nonFictionBooks.push_back(book);
            else if (category == "Science Fiction & Fantasy") scienceBooks.push_back(book);
            else if (category == "Mystery & Thriller") mysteryBooks.push_back(book);
            else if (category == "Romance") romanceBooks.push_back(book);
            else if (category == "Biography & Autobiography") biographyBooks.push_back(book);
            else if (category == "History") historyBooks.push_back(book);
            else if (category == "Science & Technology") scienceBooks.push_back(book);
            else if (category == "Children's Book") childrenBooks.push_back(book);
            else if (category == "Art & Design") artBooks.push_back(book);
        }
        inFile.close();
    } else {
        cout << "Error opening books file for reading.\n";
    }
}

void saveBorrowers() {
    ofstream outFile(BORROWERS_FILE);
    if (outFile.is_open()) {
        for (const auto& borrower : borrowers) {
            outFile << borrower.id << "," << borrower.lastName << "," << borrower.firstName << ","
                    << borrower.middleInitial << ",";

            // Save borrowed book details
            for (const auto& book : borrower.borrowedBooks) {
                    int bookID = book.id;

                    auto it = find_if(fictionBooks.begin(), fictionBooks.end(), [bookID](const Book& book) {
                    return book.id == bookID;
                    });

                    if (it == fictionBooks.end()) {
                        auto it = find_if(nonFictionBooks.begin(), nonFictionBooks.end(), [bookID](const Book& book) {
                        return book.id == bookID;
                        });

                        if (it == nonFictionBooks.end()) {
                            auto it = find_if(scienceBooks.begin(), scienceBooks.end(), [bookID](const Book& book) {
                            return book.id == bookID;
                            });
                            }
                    }

                        Book foundBook = *it;
                        outFile << foundBook.title << "," << book.dateBorrow << "," << book.dateReturn << ",";
            }
            outFile << borrower.overdueFee << endl;
        }
        outFile.close();
    } else {
        cout << "Error opening borrowers file for writing.\n";
    }
}

void loadBorrowers() {
    ifstream inFile(BORROWERS_FILE);
    if (inFile.is_open()) {
        string line;
        while (getline(inFile, line)) {
            stringstream ss(line);
            Borrower borrower;
            int borrowedBookid;
            string dateBorrow, dateReturn;

            ss >> borrower.id;
            ss.ignore();  // Ignore the comma
            getline(ss, borrower.lastName, ',');
            getline(ss, borrower.firstName, ',');
            getline(ss, borrower.middleInitial, ',');

            // Read borrowed book details
            string testing;
            while (ss >> borrowedBookid) {
                    ss.ignore();  // Ignore the comma
                    getline(ss, dateBorrow, ',');
                    getline(ss, dateReturn, ',');
                    borrower.borrowedBooks.push_back({borrowedBookid, dateBorrow, dateReturn});
                }

            ss >> borrower.overdueFee;
            borrowers.push_back(borrower);
            uniqueBorrowerIDs.insert(borrower.id); // Ensure unique IDs
        }
        inFile.close();
    } else {
        cout << "Error opening borrowers file for reading.\n";
    }
}

void displayMainMenu() {

    int choice;
    do {
                cout <<"    ________      __  __      ______     __         ______    __     ______              "<<endl;
        cout <<"   /\\   ____\\    /\\ \\_\\ \\    /\\  ___\\   /\\ \\       /\\  ___\\  /\\ \\   /\\  ___\\                             "<<endl;
        cout <<"   \\ \\____   \\   \\ \\  __ \\   \\ \\  __\\   \\ \\ \\____  \\ \\  __\\  \\ \\ \\  \\ \\  __\\                       "<<endl;
        cout <<"    \\/\\_______\\   \\ \\_\\ \\_\\   \\ \\_____\\  \\ \\_____\\  \\ \\_\\     \\ \\_\\  \\ \\_____\\                                "<<endl;
        cout <<"     \\/_______/    \\/_/\\/_/    \\/_____/   \\/_____/   \\/_/      \\/_/   \\/_____/                 "<<endl;
        cout << "\n==== Library Book Borrowing System ====\n";
        cout << "[1] Add Menu\n";
        cout << "[2] Display Menu\n";
        cout << "[3] Search Menu\n";
        cout << "[4] Borrow Book\n";
        cout << "[5] Return Book\n";
        cout << "[6] Exit\n";
        cout << "Enter your choice: ";
        cin >> choice;

        switch (choice) {
            case 1:
                displayAddMenu();
                break;
            case 2:
                displayMenu();
                break;
            case 3:
                displaySearchMenu();
                break;
            case 4:
                borrowBook();
                break;
            case 5:
                returnBook();
                break;
            case 6:
                char confirm;
                cout << "Are you sure you want to exit the system? (Y/N): ";
                cin >> confirm;
                saveBooks();
                saveBorrowers();
                if (confirm == 'Y' || confirm == 'y') {
                    cout << "Exiting system. Goodbye!\n";
                    exit(0);
                } else {
                    choice = 0; // Reset the choice to prevent exiting
                }
                break;
            default: cout << "Invalid choice. Please try again.\n";
        }
    } while (choice != 6);
}

void displayTableHeader() {
    cout << "---------------------------------------------------\n";
    cout << "| ID        | Title                      | Copies  |\n";
    cout << "---------------------------------------------------\n";
}

void displayTable(const vector<Book>& books, const string& header = "") {
    for (const auto& book : books) {
        cout << "| " << setw(10) << book.id << " | "
             << setw(25) << left << book.title.substr(0, 25) << "| "
             << setw(7) << right << book.copies << " |\n";
    }
    cout << "---------------------------------------------------\n";
}

void displayAddMenu() {
    int choice;
    do {
        cout << "\n==== Add Menu ====\n";
        cout << "[1] Add Book\n";
        cout << "[2] Add Borrower\n";
        cout << "[3] Return to Main Menu\n";
        cout << "Enter your choice: ";
        cin >> choice;

        switch (choice) {
            case 1:
                addBook();
                break;
            case 2:
                addBorrower();
                break;
            case 3:
                return;  // Return to the main menu
            default:
                cout << "Invalid choice. Please try again.\n";
        }
    } while (choice != 3);
}


void addBook() {
    int category;

    // Clear the screen at the start
    system("CLS");  // Use "clear" for Unix/Linux systems

    cout << "\nSELECT BOOK CATEGORY:\n";
    cout << "[1] Fiction\n";
    cout << "[2] Non-Fiction\n";
    cout << "[3] Science Fiction & Fantasy\n";
    cout << "[4] Mystery & Thriller\n";
    cout << "[5] Romance\n";
    cout << "[6] Biography & Autobiography\n";
    cout << "[7] History\n";
    cout << "[8] Science & Technology\n";
    cout << "[9] Children's Book\n";
    cout << "[10] Art & Design\n";
    cout << "Enter category: ";
    cin >> category;

    cin.clear();
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    if (category < 1 || category > 10) {
        cout << "Invalid category. Please enter a number between 1 and 10.\n";
        return;
    }

    Book newBook;
    cout << "Enter Book ID: ";
    cin >> newBook.id;

    cin.clear();
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    if (uniqueBookIDs.find(newBook.id) != uniqueBookIDs.end()) {
        cout << "Error: Book ID must be unique. Book not added.\n";
        return;
    }

    cout << "Enter Book Title: ";
    getline(cin, newBook.title);

    cout << "Enter Number of Copies: ";
    string copiesInput;
    getline(cin, copiesInput);
    if (!copiesInput.empty()) {
        newBook.copies = stoi(copiesInput);
    } else {
        cout << "Invalid number of copies. Please enter a valid number.\n";
        return;
    }

    // Add the book to the respective category
    switch (category) {
        case 1: fictionBooks.push_back(newBook); break;
        case 2: nonFictionBooks.push_back(newBook); break;
        case 3: scienceBooks.push_back(newBook); break;
        case 4: mysteryBooks.push_back(newBook); break;
        case 5: romanceBooks.push_back(newBook); break;
        case 6: biographyBooks.push_back(newBook); break;
        case 7: historyBooks.push_back(newBook); break;
        case 8: technologyBooks.push_back(newBook); break;
        case 9: childrenBooks.push_back(newBook); break;
        case 10: artBooks.push_back(newBook); break;
        default:
            cout << "Invalid category. Book not added.\n";
            return;
    }

    uniqueBookIDs.insert(newBook.id);

    // Display the recently added book
    cout << "\nBOOK ADDED SUCCESSFULLY!\n";
    cout << "Recently Added Book Details:\n";

    displayTableHeader();
    displayTable({newBook});

    // Clear input buffer and screen after displaying the book
    cin.clear();
    cout << "\nPress Enter to return to the main menu...";
    cin.get();  // Wait for the user to press Enter
    system("CLS");  // Use "clear" for Unix/Linux systems
    displayMainMenu();
}

void displayCategoryBooks(vector<Book>* books, const string& categoryName) {


    cout << "\nCategory: " << categoryName << "\n";

    if (books->empty()) {
        cout << "No books available in this category.\n";
    } else {
        // Call the displayTable function to display the table
        displayTableHeader();
        displayTable(*books);
    }

    // Clear input buffer
    cin.clear();
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    // Pause before returning
    cout << "\nPress Enter to return to the previous menu...";
    cin.get();
    system("CLS");  // Use "clear" for Unix/Linux systems
}

void displayMenu() {
    int displayChoice;
    do {
        system("CLS");  // Clear the screen
        cout << "\n==== Display Menu ====\n";
        cout << "[1] Display Books\n";
        cout << "[2] View Borrowers\n";
        cout << "[3] Back to Main Menu\n";
        cout << "Enter your choice: ";
        cin >> displayChoice;

        switch (displayChoice) {
            case 1:
                displayBooks();
                break;
            case 2:
                viewBorrowers();
                break;
            case 3:
                return;  // Return to the main menu
            default:
                cout << "Invalid choice. Please try again.\n";
        }
    } while (displayChoice != 3);
}

void displayBooks() {
    system("CLS");  // Clear the screen
    int category;

    cout << "\nSelect Book Category:\n";
    cout << "[1] Fiction\n";
    cout << "[2] Non-Fiction\n";
    cout << "[3] Science Fiction & Fantasy\n";
    cout << "[4] Mystery & Thriller\n";
    cout << "[5] Romance\n";
    cout << "[6] Biography & Autobiography\n";
    cout << "[7] History\n";
    cout << "[8] Science & Technology\n";
    cout << "[9] Children's Book\n";
    cout << "[10] Art & Design\n";
    cout << "[11] Display all books\n";
    cout << "Enter category: ";
    cin >> category;

    if (cin.fail()) {
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cout << "Invalid input. Please enter a valid number.\n";
        return;
    }

    vector<pair<vector<Book>*, string>> categories = {
        {&fictionBooks, "Fiction"},
        {&nonFictionBooks, "Non-Fiction"},
        {&scienceBooks, "Science Fiction & Fantasy"},
        {&mysteryBooks, "Mystery & Thriller"},
        {&romanceBooks, "Romance"},
        {&biographyBooks, "Biography & Autobiography"},
        {&historyBooks, "History"},
        {&technologyBooks, "Science & Technology"},
        {&childrenBooks, "Children's Book"},
        {&artBooks, "Art & Design"},
    };

    if (category >= 1 && category <= 10) {
        displayCategoryBooks(categories[category - 1].first, categories[category - 1].second);
    } else if (category == 11) {
        vector<Book> allBooks;

        for (const auto& cat : categories) {
            allBooks.insert(allBooks.end(), cat.first->begin(), cat.first->end());
        }

        cout << "\nDisplaying all books:\n";
        if (allBooks.empty()) {
            cout << "No books available to display.\n";
        } else {
            displayTableHeader();
            displayTable(allBooks);
        }

        // Pause before returning
        cout << "\nPress Enter to return to the menu...";
        cin.ignore();
        cin.get();
        system("CLS");
    } else {
        cout << "Invalid category.\n";
    }
}


void searchBook() {

    system("CLS");  // Use "clear" for Unix/Linux systems

    int choice;
    int bookID;

    cout << "Enter Book ID: ";
    cin >> bookID;

    // Function to find and manage books
    auto findAndManageBook = [&](vector<Book>& books) -> bool {
        auto it = find_if(books.begin(), books.end(), [bookID](const Book& book) {
            return book.id == bookID;
        });

        if (it != books.end()) {
            cout << "\nBook Found:\n";

            displayTableHeader();

            // Display the found book details
            vector<Book> foundBook = {*it};  // Create a vector with the found book
            displayTable(foundBook);  // Display the book in table format

            cout << "[1] Edit\n";
            cout << "[2] Delete\n";
            cout << "[3] Go Back to Main Menu\n";
            cout << "Enter your choice: ";
            cin >> choice;

            switch (choice) {
                case 1: {
                    // Ask which part of the book the user wants to edit
                    int editChoice;
                    cout << "\nWhat would you like to edit?\n";
                    cout << "[1] Title\n";
                    cout << "[2] Number of Copies\n";
                    cout << "[3] Both Title and Copies\n";
                    cout << "Enter your choice: ";
                    cin >> editChoice;

                    if (editChoice == 1) {
                        cout << "Enter new title: ";
                        cin.ignore(); // Clear input buffer
                        getline(cin, it->title);
                        cout << "Book title updated successfully.\n";
                    }
                    else if (editChoice == 2) {
                        cout << "Enter new number of copies: ";
                        cin >> it->copies;
                        cout << "Number of copies updated successfully.\n";
                    }
                    else if (editChoice == 3) {
                        cout << "Enter new title: ";
                        cin.ignore(); // Clear input buffer
                        getline(cin, it->title);
                        cout << "Enter new number of copies: ";
                        cin >> it->copies;
                        cout << "Book updated successfully.\n";
                    }
                    else {
                        cout << "Invalid choice. Returning to Main Menu.\n";
                    }

                    // Display the updated book details in a tabular format
                    cout << "\nUpdated Book:\n";

                    displayTableHeader();  // Display the table header

                    vector<Book> updatedBook = {*it};  // Create a vector with the updated book

                    displayTable(updatedBook);  // Display the updated book in table format
                    // Pause before returning to the search menu
                    cout << "\nPress Enter to return to the Search Menu...";
                    cin.ignore();
                    cin.get();
                    break;
                }
                case 2:
                    char confirm;
                    cout << "Are you sure you want to delete this book? (y/n): ";
                    cin >> confirm;
                    if (confirm == 'y' || confirm == 'Y') {
                        books.erase(it); // Remove the book from the list
                        cout << "Book deleted successfully.\n";
                    } else {
                        cout << "Book deletion canceled.\n";
                    }
                     // Pause before returning to the search menu
                    cout << "\nPress Enter to return to the Search Menu...";
                    cin.ignore();
                    cin.get();
                    break;
                case 3:
                    cout << "Returning to Search Menu.\n";
                    return true;
                default:
                    cout << "Invalid choice. Returning to Main Menu.\n";
            }
            return true;
        }
        return false;
    };

    // Search in fictionBooks and nonFictionBooks
    if (!findAndManageBook(fictionBooks) && !findAndManageBook(nonFictionBooks) && !findAndManageBook(scienceBooks)  && !findAndManageBook(mysteryBooks ) && !findAndManageBook(romanceBooks) && !findAndManageBook(biographyBooks) && !findAndManageBook(historyBooks) && !findAndManageBook(technologyBooks) && !findAndManageBook(childrenBooks) && !findAndManageBook(artBooks)) {
        cout << "Book not found.\n";

        // Pause before returning to the search menu
        cout << "\nPress Enter to return to the Search Menu...";
        cin.ignore();
        cin.get();
    }
}

void displaySearchMenu() {
    int choice;
    do {
        system("CLS"); // Clear the screen
        cout << "==== Search Menu ====\n";
        cout << "[1] Search Book\n";
        cout << "[2] Search Borrower\n";
        cout << "[3] Return to Main Menu\n";
        cout << "Enter your choice: ";
        cin >> choice;

        switch (choice) {
            case 1:
                searchBook();
                break;
            case 2:
                searchBorrower();
                break;
            case 3:
                cout << "Returning to Main Menu.\n";
                return;
            default:
                cout << "Invalid choice. Please try again.\n";
        }
    } while (choice != 3);
}


void searchBorrower() {
    int borrowerID;
    cout << "Enter Borrower ID to search: ";
    cin >> borrowerID;

    // Find borrower by ID
    auto it = find_if(borrowers.begin(), borrowers.end(), [borrowerID](const Borrower& b) {
        return b.id == borrowerID;
    });

    if (it != borrowers.end()) {
        // Display borrower details
        cout << "\nBorrower Found:\n";
        cout << setw(10) << "ID" << setw(20) << "Name" << endl;
        cout << setw(10) << it->id
             << setw(20) << it->lastName + ", " + it->firstName + " " + it->middleInitial + "." << endl;

        // Provide options
        int choice;
        cout << "\n[1] View Borrowed Books\n";
        cout << "[2] Return to Main Menu\n";
        cout << "Enter your choice: ";
        cin >> choice;

        if (choice == 1) {
            if (it->borrowedBooks.empty()) {
                cout << "No borrowed books.\n";
            } else {
                cout << "\nBorrowed Books:\n";
                cout << setw(20) << "Book Title" << setw(20) << "Borrowed Date" << setw(20) << "Date Returned" << endl;

                for (const auto& book : it->borrowedBooks) {
                    int bookID = book.id;

                    auto it = find_if(fictionBooks.begin(), fictionBooks.end(), [bookID](const Book& book) {
                    return book.id == bookID;
                    });

                    if (it == fictionBooks.end()) {
                        auto it = find_if(nonFictionBooks.begin(), nonFictionBooks.end(), [bookID](const Book& book) {
                        return book.id == bookID;
                        });

                        if (it == nonFictionBooks.end()) {
                            auto it = find_if(scienceBooks.begin(), scienceBooks.end(), [bookID](const Book& book) {
                            return book.id == bookID;
                            });
                            }
                    }

                        Book foundBook = *it;
                    cout << setw(20) << foundBook.title
                         << setw(20) << book.dateBorrow
                         << setw(20) << (book.dateReturn.empty() ? "Not Returned" : book.dateReturn) << endl;
                }
            }

            // Wait for user input to continue
            cout << "\nPress any key to return to the menu...\n";
            cin.ignore();
            cin.get();
        } else if (choice == 2) {
            return; // Go back to main menu
        } else {
            cout << "Invalid choice. Returning to main menu.\n";
        }
    } else {
        cout << "Borrower with ID " << borrowerID << " not found.\n";
    }
}


void addBorrower() {
    Borrower newBorrower;

    cout << "Enter Borrower ID: ";
    cin >> newBorrower.id;

    // Check if the ID is unique
    if (uniqueBorrowerIDs.find(newBorrower.id) != uniqueBorrowerIDs.end()) {
        cout << "Error: Borrower ID must be unique. Borrower not added.\n";
        return;
    }
    cin.ignore(); // Clear the input buffer
    cout << "Enter Last Name: ";
    getline(cin, newBorrower.lastName);
    cout << "Enter First Name: ";
    getline(cin, newBorrower.firstName);
    cout << "Enter Middle Initial: ";
    getline(cin, newBorrower.middleInitial);

    borrowers.push_back(newBorrower);
    uniqueBorrowerIDs.insert(newBorrower.id); // Add the ID to the unique set
    cout << "Borrower added successfully!\n";

    // Display the recently added borrower in table format
    displayBorrowerTableHeader();
    displayBorrowerTable(newBorrower);
}

void displayBorrowerTableHeader() {
    cout << "------------------------------------------------------------------------------------------\n";
    cout << "| ID        | Full Name               | Book       | Borrowed Date | Return Date | Fee   |\n";
    cout << "------------------------------------------------------------------------------------------\n";
}

void displayBorrowerTable(const Borrower& borrower) {
    if (borrower.borrowedBooks.empty()) {
        // Display borrower details with no books borrowed
        cout << "| " << left << setw(10) << borrower.id
             << "| " << setw(25) << borrower.firstName + " " + borrower.middleInitial + " " + borrower.lastName
             << "| " << setw(20) << "No books borrowed"  // Indicating no books borrowed
             << "| " << setw(14) << "N/A"               // No borrow date
             << "| " << setw(12) << "N/A"               // No return date
             << "| " << setw(6) << borrower.overdueFee << " |\n";
    } else {
        for (const auto& bookDetails : borrower.borrowedBooks) {
                int bookID = bookDetails.id;

                    auto it = find_if(fictionBooks.begin(), fictionBooks.end(), [bookID](const Book& book) {
                    return book.id == bookID;
                    });

                    if (it == fictionBooks.end()) {
                        auto it = find_if(nonFictionBooks.begin(), nonFictionBooks.end(), [bookID](const Book& book) {
                        return book.id == bookID;
                        });

                        if (it == nonFictionBooks.end()) {
                            auto it = find_if(scienceBooks.begin(), scienceBooks.end(), [bookID](const Book& book) {
                            return book.id == bookID;
                            });
                            }
                    }

                        Book foundBook = *it;
            cout << "| " << left << setw(10) << borrower.id
                 << "| " << setw(25) << borrower.firstName + " " + borrower.middleInitial + " " + borrower.lastName
                 << "| " << setw(20) << foundBook.title
                 << "| " << setw(14) << bookDetails.dateBorrow
                 << "| " << setw(12) << bookDetails.dateReturn
                 << "| " << setw(6) << borrower.overdueFee << " |\n";
        }
    }
    cout << "------------------------------------------------------------------------------------------\n";
}


void viewBorrowers() {
    system("CLS"); // Clear the screen for a clean display

    cout << "\n==== List of Borrowers ====\n";

    if (borrowers.empty()) {
        cout << "No borrowers found.\n";
    } else {
        // Call displayBorrowerTableHeader to print the table header
        displayBorrowerTableHeader();

        // Print borrower details using displayBorrowerTable for each borrower in the list
        for (const auto& borrower : borrowers) {
            displayBorrowerTable(borrower);
        }
    }

    // Pause to allow the user to see the output
    cout << "\nPress Enter to return to the Display Menu...";
    cin.ignore();
    cin.get(); // Waits for the user to press Enter
}

void borrowFromCategory(Borrower& borrower, int bookID, const string& date) {
    // Check each category
    for (auto& book : fictionBooks) {
        if (book.id == bookID && book.copies > 0) {
            borrower.borrowedBooks.push_back({book.id, date, ""});
            book.copies--;
            cout << "Book borrowed successfully from Fiction category!\n";
            displayBorrowedDetails(borrower);
            return;
        }
    }
    // Repeat the check for other categories (Non-Fiction, Science, etc.)
    for (auto& book : nonFictionBooks) {
        if (book.id == bookID && book.copies > 0) {
            borrower.borrowedBooks.push_back({book.id, date, ""});
            book.copies--;
            cout << "Book borrowed successfully from Non-Fiction category!\n";
            displayBorrowedDetails(borrower);
            return;
        }
    }

    for (auto& book : scienceBooks) {
        if (book.id == bookID && book.copies > 0) {
            borrower.borrowedBooks.push_back({book.id, date, ""});
            book.copies--;
            cout << "Book borrowed successfully from Science Fiction & Fantasy category!\n";
            displayBorrowedDetails(borrower);
            return;
        }
    }
    for (auto& book : mysteryBooks) {
        if (book.id == bookID && book.copies > 0) {
            borrower.borrowedBooks.push_back({book.id, date, ""});
            book.copies--;
            cout << "Book borrowed successfully from  Mystery & Thriller category!  \n";
            displayBorrowedDetails(borrower);
            return;
        }
    }
    for (auto& book : romanceBooks) {
        if (book.id == bookID && book.copies > 0) {
            borrower.borrowedBooks.push_back({book.id, date, ""});
            book.copies--;
            cout << "Book borrowed successfully from Romance category!!\n";
            displayBorrowedDetails(borrower);
            return;
        }
    }
    for (auto& book : biographyBooks) {
        if (book.id == bookID && book.copies > 0) {
            borrower.borrowedBooks.push_back({book.id, date, ""});
            book.copies--;
            cout << "Book borrowed successfully from Biography category!\n";
            displayBorrowedDetails(borrower);
            return;
        }
    }
    for (auto& book : historyBooks) {
        if (book.id == bookID && book.copies > 0) {
            borrower.borrowedBooks.push_back({book.id, date, ""});
            book.copies--;
            cout << "Book borrowed successfully from History category!\n";
            displayBorrowedDetails(borrower);
            return;
        }
    }
    for (auto& book : technologyBooks) {
        if (book.id == bookID && book.copies > 0) {
            borrower.borrowedBooks.push_back({book.id, date, ""});
            book.copies--;
            cout << "Book borrowed successfully from Science & Technology category!\n";
            displayBorrowedDetails(borrower);
            return;
        }
    }
    for (auto& book : childrenBooks) {
        if (book.id == bookID && book.copies > 0) {
            borrower.borrowedBooks.push_back({book.id, date, ""});
            book.copies--;
            cout << "Book borrowed successfully from Children's category!\n";
            displayBorrowedDetails(borrower);
            return;
        }
    }
    for (auto& book : artBooks) {
        if (book.id == bookID && book.copies > 0) {
            borrower.borrowedBooks.push_back({book.id, date, ""});
            book.copies--;
            cout << "Book borrowed successfully from Art & Design!\n";
            displayBorrowedDetails(borrower);
            return;
        }
    }
}

void borrowBook() {
    int borrowerID, bookID;
    string date;
    cout << "Enter Borrower ID: ";
    cin >> borrowerID;

    // Check if the Borrower ID is valid
    bool borrowerFound = false;
    for (auto& borrower : borrowers) {
        if (borrower.id == borrowerID) {
            borrowerFound = true;
            break;
        }
    }

    if (!borrowerFound) {
        cout << "Error: Borrower ID not found. Please enter a valid Borrower ID.\n";
        return;  // Exit the function if Borrower ID is invalid
    }

    cout << "Enter Book ID: ";
    cin >> bookID;

    // Check if the Book ID is valid and available
    bool bookFound = false;
    for (auto& book : fictionBooks) {
        if (book.id == bookID && book.copies > 0) {
            bookFound = true;
            break;
        }
    }
    if (!bookFound) {
        for (auto& book : nonFictionBooks) {
            if (book.id == bookID && book.copies > 0) {
                bookFound = true;
                break;
            }
        }

        for (auto& book : scienceBooks) {
            if (book.id == bookID && book.copies > 0) {
                bookFound = true;
                break;
            }
        }

        for (auto& book : mysteryBooks) {
            if (book.id == bookID && book.copies > 0) {
                bookFound = true;
                break;
            }
        }

        for (auto& book : romanceBooks) {
            if (book.id == bookID && book.copies > 0) {
                bookFound = true;
                break;
            }
        }

        for (auto& book : biographyBooks) {
            if (book.id == bookID && book.copies > 0) {
                bookFound = true;
                break;
            }
        }

        for (auto& book : historyBooks) {
            if (book.id == bookID && book.copies > 0) {
                bookFound = true;
                break;
            }
        }

        for (auto& book : technologyBooks) {
            if (book.id == bookID && book.copies > 0) {
                bookFound = true;
                break;
            }
        }

        for (auto& book : childrenBooks) {
            if (book.id == bookID && book.copies > 0) {
                bookFound = true;
                break;
            }
        }

        for (auto& book : artBooks) {
            if (book.id == bookID && book.copies > 0) {
                bookFound = true;
                break;
            }
        }
    }

    cin.ignore();
    cout << "Enter Date of Borrow (YYYY-MM-DD): ";
    getline(cin, date);

    if (!isValidDate(date)) {
        cout << "Invalid date format. Please enter a valid date (YYYY-MM-DD).\n";
        return;
    }

    for (auto& borrower : borrowers) {
        if (borrower.id == borrowerID) {
            // Check Fiction books
            for (auto& book : fictionBooks) {
                if (book.id == bookID && book.copies > 0) {
                    borrower.borrowedBooks.push_back({book.id, date, ""});
                    book.copies--;
                    cout << "Book borrowed successfully from Fiction category!\n";
                    displayBorrowedDetails(borrower);
                    return;
                }
            }

            // Repeat for other categories
            for (auto& book : nonFictionBooks) {
                if (book.id == bookID && book.copies > 0) {
                    borrower.borrowedBooks.push_back({book.id, date, ""});
                    book.copies--;
                    cout << "Book borrowed successfully from Non-Fiction category!\n";
                    displayBorrowedDetails(borrower);
                    return;
                }
            }
            for (auto& book : scienceBooks) {
                if (book.id == bookID && book.copies > 0) {
                    borrower.borrowedBooks.push_back({book.id, date, ""});
                    book.copies--;
                    cout << "Book borrowed successfully from Science category!\n";
                    displayBorrowedDetails(borrower);
                    return;
                }
            }
            for (auto& book : mysteryBooks) {
                if (book.id == bookID && book.copies > 0) {
                    borrower.borrowedBooks.push_back({book.id, date, ""});
                    book.copies--;
                    cout << "Book borrowed successfully from Mystery category!\n";
                    displayBorrowedDetails(borrower);
                    return;
                }
            }
            for (auto& book : romanceBooks) {
                if (book.id == bookID && book.copies > 0) {
                    borrower.borrowedBooks.push_back({book.id, date, ""});
                    book.copies--;
                    cout << "Book borrowed successfully from Romance category!\n";
                    displayBorrowedDetails(borrower);
                    return;
                }
            }

            for (auto& book : biographyBooks) {
                if (book.id == bookID && book.copies > 0) {
                    borrower.borrowedBooks.push_back({book.id, date, ""});
                    book.copies--;
                    cout << "Book borrowed successfully from Biography category!\n";
                    displayBorrowedDetails(borrower);
                    return;
                }
            }
            for (auto& book : historyBooks) {
                if (book.id == bookID && book.copies > 0) {
                    borrower.borrowedBooks.push_back({book.id, date, ""});
                    book.copies--;
                    cout << "Book borrowed successfully from History category!\n";
                    displayBorrowedDetails(borrower);
                    return;
                }
            }
            for (auto& book : technologyBooks) {
                if (book.id == bookID && book.copies > 0) {
                    borrower.borrowedBooks.push_back({book.id, date, ""});
                    book.copies--;
                    cout << "Book borrowed successfully from Technology category!\n";
                    displayBorrowedDetails(borrower);
                    return;
                }
            }
            for (auto& book : childrenBooks) {
                if (book.id == bookID && book.copies > 0) {
                    borrower.borrowedBooks.push_back({book.id, date, ""});
                    book.copies--;
                    cout << "Book borrowed successfully from Children category!\n";
                    displayBorrowedDetails(borrower);
                    return;
                }
            }
            for (auto& book : artBooks) {
                if (book.id == bookID && book.copies > 0) {
                    borrower.borrowedBooks.push_back({book.id, date, ""});
                    book.copies--;
                    cout << "Book borrowed successfully from Art category!\n";
                    displayBorrowedDetails(borrower);
                    return;
                }
            }

            cout << "Book not found or no copies available in any category.\n";
            return;
        }
    }

    cout << "Borrowing failed. Borrower ID not found.\n";
}

// Function definition for displaying borrower details
void displayBorrowedDetails(const Borrower& borrower) {
    cout << "---------------------------------------------------------------\n";
    cout << "| Borrower Name           | Book Title            | Date Borrowed |\n";
    cout << "---------------------------------------------------------------\n";

    if (borrower.borrowedBooks.empty()) {
    cout << "| " << left << setw(58) << "No books borrowed yet." << " |\n";
    cout << "---------------------------------------------------------------\n";
    } else {
    // If there are borrowed books, print them
        for (const auto& borrowedBook : borrower.borrowedBooks) {
                    int bookID = borrowedBook.id;

                    auto it = find_if(fictionBooks.begin(), fictionBooks.end(), [bookID](const Book& book) {
                    return book.id == bookID;
                    });

                    if (it == fictionBooks.end()) {
                        auto it = find_if(nonFictionBooks.begin(), nonFictionBooks.end(), [bookID](const Book& book) {
                        return book.id == bookID;
                        });

                        if (it == nonFictionBooks.end()) {
                            auto it = find_if(scienceBooks.begin(), scienceBooks.end(), [bookID](const Book& book) {
                            return book.id == bookID;
                            });
                            }
                    }

                        Book foundBook = *it;
            cout << "| " << left << setw(20) << borrower.firstName + " " + borrower.middleInitial + " " + borrower.lastName
                 << "| " << setw(20) << foundBook.title
                 << "| " << setw(14) << borrowedBook.dateBorrow << " |\n";
        }
        cout << "---------------------------------------------------------------\n";
    }
}

// Return the book to inventory
void returnBook() {
    int borrowerID, bookID;
    string returnDate;

    // Input borrower and book IDs and the return date
    cout << "Enter Borrower ID: ";
    cin >> borrowerID;

    // Check if the borrower ID is valid
    bool borrowerFound = false;
    for (auto& borrower : borrowers) {
        if (borrower.id == borrowerID) {
            borrowerFound = true;
            break;
        }
    }
    if (!borrowerFound) {
        cout << "Error: Borrower ID is not valid.\n";
        return;
    }

    cout << "Enter Book ID: ";
    cin >> bookID;

    // Check if the book ID is valid in any book category
    bool bookFound = false;
    for (auto& category : {fictionBooks, nonFictionBooks, scienceBooks, mysteryBooks, romanceBooks,
                           biographyBooks, historyBooks, technologyBooks, childrenBooks, artBooks}) {
        for (auto& book : category) {
            if (book.id == bookID) {
                bookFound = true;
                break;
            }
        }
        if (bookFound) {
            break;
        }
    }

    if (!bookFound) {
        cout << "Error: Book ID is not valid or not found in the inventory.\n";
        return;
    }

    cin.ignore();
    cout << "Enter Date of Return (YYYY-MM-DD): ";
    getline(cin, returnDate);

    // Iterate through the list of borrowers
    for (auto& borrower : borrowers) {
        if (borrower.id == borrowerID && !borrower.borrowedBooks.empty()) {  // Check if the borrower exists and has borrowed books
            bool bookFoundInBorrowedBooks = false;

            // Find the book that matches the bookID in the borrower's list of borrowed books
            for (auto& borrowedBook : borrower.borrowedBooks) {
                if (bookFoundInBorrowedBooks) break;
                if (borrowedBook.id == bookID) {

                    int overdueFee = calculateOverdueFee(borrowedBook.dateBorrow, returnDate);  // Calculate the overdue fee
                    borrowedBook.dateReturn = returnDate;  // Set the return date
                    borrower.overdueFee = overdueFee;  // Update the borrower's overdue fee

                   cout<<"[DEBUG] " << overdueFee <<endl;

                    if (overdueFee == 0) {
                        // Case 1: On-time return
                        cout << "Book returned SUCCESSFULLY.\n";

                        displayBorrowerTableHeader();

                        // Display the borrower details using displayBorrowerTable
                        displayBorrowerTable(borrower);
                    } else {
                        int bookID = borrowedBook.id;

                        auto it = find_if(fictionBooks.begin(), fictionBooks.end(), [bookID](const Book& book) {
                        return book.id == bookID;
                        });

                        if (it == fictionBooks.end()) {
                            auto it = find_if(nonFictionBooks.begin(), nonFictionBooks.end(), [bookID](const Book& book) {
                            return book.id == bookID;
                            });

                            if (it == nonFictionBooks.end()) {
                                auto it = find_if(scienceBooks.begin(), scienceBooks.end(), [bookID](const Book& book) {
                                return book.id == bookID;
                                });
                                }
                        }

                            Book foundBook = *it;

                        // Case 2: Late return with fee
                        cout << "Book returned SUCCESSFULLY. But, you need to pay for not following the rules.\n";
                        cout << "\n--- E-Receipt ---\n";
                        cout << "Borrower's Name: " << borrower.firstName + " " + borrower.middleInitial + " " + borrower.lastName << "\n";
                        cout << "Book Title: " << foundBook.title << "\n";
                        cout << "Date Borrowed: " << borrowedBook.dateBorrow << "\n";
                        cout << "Date Returned: " << borrowedBook.dateReturn << "\n";
                        cout << "Overdue Fee: " << overdueFee << " pesos\n";
                        cout << "------------------\n";
                    }
                    }

                    // Return the book to inventory
                    for (auto& book : fictionBooks) {  // Repeat for all categories
                        if (book.id == bookID) {
                            book.copies++;  // Increase the available copies
borrower.borrowedBooks.erase(remove_if(borrower.borrowedBooks.begin(), borrower.borrowedBooks.end(), [bookID](const BorrowedBookDetails& book) {
                                return book.id == bookID;
                            }), borrower.borrowedBooks.end());
                                                        return;
                        }
                    }

                    for (auto& book : nonFictionBooks) {  // Repeat for all categories
                        if (book.id == bookID) {
                            book.copies++;  // Increase the available copies
borrower.borrowedBooks.erase(remove_if(borrower.borrowedBooks.begin(), borrower.borrowedBooks.end(), [bookID](const BorrowedBookDetails& book) {
                                return book.id == bookID;
                            }), borrower.borrowedBooks.end());
                                                        return;
                        }
                    }

                    for (auto& book : scienceBooks) {  // Repeat for all categories
                        if (book.id == bookID) {
                            book.copies++;  // Increase the available copies
borrower.borrowedBooks.erase(remove_if(borrower.borrowedBooks.begin(), borrower.borrowedBooks.end(), [bookID](const BorrowedBookDetails& book) {
                                return book.id == bookID;
                            }), borrower.borrowedBooks.end());
                                                        return;
                        }
                    }

                    for (auto& book : mysteryBooks) {  // Repeat for all categories
                        if (book.id == bookID) {
                            book.copies++;  // Increase the available copies
borrower.borrowedBooks.erase(remove_if(borrower.borrowedBooks.begin(), borrower.borrowedBooks.end(), [bookID](const BorrowedBookDetails& book) {
                                return book.id == bookID;
                            }), borrower.borrowedBooks.end());
                                                        return;
                        }
                    }

                    for (auto& book : romanceBooks) {  // Repeat for all categories
                        if (book.id == bookID) {
                            book.copies++;  // Increase the available copies
borrower.borrowedBooks.erase(remove_if(borrower.borrowedBooks.begin(), borrower.borrowedBooks.end(), [bookID](const BorrowedBookDetails& book) {
                                return book.id == bookID;
                            }), borrower.borrowedBooks.end());
                                                        return;
                        }
                    }

                    for (auto& book : biographyBooks) {  // Repeat for all categories
                        if (book.id == bookID) {
                            book.copies++;  // Increase the available copies
borrower.borrowedBooks.erase(remove_if(borrower.borrowedBooks.begin(), borrower.borrowedBooks.end(), [bookID](const BorrowedBookDetails& book) {
                                return book.id == bookID;
                            }), borrower.borrowedBooks.end());
                                                        return;
                        }
                    }

                    for (auto& book : historyBooks) {  // Repeat for all categories
                        if (book.id == bookID) {
                            book.copies++;  // Increase the available copies
borrower.borrowedBooks.erase(remove_if(borrower.borrowedBooks.begin(), borrower.borrowedBooks.end(), [bookID](const BorrowedBookDetails& book) {
                                return book.id == bookID;
                            }), borrower.borrowedBooks.end());
                                                        return;
                        }
                    }

                    for (auto& book : technologyBooks) {  // Repeat for all categories
                        if (book.id == bookID) {
                            book.copies++;  // Increase the available copies
borrower.borrowedBooks.erase(remove_if(borrower.borrowedBooks.begin(), borrower.borrowedBooks.end(), [bookID](const BorrowedBookDetails& book) {
                                return book.id == bookID;
                            }), borrower.borrowedBooks.end());
                                                        return;
                        }
                    }

                    for (auto& book : childrenBooks) {  // Repeat for all categories
                        if (book.id == bookID) {
                            book.copies++;  // Increase the available copies
borrower.borrowedBooks.erase(remove_if(borrower.borrowedBooks.begin(), borrower.borrowedBooks.end(), [bookID](const BorrowedBookDetails& book) {
                                return book.id == bookID;
                            }), borrower.borrowedBooks.end());
                                                        return;
                        }
                    }

                    for (auto& book : artBooks) {  // Repeat for all categories
                        if (book.id == bookID) {
                            book.copies++;  // Increase the available copies
borrower.borrowedBooks.erase(remove_if(borrower.borrowedBooks.begin(), borrower.borrowedBooks.end(), [bookID](const BorrowedBookDetails& book) {
                                return book.id == bookID;
                            }), borrower.borrowedBooks.end());
                                                        return;
                        }
                    }

                    cout << "Book not found in the library inventory.\n";
                    return;
                }
            }
        }


    // If borrower or book ID not found
    cout << "Borrower ID or Book ID not found, or the borrower did not borrow any books.\n";
}

int daysSinceStartOfYear(int year, int month, int day) {
    static const int daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int totalDays = 0;

    // Add days of months in the same year
    for (int i = 0; i < month - 1; ++i) {
        totalDays += daysInMonth[i];
    }

    // Add the current month's days
    totalDays += day;

    // Handle leap years for February
    if (month > 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))) {
        totalDays += 1; // Leap day
    }

    return totalDays;
}

int daysFromDate(const string& date) {
    int year, month, day;
    sscanf(date.c_str(), "%d-%d-%d", &year, &month, &day);

    // Calculate total days since 1900-01-01
    int totalDays = (year - 1900) * 365 + (year - 1900) / 4 - (year - 1900) / 100 + (year - 1900) / 400;
    totalDays += daysSinceStartOfYear(year, month, day);
    return totalDays;
}

int calculateOverdueFee(const string& borrowDate, const string& returnDate) {
    int borrowDays = daysFromDate(borrowDate);
    int returnDays = daysFromDate(returnDate);
    int daysBorrowed = returnDays - borrowDays;
    int maxDays = 7;
    int overdueDays = max(0, daysBorrowed - maxDays);
    return overdueDays * 5; // Fee of 5 pesos per day
}
Editor is loading...
Leave a Comment