#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <queue>
#include <memory>
#include <thread>
#include <mutex>
#include <algorithm>
#include <chrono>
#include <random>
using namespace std;
// defining enums for different types and statuses in the system
enum class bookstatus {
available,
borrowed,
reserved,
maintenance
};
enum class membertype {
student,
faculty,
staff,
guest
};
enum class transactiontype {
borrow,
return_book,
reserve,
fine_payment
};
// creating a template class for different media items
template<typename t>
class mediaitem {
protected:
string id;
string title;
string author;
bookstatus status;
chrono::system_clock::time_point due_date;
public:
// using constructor initialization lists for efficiency
mediaitem(const string& id, const string& title, const string& author)
: id(id), title(title), author(author), status(bookstatus::available) {}
virtual ~mediaitem() = default;
// overloading operators for easy comparison
bool operator<(const mediaitem& other) const {
return title < other.title;
}
bool operator==(const mediaitem& other) const {
return id == other.id;
}
// using reference parameters to avoid copying
void set_status(const bookstatus& new_status) {
status = new_status;
}
bookstatus get_status() const { return status; }
string get_id() const { return id; }
string get_title() const { return title; }
string get_author() const { return author; }
virtual string get_type() const = 0;
};
// creating specific media types using inheritance
class book : public mediaitem<string> {
private:
string isbn;
string category;
int pages;
public:
book(const string& id, const string& title, const string& author,
const string& isbn, const string& category, int pages)
: mediaitem(id, title, author), isbn(isbn), category(category), pages(pages) {}
string get_type() const override { return "book"; }
string get_isbn() const { return isbn; }
string get_category() const { return category; }
int get_pages() const { return pages; }
};
class journal : public mediaitem<string> {
private:
string issn;
int volume;
int issue;
public:
journal(const string& id, const string& title, const string& author,
const string& issn, int volume, int issue)
: mediaitem(id, title, author), issn(issn), volume(volume), issue(issue) {}
string get_type() const override { return "journal"; }
string get_issn() const { return issn; }
};
class dvd : public mediaitem<string> {
private:
string director;
int duration_minutes;
string genre;
public:
dvd(const string& id, const string& title, const string& director,
int duration, const string& genre)
: mediaitem(id, title, director), director(director),
duration_minutes(duration), genre(genre) {}
string get_type() const override { return "dvd"; }
string get_director() const { return director; }
int get_duration() const { return duration_minutes; }
};
// implementing a member class with overloaded operators
class member {
private:
string member_id;
string name;
string email;
membertype type;
vector<string> borrowed_items;
double fine_amount;
public:
member(const string& id, const string& name, const string& email, membertype type)
: member_id(id), name(name), email(email), type(type), fine_amount(0.0) {}
// overloading comparison operators for member comparison
bool operator<(const member& other) const {
return member_id < other.member_id;
}
bool operator==(const member& other) const {
return member_id == other.member_id;
}
void add_borrowed_item(const string& item_id) {
borrowed_items.push_back(item_id);
}
void remove_borrowed_item(const string& item_id) {
borrowed_items.erase(
remove(borrowed_items.begin(), borrowed_items.end(), item_id),
borrowed_items.end()
);
}
void add_fine(double amount) { fine_amount += amount; }
void pay_fine(double amount) { fine_amount = max(0.0, fine_amount - amount); }
string get_id() const { return member_id; }
string get_name() const { return name; }
membertype get_type() const { return type; }
double get_fine() const { return fine_amount; }
const vector<string>& get_borrowed_items() const { return borrowed_items; }
};
// implementing a bst node for book storage
template<typename t>
class bstnode {
public:
shared_ptr<t> data;
shared_ptr<bstnode<t>> left;
shared_ptr<bstnode<t>> right;
int height;
bstnode(shared_ptr<t> item) : data(item), left(nullptr), right(nullptr), height(1) {}
};
// creating a balanced bst (avl tree) for efficient book storage
template<typename t>
class balancedbst {
private:
shared_ptr<bstnode<t>> root;
// implementing recursive height calculation
int get_height(shared_ptr<bstnode<t>> node) {
return node ? node->height : 0;
}
// calculating balance factor for avl operations
int get_balance(shared_ptr<bstnode<t>> node) {
return node ? get_height(node->left) - get_height(node->right) : 0;
}
// implementing right rotation for tree balancing
shared_ptr<bstnode<t>> rotate_right(shared_ptr<bstnode<t>> y) {
auto x = y->left;
auto temp = x->right;
x->right = y;
y->left = temp;
// updating heights after rotation
y->height = max(get_height(y->left), get_height(y->right)) + 1;
x->height = max(get_height(x->left), get_height(x->right)) + 1;
return x;
}
// implementing left rotation for tree balancing
shared_ptr<bstnode<t>> rotate_left(shared_ptr<bstnode<t>> x) {
auto y = x->right;
auto temp = y->left;
y->left = x;
x->right = temp;
// updating heights after rotation
x->height = max(get_height(x->left), get_height(x->right)) + 1;
y->height = max(get_height(y->left), get_height(y->right)) + 1;
return y;
}
// implementing recursive insertion with balancing
shared_ptr<bstnode<t>> insert_recursive(shared_ptr<bstnode<t>> node, shared_ptr<t> item) {
// handling base case for insertion
if (!node) {
return make_shared<bstnode<t>>(item);
}
// performing standard bst insertion
if (*item < *(node->data)) {
node->left = insert_recursive(node->left, item);
} else if (*(node->data) < *item) {
node->right = insert_recursive(node->right, item);
} else {
return node; // not allowing duplicates
}
node->height = 1 + max(get_height(node->left), get_height(node->right));
int balance = get_balance(node);
if (balance > 1 && *item < *(node->left->data)) {
return rotate_right(node);
}
if (balance < -1 && *(node->right->data) < *item) {
return rotate_left(node);
}
if (balance > 1 && *(node->left->data) < *item) {
node->left = rotate_left(node->left);
return rotate_right(node);
}
if (balance < -1 && *item < *(node->right->data)) {
node->right = rotate_right(node->right);
return rotate_left(node);
}
return node;
}
// implementing recursive in-order traversal
void inorder_recursive(shared_ptr<bstnode<t>> node, vector<shared_ptr<t>>& result) {
if (node) {
inorder_recursive(node->left, result);
result.push_back(node->data);
inorder_recursive(node->right, result);
}
}
// implementing recursive search
shared_ptr<t> search_recursive(shared_ptr<bstnode<t>> node, const string& key) {
if (!node) return nullptr;
if (node->data->get_title() == key || node->data->get_id() == key) {
return node->data;
}
auto left_result = search_recursive(node->left, key);
if (left_result) return left_result;
return search_recursive(node->right, key);
}
public:
balancedbst() : root(nullptr) {}
void insert(shared_ptr<t> item) {
root = insert_recursive(root, item);
}
shared_ptr<t> search(const string& key) {
return search_recursive(root, key);
}
vector<shared_ptr<t>> get_all_items() {
vector<shared_ptr<t>> result;
inorder_recursive(root, result);
return result;
}
};
// implementing a reservation system using priority queue
struct reservation {
string member_id;
string item_id;
chrono::system_clock::time_point request_time;
membertype priority_type;
reservation(const string& mid, const string& iid, membertype type)
: member_id(mid), item_id(iid), request_time(chrono::system_clock::now()), priority_type(type) {}
// defining priority order (faculty > staff > student > guest)
bool operator<(const reservation& other) const {
if (priority_type != other.priority_type) {
return static_cast<int>(priority_type) > static_cast<int>(other.priority_type);
}
return request_time > other.request_time; // earlier requests have higher priority
}
};
// creating the main library management system class
class librarysystem {
private:
balancedbst<book> book_collection;
balancedbst<journal> journal_collection;
balancedbst<dvd> dvd_collection;
unordered_map<string, shared_ptr<member>> members;
priority_queue<reservation> reservation_queue;
unordered_map<string, vector<string>> borrowing_history; // member_id -> item_ids
mutable mutex system_mutex;
// implementing a recommendation engine using collaborative filtering
vector<string> generate_recommendations_recursive(const string& member_id,
const vector<string>& all_items,
int depth = 0) {
if (depth > 3) return {}; // limiting recursion depth
vector<string> recommendations;
auto member_it = members.find(member_id);
if (member_it == members.end()) return recommendations;
const auto& member_history = borrowing_history[member_id];
vector<pair<string, int>> similar_members;
for (const auto& other_pair : borrowing_history) {
if (other_pair.first == member_id) continue;
// calculating similarity score
int common_items = 0;
for (const string& item : member_history) {
if (find(other_pair.second.begin(), other_pair.second.end(), item)
!= other_pair.second.end()) {
common_items++;
}
}
if (common_items > 0) {
similar_members.push_back({other_pair.first, common_items});
}
}
// sorting by similarity score
sort(similar_members.begin(), similar_members.end(),
[](const pair<string, int>& a, const pair<string, int>& b) {
return a.second > b.second;
});
// getting recommendations from similar members
for (const auto& similar : similar_members) {
if (recommendations.size() >= 5) break;
const auto& similar_history = borrowing_history[similar.first];
for (const string& item : similar_history) {
// checking if member hasn't borrowed this item
if (find(member_history.begin(), member_history.end(), item)
== member_history.end()) {
if (find(recommendations.begin(), recommendations.end(), item)
== recommendations.end()) {
recommendations.push_back(item);
if (recommendations.size() >= 5) break;
}
}
}
}
return recommendations;
}
// implementing multithreaded fine calculation
void calculate_fines_threaded() {
vector<thread> threads;
vector<shared_ptr<member>> member_list;
// collecting all members
for (const auto& pair : members) {
member_list.push_back(pair.second);
}
// dividing work among threads
int num_threads = min(4, static_cast<int>(member_list.size()));
int chunk_size = member_list.size() / num_threads;
for (int i = 0; i < num_threads; ++i) {
int start = i * chunk_size;
int end = (i == num_threads - 1) ? member_list.size() : (i + 1) * chunk_size;
threads.emplace_back([this, &member_list, start, end]() {
for (int j = start; j < end; ++j) {
this->calculate_member_fine(member_list[j]);
}
});
}
// waiting for all threads to complete
for (auto& t : threads) {
t.join();
}
}
void calculate_member_fine(shared_ptr<member> mem) {
lock_guard<mutex> lock(system_mutex);
auto now = chrono::system_clock::now();
double total_fine = 0.0;
// calculating fines for overdue items
for (const string& item_id : mem->get_borrowed_items()) {
// searching for the item across all collections
auto book_item = book_collection.search(item_id);
if (book_item) {
// calculating days overdue (simplified logic)
auto days_overdue = chrono::duration_cast<chrono::hours>(
now - chrono::system_clock::now()).count() / 24;
if (days_overdue > 14) { // assuming 14 day loan period
total_fine += (days_overdue - 14) * 0.50; // $0.50 per day
}
}
}
if (total_fine > 0) {
mem->add_fine(total_fine);
}
}
public:
librarysystem() = default;
// implementing function overloading for different search methods
shared_ptr<book> search_book(const string& title) {
return book_collection.search(title);
}
shared_ptr<book> search_book_by_isbn(const string& isbn) {
auto all_books = book_collection.get_all_items();
for (const auto& book : all_books) {
if (book->get_isbn() == isbn) {
return book;
}
}
return nullptr;
}
vector<shared_ptr<book>> search_books_by_category(const string& category) {
vector<shared_ptr<book>> results;
auto all_books = book_collection.get_all_items();
for (const auto& book : all_books) {
if (book->get_category() == category) {
results.push_back(book);
}
}
return results;
}
// adding items to collections
void add_book(const string& id, const string& title, const string& author,
const string& isbn, const string& category, int pages) {
auto book_ptr = make_shared<book>(id, title, author, isbn, category, pages);
book_collection.insert(book_ptr);
}
void add_journal(const string& id, const string& title, const string& author,
const string& issn, int volume, int issue) {
auto journal_ptr = make_shared<journal>(id, title, author, issn, volume, issue);
journal_collection.insert(journal_ptr);
}
void add_dvd(const string& id, const string& title, const string& director,
int duration, const string& genre) {
auto dvd_ptr = make_shared<dvd>(id, title, director, duration, genre);
dvd_collection.insert(dvd_ptr);
}
// managing members
void add_member(const string& id, const string& name, const string& email, membertype type) {
members[id] = make_shared<member>(id, name, email, type);
}
shared_ptr<member> get_member(const string& id) {
auto it = members.find(id);
return (it != members.end()) ? it->second : nullptr;
}
// implementing borrowing system
bool borrow_book(const string& member_id, const string& book_id) {
lock_guard<mutex> lock(system_mutex);
auto member_ptr = get_member(member_id);
auto book_ptr = search_book(book_id);
if (!member_ptr || !book_ptr) return false;
if (book_ptr->get_status() != bookstatus::available) return false;
// updating book status and member records
book_ptr->set_status(bookstatus::borrowed);
member_ptr->add_borrowed_item(book_id);
borrowing_history[member_id].push_back(book_id);
return true;
}
bool return_book(const string& member_id, const string& book_id) {
lock_guard<mutex> lock(system_mutex);
auto member_ptr = get_member(member_id);
auto book_ptr = search_book(book_id);
if (!member_ptr || !book_ptr) return false;
// updating records
book_ptr->set_status(bookstatus::available);
member_ptr->remove_borrowed_item(book_id);
// checking for reservations
while (!reservation_queue.empty()) {
auto reservation = reservation_queue.top();
if (reservation.item_id == book_id) {
reservation_queue.pop();
book_ptr->set_status(bookstatus::reserved);
// notifying the member (simplified)
cout << "book " << book_id << " is now reserved for member "
<< reservation.member_id << endl;
break;
} else {
break; // keeping other reservations
}
}
return true;
}
// implementing reservation system
void reserve_item(const string& member_id, const string& item_id) {
auto member_ptr = get_member(member_id);
if (member_ptr) {
reservation_queue.emplace(member_id, item_id, member_ptr->get_type());
}
}
// getting recommendations for a member
vector<string> get_recommendations(const string& member_id) {
vector<string> all_books;
auto books = book_collection.get_all_items();
for (const auto& book : books) {
all_books.push_back(book->get_id());
}
return generate_recommendations_recursive(member_id, all_books);
}
// generating statistical reports
void generate_statistics() {
cout << "\n=== library statistics ===" << endl;
auto books = book_collection.get_all_items();
auto journals = journal_collection.get_all_items();
auto dvds = dvd_collection.get_all_items();
cout << "total books: " << books.size() << endl;
cout << "total journals: " << journals.size() << endl;
cout << "total dvds: " << dvds.size() << endl;
cout << "total members: " << members.size() << endl;
cout << "pending reservations: " << reservation_queue.size() << endl;
// calculating category statistics
unordered_map<string, int> category_count;
for (const auto& book : books) {
category_count[book->get_category()]++;
}
cout << "\nbooks by category:" << endl;
for (const auto& pair : category_count) {
cout << " " << pair.first << ": " << pair.second << endl;
}
// calculating borrowing statistics
int total_borrowed = 0;
for (const auto& member_pair : members) {
total_borrowed += member_pair.second->get_borrowed_items().size();
}
cout << "total items borrowed: " << total_borrowed << endl;
}
// running the fine calculation system
void process_fines() {
cout << "calculating fines using multithreading..." << endl;
calculate_fines_threaded();
cout << "fine calculation completed." << endl;
}
// displaying all items in collections
void display_collection() {
cout << "\n=== book collection ===" << endl;
auto books = book_collection.get_all_items();
for (const auto& book : books) {
cout << "id: " << book->get_id()
<< ", title: " << book->get_title()
<< ", author: " << book->get_author()
<< ", isbn: " << book->get_isbn()
<< ", category: " << book->get_category()
<< ", status: " << static_cast<int>(book->get_status()) << endl;
}
}
};
// creating a demonstration function
void demonstrate_system() {
librarysystem library;
cout << "initializing advanced library management system..." << endl;
library.add_book("b001", "the great gatsby", "f. scott fitzgerald",
"978-0-7432-7356-5", "fiction", 180);
library.add_book("b002", "to kill a mockingbird", "harper lee",
"978-0-06-112008-4", "fiction", 281);
library.add_book("b003", "introduction to algorithms", "cormen",
"978-0-262-03384-8", "computer science", 1312);
library.add_book("b004", "clean code", "robert martin",
"978-0-13-235088-4", "programming", 464);
library.add_journal("j001", "nature", "various", "0028-0836", 595, 7875);
library.add_journal("j002", "science", "various", "0036-8075", 375, 6570);
library.add_dvd("d001", "the matrix", "wachowski sisters", 136, "sci-fi");
library.add_dvd("d002", "inception", "christopher nolan", 148, "thriller");
library.add_member("m001", "A", "
[email protected]", membertype::student);
library.add_member("m002", "B", "
[email protected]", membertype::faculty);
library.add_member("m003", "C", "
[email protected]", membertype::staff);
cout << "\ndemonstrating borrowing system..." << endl;
if (library.borrow_book("m001", "b001")) {
cout << "A successfully borrowed 'the great gatsby'" << endl;
}
if (library.borrow_book("m002", "b003")) {
cout << "B successfully borrowed 'introduction to algorithms'" << endl;
}
cout << "\ndemonstrating reservation system..." << endl;
library.reserve_item("m003", "b001");
cout << "\ndemonstrating search functionality..." << endl;
auto found_book = library.search_book("clean code");
if (found_book) {
cout << "found book: " << found_book->get_title()
<< " by " << found_book->get_author() << endl;
}
auto fiction_books = library.search_books_by_category("fiction");
cout << "fiction books found: " << fiction_books.size() << endl;
cout << "\ndemonstrating return system..." << endl;
if (library.return_book("m001", "b001")) {
cout << "Ae returned 'the great gatsby'" << endl;
}
cout << "\ndemonstrating recommendation system..." << endl;
auto recommendations = library.get_recommendations("m001");
cout << "recommendations for A: ";
for (const auto& rec : recommendations) {
cout << rec << " ";
}
cout << endl;
library.process_fines();
library.generate_statistics();
library.display_collection();
cout << "\nadvanced library management system demonstration completed!" << endl;
}
int main() {
cout << "welcome to the advanced library management system" << endl;
cout << "this system demonstrates:" << endl;
cout << "- balanced bst for efficient storage" << endl;
cout << "- hash tables for member lookup" << endl;
cout << "- priority queues for reservations" << endl;
cout << "- template classes for different media types" << endl;
cout << "- function overloading for search methods" << endl;
cout << "- operator overloading for comparisons" << endl;
cout << "- recursive algorithms for recommendations" << endl;
cout << "- multithreading for fine calculations" << endl;
cout << "- smart pointers for memory management" << endl;
cout << "- advanced c++ features throughout" << endl;
demonstrate_system();
return 0;
}