Spaces:
Sleeping
Sleeping
| from datetime import date | |
| from enum import Enum | |
| import pandas as pd | |
| from fuzzywuzzy import fuzz | |
| from tinydb import TinyDB, Query | |
| from enum import Enum | |
| from helper import send_message, response_generator | |
| import streamlit as st | |
| class Database: | |
| def __init__(self, db_name): | |
| self.db = TinyDB(db_name) | |
| self.students = self.db.table("students") | |
| self.User = Query() | |
| self.trackBook = self.db.table("trackBook") | |
| def createUser(self, data): | |
| if not self.students.contains(self.User.id == data['id']): | |
| self.students.insert(data) | |
| else: | |
| print("User with this ID already exists.") | |
| def deleteUser(self, id, user_type): | |
| self.students.remove(self.User.id == id) | |
| def searchUser(self, id): | |
| search = Query() | |
| item = self.students.search(search.id == id ) | |
| return item[0] if item else None | |
| def addBorrowedBook(self, data): | |
| self.trackBook.insert(data) | |
| def updateBorrowedBook(self, data): | |
| self.trackBook.update(data) | |
| def listBorrowedBooks(self): | |
| print(self.trackBook.all()) | |
| def listBorrowedBooks(self, studentId): | |
| search = Query() | |
| items = self.trackBook.search(search.studentId == studentId ) | |
| return items | |
| def searchBorrowedBookById(self, id): | |
| search = Query() | |
| item = self.trackBook.search(search.isbn == id ) | |
| return item[0] if item else None | |
| class RecommendationSystem: | |
| def __init__(self): | |
| self.books = pd.read_csv("books-2.csv") | |
| self.books = self.books.drop(columns=['isbn10', 'subtitle', 'published_year', 'num_pages']) | |
| def getBookByTitle(self, title): | |
| return self.books[self.books['title'].str.contains(title, case=False)] | |
| # def recommend_by_titles(self,book_titles, num_recommendations=5): | |
| # reader = Reader(rating_scale = (1, 10)) | |
| # data = Dataset.load_from_df(books[["title","categories","average_rating"]], reader) | |
| # trainset = data.build_full_trainset() | |
| # model_svd = SVD() | |
| # model_svd.fit(trainset) | |
| # books['categories'] = books['categories'].astype(str) | |
| # similar_books = self.books[self.books['title'].apply(lambda x: any(fuzz.ratio(x, book_title) > 80 for book_title in book_titles))] | |
| # if similar_books.empty: | |
| # print("No books found with similar titles. Recommending books.") | |
| # return books.sort_values(by='average_rating', ascending=False).head(num_recommendations) | |
| # similar_categories = set() | |
| # for categories in similar_books['categories']: | |
| # similar_categories.update(categories.split(', ')) | |
| # recommended_books = books[books['categories'].apply(lambda x: any(cat in similar_categories for cat in x.split(', ')))] | |
| # return recommended_books.head(num_recommendations) | |
| class LibrarySystem: | |
| def __init__(self): | |
| self.user = None | |
| self.database = Database('db.json') | |
| self.recommendation = RecommendationSystem() | |
| def display_menu(self, options): | |
| for i, option in enumerate(options, 1): | |
| return f"{i}. {option}" | |
| def get_choice(self, options, incoming_msg=None): | |
| while True: | |
| try: | |
| choice = int(incoming_msg) | |
| if 1 <= choice <= len(options): | |
| return choice | |
| print("Invalid choice. Try again.") | |
| except ValueError: | |
| print("Invalid input. Enter a number.") | |
| def startMessage(self): | |
| message = ''' | |
| Welcome to our chatbot! I'm here to help you with your needs. | |
| You can interact with me to learn about our services, get support, or provide feedback. | |
| Please choose one of the following options:\n\n | |
| **1. Login** | |
| **2. Register** | |
| ''' | |
| st.session_state.app_state = 'welcome' | |
| send_message(message) | |
| return message | |
| def login_or_register(self, incoming_msg): | |
| if self.get_choice(["Login", "Register"], incoming_msg) == 1: | |
| st.session_state.app_state = 'login' | |
| self.login(incoming_msg) | |
| else: | |
| self.register() | |
| def login(self, incoming_msg=None): | |
| if st.session_state.app_state == "login": | |
| message = "Hi there! π Please enter your ID to continue(eg. 10944444)" | |
| response = st.write_stream(response_generator(message)) | |
| st.session_state.messages.append({"role": "assistant", "content": response}) | |
| st.session_state.app_state = 'login_search' | |
| def loginSearch(self, incoming_msg): | |
| self.user = self.database.searchUser(incoming_msg) | |
| print(self.user) | |
| if self.user != None: | |
| st.session_state.app_state = "default" | |
| st.session_state.user = self.user | |
| self.run_main_app() | |
| else: | |
| response = st.write_stream(response_generator("User not found")) | |
| st.session_state.messages.append({"role": "assistant", "content": response}) | |
| def register(self): | |
| send_message("Enter your name: ") | |
| # response = st.write_stream(response_generator("enter your name: ")) | |
| # st.session_state.messages.append({"role": "assistant", "content": response}) | |
| # we need to set the state here to wait for the user to provide a username | |
| st.session_state.app_state = "waiting_for_name" | |
| # new function to handle the user input for registration | |
| def handle_registration_input(self, incoming_msg): | |
| if st.session_state.app_state == "waiting_for_name": | |
| self.user = incoming_msg | |
| st.session_state.user = self.user | |
| st.session_state.app_state = "waiting_for_id" | |
| send_message("Enter your ID: ") | |
| elif st.session_state.app_state == "waiting_for_id": | |
| user_id = incoming_msg | |
| self.user = st.session_state.user | |
| self.database.createUser({"name": self.user, "id": user_id}) | |
| st.session_state.app_state = "default" # we set to default here when registration is done | |
| self.user = self.database.searchUser(user_id) | |
| st.session_state.user = self.user | |
| self.run_main_app() | |
| def run_main_app(self): | |
| message = f"""Welcome {st.session_state.user["name"].title()}! π\nPlease choose an option: | |
| 1οΈβ£ Search Book | |
| 2οΈβ£ Borrow Book | |
| 3οΈβ£ Return Book | |
| 4οΈβ£ List Borrowed Books | |
| 5οΈβ£ Recommend Book | |
| 6οΈβ£ Exit | |
| Reply with the number of your choice. | |
| """ | |
| send_message(message) | |
| def main_menu(self, incoming_msg): | |
| if incoming_msg in ["1", "2", "3", "4", "5", "6"]: | |
| self.handle_student_choice(int(incoming_msg), incoming_msg) | |
| else: | |
| print(f"Invalid input. Enter a number. {incoming_msg}") | |
| send_message("Please enter a valid number") | |
| def handle_student_choice(self, choice, incoming_msg): | |
| if choice == 1: | |
| self.search_book(incoming_msg) | |
| else: | |
| send_message("We are still working on this feature. Please try again later.") | |
| # elif choice == 2: | |
| # self.borrow_book() | |
| # elif choice == 3: | |
| # self.return_book() | |
| # elif choice == 4: | |
| # self.list_borrowed_books() | |
| # elif choice == 5: | |
| # self.recommendBook() | |
| def search_book(self, incoming_msg): | |
| message = f"π , please enter the title of the book:" | |
| st.session_state.app_state = "search" # we set to default here when | |
| send_message(message) | |
| def fetchbook(self, incoming_msg): | |
| book = self.recommendation.getBookByTitle(incoming_msg) | |
| st.session_state.book = book | |
| if book.empty: | |
| message = "β Book not found. Please check the title and try again." | |
| send_message(message) | |
| return | |
| message = f''' | |
| π Title: {book.iloc[0]["title"]} | |
| π ISBN: {book.iloc[0]["isbn13"]} | |
| π Borrow this book? (yes/no): | |
| ''' | |
| send_message(message) | |
| st.session_state.app_state = "borrow" # we set to default here when | |
| def hasborrowed(self, book, incoming_msg): | |
| if incoming_msg.strip().lower() == "yes": | |
| self.borrow_book_by_isbn(book.iloc[0]["isbn13"], book.iloc[0]["title"]) | |
| def borrow_book_by_isbn(self, isbn, title): | |
| data = { | |
| "title": title, | |
| "isbn": str(isbn), | |
| "studentId": st.session_state.user["id"], | |
| "returned": False, | |
| "borrowedDate": date.today().isoformat(), | |
| "returnDate": "" | |
| } | |
| self.database.addBorrowedBook(data) | |
| message = "β Book borrowed successfully!" | |
| send_message(message) | |
| st.balloons() | |
| def borrow_book(self): | |
| send_message("Enter the title of the book to borrow: ") | |
| if st.session_state.state == "borrowing": | |
| isbn = self.incoming_msg | |
| books = self.recommendation.getBookByTitle(isbn) | |
| if books.empty: # Check if the DataFrame is empty | |
| send_message("Book not found.") | |
| return | |
| book_titles = books["title"].tolist() | |
| send_message(book_titles) | |
| choice = self.get_choice(book_titles) | |
| book = books.iloc[choice - 1:choice] | |
| self.borrow_book_by_isbn(book.iloc[0]["isbn13"], book.iloc[0]["title"]) | |
| def recommendBook(self): | |
| borrowedBookByUser = self.database.listBorrowedBooks(self.user["id"]) | |
| print(borrowedBookByUser) | |
| if not borrowedBookByUser: | |
| print("No books borrowed, cannot recommend.") | |
| return | |
| book_titles = [book['title'] for book in borrowedBookByUser] | |
| recommendations = self.recommendation.recommend_by_titles(book_titles) | |
| print("Recommended Books:") | |
| self.display_menu(recommendations['title']) | |
| choice = self.get_choice(recommendations['title']) | |
| shouldBorrow = input("Do you want to borrow this book? (yes/no): ") | |
| if shouldBorrow == 'yes': | |
| book = recommendations.iloc[choice - 1:choice] | |
| self.borrow_book_by_isbn(book.iloc[0]["isbn13"], book.iloc[0]["title"]) | |
| def return_book(self): | |
| isbn = input("Enter the ISBN of the book to return: ") | |
| borrowed_book = self.database.searchBorrowedBookById(isbn) | |
| if borrowed_book: | |
| borrowed_book["returned"] = True | |
| borrowed_book["actualReturnDate"] = date.today().isoformat() | |
| self.database.updateBorrowedBook(borrowed_book) | |
| print("Book returned successfully!") | |
| else: | |
| print("Book not found in borrowed list.") | |
| def list_borrowed_books(self): | |
| books = self.database.listBorrowedBooks(self.user["id"]) | |
| if books: | |
| for book in books: | |
| print(book) | |
| else: | |
| print("No books borrowed.") |