def compute(movieID, userID, ratings_sum=None, review_count=None, banned_users=None): ''' This method computes a movie's average rating, free of the influence of banned users. If the caller already knows the movie's ratings sum or review count, or the FilmFinders banned by the user, these can be passed in to make the computation more efficient. ''' session = Session() if ratings_sum is None or review_count is None: query = session.query( Movie.ratings_sum, Movie.review_count).filter(Movie.movieID == movieID).one_or_none() ratings_sum, review_count = query if query else (0, 0) if banned_users is None: banned_users = tuple( banned_user for banned_user, in session.query(BannedList.bannedUserID).filter( BannedList.userID == userID)) banned_user_ratings = session.query(MovieReview.rating)\ .filter(MovieReview.movieID == movieID, MovieReview.userID.in_(banned_users) ).all() review_count -= len(banned_user_ratings) rating_times_ten = ((ratings_sum - sum(rating for rating, in banned_user_ratings)) / review_count)\ * 10\ if review_count\ else 0 # This is to ensure multiples of 0.05 are always rounded up, # in contrast to the behaviour of Python's round() method. # Reference: <https://stackoverflow.com/questions/33019698/how-to-properly-round-up-half-float-numbers-in-python> return floor(rating_times_ten) / 10 if rating_times_ten - floor(rating_times_ten) < 0.5\ else ceil(rating_times_ten) / 10
def get(self): ''' View list of movies in user's Watchlist :return: ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() session = Session() userID = g.userID is_valid_integer(userID) results = session.query(Movie.movieID, Movie.title, Movie.year, Movie.ratings_sum, \ Movie.review_count).filter(Watchlist.userID == userID) \ .filter(Watchlist.movieID == Movie.movieID) movies = list() for movieID, title, year, ratings_sum, review_count in results: movies.append({ 'movieID': movieID, 'title': title, 'year': year, 'rating': str(compute(movieID, userID, ratings_sum, review_count)) }) response = {'watchlist': movies} return response, 200
def post(self): # Get params username = request.json.get('username') username = cleanString(username) yob = request.json.get('yob') email = request.json['email'] email = cleanString(email) isValidEmail(email) password = request.json['password'] session = Session() if session.query(User).filter(User.email == email).first(): raise BadRequest hashed_password = HashGenerator(password).generate() new_user = User(username, email, hashed_password, yob) session.add(new_user) session.commit() session.close() response = {'message': 'Registration successful.'} return response, 201
def readWriteComputeMoviePred(): session = Session() fc = pd.read_sql('filmCast', session.bind) fd = pd.read_sql('filmDirectors', session.bind) person = pd.read_sql('persons', session.bind) genre = pd.read_sql('genreOfFilm', session.bind) genlist = pd.read_sql('genres', session.bind) movies = pd.read_sql('movies', session.bind) review = pd.read_sql('movieReviews', session.bind) session.close() return getPerdictionsOfMovies(fc, fd, person, genre, genlist, movies, review)
def readWriteComputeGenrePred(): session = Session() genreoffilm = pd.read_sql('genreOfFilm', session.bind) genre = pd.read_sql('genres', session.bind) gen = pd.merge(genreoffilm, genre, on = 'genreID') recoDir = 'RecSystem' dataDir = 'RecoData' location = path.join(recoDir, dataDir) movie_movie = pd.read_csv(path.join(location, 'movie_movie.csv'), header = 0) #load the movie-movie file session.close() return getPerdictionsOfGenres(gen, movie_movie)
def readWriteComputeDirectorPred(): session = Session() fd = pd.read_sql('filmDirectors', session.bind) person = pd.read_sql('persons', session.bind) final = pd.merge(person, fd, on='personID') final = final.drop(columns=['personID']) recoDir = 'RecSystem' dataDir = 'RecoData' location = path.join(recoDir, dataDir) movie_movie = pd.read_csv(path.join(location, 'movie_movie.csv'), header=0) # load the movie-movie file session.close() return getPredictionsOfDirectors(final, movie_movie)
def get(self): ''' Show list of subscribed users ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() session = Session() results = session.query(Subscription.subscribedUserID, User.username) \ .filter(Subscription.userID == g.userID) \ .filter(User.userID == Subscription.subscribedUserID) users = list() for id, username in results: users.append({'userID': id, 'username': username}) response = {'subscribedUsers': users} return response, 200
def readWriteComputeUserPred(): session = Session() dataset = pd.read_sql('movieReviews', session.bind) recoDir = 'RecSystem' dataDir = 'RecoData' location = path.join(recoDir, dataDir) movie_movie = pd.read_csv(path.join(location, 'movie_movie.csv'), header=0) # load the movie-movie file sub_dict = { userID: list(map(int, subscribedUserIDs.split(','))) for userID, subscribedUserIDs in session.query( Subscription.userID, func.group_concat(Subscription.subscribedUserID)).group_by( Subscription.userID) } session.close() return getPerdictionsOfUsers(dataset, sub_dict, movie_movie)
def get(self): ''' Search for movies by name, description, mood, genre or director. ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() args = parser.parse_args() page_size = args.get('page_size') is_valid_integer(page_size) page_index = args.get('page_index') is_valid_integer(page_index) name_keywords = validate_search_keywords(args.get('name')) description_keywords = validate_search_keywords(args.get('description')) director = validate_search_keywords(args.get('director')) genre = args.get('genre') mood = args.get('mood') if mood: genres = mood_mappings[mood] | {genre} if genre else mood_mappings[mood] else: genres = {genre} if genre else None session = Session() query = session.query(Movie.movieID, Movie.title, Movie.year, Movie.ratings_sum, Movie.review_count ).filter(Movie.title.ilike(f'%{name_keywords}%'), Movie.description.ilike(f'%{description_keywords}%') ).order_by(desc(Movie.average_rating(g.userID)), Movie.title) count = session.query(Movie.movieID).filter(Movie.title.ilike(f'%{name_keywords}%'), Movie.description.ilike(f'%{description_keywords}%') ) if director: query = query.join(FilmDirector).join(Person).filter(Person.name.ilike(f'%{director}%')).distinct() count = count.join(FilmDirector).join(Person).filter(Person.name.ilike(f'%{director}%')).distinct() if genres: query = query.join(GenreOfFilm).join(Genres).filter(Genres.genre.in_(genres)).distinct() count = count.join(GenreOfFilm).join(Genres).filter(Genres.genre.in_(genres)).distinct() banned_users = tuple(banned_user for banned_user, in session.query(BannedList.bannedUserID) .filter(BannedList.userID == g.userID) ) search_results = [{'movieID': movieID, 'title': title, 'year': year, 'rating': str(compute(movieID, g.userID, ratings_sum, review_count, banned_users)) } for movieID, title, year, ratings_sum, review_count in query.limit(page_size).offset(page_size * page_index) ] return {'data': search_results, 'count': count.count()}, 200
def delete(self, id): ''' Remove a FilmFinder from your Banned List. ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() is_valid_integer(id) session = Session() if not session.query(BannedList).filter(BannedList.userID == g.userID, BannedList.bannedUserID == id).delete(): # If the FilmFinder being unbanned is not in # the user's Banned List, raise an Exception. session.commit() raise NotFound session.commit() session.close() return {'message': 'Reviewer unbanned.'}, 200
def get(self): ''' View your Banned List. ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() banned_list = Session().query(User.userID, User.username)\ .join(BannedList, User.userID == BannedList.bannedUserID)\ .filter(BannedList.userID == g.userID) return [{ 'userID': userID, 'username': username } for userID, username in banned_list], 200
def post(self): ''' Adds a movie to the users' Watchlist. ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() movieID = request.json.get('movieID') is_valid_integer(movieID) new_watchlist = Watchlist(movieID, g.userID) session = Session() session.add(new_watchlist) try: session.commit() session.close() except IntegrityError: #If Watchlist already present session.rollback() raise BadRequest response = {'message': 'Movie added to Watchlist.'} return response, 201
def get(self): TokenAuthenticator(request.headers.get('Authorization')).authenticate() session = Session() cid = g.userID results = session.query(User.username, Movie.title, User.userID)\ .select_from(Subscription)\ .join(Wishlist, Wishlist.userID == Subscription.subscribedUserID)\ .join(Movie, Movie.movieID == Wishlist.movieID)\ .join(User, User.userID == Subscription.subscribedUserID)\ .filter(Subscription.userID == cid) movies = list() for username, title, userID in results: movies.append({ 'userID': userID, 'username': username, 'title': title }) response = {'movies': movies} return response, 200
def delete(self, userID): ''' Unsubscribe to said user. ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() session = Session() curUserID = g.userID # Can't subscribe to oneself. if curUserID == int(userID): raise BadRequest affectedRows = session.query(Subscription).filter(Subscription.userID == curUserID) \ .filter(Subscription.subscribedUserID == userID).delete() # When 0, it means userIDs are not present in database. if affectedRows == 0: raise NotFound else: session.commit() return 204
def get(self, id): ''' View a movie's full details. ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() is_valid_integer(id) session = Session() movie = session.query(Movie.movieID, Movie.title, Movie.year, Movie.description, Movie.ratings_sum, Movie.review_count ).filter(Movie.movieID == id).one_or_none() if not movie: raise NotFound genres = [genre for genre, in session.query(Genres.genre).join(GenreOfFilm) .filter(GenreOfFilm.movieID == id) ] directors = [director for director, in session.query(Person.name) .join(FilmDirector) .filter(FilmDirector.movieID == id) ] cast = [member for member, in session.query(Person.name).join(FilmCast) .filter(FilmCast.movieID == id) ] banned_users = tuple(banned_user for banned_user, in session.query(BannedList.bannedUserID) .filter(BannedList.userID == g.userID) ) reviews = session.query(User.userID, User.username, MovieReview.rating, MovieReview.review ).join(MovieReview).filter(MovieReview.movieID == id, User.userID.notin_(banned_users) ) reviews = [{'userID': userID, 'username': username, 'rating': str(rating), 'review': review } for userID, username, rating, review in reviews ] return {'movieID': id, 'title': movie.title, 'year': movie.year, 'description': movie.description, 'genre': genres, 'director': directors, 'cast': cast, 'rating': str(compute(id, g.userID, movie.ratings_sum, movie.review_count, banned_users)), 'reviews': reviews }, 200
def delete(self, movieID): ''' Removes said movie from current user's Wishlist. ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() session = Session() is_valid_integer(movieID) affectedRows = session.query(Wishlist).filter(Wishlist.movieID == movieID)\ .filter(Wishlist.userID == g.userID).delete() # When 0, it means either of movieID or userID are not present in database. if affectedRows == 0: raise NotFound else: session.commit() session.close() return 204
def post(self): ''' Subscribe to the user. ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() subscribedUserID = request.json.get('userID') curUserID = g.userID # Can't subscribe to oneself. if curUserID == int(subscribedUserID): raise BadRequest subscribe = Subscription(curUserID, subscribedUserID) session = Session() session.add(subscribe) try: session.commit() except IntegrityError: #If subscription already present session.rollback() raise BadRequest response = {'message': 'Subscribed to User'} return response, 201
def get(self, userID): ''' View said user's Wishlist of movies. ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() session = Session() is_valid_integer(userID) results = session.query(Movie.movieID, Movie.title, Movie.year, Movie.ratings_sum, \ Movie.review_count).filter(Wishlist.userID == userID)\ .filter(Wishlist.movieID == Movie.movieID) username = session.query(User.username).filter(User.userID == userID).first() if not username: raise NotFound movies = list() for movieID, title, year, ratings_sum, review_count in results: movies.append({'movieID': movieID, 'title': title, 'year': year, 'rating': str(compute(movieID, g.userID, ratings_sum, review_count)) }) # Check if current user is subscribed to said user res = session.query(Subscription).filter(Subscription.userID == g.userID) \ .filter(Subscription.subscribedUserID == userID).first() session.close() isSubscribed = False if res: isSubscribed = True response = {'username': username, 'wishlist': movies, 'isSubscribed': isSubscribed} return response, 200
def post(self, id): ''' Leave a movie review ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() is_valid_integer(id) validate_rating(request.json['rating']) validate_review(request.json['review']) session = Session() movie = session.query(Movie).filter(Movie.movieID == id).one_or_none() if not movie: raise NotFound query = session.query(MovieReview).filter( MovieReview.movieID == id, MovieReview.userID == g.userID).one_or_none() if query: # We disallow a user from leaving more than one review for the same movie. raise Forbidden query = session.query(Watchlist).filter( Watchlist.movieID == id, Watchlist.userID == g.userID).one_or_none() if not query: # When a user leaves a review for a film, we add that # film to his Watchlist if it isn't there already. session.add(Watchlist(id, g.userID)) request.json['rating'] = float(request.json['rating']) session.add( MovieReview(id, g.userID, request.json['rating'], request.json['review'])) movie.ratings_sum += request.json['rating'] movie.review_count += 1 session.commit() session.close() return {'message': 'Review saved.'}, 201
def post(self): ''' Add a FilmFinder to your Banned List. ''' TokenAuthenticator(request.headers.get('Authorization')).authenticate() is_valid_integer(request.json['userID']) session = Session() query = session.query(User).filter( User.userID == request.json['userID']).one_or_none() if not query: raise NotFound query = session.query(BannedList).filter( BannedList.userID == g.userID, BannedList.bannedUserID == request.json['userID']).one_or_none() if query or g.userID == request.json['userID']: # If the FilmFinder being banned is already in the user's Banned List, # or if a user is attempting to ban himself, raise an Exception. raise Forbidden # Remove a user's subscription to a FilmFinder when banning that FilmFinder. session.query(Subscription).filter( Subscription.userID == g.userID, Subscription.subscribedUserID == request.json['userID']).delete() session.add(BannedList(g.userID, request.json['userID'])) session.commit() session.close() return {'message': 'Reviewer banned.'}, 201
def get(self, movieID): TokenAuthenticator(request.headers.get('Authorization')).authenticate() is_valid_integer(movieID) userID = g.userID args = parser.parse_args() use_genre = args.get('use_genre') use_director = args.get('use_director') topMovieIds = list() movies = list() # Need this try/except block to catch errors when calling # recommendations if dataframes haven't loaded yet. try: movie = current_app.movieDf director = current_app.dirDf genre = current_app.genDf user = current_app.userDf topMovieIds = movie_similarity_calc(movieID=movieID, userID=userID, movie=movie, director=director, genre=genre, user=user, use_genre=use_genre, use_director=use_director) session = Session() result = session.query(Movie.movieID, Movie.title, Movie.year, Movie.ratings_sum, Movie.review_count).filter( Movie.movieID.in_(topMovieIds)).all() banned_users = tuple(banned_user for banned_user, in session.query(BannedList.bannedUserID)\ .filter(BannedList.userID == userID)) for id, title, year, ratings_sum, review_count in result: movies.append({ 'movieID': id, 'title': title, 'year': year, 'rating': compute(movieID, g.userID, ratings_sum, review_count, banned_users) }) movies.sort(key=lambda film: (-film['rating'], film['title'])) except ProgrammingError as pe: print("Df hasn't loaded yet.") except Exception as e: print("Df hasn't loaded yet.") response = {'movies': movies} return response, 200
processor.asc_process(category, number_of_offers=4, from_year=2005, to_year=2011, save=True) category = 'passat b8' processor.asc_process(category, number_of_offers=4, from_year=2014, to_year=2019, save=True) if __name__ == '__main__': start_time = time.time() my_logger = logging.getLogger('Offers_processor') logging.basicConfig(filename='{}.log'.format(sys.argv[0]), level=logging.DEBUG) my_provider = "portal" my_session = Session() test_allegro_processor(my_logger, my_session, my_provider) test_otomoto_processor(my_logger, my_session, my_provider) test_olx_processor(my_logger, my_session, my_provider) test_autoscout24_processor(my_logger, my_session, my_provider) stop_time = time.time() print('Duration: {0:.3} seconds'.format(stop_time - start_time))
def post(self, userID): TokenAuthenticator(request.headers.get('Authorization')).authenticate() session = Session() is_valid_integer(userID) # User not Found if not session.query(User).filter(User.userID == userID).first(): raise NotFound cID = g.userID # Can't subscribe to oneself. if cID == userID: raise BadRequest new = set(session.query(Wishlist.movieID).filter(Wishlist.userID == userID)) cur = set(session.query(Wishlist.movieID).filter(Wishlist.userID == cID)) # Add only absent movies toAdd = new.difference(cur) if toAdd: for movie in toAdd: for m in movie: wl = Wishlist(m, cID) session.add(wl) session.commit() session.close() response = {'message': 'Wishlisted Movies imported'} return response, 201 else: response = {'message': 'No Movies were imported'} return response, 200