I have already done objective 1, looking forward for the answers for the rest. O
ID: 3716215 • Letter: I
Question
I have already done objective 1, looking forward for the answers for the rest.
Objective 1: Bayesian Average
Your first objective in this project is to compute the Bayesian average for a given list of ratings. The Bayesian average is computed by adding a fixed number of extra ratings at a certain value to the existing ratings.
Background
By comparing items based on their Bayesian average, as opposed to directly using the average of all review scores, we can improve the usefulness of these comparisons. For example, in a 5 star rating system an item with 1 rating of 5 stars 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 since we can be more confident that it is a highly rated item since there are 200 opinions being considered. To address this we can rank the items by their Bayesian rating and choose 5 extra ratings of 3 stars 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.
Tasks
Setup the structure for this project and write a method to compute the Bayesian average of a list of ratings.
Create a new project in Eclipse that will contain you work for all 5 objectives
Create a new package in the src folder named "ratings"
In the ratings package, create a new class named "Main" and write a main method in this class. This class will be the entry point for the project and will be the only class with a main method. You should use this class to test your project
Create a class named "RatingsAnalyzer" in the ratings package. In this new class, write a public static method named "bayesianAverage" that takes three parameters (an ArrayList of Doubles, an int, then a double) and returns a double. The first parameter represents all the ratings for a particular item, the second parameter is the number of additional ratings to add, and the third parameter is the value of these additional ratings. The return value is the bayesian average of these ratings based on these parameters.
Objective 2: Find the Best Song
Now that we can compute the Bayesian average of a list of ratings we can start computing ratings. The first ratings that we'll compute will be of songs. For this objective you will be given a csv file with song ratings and you'll compute the song with the highest Bayesian average.
sample_songs.csv
large_songs.csv
Tasks
Create a Song class, create Song instances based on data read from a file, and compute the Song with the highest Bayesian average.
Create a package named "ratables" inside the ratings package. In the newly created ratables package, create a class named "Song" containing the following methods. Note that none of these methods are static since they will belong to instances of the Song class and not the class itself:
A public constructor taking three Strings as parameters in the order (youTubeID, artist, title). These values must be stored in instance variables of your choosing
A public method named "getID" that takes no parameters and returns the youTubeID that was provided when the constructor was called as a String
A public method named "getLink" that takes no parameters and return the YouTube url for this song as a String. The url must be in the format "https://www.youtube.com/watch?v=###########" with ########### replaced with the youTubeID for this song
A public method named "getDescription" that takes no parameters and returns a String containing the artist and title provided when the constructor was called. The format of this description must be "artist - title", as in the artist of the song then the title of the song separated by the String " - "
A public method named "addRating" that takes a double as a parameter and returns void. The double represents a rating made for this song which must be stored in an instance variable. Note that this method will be called each time a new rating in found for the same song and all ratings must be stored in an instance variable
A public method named "getRatings" that takes no parameters and returns an ArrayList of Doubles containing every rating that was added to this song with the addRating method
[optional] You may add any other methods or instance variables that will help you complete the project objectives. For example, it is helpful to override the toString method so you can print out songs while testing your program to verify the output
Create a new class in the ratings package named "DataSources" that will contains methods that read data into our program. In this class write a public static method named "readSongCSVFile" that takes one String as a parameter and returns an ArrayList of Songs. The input parameter is the name of a csv file containing song ratings where each line is in the format "YouTubeID,artist,title,rating" This method will return all the data in this file in an ArrayList of Songs. Note that songs can be rated multiple times in the file and each rating must be recorded in the same Song object that represents that song. (Hint: The YouTubeIDs are unique and can be used to identify a song and can stored in a data structure to check if you've seen a song multiple times. For each line that is read from the file, check if the YouTubeID from the line is already in your data structure. If it is, the rating needs to be added to the existing Song instead of creating a new Song object. One way to do this is by using a HashMap of YouTubeIDs (Strings) to Song objects)
In the RatingsAnalyzer class write a public static method named "bestSong" that takes three parameters (an ArrayList of Songs, an int, and a double) and returns a Song. The method will return the Song from the parameter ArrayList with the highest Bayesian average. The int and double parameters are the number of extra reviews and the value of those reviews to be used while computing the Bayesian averages (You should call your method from objective 1 to compute these Bayesian averages)
Objective 3: Abstraction and Products
So far our program can find the best song by bayesian average, but what if we want to rate more than just songs? In this objective we will refactor our code so it can also be used for Amazon.com products. To do this we will create an abstract class that will be extended by both Song and Product classes. With this structure we can easily expand our program to rate anything we'd like by writing another class that extends our abstract class and implements its methods.
sample_products.csv
large_products.csv
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
Image-based recommendations on styles and substitutes J. McAuley, C. Targett, J. Shi, A. van den Hengel SIGIR, 2015
Tasks
In the ratables package create an abstract class named "Ratable" containing the following. Note that none of these methods are static:
A public default constructor (take no parameters). This constructor will be implicitly called whenever an extending classes constructor is called. You can use this constructor to initialize and instance variables that are needed by all sub-classes (ex. An ArrayList of Doubles storing all the ratings)
A public abstract method named "getID" that takes no parameters and returns a String. This method will be used to return a unique id for any type of Ratable
A public abstract method named "getLink" that takes no parameters and returns a String. This method will be used to return a url for any type of Ratable
A public abstract method named "getDescription" that takes no parameters and returns a String. This method will be used to a description for any type of Ratable
A public method named "addRating" that takes a double as a parameter and returns void. The double represents a rating made for this ratable which must be stored in an instance variable. Note this method is identical to the one from the Song class. The method is being moved from Song to Ratable
A public method named "getRatings" that takes no parameters and returns an ArrayList of Doubles containing every rating that was added to this ratable with the addRating method. Note this method is identical to the one from the Song class. The method is being moved from Song to Ratable
[optional] You may add any other methods or instance variables that will help you complete the project objectives. For example, it is helpful to override the toString method so you can print out ratables while testing your program to verify the output
Modify the Song class to extend the Ratable abstract class
Extend Ratable from Song using the extends keyword
Remove the addRating and getRatings methods from the Song class. Since Song now extends Ratable, and Ratable defines these methods, each Song will inherit these methods from the Ratable class
Note that since we already defined the three abstract methods from the Ratable class in the Song class there is no more work needed to extend Ratable from Song. However, depending on your previous implementation you may have to make a few more changes as needed (ex. Remove a line where you create a new ArrayList for the ratings)
In the ratables package create a class named "Product" that extends Ratable and containing the following:
A public constructor that takes 1 String as a parameter. This string represents the asin (Amazon Standard Identification Number) of the product and it should be stored in an instance variable
Implement the getID method to return the asin that was provided in the constructor call
Implement the getLink method to return a link to the product page for this product. The format of this url must be "https://www.amazon.com/dp/##########" where ########## is the asin for this product
Implement the getDescription method to return the asin for this product. Note that this is the same as the getID method
Now that we've implemented the 3 abstract methods we have completed this class
Now that we've refactored the our ratables to be either songs or products we will need to write methods in the rest of our program that will handle and ratables. To start, whenever we read data from a source we will return the data as Ratables instead of Songs or Products. For this task, write a public static method in the DataSources class named "readSongsAsRatables" that takes a String as a parameter and returns an ArrayList of Ratables. This method will read a csv file with Song ratings in the same format as in the readSongCSVFile method. The only difference is the return type which is an ArrayList of Ratables instead of an ArrayList of Songs. (Hint: you can call readSongCSVFile from this method and add all the Songs into a new ArrayList of Ratables)
Write a public static method in the DataSources class named "readProductCSVFile" that takes a String as a parameter and returns an ArrayList of Ratables. The input String is the name of a csv file where each line is in the format "asin,reviewerName,rating,review" and the output is an ArrayList of Ratables containing all the product ratings from this file.
In the RatingsAnalyzer class write a public static method named "bestRatable" that takes three parameters (an ArrayList of Ratable, an int, and a double) and returns a Ratable. The method will return the Ratable from the parameter ArrayList with the highest Bayesian average. The int and double parameters are the number of extra reviews and the value of those reviews to be used while computing the Bayesian averages. Note that this method can be used for Songs or Products.
Objective 4: Top k Lists
We have a lot of structure in place for our project are we have the flexibility to write code that can be used for Songs, Products, and any other class that we add as long as it extends Ratable. For this objective we now want to analyze the ratings beyond just finding the Ratable with highest Bayesian average.
Tasks
Write three Comparator classes for Ratables
In the ratings package create a new package named "comparators"
In the comparators package create a new class named AlphabeticalComparator that implements the Comparator of Ratable interface. Implement the compare method to order the ratables alphabetically, ignoring case, according to their descriptions (Use the getDescription method)
In the comparators package create a new class named NumberOfRatingsComparator that implements the Comparator of Ratable interface. Implement the compare method to order the ratables by the number of reviews for each ratable in decreasing order
In the comparators package create a new class named BayesianAverageComparator that implements the Comparator of Ratable interface. Implement the compare method to order the ratables by their bayesian average in decreasing order. For this class you will need a constructor that takes an int and a double as parameters representing the number of extra ratings and the value of these ratings and store these values in instance variables so they can be used in the compare method
In the RatingsAnalyzer class write a public static method named "getTopK" an ArrayList of Ratables, an int (k), and a Comparator of Ratables as parameters and returns an ArrayList of Ratables. This method returns the top k ratables from the ArrayList based on the provided Comparator. This method must return the list in order such that the first element is the first ratable according to the provided Comparator. Ties can be broken arbitrarily
While testing you top k method you should write code in your Main class that calls a method from your DataSources class to get an ArrayList of Ratables and call getTopK with this ArrayList.
Objective 5: The Internet
So far we've been reading data from csv files that are saved on our hard drive. Our next objective to access song data that is hosted on the Internet through a web API and use the data in our program. This will allow us to work with real-time data that is constantly updating
Task
Write a public static method in the DataSources class named "getSongsFromAPI" that takes no parameters and returns an ArrayList of Ratables. This method will access the API endpoint at the url "https://fury.cse.buffalo.edu/api/musicRatings/getAllSongs" which will return a JSON array where each element in the array is a JSON object in the format {"title":"No Regrets", "artist":"Aesop Rock", "ratings":[5,5,4,5], "youtubeID":"sClhmDN5Fcs"}. The method will return all the data given by the API in an ArrayList of Ratables
Explanation / Answer
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<Ratable> songs = RatingsManager.readSongCSVFile(filenameAllSongs);
// ArrayList<Ratable> products = RatingsManager.readProductCSVFile(filenameProducts);
//
// ArrayList<Ratable> songsAboveThreshold = RatingsManager.bayesianRatingThreshold(songs, numberOfExtraRatings, extraRatingValue, threshold);
// RatingsManager.printList(songsAboveThreshold);
//
// ArrayList<Ratable> 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)));
}
}
import java.util.ArrayList;
public class Product extends Ratable{
public Product(String id1){
id = id1;
}
@Override
public String getDescription() {
// TODO Auto-generated method stub
return id;
}
@Override
public ArrayList<String> ReviewObjects() {
// TODO Auto-generated method stub
return null;
}
@Override
public String id() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getLink() {
// TODO Auto-generated method stub
return "https://www.amazon.com/dp/"+id;
}
}
import java.util.ArrayList;
public abstract class Ratable{
//list of review objects
public ArrayList<Review> reviewObjs;
//id of ecan ratable
public String id;
// provided since it's required by the example AlphabeticalComparator class
//constructor
public Ratable(){
reviewObjs = new ArrayList<>();
}
public abstract String getDescription();
public abstract ArrayList <String> ReviewObjects();
public abstract String id();
public abstract String getLink();
public String getId(){
return id;
}
public ArrayList<Review> getReviews(){
return reviewObjs;
}
/**
* Adds a new rating to this song
*
* @param rating The rating to be added. Must be an integer between 1 and 5 inclusive
*/
public void addRating(Review rating){
reviewObjs.add(rating);
}
// After you implement the required methods you uncomment the toString method for more descriptive output
// @Override
// public String toString(){
// return "(" + this.getLink() + ") " + this.getDescription() + " | ratings: " + this.getReviews();
// }
}
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;
import java.util.Iterator;
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<Integer> 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 ArrayList<Ratable> readSongCSVFile(ArrayList<Ratable> filename){
HashMap<String, Song> songs = new HashMap<>();
ArrayList<Ratable> songs1 = new ArrayList<>();
try{
for(String line : Files.readAllLines(Paths.get(filename.get(0)))){
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));
songs1.add(songs.get(id));
}
}catch(IOException e){
e.printStackTrace();
}
return songs1;
}
public static ArrayList<Product> readProductCSV(String asin, String reviewerName, String rating, Review review){
}
public static ArrayList<Ratable> 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<Ratable> allFives(ArrayList<Ratable> filename){
ArrayList<Ratable> ans = new ArrayList<>();
//HashMap<String, Song> songs = readSongCSVFile(filename);
for(Ratable song : filename){
if(songAllFives(song)){
ans.add(song);
}
}
return ans;
}
// Helper method used to implement allFives
private static boolean songAllFives(Ratable 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<Song> bayesianRatingThreshold(ArrayList<Ratable> filename, int numberOfExtraRatings,
double extraRatingValue, double threshold){
ArrayList<Song> ans = new ArrayList<>();
HashMap<String, Song> 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<Song> songsByArtist(String filename, String artist){
ArrayList<Song> ans = new ArrayList<>();
HashMap<String, Song> 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<Ratable> 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<Ratable> 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<Ratable> 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<Ratable> 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<Ratable> getTopK(ArrayList<Ratable> ratables, int k, Comparator<Ratable> 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<Ratable> ratables, int numberOfExtraRatings, double extraRatingValue){
// TODO Implement this method
}
}
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 + ")";
}
}
}
package code.ratables;
import java.awt.*;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
public class Song extends Ratable{
//private ArrayList<Integer> ratings;
//private String youtubeID;
private String artist;
private String title;
/**
* The constructor used to create new Song instances
*
* @param youtubeID The 11 character unique id for the song
* @param artist The artist of the song
* @param title The title of the song
*/
public Song(String youtubeID, String artist, String title){
id = youtubeID;
this.artist = artist;
this.title = title;
//this.ratings = new ArrayList<>();
}
public String getArtist(){
return artist;
}
public String getTitle(){
return title;
}
/**
* Returns all the ratings that have been added to this song
*
* @return A list of ratings for this song
*/
public ArrayList<Review> getRatings(){
return reviewObjs;
}
/**
* Formats this song's YouTube ID into a full url
*
* @return A YouTube link for this song
*/
public String getLink(){
return "https://www.youtube.com/watch?v=" + id;
}
@Override
public String getDescription(){
return artist+" - "+title;
}
@Override
public String toString(){
return "(" + this.getLink() + ") " + this.getArtist() +
" - " + this.getTitle() + " | ratings: " + this.getRatings();
}
/**
* Play this song in the default web browser
*/
public void play(){
if(Desktop.isDesktopSupported()){
try{
String url = this.getLink();
Desktop.getDesktop().browse(new URI(url));
}catch(IOException e){
e.printStackTrace();
}catch(URISyntaxException e){
e.printStackTrace();
}
}
}
/**
* Opens a playlist of songs in YouTube using the machine's default we browser. A maximum of 50 songs
* can be added to a playlist
*
* @param songs A list of songs to play
*/
public static void playList(ArrayList<Song> songs){
if(songs != null && Desktop.isDesktopSupported()){
try{
String url = "https://www.youtube.com/watch_videos?video_ids=";
if(!songs.isEmpty()){
url += songs.get(0).getYoutubeID();
}
for(int i = 1; i < songs.size(); i++){
url += "," + songs.get(i).getYoutubeID();
}
Desktop.getDesktop().browse(new URI(url));
}catch(IOException e){
e.printStackTrace();
}catch(URISyntaxException e){
e.printStackTrace();
}
}
}
}
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<Integer> 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<Review> reviews){
double total = 0.0;
for(Review review : reviews){
total += review.getRating();//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<Integer> 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<Review> 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;
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.