Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

please answer the question correctly. Show the correct code, and the output of the code provided on screen. Please ensure its correct QUESTION: Ratings and

please answer the question correctly. Show the correct code, and the output of the code provided on screen. Please ensure its correct

QUESTION:

Ratings and Reviews - Part 3

For part 3 of ratings and reviews you are provided the solutions to part 2 with a few modifications as a starting point. You will further modify this solution to be able to rate more than just songs by applying the OOP principles we've been studying in class. To do this you will refactor the existing code and reuse as much code as possible while adapting it to function with more than just songs. Once the code is refactored you will add functionality to sort rated items and generate top k lists based on different criteria.

Notes: -Part 3 of each project will be worth 6 proficiency points instead of 4 -All Utilities and RatingsManager methods have been made static -There is a new class called Review that stores an integer rating along with a String review. This will replace the int ratings used in the first 2 parts of this project. -averageRatingOfReviews and bayesianAverageOfReviews have been added to Utilities to compute averages of Reviews -Each step is worth 1 Proficiency Point for a total of 6 available points -The amazon reviews file only contains a small subset of the reviews for each product which may cause a discrepancy between the computed star ratings and the rating on the site. Specifically, all reviews containing commas were removed in order to simplify your parsing tasks allowing you to use split(",")

Amazon data provided by: Ups and downs: Modeling the visual evolution of fashion trends with one-class collaborative filtering R. He, J. McAuley WWW, 2016

and

Image-based recommendations on styles and substitutes J. McAuley, C. Targett, J. Shi, A. van den Hengel SIGIR, 2015

** Step 1: Implement Ratable and Refactor Song Create an abstract class called Ratable in the code.ratables package and refactor the Song class to extend Ratable. This class will be extended by any class that can be rated on a 1-5 scale and we will move much of the code from the Song class into the Ratable abstract class. This will make it easier to add new types that can be rated beyond songs without rewriting our entire program.

You must add the following to the Ratable abstract class while updating the Song class where noted.

Instance variables: -Add an ArrayList of Review objects to the Ratable abstract class to store all the ratings and reviews of each Ratable --This replaces the ratings ArrayList variable in the Song class (Remove ratings from the Song class) -Add a String variable to the Ratable abstract class that will store the id of each Ratable --This replaces the youtubeID variable in the Song class (Remove youtubeID from the Song class) --In the Song constructor assign the id variable inherited from the Ratable class to the YouTube id

Constructor: -Add a default constructor to Ratable that initializes the ArrayList of Reviews to an empty ArrayList

Abstract methods: -Add getLink() to Ratable that will return a link as a String corresponding to the Ratable --Implement this method in the Song class to return the YouTube Link for the song using the inherited id variable -Add getDescription() to Ratable that will return a String description of the Ratable --Implement this method in the Song class to return a String in the format "artist - title"

Concrete methods: -Add getID() to Ratable that returns the value of the instance variable storing the id --Remove getYoutubeID() from the Song class -Add getReviews() to Ratable that returns the instance variable storing the ArrayList of Reviews --Remove the getRatings() method from the Song class --*Note: After changing this method you will have to update each method in RatingsManager that calls getRatings() to getReviews() and edit the methods to use an ArrayList instead of an ArrayList -Add addRating(int rating) to Ratable that adds a new Review to the reviews instance variable --the new review will only contain an int rating without a text review --Remove the method with this same name from the Song class -Add addRatingWithReview(int rating, String review) to Ratable that adds a new Review with an int rating and a text review to the reviews instance variable

Cleanup: -Once Ratable and Song are refactored you can uncomment the toString method in Ratable and remove the toString method from Song. Song will inherit this method from Ratable -You can either update the play and playList methods or delete them

** Step 2: Refactor RatingsManager to use Ratable instead of Song -In RatingsManager, rewrite the ReadSongCSVFile method to return an ArrayList instead of a HashMap --Hint: You can still create the HashMap and leave most of the method in tact, but add all the values of the HashMap into a new ArrayList at the end of the method and return the ArrayList. Since Song is now a Ratable you can add the Songs to an ArrayList of type Ratable -In RatingsManager, modify the allFives and bayesianRatingThreshold methods to take an ArrayList instead of a String representing a filename as input and return an ArrayList of type Ratable instead of an ArrayList of type Song -In RatingsManager, modify the songsByArtist method to take an ArrayList instead of a String representing a filename as input. Or you can delete songsByArtist as it is not being graded in this submission.

** Step 3: Amazon ratings and reviews Now that the existing code base has been refactored we will take advantage of the new structure and add more functionality using OOP. For this step you will create a Product class in the code.ratables package that extends the Ratable abstract class. This class will be used to store ratings and reviews of Amazon products. The data will be provided from http://jmcauley.ucsd.edu/data/amazon/. Implement the Product class with the following.

Constructor: -A constructor that takes 1 String and sets its value to the id variable inherited from the Ratable class

Abstract Methods: -Implement the inherited getLink() method to return the String "https://www.amazon.com/dp/" concatenated with the value of the id variable -Implement the inherited getDescription() method to return only the value of the inherited id variable --Note: The product details are not provided with the data. You can visit the product link what's being rated

File Reader -In the RatingsManager class implement the readProductCSVFile method to read a file containing Product ratings and reviews in the format "asin,reviewerName,rating,review" where asin is the id for the product. You must add both the rating and review to each Product object similar to the way ratings were added to Songs. To add both you should use the method addRatingWithReview(int rating, String review) inherited from the Ratable class that you implemented.

** Step 4: Custom sorting Study the provided AlphabeticalComparator class and its sortAlphabetically method before attempting this step. This class and method are provided as an example of sorting custom types. By using these we can sort an ArrayList of Ratables alphabetically by their description.

a. Create and implement a class named NumberOfReviewsComparator in the code.comparators package that sorts Ratables by number of reviews in decreasing order and implement the sortByNumberOfReviews method in RatingsManager to sort an ArrayList of Ratables by number of ratings (the size of the reviews ArrayList).

b. Create and implement a class named AverageRatingComparator in the code.comparators package that sorts by average rating in decreasing order and implement the sortByAverageRating method in RatingsManager that sorts an ArrayList of Ratables by average rating.

** Step 5: Top k lists Implement the getTopK method according to the comments in the RatingsManager class. This method will produce top k lists based on an input Comparator. By using the Ratable abstract class and the Comparator interface we can use this one method to compute top k lists of Songs or Products based on average ratings, bayesian rating, number of reviews, or alphabetically by description. We can also add more Ratables or Comparators that will be compatible with our existing code as long as we implement the few abstract methods required by inherited types.

** Step 6: Sorting by bayesian average Create and implement a class named BayesianAverageComparator in the code.comparators package that sorts by bayesian rating in decreasing order and implement the sortByBayesianAverage method in RatingsManager that sorts an ArrayList of Ratables by bayesian rating. This method takes as parameters the two numbers required to compute the bayesian averages. Since these numbers must be used by BayesianAverageComparator, they must be "sent" to an instance of this class. To do this you can implement the following in the BayesianAverageComparator class.

-Instance variables to store the 2 numbers -A constructor that takes the 2 numbers as parameters and assigns their values to the instance variables -Use these 2 instance variables when comparing the two Ratables in the compare method

Remember that the Comparator class are just like any other classes and you can use all the techniques we've used while studying classes and objects. The ony difference is that you must also implement the compare method from the Comparator interface. In this case we'll use a constructor and instance variables to help us implement the compare method.

DRIVER.JAVA

package code;

public class Driver{

/** * This class contains test code that calls the methods from RatingsManager. You can, and should, edit * this file to test various aspects of your program or to find new music */ public static void main(String[] args){

String filenameAllSongs = "data/all_ratings.csv"; String filenameProducts = "data/amazonReviews.csv";

// Edit these values to change the program behavior int numberOfExtraRatings = 3; double extraRatingValue = 3.0; double threshold = 4.2; int k = 20;

// uncomment this code as you implement the methods to test their functionality

// ArrayList songs = RatingsManager.readSongCSVFile(filenameAllSongs); // ArrayList products = RatingsManager.readProductCSVFile(filenameProducts); // // ArrayList songsAboveThreshold = RatingsManager.bayesianRatingThreshold(songs, numberOfExtraRatings, extraRatingValue, threshold); // RatingsManager.printList(songsAboveThreshold); // // ArrayList productsAboveThreshold = RatingsManager.bayesianRatingThreshold(products, numberOfExtraRatings, extraRatingValue, threshold); // RatingsManager.printList(productsAboveThreshold); // // RatingsManager.sortAlphabetically(songs); // RatingsManager.printList(songs); // // // System.out.println(); // RatingsManager.printList(RatingsManager.getTopK(songs, k, new BayesianAverageComparator(numberOfExtraRatings, extraRatingValue))); // // System.out.println(); // RatingsManager.printList(RatingsManager.getTopK(products, k, new BayesianAverageComparator(numberOfExtraRatings, extraRatingValue))); }

}

RATINGSMANAGER.JAVA

package code;

import code.comparators.AlphabeticalComparator; import code.ratables.Ratable; import code.ratables.Song;

import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap;

public class RatingsManager{

/** * Return a map of YouTubeID's to Song objects containing all the information from the provided file. * * In this method, and others in this class, you are provided a filename for a csv file containing song * ratings. Each line of these files will be in the format "YouTubeID,artist,songName,rating" where the * YouTubeID is an 11 character String identifying the video for the song and the rating is an integer * in the range 1-5 inclusive. * * Since the YouTubeID's will be unique (no duplicates) we will use them as the keys in the HashMap. This * allows us to quickly find a specific song given its id by calling .get on the HashMap. The values of * this HashMap will be Song objects containing the information for each Song. Review the Song class in * the ratables package to find all the methods that can be called on these Songs. Most notably you will * need the following Song methods: * * // Create a new Song * Song song = new Song("DmeUuoxyt_E", "Nickleback", "Rockstar"); * * // Add a rating to a song * song.addRating(5); * song.addRating(4); * * // Get an ArrayList of all ratings for a Song * ArrayList ratings = song.getRatings(); * * Hint: When a song has multiple ratings in the file you must not add the song to the map a second time * or the original song will be overwritten (no duplicates in a HashMap). Instead, you only want ot call the * addRating method on the existing song in the HashMap. One way to avoid overwriting the song is to * call putIfAbsent(key, value) when putting a key-value pair into the HashMap. This method is used in the * same way as the .put(key, value) method except it will not do anything if the key already exists in * the HashMap. * * @param filename The name of a csv file containing song ratings * @return A map of YouTubeID's to Song objects containing all the information from the provided file */ public static HashMap readSongCSVFile(String filename){ HashMap songs = new HashMap<>(); try{ for(String line : Files.readAllLines(Paths.get(filename))){ String[] values = line.split(","); String id = values[0]; String artist = values[1]; String title = values[2]; int rating = new Integer(values[3]);

songs.putIfAbsent(id, new Song(id, artist, title)); songs.get(id).addRating(rating); } }catch(IOException e){ e.printStackTrace(); }

return songs; }

public static ArrayList readProductCSVFile(String filename){ return null; }

/** * Return every song that has only 5 star ratings (average rating of 5.0) * * Note: These songs all have the highest possible average rating and there are a lot of them! In the * all_ratings.csv there are 505 such songs which would make it meaningless to sort the songs by * their average rating. For this reason, we will only consider their Bayesian average when searching for * the top songs * * @param filename The name of a csv file containing song ratings * @return A list of all songs with an average rating of 5.0 */ public static ArrayList allFives(String filename){ ArrayList ans = new ArrayList<>(); HashMap songs = readSongCSVFile(filename); for(Song song : songs.values()){ if(songAllFives(song)){ ans.add(song); } } return ans; }

// Helper method used to implement allFives private static boolean songAllFives(Song song){ for(int rating : song.getRatings()){ if(rating != 5){ return false; } } return true; }

/** * Return a list of all songs with a Bayesian average greater than or equal to the threshold. * * Note: calling this method with 0 extra ratings will return the same results as the using * the average rating without Bayesian averaging. * * Hint: For each song you can call .getRatings() to access its ratings and use this as * an input to your Bayesian average method from step 3.2. You can use any method from * the Utilities class through the utils instance variable as follows: * * double average = utils.averageRating(4, 5); * * @param filename The name of a csv file containing song ratings * @param numberOfExtraRatings The number of extra ratings to be added to the average * @param extraRatingValue The value of the extra ratings * @param threshold The minimum Bayesian rating of the returned songs * @return All songs from filename with a Bayesian average greater than, or equal to, threshold */ public static ArrayList bayesianRatingThreshold(String filename, int numberOfExtraRatings, double extraRatingValue, double threshold){

ArrayList ans = new ArrayList<>(); HashMap songs = readSongCSVFile(filename); for(Song song : songs.values()){ double avg = Utilities.bayesianAverage(song.getRatings(), numberOfExtraRatings, extraRatingValue); if(avg >= threshold){ ans.add(song); } } return ans; }

/** * Return all rated songs by the given artist. * * Hint: When comparing String, as well as any other objects, in java you should use the .equals method * and not the == operator. Using == does not always return true even when the two Strings have identical * values. However, the .equals method will compare the values of the Strings and return true only if these * values are identical (same characters in the same order). * * Example: * String x = "hello"; * String y = "hello"; * if(x.equals(y)){ * System.out.println("hello!"); * } * * Note: For this assignment you should only return the songs that match the provided artist String exactly. * However, this this may miss some songs when the rater did not use proper capitalization, didn't add * spaces, or even misspelled the artists name. * * @param filename The name of a csv file containing song ratings * @param artist The artist to be searched * @return All songs by the artist that have been rated in the provided file */ public static ArrayList songsByArtist(String filename, String artist){ ArrayList ans = new ArrayList<>(); HashMap songs = readSongCSVFile(filename); for(Song song : songs.values()){ if(song.getArtist().equals(artist)){ ans.add(song); } } return ans; }

/** * Prints a list of ratables to the console with one ratable per line instead of on a single line as is the * behavior of printing an ArrayList directly * * @param ratables A list of ratables to be printed */ public static void printList(ArrayList ratables){ if(ratables != null){ for(Ratable ratable : ratables){ System.out.println(ratable); } } }

/** * Sorts the input list alphabetically by description * * @param ratables The Ratables to be sorted */ public static void sortAlphabetically(ArrayList ratables){ Collections.sort(ratables, new AlphabeticalComparator()); }

/** * Sorts the input list by number of reviews in decreasing order (The most reviewed Ratable should be at index 0) * * @param ratables The Ratables to be sorted */ public static void sortByNumberOfReviews(ArrayList ratables){ // TODO Implement this method }

/** * Sorts the input list by average rating in decreasing order (The highest rated Ratable should be at index 0) * * @param ratables The Ratables to be sorted */ public static void sortByAverageRating(ArrayList ratables){ // TODO Implement this method }

/** * return an ArrayList containing the top k ratables according to the given Comparator * * Hint: You can fist sort the ArraList with the Comparator, then copy the Ratables from index 0 to k-1 into a * new ArrayList to return * * @param ratables The Ratables to be sorted * @param k The number of top ratables to be returned (Ex. if k=10 you'll return a top ten list) * @param comparator A Comparator to define the sorting order * @return The top k list based on the given Comparator */ public static ArrayList getTopK(ArrayList ratables, int k, Comparator comparator){ // TODO Implement this method return null; }

/** * Sorts the input list by bayesian rating in decreasing order (The highest rated Ratable should be at index 0) * * @param ratables The Ratables to be sorted * @param numberOfExtraRatings The number of extra ratings to be added to the average * @param extraRatingValue The value of the extra ratings */ public static void sortByBayesianAverage(ArrayList ratables, int numberOfExtraRatings, double extraRatingValue){ // TODO Implement this method }

}

REVIEW.JAVA

package code;

/** * Used to store a ratings and text review in a single instance */ public class Review{

private int rating; private String review;

/** * If only a rating is provided, set the review to the empty String * * @param rating An integer rating in the range 1-5 */ public Review(int rating){ this(rating, ""); }

public Review(int rating, String review){ this.rating = rating; this.review = review; }

public int getRating(){ return this.rating; }

public String getReview(){ return this.review; }

@Override public String toString(){ if(this.review.equals("")){ return "" + this.rating; }else{ return "(" + this.rating + ", " + this.review + ")"; } } }

UTILITIES.JAVA

package code;

import java.util.ArrayList;

/** * This class contains a variety of methods that will be used throughout the Ratings and Reviews * project. */ public class Utilities{

/** * Computes the average of any number of ratings * * @param ratings A list of integer ratings in the range of 1-5 inclusive * @return The average of all ratings in the list as a double */ public static double averageRating(ArrayList ratings){ double sum = 0; for(int i : ratings){ sum += i; } return sum / ratings.size(); }

/** * Computes the average of any number of ratings provided in Review objects * * @param reviews A list of integer ratings in the range of 1-5 inclusive * @return The average of all ratings in the list as a double */ public static double averageRatingOfReviews(ArrayList reviews){ double total = 0.0; for(Review review : reviews){ total += review.getRating(); } return total / reviews.size(); }

/** * Computes the Bayesian average of any number of reviews * * Hint: You can call your method from 3.1 to compute the standard average of the ratings then * call the Bayesian average method from part 1 to compute the Bayesian average. * * @param ratings A list of integer ratings in the range of 1-5 inclusive * @param numberOfExtraRatings The number of extra ratings to be added to the average * @param extraRatingValue The value of the extra ratings * @return The Bayesian average of all ratings in the list as a double */ public static double bayesianAverage(ArrayList ratings, int numberOfExtraRatings, double extraRatingValue){ return bayesianAverage(averageRating(ratings), ratings.size(), numberOfExtraRatings, extraRatingValue); }

/** * Computes the Bayesian average of any number of reviews provided in Review objects * * Hint: You can call your method from 3.1 to compute the standard average of the ratings then * call the Bayesian average method from part 1 to compute the Bayesian average. * * @param reviews A list of integer ratings in the range of 1-5 inclusive * @param numberOfExtraRatings The number of extra ratings to be added to the average * @param extraRatingValue The value of the extra ratings * @return The Bayesian average of all ratings in the list as a double */ public static double bayesianAverageOfReviews(ArrayList reviews, int numberOfExtraRatings, double extraRatingValue){ return bayesianAverage(averageRatingOfReviews(reviews), reviews.size(), numberOfExtraRatings, extraRatingValue); }

/** * Computes the average of two ratings * * @param rating0 An integer rating in the range of 1-5 inclusive * @param rating1 An integer rating in the range of 1-5 inclusive * @return the average of rating0 and rating1 as a double */ public static double averageRating(int rating0, int rating1){ return (rating0 + rating1) / 2.0; }

/** * Computes the average of three ratings * * @param rating0 An integer rating in the range of 1-5 inclusive * @param rating1 An integer rating in the range of 1-5 inclusive * @param rating2 An integer rating in the range of 1-5 inclusive * @return the average of rating0, rating1, and rating2 as a double */ public static double averageRating(int rating0, int rating1, int rating2){ return (rating0 + rating1 + rating2) / 3.0; }

/** * Computes the number of stars for a given rating to the nearest half star. This is * equivalent to rounding the input to the nearest 0.5. For example, a something with * a rating of 3.34 would have a star rating of 3.5 stars. * * @param rating An average rating as a double in the range of 1.0-5.0 inclusive * @return The star rating of the input rating */ public static double starRating(double rating){ return Math.round(rating * 2.0) / 2.0; }

/** * Updates an average rating after a new rating is made. * * @param average The current average rating * @param numberOfRatings The number of ratings contributing to the current average rating * @param newRatingValue The value of the new rating as a double in the range of 1.0-5.0 inclusive * @return The new average rating after the new rating has been applied */ public static double updateAverage(double average, int numberOfRatings, double newRatingValue){ return (average * numberOfRatings + newRatingValue) / (numberOfRatings + 1); }

/** * Computes the Bayesian average for the given inputs. The Bayesian average is computed * by adding a fixed number of extra ratings at a certain value to the current rating. * * Background: Sorting rated items by their Bayesian average can improve the usefulness of * their rankings. For example, an item with 1 rating of 5 with no other ratings will * be ranked higher than an item with 200 ratings at an average rating of 4.9. Most * likely we would prefer the later item. To address this we can rank the items by their * Bayesian rating and choose 5 extra ratings of 3 to be added to each item. Now the * first item has 1 rating of 5 and 5 ratings of 3 for a Bayesian average of 3.33 and the * second item has 200 ratings at an average of 4.9 and 5 ratings of 3 for a Bayesian * average of 4.85. Bayesian averages can be used in this way to lower ratings where * there is not enough information to make a judgment on the item. * * Hint: You can call your updateAverage method in a loop to complete this method * * @param average The current average rating * @param numberOfRatings The number of ratings contributing to the current average rating * @param numberOfExtraRatings The number of extra ratings to be added to the current average * @param extraRatingValue The value of the extra ratings * @return The new average after the extra ratings have been taken into account */ public static double bayesianAverage(double average, int numberOfRatings, int numberOfExtraRatings, double extraRatingValue){

int totalRatings = numberOfRatings; double rating = average; for(int i = 0; i < numberOfExtraRatings; i++){ rating = updateAverage(rating, totalRatings, extraRatingValue); totalRatings++; }

return rating; }

}

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image_2

Step: 3

blur-text-image_3

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

T Sql Window Functions For Data Analysis And Beyond

Authors: Itzik Ben Gan

2nd Edition

0135861446, 978-0135861448

More Books

Students also viewed these Databases questions

Question

107 MA ammeter 56 resistor ? V voltmeter

Answered: 1 week ago

Question

Generally If Drug A is an inducer of Drug B , Drug B levels will

Answered: 1 week ago