Ana / node.py
rexthecoder's picture
chore: fix issue
bd3f5b0
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.")