From 947bbfabfb29bd258a63998fb1a34507b4695785 Mon Sep 17 00:00:00 2001 From: adipai Date: Thu, 12 Oct 2023 13:11:54 -0400 Subject: [PATCH 1/2] Overhaul of coding standards --- Code/recommenderapp/app.py | 13 +++++--- Code/recommenderapp/constants.py | 31 ++++++++++++++++++ Code/recommenderapp/search.py | 49 ++++++++++++++++++---------- Code/recommenderapp/utils.py | 55 ++++++++++---------------------- 4 files changed, 90 insertions(+), 58 deletions(-) create mode 100644 Code/recommenderapp/constants.py diff --git a/Code/recommenderapp/app.py b/Code/recommenderapp/app.py index ecf96e9af..dc94f4631 100644 --- a/Code/recommenderapp/app.py +++ b/Code/recommenderapp/app.py @@ -1,11 +1,16 @@ +""" +Module for routing all calls from the frontend +""" + import json import sys +from search import Search from flask import Flask, jsonify, render_template, request from flask_cors import CORS from utils import send_email_to_user, beautify_feedback_data + sys.path.append("../../") from Code.prediction_scripts.item_based import recommend_for_new_user -from search import Search app = Flask(__name__) app.secret_key = "secret key" @@ -45,8 +50,8 @@ def search(): Handles movie search requests. """ term = request.form["q"] - search = Search() - filtered_dict = search.resultsTop10(term) + finder = Search() + filtered_dict = finder.results_top_ten(term) resp = jsonify(filtered_dict) resp.status_code = 200 return resp @@ -58,7 +63,7 @@ def feedback(): Handles user feedback submission and mails the results. """ data = json.loads(request.data) - user_email = "ananyamantravadi@gmail.com" + user_email = "adipai16@gmail.com" send_email_to_user(user_email, beautify_feedback_data(data)) return data diff --git a/Code/recommenderapp/constants.py b/Code/recommenderapp/constants.py new file mode 100644 index 000000000..31a92b464 --- /dev/null +++ b/Code/recommenderapp/constants.py @@ -0,0 +1,31 @@ +""" +This module contains all the constants +""" + +EMAIL_HTML_CONTENT = """ + + + +

Movie Recommendations from PopcornPicks

+

Dear Movie Enthusiast,

+

We hope you're having a fantastic day!

+
+

Your Movie Recommendations:

+

Movies Liked:

+ +

Movies Disliked:

+ +

Movies Yet to Watch:

+ +
+

Enjoy your movie time with PopcornPicks!

+

Best regards,
PopcornPicks Team 🍿

+ + + """ diff --git a/Code/recommenderapp/search.py b/Code/recommenderapp/search.py index 776336306..dce873a2f 100644 --- a/Code/recommenderapp/search.py +++ b/Code/recommenderapp/search.py @@ -1,9 +1,11 @@ -import pandas as pd +""" +Search feature for the web application +""" -# from app import app -from flask import jsonify, request, render_template -import sys import os +import pandas as pd +#from flask import jsonify, request, render_template + app_dir = os.path.dirname(os.path.abspath(__file__)) code_dir = os.path.dirname(app_dir) @@ -11,13 +13,19 @@ class Search: + """ + Search feature for landing page + """ df = pd.read_csv(project_dir + "/data/movies.csv") def __init__(self): pass - def startsWith(self, word): + def starts_with(self, word): + """ + Function to check movie prefix + """ n = len(word) res = [] word = word.lower() @@ -27,26 +35,35 @@ def startsWith(self, word): res.append(x) return res - def anywhere(self, word, visitedWords): + def anywhere(self, word, visited_words): + """ + Function to check visited words + """ res = [] word = word.lower() for x in self.df["title"]: - if x not in visitedWords: + if x not in visited_words: curr = x.lower() if word in curr: res.append(x) return res def results(self, word): - startsWith = self.startsWith(word) - visitedWords = set() - for x in startsWith: - visitedWords.add(x) - anywhere = self.anywhere(word, visitedWords) - startsWith.extend(anywhere) - return startsWith - - def resultsTop10(self, word): + """ + Function to serve the result render + """ + starts_with = self.starts_with(word) + visited_words = set() + for x in starts_with: + visited_words.add(x) + anywhere = self.anywhere(word, visited_words) + starts_with.extend(anywhere) + return starts_with + + def results_top_ten(self, word): + """ + Function to get top 10 results + """ return self.results(word)[:10] diff --git a/Code/recommenderapp/utils.py b/Code/recommenderapp/utils.py index 37aae3228..7858f4244 100644 --- a/Code/recommenderapp/utils.py +++ b/Code/recommenderapp/utils.py @@ -1,7 +1,12 @@ +""" Module contains utility functions used for various purposes in the backend """ + +import logging import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart -import logging + +import constants as c + def beautify_feedback_data(data): """ @@ -22,12 +27,11 @@ def beautify_feedback_data(data): dislike.append(movie) # Create a category-dictionary of liked, disliked and yet to watch movies - categorized_data_dict = {"Liked":like, "Disliked":dislike, "Yet to Watch":yet_to_watch} + categorized_data_dict = {"Liked": like, + "Disliked": dislike, "Yet to Watch": yet_to_watch} return categorized_data_dict - - def send_email_to_user(recipient_email, categorized_data): """ Utility function to send movie recommendations to user over email @@ -36,11 +40,11 @@ def send_email_to_user(recipient_email, categorized_data): # Email configuration smtp_server = 'smtp.gmail.com' # Port for TLS - smtp_port = 587 + smtp_port = 587 sender_email = 'popcornpicks504@gmail.com' # Use an app password since 2-factor authentication is enabled - sender_password = 'uxnd shis sazo mstj' + sender_password = 'uxnd shis sazo mstj' subject = 'Your movie recommendation from PopcornPicks' # Create the email message @@ -50,44 +54,19 @@ def send_email_to_user(recipient_email, categorized_data): message['Subject'] = subject # Create the email message with HTML content - html_content = """ - - - -

Movie Recommendations from PopcornPicks

-

Dear Movie Enthusiast,

-

We hope you're having a fantastic day!

-
-

Your Movie Recommendations:

-

Movies Liked:

- -

Movies Disliked:

- -

Movies Yet to Watch:

- -
-

Enjoy your movie time with PopcornPicks!

-

Best regards,
PopcornPicks Team 🍿

- - - """.format('\n'.join(f'
  • {movie}
  • ' for movie in categorized_data['Liked']), - '\n'.join(f'
  • {movie}
  • ' for movie in categorized_data['Disliked']), - '\n'.join(f'
  • {movie}
  • ' for movie in categorized_data['Yet to Watch'])) + html_content = c.EMAIL_HTML_CONTENT.format('\n'.join(f'
  • {movie}
  • ' for movie in categorized_data['Liked']), + '\n'.join( + f'
  • {movie}
  • ' for movie in categorized_data['Disliked']), + '\n'.join(f'
  • {movie}
  • ' for movie in categorized_data['Yet to Watch'])) # Attach the HTML email body message.attach(MIMEText(html_content, 'html')) - + # Connect to the SMTP server try: server = smtplib.SMTP(smtp_server, smtp_port) # Start TLS encryption - server.starttls() + server.starttls() server.login(sender_email, sender_password) # Send the email @@ -95,7 +74,7 @@ def send_email_to_user(recipient_email, categorized_data): logging.info("Email sent successfully!") except Exception as e: - logging.warning(f'Email could not be sent. Error: {str(e)}') + logging.warning("Email could not be sent. Error: %s", str(e)) finally: server.quit() From 93569e5f6107da070f4646ba982c098c4693ae62 Mon Sep 17 00:00:00 2001 From: adipai Date: Thu, 12 Oct 2023 14:27:45 -0400 Subject: [PATCH 2/2] Updated test suite --- Code/recommenderapp/search.py | 4 +- test/test_search.py | 45 +++++++++---- test/tests.py | 115 +++++++++++++++++++++++++--------- 3 files changed, 118 insertions(+), 46 deletions(-) diff --git a/Code/recommenderapp/search.py b/Code/recommenderapp/search.py index dce873a2f..56ee49a6f 100644 --- a/Code/recommenderapp/search.py +++ b/Code/recommenderapp/search.py @@ -67,5 +67,5 @@ def results_top_ten(self, word): return self.results(word)[:10] -if __name__ == "__main__": - app.run() +#if __name__ == "__main__": +# app.run() diff --git a/test/test_search.py b/test/test_search.py index 6fc5b1188..e5c8cb788 100644 --- a/test/test_search.py +++ b/test/test_search.py @@ -1,3 +1,7 @@ +""" +Test suit for search feature +""" + import unittest import warnings import sys @@ -8,12 +12,18 @@ warnings.filterwarnings("ignore") - class Tests(unittest.TestCase): - def testSearchToy(self): + """ + Test cases for search feature + """ + + def test_search_toy(self): + """ + Test case 1 + """ search_word = "toy" - search = Search() - filtered_dict = search.resultsTop10(search_word) + finder = Search() + filtered_dict = finder.results_top_ten(search_word) expected_resp = [ "Toy Story (1995)", "Toys (1992)", @@ -26,10 +36,13 @@ def testSearchToy(self): ] self.assertTrue(filtered_dict == expected_resp) - def testSearchLove(self): + def test_search_love(self): + """ + Test case 2 + """ search_word = "love" - search = Search() - filtered_dict = search.resultsTop10(search_word) + finder = Search() + filtered_dict = finder.results_top_ten(search_word) expected_resp = [ "Love & Human Remains (1993)", "Love Affair (1994)", @@ -44,17 +57,23 @@ def testSearchLove(self): ] self.assertTrue(filtered_dict == expected_resp) - def testSearchGibberish(self): + def test_search_gibberish(self): + """ + Test case 3 + """ search_word = "gibberish" - search = Search() - filtered_dict = search.resultsTop10(search_word) + finder = Search() + filtered_dict = finder.results_top_ten(search_word) expected_resp = [] self.assertTrue(filtered_dict == expected_resp) - def testSearch1995(self): + def test_search_1995(self): + """ + Test case 4 + """ search_word = "1995" - search = Search() - filtered_dict = search.resultsTop10(search_word) + finder = Search() + filtered_dict = finder.results_top_ten(search_word) expected_resp = [ "Toy Story (1995)", "Jumanji (1995)", diff --git a/test/tests.py b/test/tests.py index c7d784455..82d3fc552 100644 --- a/test/tests.py +++ b/test/tests.py @@ -1,120 +1,173 @@ +""" +Test suite for recommender system +""" + import unittest import warnings import sys sys.path.append("../") -from Code.prediction_scripts.item_based import recommendForNewUser +from Code.prediction_scripts.item_based import recommend_for_new_user warnings.filterwarnings("ignore") class Tests(unittest.TestCase): - def testToyStory(self): + """ + Test cases for recommender system + """ + + def test_toy_story(self): + """ + Test case 1 + """ ts = [ {"title": "Toy Story (1995)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue("Toy Story 3 (2010)" in recommendations) - def testKunfuPanda(self): + def test_kunfu_panda(self): + """ + Test case 2 + """ ts = [ {"title": "Kung Fu Panda (2008)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue("Toy Story (1995)" in recommendations) - def testHorrorWithCartoon(self): + def test_horror_with_cartoon(self): + """ + Test case 3 + """ ts = [ {"title": "Strangers, The (2008)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("Toy Story (1995)" in recommendations) == False) - def testIronMan(self): + def test_iron_man(self): + """ + Test case 4 + """ ts = [ {"title": "Iron Man (2008)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("Avengers: Infinity War - Part I (2018)" in recommendations)) - def testRoboCop(self): + def test_robo_cop(self): + """ + Test case 5 + """ ts = [ {"title": "RoboCop (1987)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("RoboCop 2 (1990)" in recommendations)) - def testNolan(self): + def test_nolan(self): + """ + Test case 6 + """ ts = [ {"title": "Inception (2010)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("Dark Knight, The (2008)" in recommendations)) - def testDC(self): + def test_dc(self): + """ + Test case 7 + """ ts = [ {"title": "Man of Steel (2013)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue( ("Batman v Superman: Dawn of Justice (2016)" in recommendations) ) - def testArmageddon(self): + def test_armageddon(self): + """ + Test case 8 + """ ts = [ {"title": "Armageddon (1998)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("2012 (2009)" in recommendations)) - def testLethalWeapon(self): + def test_lethal_weapon(self): + """ + Test case 9 + """ ts = [ {"title": "Lethal Weapon (1987)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("Lethal Weapon 3 (1992)" in recommendations)) - def testDarkAction(self): + def test_dark_action(self): + """ + Test case 10 + """ ts = [ {"title": "Batman: The Killing Joke (2016)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("Punisher: War Zone (2008)" in recommendations)) - def testDark(self): + def test_dark(self): + """ + Test case 11 + """ ts = [ {"title": "Puppet Master (1989)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("Black Mirror: White Christmas (2014)" in recommendations)) - def testHorrorComedy(self): + def test_horror_comedy(self): + """ + Test case 12 + """ ts = [ {"title": "Scary Movie (2000)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("I Sell the Dead (2008)" in recommendations)) - def testSuperHeroes(self): + def test_super_heroes(self): + """ + Test case 13 + """ ts = [ {"title": "Spider-Man (2002)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("Iron Man 2 (2010)" in recommendations)) - def testCartoon(self): + def test_cartoon(self): + """ + Test case 14 + """ ts = [ {"title": "Moana (2016)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("Monsters, Inc. (2001)" in recommendations)) - def testMultipleMovies(self): + def test_multiple_movies(self): + """ + Test case 15 + """ ts = [ {"title": "Harry Potter and the Goblet of Fire (2005)", "rating": 5.0}, {"title": "Twilight Saga: New Moon, The (2009)", "rating": 5.0}, ] - recommendations = recommendForNewUser(ts) + recommendations = recommend_for_new_user(ts) self.assertTrue(("Twilight (2008)" in recommendations))