FINAL LIBRARY SYSTEM
unknown
c_cpp
a year ago
58 kB
4
Indexable
#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <cmath>
#include <limits>
#include <algorithm>
#include <set>
#include <sstream>
#include <fstream>
// ANSI escape codes for colors
#define RESET "\033[0m"
#define BLACK "\033[30m"
#define RED "\033[31m"
#define GREEN "\033[32m"
#define YELLOW "\033[33m"
#define BLUE "\033[34m"
#define MAGENTA "\033[35m"
#define CYAN "\033[36m"
#define WHITE "\033[37m"
#define BOLD "\033[1m"
#define UNDERLINE "\033[4m"
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;
int overdueFee = 0;
};
struct Borrower {
int id;
string lastName, firstName, middleInitial;
vector<BorrowedBookDetails> borrowedBooks; // Stores multiple borrowed books
};
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();
void displayLogo();
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 << ",";
if (borrower.borrowedBooks.empty()) {
outFile << "~~~";
} else {
// Save borrowed book details
for (const auto& book : borrower.borrowedBooks) {
outFile << book.id << "~" << book.dateBorrow << "~" << book.dateReturn << "~" << book.overdueFee << "~";
}
outFile.seekp(-1, ios_base::cur); // Remove the last '~'
}
outFile << "\n";
}
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;
string borrowedBookID, dateBorrow, dateReturn, strOverdueFee;
ss >> borrower.id;
ss.ignore(); // Ignore the comma
getline(ss, borrower.lastName, ',');
getline(ss, borrower.firstName, ',');
getline(ss, borrower.middleInitial, ',');
// Read borrowed book details
while (getline(ss, borrowedBookID, '~')) {
if (borrowedBookID.length() == 0) break; // No borrowed books
getline(ss, dateBorrow, '~');
getline(ss, dateReturn, '~');
getline(ss, strOverdueFee, '~');
BorrowedBookDetails borrowedBook;
borrowedBook.id = stoi(borrowedBookID);
borrowedBook.dateBorrow = dateBorrow;
borrowedBook.dateReturn = dateReturn;
try {
borrowedBook.overdueFee = stoi(strOverdueFee);
} catch (const invalid_argument& e) {
borrowedBook.overdueFee = 0; // Default to 0 if conversion fails
}
borrower.borrowedBooks.push_back(borrowedBook);
}
borrowers.push_back(borrower);
uniqueBorrowerIDs.insert(borrower.id); // Ensure unique IDs
}
inFile.close();
} else {
cout << "Error opening borrowers file for reading.\n";
}
}
void displayLogo(){
cout << CYAN << BOLD << " ________ __ __ ______ __ ______ __ ______ "<< RESET << endl;
cout << CYAN << BOLD << " /\\ ____\\ /\\ \\_\\ \\ /\\ ___\\ /\\ \\ /\\ ___\\ /\\ \\ /\\ ___\\ "<< RESET <<endl;
cout << CYAN << BOLD << " \\ \\____ \\ \\ \\ __ \\ \\ \\ __\\ \\ \\ \\____ \\ \\ __\\ \\ \\ \\ \\ \\ __\\ "<< RESET <<endl;
cout << CYAN << BOLD << " \\/\\_______\\ \\ \\_\\ \\_\\ \\ \\_____\\ \\ \\_____\\ \\ \\_\\ \\ \\_\\ \\ \\_____\\ "<< RESET <<endl;
cout << CYAN << BOLD << " \\/_______/ \\/_/\\/_/ \\/_____/ \\/_____/ \\/_/ \\/_/ \\/_____/ "<< RESET <<endl;
cout << BLUE << BOLD << "\n\t\t==== Library Book Borrowing System ====\n\n" << RESET;
}
void displayMainMenu() {
int choice;
do {
displayLogo();
cout << BLUE << BOLD << "\n\t====MAIN MENU====\n" << RESET;
cout << "\t[1] Add Menu\n";
cout << "\t[2] Display Menu\n";
cout << "\t[3] Search Menu\n";
cout << "\t[4] Borrow Book\n";
cout << "\t[5] Return Book\n";
cout << "\t[6] Exit\n";
cout << BLUE << BOLD << "\tEnter your choice: " << RESET;
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 << RED << BOLD <<"\tAre you sure you want to exit the system? (Y/N): " RESET;
cin >> confirm;
saveBooks();
saveBorrowers();
if (confirm == 'Y' || confirm == 'y') {
cout << "\tExiting system. Goodbye!\n";
exit(0);
} else {
choice = 0; // Reset the choice to prevent exiting
system("CLS");
}
break;
default:
cout << RED << BOLD <<"\tInvalid choice. Please try again.\n" << RESET;
cout << BLUE << BOLD <<"\n\tPress Enter to return to the main menu..." << RESET;
cin.clear();
cin.ignore();
cin.get();
system("CLS"); // Use "clear" for Unix/Linux systems
break;
}
} while (choice != 6);
}
void displayAddMenu() {
int choice;
do {
system("CLS");
displayLogo();
cout << BLUE << BOLD << "\n\t==== Add Menu ====\n" << RESET;
cout << "\t[1] Add Book\n";
cout << "\t[2] Add Borrower\n";
cout << "\t[3] Return to Main Menu\n";
cout << BLUE << BOLD << "\tEnter your choice: ";
cin >> choice;
switch (choice) {
case 1:
addBook();
break;
case 2:
addBorrower();
break;
case 3:
system("CLS");
return; // Return to the main menu
default:
cout << RED << BOLD << "Invalid choice. Please try again.\n" << RESET;
cout << BLUE << BOLD << "\nPress Enter to return to the Main menu..." << RESET;
cin.clear();
cin.ignore();
cin.get();
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
}
} while (choice != 3);
}
void addBook() {
int category;
// Clear the screen at the start
system("CLS"); // Use "clear" for Unix/Linux systems
displayLogo();
cout << BLUE << BOLD << "\n\tSELECT BOOK CATEGORY:\n" << RESET;
cout << "\t[1] Fiction\n";
cout << "\t[2] Non-Fiction\n";
cout << "\t[3] Science Fiction & Fantasy\n";
cout << "\t[4] Mystery & Thriller\n";
cout << "\t[5] Romance\n";
cout << "\t[6] Biography & Autobiography\n";
cout << "\t[7] History\n";
cout << "\t[8] Science & Technology\n";
cout << "\t[9] Children's Book\n";
cout << "\t[10] Art & Design\n";
cout << BLUE << BOLD << "\tEnter category: " << RESET;
cin >> category;
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (category < 1 || category > 10) {
cout << RED << BOLD <<"\tInvalid category. Please enter a number between 1 and 10.\n" << RESET;
return;
}
system("CLS");
Book newBook;
displayLogo();
cout << "\tEnter Book ID: ";
cin >> newBook.id;
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (uniqueBookIDs.find(newBook.id) != uniqueBookIDs.end()) {
cout << RED << BOLD << "\tError: Book ID must be unique. Book not added.\n" << RESET;
cout << BLUE << BOLD << "\n\tPress Enter to return to the Main menu..." << RESET;
cin.clear();
cin.ignore();
cin.get();
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
}
cout << "\tEnter Book Title: ";
getline(cin, newBook.title);
cout << "\tEnter Number of Copies: ";
string copiesInput;
getline(cin, copiesInput);
if (!copiesInput.empty()) {
newBook.copies = stoi(copiesInput);
} else {
cout << RED << BOLD << "\tInvalid number of copies. Please enter a valid number.\n" << RESET;
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 << GREEN << BOLD <<"\n\tBOOK ADDED SUCCESSFULLY!\n" << RESET;
cout << BLUE << BOLD << "\tRecently Added Book Details:\n" << RESET;
displayTableHeader();
displayTable({newBook});
// Clear input buffer and screen after displaying the book
cin.clear();
cout << BLUE << BOLD << "\n\tPress 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 addBorrower() {
Borrower newBorrower;
system("CLS");
displayLogo();
cout << "\tEnter Borrower ID: ";
cin >> newBorrower.id;
// Check if the ID is unique
if (uniqueBorrowerIDs.find(newBorrower.id) != uniqueBorrowerIDs.end()) {
cout << RED << BOLD << "\tError: Borrower ID must be unique. Borrower not added.\n" << RESET;
return;
}
cin.ignore();
// Clear the input buffer
cout << "\tEnter Last Name: ";
getline(cin, newBorrower.lastName);
cout << "\tEnter First Name: ";
getline(cin, newBorrower.firstName);
cout << "\tEnter Middle Initial: ";
getline(cin, newBorrower.middleInitial);
borrowers.push_back(newBorrower);
uniqueBorrowerIDs.insert(newBorrower.id); // Add the ID to the unique set
cout << GREEN << BOLD << "\tBorrower added successfully!\n" << RESET;
// Display the recently added borrower in table format
displayBorrowerTableHeader();
displayBorrowerTable(newBorrower);
cout << "\n\tPress Enter to return to the Display Menu...";
cin.clear(); // Clear any error flags
cin.get(); // Waits for the user to press Enter
}
void displayMenu() {
int displayChoice;
do {
system("CLS");
displayLogo();
cout << BLUE << BOLD << "\n\t==== Display Menu ====\n" << RESET;
cout << "\t[1] Display Books\n";
cout << "\t[2] View Borrowers\n";
cout << "\t[3] Back to Main Menu\n";
cout << BLUE << BOLD << "\tEnter your choice: " << RESET;
cin >> displayChoice;
switch (displayChoice) {
case 1:
displayBooks();
break;
case 2:
viewBorrowers();
break;
case 3:
system("CLS");
return;
// Return to the main menu
default:
cout << RED << BOLD << "\tInvalid choice. Please try again.\n" << RESET;
cout << BLUE << BOLD << "\n\tPress Enter to return to the Main menu..." << RESET;
cin.clear();
cin.ignore();
cin.get();
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
}
} while (displayChoice != 3);
}
void displayBooks() {
system("CLS"); // Clear the screen
int category;
cout << BLUE << BOLD << "\n\tSelect Book Category:\n" << RESET;
cout << "\t[1] Fiction\n";
cout << "\t[2] Non-Fiction\n";
cout << "\t[3] Science Fiction & Fantasy\n";
cout << "\t[4] Mystery & Thriller\n";
cout << "\t[5] Romance\n";
cout << "\t[6] Biography & Autobiography\n";
cout << "\t[7] History\n";
cout << "\t[8] Science & Technology\n";
cout << "\t[9] Children's Book\n";
cout << "\t[10] Art & Design\n";
cout << "\t[11] Display all books\n";
cout << BLUE << BOLD << "\tEnter category: " << RESET;
cin >> category;
if (cin.fail()) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << RED << BOLD << "\tInvalid input. Please enter a valid number.\n" << RESET;
return;
}
vector<pair<vector<Book>*, string>> categories = {
{&fictionBooks, "\tFiction"},
{&nonFictionBooks, "\tNon-Fiction"},
{&scienceBooks, "\tScience Fiction & Fantasy"},
{&mysteryBooks, "\tMystery & Thriller"},
{&romanceBooks, "\tRomance"},
{&biographyBooks, "\tBiography & Autobiography"},
{&historyBooks, "\tHistory"},
{&technologyBooks, "\tScience & Technology"},
{&childrenBooks, "\tChildren's Book"},
{&artBooks, "\tArt & 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 << BLUE << BOLD << "\n\tDisplaying all books:\n" << RESET;
if (allBooks.empty()) {
cout << YELLOW << BOLD <<"No books available to display.\n" << RESET;
} else {
displayTableHeader();
displayTable(allBooks);
}
// Pause before returning
cout << BLUE << BOLD << "\n\tPress Enter to return to the menu..." << RESET;
cin.ignore();
cin.get();
system("CLS");
} else {
cout << RED << BOLD <<"\tInvalid category.\n" << RESET;
}
}
void viewBorrowers() {
cout << BLUE << BOLD << "\n\t==== List of Borrowers ====\n" << RESET;
if (borrowers.empty()) {
cout << RED << BOLD << "\tNo borrowers found.\n" << RESET;
} else {
// Display table header
displayBorrowerTableHeader();
// Display details for each borrower
for (const auto& borrower : borrowers) {
displayBorrowerTable(borrower);
}
}
// Pause to allow the user to see the output
cout << BLUE << BOLD << "\n\tPress Enter to return to the Display Menu..." << RESET;
cin.clear(); // Clear any error flags
cin.ignore(); // Discard leftover input
cin.get(); // Waits for the user to press Enter
}
void displaySearchMenu() {
int choice;
do {
system("CLS"); // Clear the screen
displayLogo();
cout << BLUE << BOLD << "\t==== Search Menu ====\n" << RESET;
cout << "\t[1] Search Book\n";
cout << "\t[2] Search Borrower\n";
cout << "\t[3] Return to Main Menu\n";
cout << BLUE << BOLD << "\tEnter your choice: " << RESET;
cin >> choice;
switch (choice) {
case 1:
searchBook();
break;
case 2:
searchBorrower();
break;
case 3:
cout << "\tReturning to Main Menu.\n";
system("CLS");
return;
default:
cout << RED << BOLD << "\tInvalid choice. Please try again.\n" << RESET;
cout << BLUE << BOLD << "\n\tPress Enter to return to the Main menu..." << RESET;
cin.clear();
cin.ignore();
cin.get();
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
}
} while (choice != 3);
}
void searchBook() {
system("CLS"); // Use "clear" for Unix/Linux systems
int choice;
int bookID;
displayLogo();
cout << "\tEnter 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;
});
system("CLS");
displayLogo();
if (it != books.end()) {
cout << GREEN << BOLD << "\n\tBook Found:\n" << RESET;
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 << "\t[1] Edit\n";
cout << "\t[2] Delete\n";
cout << "\t[3] Go Back to Main Menu\n";
cout << BLUE << BOLD << "\tEnter your choice: " << RESET;
cin >> choice;
switch (choice) {
case 1: {
// Ask which part of the book the user wants to edit
int editChoice;
cout << BLUE << BOLD << "\n\tWhat would you like to edit?\n" << RESET;
cout << "\t[1] Title\n";
cout << "\t[2] Number of Copies\n";
cout << "\t[3] Both Title and Copies\n";
cout << BLUE << BOLD << "\tEnter your choice: " << RESET;
cin >> editChoice;
if (editChoice == 1) {
cout << BOLD <<"\tEnter new title: " << RESET;
cin.ignore(); // Clear input buffer
getline(cin, it->title);
cout << GREEN << BOLD << "\tBook title updated successfully.\n" << RESET;
system("CLS");
}
else if (editChoice == 2) {
cout << BOLD << "\tEnter new number of copies: " << RESET;
cin >> it->copies;
cout << GREEN << BOLD << "\tNumber of copies updated successfully.\n" << RESET;
system("CLS");
}
else if (editChoice == 3) {
cout << BOLD << "\tEnter new title: " << RESET;
cin.ignore(); // Clear input buffer
getline(cin, it->title);
cout << BOLD << "\tEnter new number of copies: " << RESET;
cin >> it->copies;
cout << GREEN << BOLD <<"\tBook updated successfully.\n" << RESET;
system("CLS");
}
else {
cout << RED << BOLD << "\tInvalid choice. Returning to Main Menu.\n" << RESET;
}
displayLogo();
// Display the updated book details in a tabular format
cout << BLUE << BOLD << "\n\tUpdated Book:\n" << RESET;
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 << BLUE << BOLD << "\n\tPress Enter to return to the Search Menu..." << RESET;
cin.ignore();
cin.get();
break;
}
case 2:
char confirm;
cout << RED << BOLD << "\tAre you sure you want to delete this book? (y/n): " << RESET;
cin >> confirm;
if (confirm == 'y' || confirm == 'Y') {
books.erase(it); // Remove the book from the list
cout << GREEN << BOLD << "\tBook deleted successfully.\n" << RESET;
} else {
cout << RED << BOLD << "\tBook deletion canceled.\n" << RESET;
}
// Pause before returning to the search menu
cout << BLUE << BOLD << "\n\tPress Enter to return to the Search Menu..." << RESET;
cin.ignore();
cin.get();
break;
case 3:
cout << "\tReturning to Search Menu.\n";
return true;
default:
cout << RED << BOLD << "Invalid choice. Please try again.\n" << RESET;
cout << BLUE << BOLD <<"\nPress Enter to return to the main menu..." << RESET;
cin.clear();
cin.ignore();
cin.get();
system("CLS"); // Use "clear" for Unix/Linux systems
}
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 << RED << BOLD << "\tBook not found.\n" << RESET;
// Pause before returning to the search menu
cout << BLUE << BOLD << "\n\tPress Enter to return to the Search Menu..." << RESET;
cin.ignore();
cin.get();
}
}
void searchBorrower() {
int borrowerID;
system("CLS");
displayLogo();
cout << BLUE << BOLD << "\tEnter Borrower ID to search: " << RESET;
cin >> borrowerID;
system("CLS");
// Find borrower by ID
auto it = find_if(borrowers.begin(), borrowers.end(), [borrowerID](const Borrower& b) {
return b.id == borrowerID;
});
if (it != borrowers.end()) {
displayLogo();
cout << GREEN << BOLD << "\n\tBorrower Found:\n" << RESET;
cout << "\t--------------------------------------\n";
cout << "\t| " << setw(10) << "ID" << " | " << setw(20) << "Name" << " |\n";
cout << "\t--------------------------------------\n";
cout << "\t| " << setw(10) << it->id << " | "
<< setw(20) << it->firstName + it->middleInitial + " " + it->lastName << " |\n";
cout << "\t--------------------------------------\n";
// Provide options
int choice;
cout << "\n\t[1] View Borrowed Books\n";
cout << "\t[2] Return to Main Menu\n";
cout << BLUE << BOLD << "\tEnter your choice: " << RESET;
cin >> choice;
if (choice == 1) {
if (it->borrowedBooks.empty()) {
cout << RED << BOLD << "\tNo borrowed books.\n" << RESET;
} else {
system("CLS");
displayLogo();
cout << "\n\tBorrowed Books:\n";
cout << "\t----------------------------------------------------------------------\n";
cout << "\t| " << setw(20) << "Book Title"
<< " \t| " << setw(20) << "Date Borrowed"
<< " \t| " << setw(20) << "Date Returned" << " |\n";
cout << "\t----------------------------------------------------------------------\n";
for (const auto& book : it->borrowedBooks) {
string bookTitle;
for (const auto& category : {fictionBooks, nonFictionBooks, scienceBooks, mysteryBooks, romanceBooks,
biographyBooks, historyBooks, technologyBooks, childrenBooks, artBooks}) {
auto it = find_if(category.begin(), category.end(), [&book](const Book& b) {
return b.id == book.id;
});
if (it != category.end()) {
bookTitle = it->title;
break;
}
}
cout << "\t| " << setw(20) << bookTitle
<< " \t| " << setw(20) << book.dateBorrow
<< " \t| " << setw(20) << (book.dateReturn.empty() ? "Not Returned" : book.dateReturn) << " |\n";
cout << "\t----------------------------------------------------------------------\n";
}
}
// Wait for user input to continue
cout << BLUE << BOLD << "\nPress any key to return to the menu...\n" << RESET;
cin.ignore();
cin.get();
} else if (choice == 2) {
return; // Go back to main menu
} else {
cout << RED << BOLD << "\tInvalid choice. Returning to main menu.\n" << RESET;
}
} else {
cout << RED << BOLD << "\tBorrower with ID " << borrowerID << " not found.\n" << RESET;
}
}
void displayTableHeader() {
cout << "\t----------------------------------------------------\n";
cout << "\t| ID | Title | Copies |\n";
cout << "\t----------------------------------------------------\n";
}
void displayTable(const vector<Book>& books, const string& header = "") {
for (const auto& book : books) {
cout << "\t| " << setw(10) << right << book.id << "| "
<< setw(25) << left << book.title.substr(0, 25) << " | "
<< setw(7) << right << book.copies << " |\n";
}
cout << "\t----------------------------------------------------\n";
}
void displayCategoryBooks(vector<Book>* books, const string& categoryName) {
cout << BLUE << BOLD << "\n\tCategory: " << categoryName << "\n" << RESET;
if (books->empty()) {
cout << YELLOW << BOLD << "\tNo books available in this category.\n" << RESET;
} 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 << BLUE << BOLD << "\n\tPress Enter to return to the previous menu..." << RESET;
cin.get();
system("CLS"); // Use "clear" for Unix/Linux systems
}
void displayBorrowerTableHeader() {
cout << "\t----------------------------------------------------------------------------------------------------\n";
cout << "\t| ID | Full Name | Book | Borrowed Date | Return Date | Fee |\n";
cout << "\t----------------------------------------------------------------------------------------------------\n";
}
void displayBorrowerTable(const Borrower& borrower) {
if (borrower.borrowedBooks.empty()) {
cout << "\t| " << 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) << "N/A" << "|\n";
} else {
for (const auto& bookDetails : borrower.borrowedBooks) {
string bookTitle;
for (const auto& category : {fictionBooks, nonFictionBooks, scienceBooks, mysteryBooks, romanceBooks,
biographyBooks, historyBooks, technologyBooks, childrenBooks, artBooks}) {
auto it = find_if(category.begin(), category.end(), [&bookDetails](const Book& b) {
return b.id == bookDetails.id;
});
if (it != category.end()) {
bookTitle = it->title;
break;
}
}
cout << "| " << left << setw(10) << borrower.id
<< "| " << setw(25) << borrower.firstName + " " + borrower.middleInitial + " " + borrower.lastName
<< "| " << setw(20) << bookTitle
<< "| " << setw(14) << bookDetails.dateBorrow
<< "| " << setw(12) << bookDetails.dateReturn
<< "| " << setw(6) << bookDetails.overdueFee << "|\n";
}
}
cout << "\t----------------------------------------------------------------------------------------------------\n";
}
void borrowBook() {
int borrowerID, bookID;
string date;
system("CLS");
displayLogo(); // Use "clear" for Unix/Linux systems
cout << "\tEnter Borrower ID: ";
cin >> borrowerID;
bool borrowerFound = false;
for (auto& borrower : borrowers) {
if (borrower.id == borrowerID) {
borrowerFound = true;
break;
}
}
if (!borrowerFound) {
cout << RED << BOLD << "\tError: Borrower ID not found. Please enter a valid Borrower ID.\n" << RESET;
return; // Exit the function if Borrower ID is invalid
}
cout << "\tEnter Book ID: ";
cin >> bookID;
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;
}
}
}
if (!bookFound) {
cout << RED << BOLD << "\tError: Book ID not found or no copies available.\n" << RESET;
return; // Exit the function if Book ID is invalid or no copies are available
}
cin.ignore();
cout << "\tEnter Date of Borrow (YYYY-MM-DD): ";
getline(cin, date);
if (!isValidDate(date)) {
cout << RED << BOLD << "\tInvalid date format. Please enter a valid date (YYYY-MM-DD).\n" RESET;
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 << GREEN << BOLD << "\tBook borrowed successfully from Fiction category!\n" << RESET;
displayBorrowedDetails(borrower);
return;
}
}
// Repeat for other categories
for (auto& book : fictionBooks) {
if (book.id == bookID && book.copies > 0) {
borrower.borrowedBooks.push_back({book.id, date, ""});
book.copies--;
cout << GREEN << BOLD << "Book borrowed successfully from Non-Fiction category!\n" << RESET;
displayBorrowedDetails(borrower);
return;
}
}
for (auto& book : nonFictionBooks) {
if (book.id == bookID && book.copies > 0) {
borrower.borrowedBooks.push_back({book.id, date, ""});
book.copies--;
cout << GREEN << BOLD << "Book borrowed successfully from Non-Fiction category!\n" << RESET;
displayBorrowedDetails(borrower);
return;
}
}
for (auto& book : scienceBooks) {
if (book.id == bookID && book.copies > 0) {
borrower.borrowedBooks.push_back({book.id, date, ""});
book.copies--;
cout << GREEN << BOLD << "Book borrowed successfully from Science category!\n" << RESET;
displayBorrowedDetails(borrower);
return;
}
}
for (auto& book : mysteryBooks) {
if (book.id == bookID && book.copies > 0) {
borrower.borrowedBooks.push_back({book.id, date, ""});
book.copies--;
cout << GREEN << BOLD << "Book borrowed successfully from Mystery category!\n" << RESET;
displayBorrowedDetails(borrower);
return;
}
}
for (auto& book : romanceBooks) {
if (book.id == bookID && book.copies > 0) {
borrower.borrowedBooks.push_back({book.id, date, ""});
book.copies--;
cout << GREEN << BOLD << "Book borrowed successfully from Romance category!\n" << RESET;
displayBorrowedDetails(borrower);
return;
}
}
for (auto& book : biographyBooks) {
if (book.id == bookID && book.copies > 0) {
borrower.borrowedBooks.push_back({book.id, date, ""});
book.copies--;
cout << GREEN << BOLD << "Book borrowed successfully from Biography category!\n" << RESET;
displayBorrowedDetails(borrower);
return;
}
}
for (auto& book : historyBooks) {
if (book.id == bookID && book.copies > 0) {
borrower.borrowedBooks.push_back({book.id, date, ""});
book.copies--;
cout << GREEN << BOLD << "Book borrowed successfully from History category!\n" << RESET;
displayBorrowedDetails(borrower);
return;
}
}
for (auto& book : technologyBooks) {
if (book.id == bookID && book.copies > 0) {
borrower.borrowedBooks.push_back({book.id, date, ""});
book.copies--;
cout << GREEN << BOLD << "Book borrowed successfully from Technology category!\n" << RESET;
displayBorrowedDetails(borrower);
return;
}
}
for (auto& book : childrenBooks) {
if (book.id == bookID && book.copies > 0) {
borrower.borrowedBooks.push_back({book.id, date, ""});
book.copies--;
cout << GREEN << BOLD << "Book borrowed successfully from Children category!\n" << RESET;
displayBorrowedDetails(borrower);
return;
}
}
for (auto& book : artBooks) {
if (book.id == bookID && book.copies > 0) {
borrower.borrowedBooks.push_back({book.id, date, ""});
book.copies--;
cout << GREEN << BOLD << "Book borrowed successfully from Art category!\n" << RESET;
displayBorrowedDetails(borrower);
return;
}
}
cout << RED << BOLD << "Book not found or no copies available in any category.\n" << RESET;
return;
}
}
cout << RED << BOLD << "Borrowing failed. Borrower ID not found.\n" << RESET;
}
// Function definition for displaying borrower details
void displayBorrowedDetails(const Borrower& borrower) {
cout << "\t--------------------------------------------------------------\n";
cout << "\t| Borrower Name | Book Title | Date Borrowed |\n";
cout << "\t--------------------------------------------------------------\n";
if (borrower.borrowedBooks.empty()) {
cout << "\t| " << left << setw(58) << "No books borrowed yet." << " |\n";
cout << "\t--------------------------------------------------------------\n";
} else {
// If there are borrowed books, print them
for (const auto& borrowedBook : borrower.borrowedBooks) {
string bookTitle;
for (const auto& category : {fictionBooks, nonFictionBooks, scienceBooks, mysteryBooks, romanceBooks,
biographyBooks, historyBooks, technologyBooks, childrenBooks, artBooks}) {
auto it = find_if(category.begin(), category.end(), [&borrowedBook](const Book& b) {
return b.id == borrowedBook.id;
});
if (it != category.end()) {
bookTitle = it->title;
break;
}
}
cout << "\t| " << left << setw(20) << borrower.firstName + " " + borrower.middleInitial + " " + borrower.lastName
<< "| " << setw(20) << bookTitle
<< "| " << setw(14) << borrowedBook.dateBorrow << " |\n";
}
cout << "\t--------------------------------------------------------------\n";
cin.clear();
cout << BLUE << BOLD << "\n\tPress Enter to return to the main menu..." << RESET;
cin.get(); // Wait for the user to press Enter
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
}
}
void returnBook() {
int borrowerID, bookID;
string returnDate;
system("CLS");
displayLogo();
// Input borrower and book IDs and the return date
cout << "\tEnter 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 << RED << BOLD << "\tError: Borrower ID is not valid.\n" << RESET;
cin.clear();
cout << BLUE << BOLD << "\n\tPress Enter to return to the main menu..." << RESET;
cin.ignore();
cin.get(); // Wait for the user to press Enter
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
}
cout << "\tEnter 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 << RED << BOLD << "\tError: Book ID is not valid or not found in the inventory.\n" << RESET;
cin.clear();
cout << BLUE << BOLD << "\n\tPress Enter to return to the main menu..." << RESET;
cin.ignore();
cin.get(); // Wait for the user to press Enter
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
}
cin.ignore();
cout << "\tEnter 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 && borrowedBook.dateReturn == "") {
int overdueFee = calculateOverdueFee(borrowedBook.dateBorrow, returnDate); // Calculate the overdue fee
borrowedBook.dateReturn = returnDate; // Set the return date
borrowedBook.overdueFee = overdueFee; // Update the borrower's overdue fee
if (overdueFee == 0) {
// Case 1: On-time return
cout << GREEN << BOLD << "\tBook returned SUCCESSFULLY.\n" << RESET;
displayBorrowerTableHeader();
// Display the borrower details using displayBorrowerTable
displayBorrowerTable(borrower);
cin.clear();
cout << BLUE << BOLD << "\n\tPress 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();
} else {
string bookTitle;
for (const auto& category : {fictionBooks, nonFictionBooks, scienceBooks, mysteryBooks, romanceBooks,
biographyBooks, historyBooks, technologyBooks, childrenBooks, artBooks}) {
auto it = find_if(category.begin(), category.end(), [&borrowedBook](const Book& b) {
return b.id == borrowedBook.id;
});
if (it != category.end()) {
bookTitle = it->title;
break;
}
}
// Case 2: Late return with fee
cout << GREEN << BOLD << "\tBook returned SUCCESSFULLY." << RESET;
cout << RED << BOLD << "But, you need to pay for not following the rules.\n" << RESET;
cout << CYAN << BOLD << "\n\t--- E-Receipt ---\n" << RESET;
cout << "\tBorrower's Name: " << borrower.firstName + " " + borrower.middleInitial + " " + borrower.lastName << "\n";
cout << "\tBook Title: " << bookTitle << "\n";
cout << "\tDate Borrowed: " << borrowedBook.dateBorrow << "\n";
cout << "\tDate Returned: " << borrowedBook.dateReturn << "\n";
cout << RED << BOLD << "\tOverdue Fee: " << overdueFee << " pesos\n" << RESET;
cout << "\t------------------\n";
cin.clear();
cout << BLUE << BOLD << "\n\tPress Enter to return to the main menu..." << RESET;
cin.get(); // Wait for the user to press Enter
}
// Return the book to inventory
for (auto& book : fictionBooks) { // Repeat for all categories
if (book.id == bookID) {
book.copies++; // Increase the available copies
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
return;
}
}
for (auto& book : nonFictionBooks) { // Repeat for all categories
if (book.id == bookID) {
book.copies++; // Increase the available copies
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
return;
}
}
for (auto& book : scienceBooks) { // Repeat for all categories
if (book.id == bookID) {
book.copies++; // Increase the available copied
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
return;
}
}
for (auto& book : mysteryBooks) { // Repeat for all categories
if (book.id == bookID) {
book.copies++; // Increase the available copied
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
return;
}
}
for (auto& book : romanceBooks) { // Repeat for all categories
if (book.id == bookID) {
book.copies++; // Increase the available copies
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
return;
}
}
for (auto& book : biographyBooks) { // Repeat for all categories
if (book.id == bookID) {
book.copies++; // Increase the available copies
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
return;
}
}
for (auto& book : historyBooks) { // Repeat for all categories
if (book.id == bookID) {
book.copies++; // Increase the available copies
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
return;
}
}
for (auto& book : technologyBooks) { // Repeat for all categories
if (book.id == bookID) {
book.copies++; // Increase the available copies
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
return;
}
}
for (auto& book : childrenBooks) { // Repeat for all categories
if (book.id == bookID) {
book.copies++; // Increase the available copies
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
return;
}
}
for (auto& book : artBooks) { // Repeat for all categories
if (book.id == bookID) {
book.copies++; // Increase the available copies
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
return;
}
}
cout << RED << BOLD << "Book not found in the library inventory.\n" << RESET;
return;
}
}
}
}
// If borrower or book ID not found
cout << RED << BOLD << "\tBorrower ID or Book ID not found, or the borrower did not borrow any books.\n" << RESET;
cin.clear();
cout << BLUE << BOLD << "\n\tPress Enter to return to the main menu..." << RESET;
cin.get(); // Wait for the user to press Enter
system("CLS"); // Use "clear" for Unix/Linux systems
displayMainMenu();
}
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