diff --git a/.idea/modules.xml b/.idea/modules.xml
index 80d3e4c..c0e0ef5 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -5,6 +5,7 @@
+
\ No newline at end of file
diff --git a/Week3/Week3.iml b/Week3/Week3.iml
new file mode 100644
index 0000000..5173e2f
--- /dev/null
+++ b/Week3/Week3.iml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Week3/src/AllFilters.java b/Week3/src/AllFilters.java
new file mode 100644
index 0000000..3f5b388
--- /dev/null
+++ b/Week3/src/AllFilters.java
@@ -0,0 +1,24 @@
+import java.util.ArrayList;
+
+public class AllFilters implements Filter {
+ ArrayList filters;
+
+ public AllFilters() {
+ filters = new ArrayList<>();
+ }
+
+ public void addFilter(Filter f) {
+ filters.add(f);
+ }
+
+ @Override
+ public boolean satisfies(String id) {
+ for (Filter f : filters) {
+ if (!f.satisfies(id)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/Week3/src/DirectorsFilter.java b/Week3/src/DirectorsFilter.java
new file mode 100644
index 0000000..d0b7bf4
--- /dev/null
+++ b/Week3/src/DirectorsFilter.java
@@ -0,0 +1,25 @@
+/**
+ * A class for filter movies by directors
+ *
+ * @author Stanislav Rakitov
+ * @version 1.0
+ */
+public class DirectorsFilter implements Filter {
+ String directors;
+
+ public DirectorsFilter(String directors) {
+ this.directors = directors;
+ }
+
+ @Override
+ public boolean satisfies(String id) {
+ String movieDirectors = MovieDatabase.getDirector(id);
+ String[] filterDirectors = directors.split(",");
+ for (String direcor : filterDirectors) {
+ if (movieDirectors.contains(direcor)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Week3/src/EfficientRater.java b/Week3/src/EfficientRater.java
new file mode 100644
index 0000000..2014403
--- /dev/null
+++ b/Week3/src/EfficientRater.java
@@ -0,0 +1,47 @@
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * The class EfficientRater keeps track of one rater and all their ratings.
+ *
+ * @author Stanislav Rakitov
+ * @version 1.0
+ */
+public class EfficientRater implements Rater {
+ private final String myID;
+ private final HashMap myRatings;
+
+ public EfficientRater(String id) {
+ myID = id;
+ myRatings = new HashMap<>();
+ }
+
+ public void addRating(String movieID, Rating rating) {
+ myRatings.put(movieID, rating);
+ }
+
+ public boolean hasRating(String movieID) {
+ return myRatings.containsKey(movieID);
+ }
+
+ public String getID() {
+ return myID;
+ }
+
+ public double getRating(String movieID) {
+ Rating rating = myRatings.get(movieID);
+ if (rating != null) {
+ return rating.getValue();
+ } else {
+ return -1;
+ }
+ }
+
+ public int numRatings() {
+ return myRatings.size();
+ }
+
+ public ArrayList getItemsRated() {
+ return new ArrayList<>(myRatings.keySet());
+ }
+}
diff --git a/Week3/src/Filter.java b/Week3/src/Filter.java
new file mode 100644
index 0000000..7e799b2
--- /dev/null
+++ b/Week3/src/Filter.java
@@ -0,0 +1,3 @@
+public interface Filter {
+ boolean satisfies(String id);
+}
diff --git a/Week3/src/FirstRatings.java b/Week3/src/FirstRatings.java
new file mode 100644
index 0000000..4db2056
--- /dev/null
+++ b/Week3/src/FirstRatings.java
@@ -0,0 +1,384 @@
+import edu.duke.FileResource;
+import org.apache.commons.csv.CSVParser;
+import org.apache.commons.csv.CSVRecord;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+/**
+ * A class to process the movie and ratings data and to answer questions about them.
+ *
+ * @author Stanislav Rakitov
+ * @version 1.0
+ */
+public class FirstRatings {
+ private ArrayList movieArrayList;
+ private ArrayList raterArrayList;
+ private HashMap> directorsAndItsMovies;
+ private HashMap ratersWithIds;
+ private HashMap ratersAndCountOfRatings;
+ private HashMap> moviesAndRatersMap;
+ // The constrictor for only Movies
+ public FirstRatings(String fileName) {
+ String fullFileName = getFullFileName(fileName);
+ this.movieArrayList = loadMovies(fullFileName);
+ this.directorsAndItsMovies = getDirectorsAndMovies();
+ }
+ // The constructor for Movies and Raters
+ public FirstRatings(String fileNameMovies, String fileNameRaters) {
+ this(fileNameMovies);
+ String fullFileNameRaters = getFullFileName(fileNameRaters);
+ this.raterArrayList = loadRaters(fullFileNameRaters);
+ this.ratersWithIds = loadRatersWithIDs(raterArrayList);
+ this.ratersAndCountOfRatings = getAllRatersIdAndItsRatingsCounterMap();
+ this.moviesAndRatersMap = getAllMoviesAndRatesMap(this.movieArrayList);
+ }
+
+ public FirstRatings() {
+ // Maybe later..
+ }
+
+ public ArrayList getMovieArrayList() {
+ return movieArrayList;
+ }
+
+ public ArrayList getRaterArrayList() {
+ return raterArrayList;
+ }
+
+ /**
+ * This method returns number of unique Raters
+ *
+ * @return int number of unique raters
+ */
+ public int getRatersNumber() {
+ return ratersWithIds.size();
+ }
+
+ private HashMap> getAllMoviesAndRatesMap(ArrayList moviesList) {
+ HashMap> allMoviesAndRatesTempMap = new HashMap<>();
+ // fulfill map with all MoviesID with null ArrayList
+ for (Movie movie : moviesList) {
+ allMoviesAndRatesTempMap.putIfAbsent(movie.getID(), new ArrayList<>());
+ }
+
+ for (Rater rater : raterArrayList) {
+ ArrayList ratedMovies = rater.getItemsRated();
+ for (String ratedMovieID : ratedMovies) {
+ allMoviesAndRatesTempMap.get(ratedMovieID).add(rater.getID());
+ }
+ }
+
+ return allMoviesAndRatesTempMap;
+ }
+
+ private HashMap loadRatersWithIDs(ArrayList ratersList) {
+ HashMap map = new HashMap<>();
+ for (Rater rater : ratersList) {
+ map.put(rater.getID(), rater);
+ }
+ return map;
+ }
+
+ // Proceed map of all directors and its movies
+ private HashMap> getDirectorsAndMovies() {
+ HashMap> map = new HashMap<>();
+ for (Movie movie : movieArrayList) {
+ String movieName = movie.getTitle();
+ String[] directors = movie.getDirector().split(",");
+ for (String director : directors) {
+ director = director.trim();
+ HashSet set = new HashSet<>();
+ if (map.containsKey(director)) {
+ set = map.get(director);
+ set.add(movieName);
+ } else {
+ set.add(movieName);
+ map.put(director, set);
+ }
+ }
+ }
+ return map;
+ }
+
+ // Process every record from the CSV file.
+ ArrayList loadMovies(String filename) {
+
+ // Create empty list of Movie's
+ ArrayList moviesList = new ArrayList<>();
+
+ // Get Duke's FileResource.
+ FileResource fileResource = new FileResource(filename);
+
+ // Get Apache CSV
+ CSVParser csvRecords = fileResource.getCSVParser();
+
+ // Proceed every CSVRecord
+ for (CSVRecord record : csvRecords) {
+ moviesList.add(parseMovieCSVRecord(record));
+ }
+ return moviesList;
+ }
+
+ // Creates new Movie object
+ private Movie parseMovieCSVRecord(CSVRecord record) {
+ /* id(0),title(1),year(2),country(3),genre(4),director(5),minutes(6),poster(7)
+ * As it shows in CSV file
+ */
+ String id = record.get(0);
+ String title = record.get(1);
+ String year = record.get(2);
+ String country = record.get(3);
+ String genre = record.get(4);
+ String director = record.get(5);
+ // The constructor takes minutes as int
+ int minutes = Integer.parseInt(record.get(6));
+ String poster = record.get(7);
+
+ // return new Movie object
+ return new Movie(id, title, year, genre, director, country, poster, minutes);
+ }
+
+ /**
+ * A void method for tests cases.
+ *
+ *
+ * - determine how many movies in total.
+ *
- determine how many movies include the Comedy genre.
+ *
- determine how many movies are greater than 150 minutes in length.
+ *
- determine the maximum number of movies by any director, and who the directors are that
+ * directed that many movies.
+ *
+ */
+ public void testLoadMovies() {
+ int totalMoviesCount = movieArrayList.size();
+ int totalComedyCount = totalComedy();
+ int totalMoviesLonger150MinutesCount = total150();
+ String directorWithMaxFilms = maxFilmsOneDirectorName()[0];
+ String oneDirectorMaxFilmsCounter = maxFilmsOneDirectorName()[1];
+
+ System.out.printf("Note there are %d movies in this file.\n", totalMoviesCount);
+ System.out.println("How many of the movies include the Comedy genre? > " + totalComedyCount);
+ System.out.println(
+ "How many of these movies run longer than 150 minutes? > "
+ + totalMoviesLonger150MinutesCount);
+ System.out.println(
+ "What is the maximum number of films directed by one director? > "
+ + oneDirectorMaxFilmsCounter);
+ System.out.println(
+ "What is the name of the director who directed more films than any other "
+ + "director? "
+ + directorWithMaxFilms);
+ System.out.println("---");
+ }
+
+ // Determine the Director with max movies and its count
+ private String[] maxFilmsOneDirectorName() {
+ String director = "";
+ int counter = 0;
+ for (Map.Entry> pair : directorsAndItsMovies.entrySet()) {
+ if (pair.getValue().size() > counter) {
+ counter = pair.getValue().size();
+ director = pair.getKey();
+ }
+ }
+ String stringCounter = String.valueOf(counter);
+ return new String[] {director, stringCounter};
+ }
+
+ // determine how many movies are greater than 150 minutes in length.
+ private int total150() {
+ int counter = 0;
+ for (Movie movie : movieArrayList) {
+ if (movie.getMinutes() > 150) {
+ counter++;
+ }
+ }
+ return counter;
+ }
+
+ // determine how many movies include the Comedy genre
+ private int totalComedy() {
+ int counter = 0;
+ for (Movie movie : movieArrayList) {
+ if (movie.getGenres().toLowerCase().contains("comedy")) {
+ counter++;
+ }
+ }
+ return counter;
+ }
+
+ // Make full filename for any OS types
+ private static String getFullFileName(String fileName) {
+ if (!(new File(fileName).exists())) {
+ fileName =
+ System.getProperty("user.dir") + File.separator + "data" + File.separator + fileName;
+ }
+ return fileName;
+ }
+
+ public void testLoadRaters(String raterID, String movieID) {
+
+ // Use for test purposes
+ testPrintAllRaterWithRatings();
+
+ // find the number of ratings for a particular rater
+ printNumberOfRatings(raterID);
+
+ // Find the maximum number of ratings by any rater
+ printMaxNumOfRatings();
+
+ // Print the number of ratings a particular movie has
+ // String movieID = "1798709";
+ System.out.printf(
+ "How many ratings does the movie %s have? > %d\n",
+ movieID, getNumberOfRatingsByMovie(movieID));
+ // And how many different movies have been rated by all these raters
+
+ // total number of unique movies that have been rated
+ printTotalNumberMoviesRated();
+ }
+
+ // Q10. What is the total number of unique movies that have been rated?
+ private void printTotalNumberMoviesRated() {
+ int total = 0;
+ for (Map.Entry> entry : moviesAndRatersMap.entrySet()) {
+ if (entry.getValue() != null) {
+ total++;
+ }
+ }
+ System.out.println(
+ "What is the total number of unique movies that have been rated? > " + total);
+ }
+
+ // Get number of Ratings by MovieID
+ private int getNumberOfRatingsByMovie(String movieID) {
+ return moviesAndRatersMap.get(movieID).size();
+ }
+
+ // Determine how many raters have this maximum number of ratings and who those raters are.
+ private void printMaxNumOfRatings() {
+
+ // Find max rating value
+ int maxRatings = getMaxRatings();
+ System.out.println("What is the maximum number of ratings by any rater? > " + maxRatings);
+
+ for (Map.Entry entry : ratersAndCountOfRatings.entrySet()) {
+ if (entry.getValue() == maxRatings) {
+ System.out.println("Which rater rated the most number of movies? > " + entry.getKey());
+ }
+ }
+ }
+
+ // find the maximum number of ratings by any rater
+ private int getMaxRatings() {
+ int maxRatings = 0;
+ for (int counter : ratersAndCountOfRatings.values()) {
+ if (counter > maxRatings) {
+ maxRatings = counter;
+ }
+ }
+ return maxRatings;
+ }
+
+ // Get map with number of rates for every Rater
+ private HashMap getAllRatersIdAndItsRatingsCounterMap() {
+ HashMap map = new HashMap<>();
+ for (String id : ratersWithIds.keySet()) {
+ int count = getNumberOfRatingsByRaterID(id);
+ map.put(id, count);
+ } // for
+ return map;
+ }
+
+ // Find the number of ratings for a particular rater
+ private void printNumberOfRatings(String id) {
+ int ratingsCount = getNumberOfRatingsByRaterID(id);
+ System.out.printf("How many ratings does the rater number %s have? > %s\n", id, ratingsCount);
+ // System.out.printf("Rater id: %s has %d ratings\n", id, ratingsCount);
+ }
+
+ // Get total number of rates for specific rater's id
+ private int getNumberOfRatingsByRaterID(String id) {
+ return ratersWithIds.get(id).numRatings();
+ }
+
+ /*
+ Print the total number of raters. Then for each rater, print the rater’s ID and the number of
+ ratings they did on one line, followed by each rating (both the movie ID and the rating given)
+ on a separate line. If you run your program on the file ratings_short.csv you will see there
+ are five raters.
+ */
+ private void testPrintAllRaterWithRatings() {
+ // Print the total number of raters.
+ int totalRaterCount = raterArrayList.size();
+ System.out.printf("Note there are %d raters in this file.\n", totalRaterCount);
+
+ // Then for each rater, print the rater’s ID
+ // and the number of ratings they did on one line
+ // printAllRaterRatings();
+ }
+
+ // Print out number o rates for all raters
+ private void printAllRaterRatings() {
+ for (Map.Entry entry : ratersAndCountOfRatings.entrySet()) {
+ String raterId = entry.getKey();
+ int ratingsCount = entry.getValue();
+ System.out.printf("Rater id: %s has %d ratings\n", raterId, ratingsCount);
+ printAllRatingsByRater(raterId);
+ }
+ }
+
+ // Print all ratings for specific Rater ID
+ private void printAllRatingsByRater(String raterID) {
+ Rater rater = ratersWithIds.get(raterID);
+ ArrayList allRatedMoviesIDs = rater.getItemsRated();
+ for (String id : allRatedMoviesIDs) {
+ double rating = rater.getRating(id);
+ System.out.printf("Movie ID: %s, rating: %f\n", id, rating);
+ }
+ }
+
+ /*
+ * This method should process every record from the CSV file whose name is
+ * filename, a file of raters and their ratings
+ */
+ static ArrayList loadRaters(String fileName) {
+ ArrayList ratersList = new ArrayList<>();
+ ArrayList idsList = new ArrayList<>();
+
+ String fullFileName = getFullFileName(fileName);
+
+ // Get Duke's FileResource.
+ FileResource fileResource = new FileResource(fullFileName);
+
+ // Get Apache CSV
+ CSVParser csvRecords = fileResource.getCSVParser();
+
+ // Proceed every CSVRecord
+ for (CSVRecord record : csvRecords) {
+ // rater_id,movie_id,rating,time
+ String rater_id = record.get(0);
+ String movie_id = record.get(1);
+ double rating = Double.parseDouble(record.get(2));
+ String time = record.get(3);
+ if (!idsList.contains(rater_id)) {
+ Rater rater = new EfficientRater(rater_id);
+ ratersList.add(rater);
+ rater.addRating(movie_id, new Rating(movie_id, rating));
+ idsList.add(rater_id);
+ } else {
+ for (Rater r : ratersList) {
+ if (r.getID().equals(rater_id)) {
+ r.addRating(movie_id, new Rating(movie_id, rating));
+ }
+ }
+ }
+ }
+
+ return ratersList;
+ } // loadRaters
+} // class
diff --git a/Week3/src/GenreFilter.java b/Week3/src/GenreFilter.java
new file mode 100644
index 0000000..7913b96
--- /dev/null
+++ b/Week3/src/GenreFilter.java
@@ -0,0 +1,22 @@
+/**
+ * A class for filter movies by genre
+ *
+ * @author Stanislav Rakitov
+ * @version 1.0
+ */
+public class GenreFilter implements Filter {
+
+ private final String genre;
+
+ // The constructor should have one parameter named genre representing one genre,
+ // and the satisfies method should return true if a movie has this genre.
+ // Note that movies may have several genres.
+ public GenreFilter(String genre) {
+ this.genre = genre.toLowerCase();
+ }
+
+ @Override
+ public boolean satisfies(String id) {
+ return MovieDatabase.getGenres(id).toLowerCase().contains(genre);
+ }
+}
diff --git a/Week3/src/MinutesFilter.java b/Week3/src/MinutesFilter.java
new file mode 100644
index 0000000..18a51c0
--- /dev/null
+++ b/Week3/src/MinutesFilter.java
@@ -0,0 +1,26 @@
+/**
+ * A class for filter movies by time
+ *
+ * @author Stanislav Rakitov
+ * @version 1.0
+ */
+public class MinutesFilter implements Filter {
+ private final int minMinutes;
+ private final int maxMinutes;
+
+ public MinutesFilter(int minMinutes, int maxMinutes) {
+ this.minMinutes = minMinutes;
+ this.maxMinutes = maxMinutes;
+ }
+
+ // No max minutes given
+ public MinutesFilter(int minMinutes) {
+ this.minMinutes = minMinutes;
+ this.maxMinutes = Integer.MAX_VALUE;
+ }
+
+ @Override
+ public boolean satisfies(String id) {
+ return MovieDatabase.getMinutes(id) >= minMinutes && MovieDatabase.getMinutes(id) <= maxMinutes;
+ }
+}
diff --git a/Week3/src/Movie.java b/Week3/src/Movie.java
new file mode 100644
index 0000000..ae38dc3
--- /dev/null
+++ b/Week3/src/Movie.java
@@ -0,0 +1,82 @@
+// An immutable passive data object (PDO) to represent item data
+public class Movie {
+ private final String id;
+ private final String title;
+ private final int year;
+ private final String genres;
+ private String director;
+ private String country;
+ private String poster;
+ private int minutes;
+
+ public Movie(String anID, String aTitle, String aYear, String theGenres) {
+ // just in case data file contains extra whitespace
+ id = anID.trim();
+ title = aTitle.trim();
+ year = Integer.parseInt(aYear.trim());
+ genres = theGenres;
+ }
+
+ public Movie(
+ String anID,
+ String aTitle,
+ String aYear,
+ String theGenres,
+ String aDirector,
+ String aCountry,
+ String aPoster,
+ int theMinutes) {
+ // just in case data file contains extra whitespace
+ id = anID.trim();
+ title = aTitle.trim();
+ year = Integer.parseInt(aYear.trim());
+ genres = theGenres;
+ director = aDirector;
+ country = aCountry;
+ poster = aPoster;
+ minutes = theMinutes;
+ }
+
+ // Returns ID associated with this item
+ public String getID() {
+ return id;
+ }
+
+ // Returns title of this item
+ public String getTitle() {
+ return title;
+ }
+
+ // Returns year in which this item was published
+ public int getYear() {
+ return year;
+ }
+
+ // Returns genres associated with this item
+ public String getGenres() {
+ return genres;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public String getPoster() {
+ return poster;
+ }
+
+ public int getMinutes() {
+ return minutes;
+ }
+
+ // Returns a string of the item's information
+ public String toString() {
+ String result = "Movie [id=" + id + ", title=" + title + ", year=" + year;
+ result += ", genres= " + genres + "]";
+ return result;
+ }
+}
diff --git a/Week3/src/MovieDatabase.java b/Week3/src/MovieDatabase.java
new file mode 100644
index 0000000..c86fa82
--- /dev/null
+++ b/Week3/src/MovieDatabase.java
@@ -0,0 +1,89 @@
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class MovieDatabase {
+ private static HashMap ourMovies;
+
+ public static void initialize(String moviefile) {
+ if (ourMovies == null) {
+ ourMovies = new HashMap<>();
+ loadMovies("data/" + moviefile);
+ }
+ }
+
+ private static void initialize() {
+ if (ourMovies == null) {
+ ourMovies = new HashMap<>();
+ loadMovies("data/ratedmoviesfull.csv");
+ }
+ }
+
+ private static void loadMovies(String filename) {
+ FirstRatings fr = new FirstRatings();
+ ArrayList list = fr.loadMovies(filename);
+ for (Movie m : list) {
+ ourMovies.put(m.getID(), m);
+ }
+ }
+
+ public static boolean containsID(String id) {
+ initialize();
+ return ourMovies.containsKey(id);
+ }
+
+ public static int getYear(String id) {
+ initialize();
+ return ourMovies.get(id).getYear();
+ }
+
+ public static String getGenres(String id) {
+ initialize();
+ return ourMovies.get(id).getGenres();
+ }
+
+ public static String getTitle(String id) {
+ initialize();
+ return ourMovies.get(id).getTitle();
+ }
+
+ public static Movie getMovie(String id) {
+ initialize();
+ return ourMovies.get(id);
+ }
+
+ public static String getPoster(String id) {
+ initialize();
+ return ourMovies.get(id).getPoster();
+ }
+
+ public static int getMinutes(String id) {
+ initialize();
+ return ourMovies.get(id).getMinutes();
+ }
+
+ public static String getCountry(String id) {
+ initialize();
+ return ourMovies.get(id).getCountry();
+ }
+
+ public static String getDirector(String id) {
+ initialize();
+ return ourMovies.get(id).getDirector();
+ }
+
+ public static int size() {
+ return ourMovies.size();
+ }
+
+ public static ArrayList filterBy(Filter f) {
+ initialize();
+ ArrayList list = new ArrayList<>();
+ for (String id : ourMovies.keySet()) {
+ if (f.satisfies(id)) {
+ list.add(id);
+ }
+ }
+
+ return list;
+ }
+}
diff --git a/Week3/src/MovieRunnerAverage.java b/Week3/src/MovieRunnerAverage.java
new file mode 100644
index 0000000..5695a38
--- /dev/null
+++ b/Week3/src/MovieRunnerAverage.java
@@ -0,0 +1,51 @@
+import java.util.ArrayList;
+import java.util.Collections;
+
+public class MovieRunnerAverage {
+ private final SecondRatings secondRatings;
+
+ public MovieRunnerAverage() {
+ secondRatings = new SecondRatings("ratedmoviesfull.csv", "ratings.csv");
+ }
+
+ public void printAverageRatings(int minimalRatings) {
+ // SecondRatings secondRatings = new SecondRatings("ratedmovies_short.csv",
+ // "ratings_short.csv");
+ // System.out.printf(
+ // "Total number of movies %d, total number of raters %d\n",
+ // secondRatings.getMovieSize(), secondRatings.getRaterSize());
+
+ /*
+ * In the MovieRunnerAverage class in the printAverageRatings method,
+ * add code to print a list of movies and their average ratings,
+ * for all those movies that have at least a specified number of ratings,
+ * sorted by averages.
+ * Specifically, this method should print the list of movies,
+ * one movie per line (print its rating first, followed by its title)
+ * in sorted order by ratings, lowest rating to highest rating.
+ * For example, if printAverageRatings is called on the files
+ * ratings_short.csv and ratedmovies_short.csv with the argument 3,
+ * then the output will display two movies:
+ *
+ * 8.25 Her
+ * 9.0 The Godfather
+ * */
+ ArrayList ratedList = secondRatings.getAverageRatings(minimalRatings);
+ Collections.sort(ratedList);
+ System.out.printf("Total movies with %d ratings is %d\n", minimalRatings, ratedList.size());
+ System.out.printf(
+ "The name of the movie that has the lowest rating is \"%s\"\n",
+ secondRatings.getTitle(ratedList.get(0).getItem()));
+ // for (Rating ratedObj : ratedList) {
+ // double rating = ratedObj.getValue();
+ // String movieID = ratedObj.getItem();
+ // String movieTitle = secondRatings.getTitle(movieID);
+ // System.out.println(rating + " " + movieTitle);
+ // }
+ }
+
+ Double getAverageRatingOneMovie(String movieTitle) {
+ String movieID = secondRatings.getID(movieTitle);
+ return secondRatings.getAverageByID(movieID, 1);
+ }
+}
diff --git a/Week3/src/MovieRunnerWithFilters.java b/Week3/src/MovieRunnerWithFilters.java
new file mode 100644
index 0000000..3d23af4
--- /dev/null
+++ b/Week3/src/MovieRunnerWithFilters.java
@@ -0,0 +1,151 @@
+import java.util.ArrayList;
+import java.util.Collections;
+
+public class MovieRunnerWithFilters {
+
+ private final ThirdRatings thirdRatings;
+
+ public MovieRunnerWithFilters(String moviesFileName, String ratingsFileName) {
+ this.thirdRatings = new ThirdRatings(moviesFileName, ratingsFileName);
+ }
+
+ public MovieRunnerWithFilters() {
+ this("ratedmovies_short.csv", "ratings_short.csv");
+ }
+
+ /**
+ * Print a list of movies and their average ratings sorted by averages
+ *
+ * @param minimalRatings int specified number of ratings
+ */
+ public void printAverageRatings(int minimalRatings) {
+ ArrayList ratedList = thirdRatings.getAverageRatings(minimalRatings);
+
+ Collections.sort(ratedList);
+ // Print the number of raters after creating a ThirdsRating object.
+ System.out.printf("Total movies with %d ratings is %d\n", minimalRatings, ratedList.size());
+
+ // Print the number of movies in the database.
+ System.out.println("The number of movies in the database is " + MovieDatabase.size());
+
+ // You will call getAverageRatings with a minimal number of raters to return an ArrayList of
+ // type Rating.
+
+ ArrayList averageRatings = thirdRatings.getAverageRatings(minimalRatings);
+
+ // Print out how many movies with ratings are returned,
+ // then sort them, and print out the rating and title of each movie
+ System.out.printf(
+ "How many movies with ratings %d are returned: %d%n",
+ minimalRatings, averageRatings.size());
+
+ printRatingsList(averageRatings);
+ }
+
+ public int getAverageRatingsNumber(int minimalRatings) {
+ return thirdRatings.getAverageRatings(minimalRatings).size();
+ }
+
+ private void printRatingsList(ArrayList averageRatingList) {
+ System.out.printf("Found %d movie(s)%n", averageRatingList.size());
+ averageRatingList.stream()
+ .sorted()
+ .forEach(
+ rating -> {
+ String movieID = rating.getItem();
+ System.out.printf("%-4s %s%n", rating.getValue(), MovieDatabase.getTitle(movieID));
+ System.out.println(" Year: " + MovieDatabase.getYear(movieID));
+ System.out.println(" Time: " + MovieDatabase.getMinutes(movieID));
+ System.out.println(" Genre(s): " + MovieDatabase.getGenres(movieID));
+ System.out.println(" Director(s): " + MovieDatabase.getDirector(movieID));
+ });
+ System.out.println("-------");
+ }
+
+ /**
+ * Print a list of movies and their average ratings sorted by Year and minimal number of raters
+ *
+ * @param minimalRatings Minimal number of ratings
+ * @param year int Year of produce
+ */
+ public void printAverageRatingsByYear(int minimalRatings, int year) {
+ System.out.println(
+ thirdRatings.getAverageRatingsByFilter(minimalRatings, new YearAfterFilter(year)).size());
+ // printRatingsList(
+ // thirdRatings.getAverageRatingsByFilter(minimalRatings, new YearAfterFilter(year)));
+ }
+
+ /**
+ * Print a list of movies and their average ratings sorted by Genre
+ *
+ * @param minimalRatings Minimal number of ratings
+ * @param genre Genre
+ */
+ public void printAverageRatingsByGenre(int minimalRatings, String genre) {
+ System.out.println(
+ thirdRatings.getAverageRatingsByFilter(minimalRatings, new GenreFilter(genre)).size());
+
+ // printRatingsList(
+ // thirdRatings.getAverageRatingsByFilter(minimalRatings, new GenreFilter(genre)));
+ }
+
+ /**
+ * Print a list of movies and their average ratings sorted by time
+ *
+ * @param minimalRatings Minimal number of ratings
+ * @param minMinutes Minimal length of movies in minutes
+ * @param maxMinutes Maximum length of movies in minutes
+ */
+ public void printAverageRatingsByMinutes(int minimalRatings, int minMinutes, int maxMinutes) {
+ System.out.println(
+ thirdRatings
+ .getAverageRatingsByFilter(minimalRatings, new MinutesFilter(minMinutes, maxMinutes))
+ .size());
+ // printRatingsList(
+ // thirdRatings.getAverageRatingsByFilter(
+ // minimalRatings, new MinutesFilter(minMinutes, maxMinutes)));
+ }
+
+ /**
+ * Print a list of movies and their average ratings sorted by Directors
+ *
+ * @param minimalRatings Minimal number of ratings
+ * @param directors directors of the movies
+ */
+ public void printAverageRatingsByDirectors(int minimalRatings, String directors) {
+ System.out.println(
+ thirdRatings
+ .getAverageRatingsByFilter(minimalRatings, new DirectorsFilter(directors))
+ .size());
+ // System.out.println("Print movies directed by " + directors);
+ // printRatingsList(
+ // thirdRatings.getAverageRatingsByFilter(minimalRatings, new
+ // DirectorsFilter(directors)));
+ }
+
+ public void printAverageRatingsByYearAfterAndGenre(int minimalRatings, int year, String genre) {
+ AllFilters filters = new AllFilters();
+ filters.addFilter(new GenreFilter(genre));
+ filters.addFilter(new YearAfterFilter(year));
+ System.out.println(thirdRatings.getAverageRatingsByFilter(minimalRatings, filters).size());
+ // System.out.printf(
+ // "Print movie(s) with at least %d rating in \"%s\" genre produced after year" + " of %d
+ // %n",
+ // minimalRatings, genre, year);
+ // printRatingsList(thirdRatings.getAverageRatingsByFilter(minimalRatings, filters));
+ }
+
+ public void printAverageRatingsByDirectorsAndMinutes(
+ int minimalRatings, int minMinutes, int maxMinutes, String director) {
+ AllFilters filters = new AllFilters();
+ filters.addFilter(new MinutesFilter(minMinutes, maxMinutes));
+ filters.addFilter(new DirectorsFilter(director));
+
+ System.out.println(thirdRatings.getAverageRatingsByFilter(minimalRatings, filters).size());
+
+ // System.out.printf(
+ // "Print movie(s) with at least %d rating at least %d minutes long directed by %s%n",
+ // minimalRatings, minMinutes, director);
+ // printRatingsList(thirdRatings.getAverageRatingsByFilter(minimalRatings, filters));
+ }
+}
diff --git a/Week3/src/Rater.java b/Week3/src/Rater.java
new file mode 100644
index 0000000..95e2281
--- /dev/null
+++ b/Week3/src/Rater.java
@@ -0,0 +1,16 @@
+import java.util.ArrayList;
+
+public interface Rater {
+ // void addRating(String item, double rating);
+ void addRating(String movieID, Rating rating);
+
+ boolean hasRating(String item);
+
+ String getID();
+
+ double getRating(String item);
+
+ int numRatings();
+
+ ArrayList getItemsRated();
+}
diff --git a/Week3/src/Rating.java b/Week3/src/Rating.java
new file mode 100644
index 0000000..68a4502
--- /dev/null
+++ b/Week3/src/Rating.java
@@ -0,0 +1,29 @@
+// An immutable passive data object (PDO) to represent the rating data
+public class Rating implements Comparable {
+ private final String item;
+ private final double value;
+
+ public Rating(String anItem, double aValue) {
+ item = anItem;
+ value = aValue;
+ }
+
+ // Returns item being rated
+ public String getItem() {
+ return item;
+ }
+
+ // Returns the value of this rating (as a number so it can be used in calculations)
+ public double getValue() {
+ return value;
+ }
+
+ // Returns a string of all the rating information
+ public String toString() {
+ return "[" + getItem() + ", " + getValue() + "]";
+ }
+
+ public int compareTo(Rating other) {
+ return Double.compare(value, other.value);
+ }
+}
diff --git a/Week3/src/SecondRatings.java b/Week3/src/SecondRatings.java
new file mode 100644
index 0000000..6d52eb7
--- /dev/null
+++ b/Week3/src/SecondRatings.java
@@ -0,0 +1,151 @@
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Week2. A new class to do many of the calculations focusing on computing averages on movie
+ * ratings.
+ *
+ * @author Stanislav Rakitov
+ * @version 1.0
+ */
+public class SecondRatings {
+ private final ArrayList myMovies;
+ private final ArrayList myRaters;
+ private final FirstRatings firstRatings;
+ private final HashMap> moviesAndRatings;
+ private final HashMap moviesIdAndTitles;
+
+ public SecondRatings() {
+ // default constructor
+ this("ratedmoviesfull.csv", "ratings.csv");
+ }
+
+ // The constructor should create a FirstRatings object and then call the loadMovies and
+ // loadRaters methods in FirstRatings to read in all the movie and ratings data and store them
+ // in the two private ArrayList variables of the SecondRatings class, myMovies and myRaters.
+ public SecondRatings(String moviesFileName, String ratingsFileName) {
+ firstRatings = new FirstRatings(moviesFileName, ratingsFileName);
+ myMovies = firstRatings.getMovieArrayList();
+ myRaters = firstRatings.getRaterArrayList();
+ moviesAndRatings = getMoviesAndRatingsMap();
+ moviesIdAndTitles = getAllMoviesAndTitlesMap();
+ }
+
+ // Get all movies and titles map
+ private HashMap getAllMoviesAndTitlesMap() {
+ HashMap map = new HashMap<>();
+ for (Movie movie : myMovies) {
+ String movieID = movie.getID();
+ String movieTitle = movie.getTitle();
+ map.put(movieID, movieTitle);
+ }
+ return map;
+ }
+
+ // Returns a Map with movieID and all its ratings
+ private HashMap> getMoviesAndRatingsMap() {
+ HashMap> map = new HashMap<>();
+
+ for (Movie movie : myMovies) {
+ map.putIfAbsent(movie.getID(), new ArrayList<>());
+ }
+
+ for (Rater rater : myRaters) {
+ ArrayList ratings = rater.getItemsRated();
+ for (String movieID : ratings) {
+ // String movieID, double rating
+ ArrayList list = map.get(movieID);
+ list.add(rater.getRating(movieID));
+ }
+ }
+
+ return map;
+ }
+
+ /**
+ * A public method which returns the number of movies that were read in and stored in the
+ * ArrayList of type Movie
+ *
+ * @return int number of movies
+ */
+ public int getMovieSize() {
+ return this.myMovies.size();
+ }
+
+ /**
+ * A public method which returns the number of raters that were read in and stored in the
+ * ArrayList of type Rater.
+ *
+ * @return int number of movies
+ */
+ public int getRaterSize() {
+ return this.firstRatings.getRatersNumber();
+ }
+
+ /*
+ This method returns a double representing the average movie rating for this ID
+ if there are at least minimalRaters ratings.
+ If there are not minimalRaters ratings, then it returns 0.0.
+ */
+ Double getAverageByID(String id, Integer minimalRaters) {
+ double result = 0.0;
+ ArrayList ratings = moviesAndRatings.get(id);
+ if (ratings != null && ratings.size() >= minimalRaters) {
+ result = ratings.stream().mapToDouble(d -> d).average().orElse(0.0);
+ }
+
+ // If there are no ratings returns 0.0
+ return result;
+ }
+
+ /**
+ * This method should find the average rating for every movie that has been rated by at least
+ * minimalRaters raters.
+ *
+ * @param minimalRaters int the minimal number of raters supplying a rating
+ * @return an ArrayList of all the Rating objects for movies that have at least the minimal number
+ * of raters supplying a rating
+ */
+ public ArrayList getAverageRatings(int minimalRaters) {
+ ArrayList list = new ArrayList<>();
+ for (Movie movie : myMovies) {
+ String movieID = movie.getID();
+ Double averageRating = getAverageByID(movieID, minimalRaters);
+ if (averageRating != 0.0) {
+ list.add(new Rating(movieID, averageRating));
+ }
+ }
+ return list;
+ }
+
+ /*
+ * This method returns the title of the movie with that ID.
+ * If the movie ID does not exist, then this method should return a String
+ * indicating the ID was not found.
+ * */
+ String getTitle(String id) {
+ String title = moviesIdAndTitles.get(id);
+ if (title != null) {
+ return title;
+ }
+ // No title found
+ return "ID " + id + " NOT FOUND";
+ }
+ /*
+ * This method returns the movie ID of this movie.
+ * If the title is not found, return “NO SUCH TITLE.
+ * */
+ String getID(String title) {
+ String result = "NO SUCH TITLE";
+
+ for (Map.Entry entry : moviesIdAndTitles.entrySet()) {
+ if (Objects.equals(title, entry.getValue())) {
+ return entry.getKey();
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/Week3/src/ThirdRatings.java b/Week3/src/ThirdRatings.java
new file mode 100644
index 0000000..da666a2
--- /dev/null
+++ b/Week3/src/ThirdRatings.java
@@ -0,0 +1,64 @@
+import java.util.ArrayList;
+import java.util.Collections;
+
+public class ThirdRatings {
+
+ private final ArrayList myRaters;
+ private final ArrayList allMoviesIDs;
+
+ public ThirdRatings(String moviesFileName, String ratingsFileName) {
+ this.myRaters = FirstRatings.loadRaters(ratingsFileName);
+ MovieDatabase.initialize(moviesFileName);
+ allMoviesIDs = MovieDatabase.filterBy(new TrueFilter());
+ }
+
+ public ArrayList getAverageRatings(int minimalRaters) {
+ ArrayList list = new ArrayList<>();
+ for (String movieID : allMoviesIDs) {
+ Double averageRating = getAverageByID(movieID, minimalRaters);
+ if (averageRating != 0.0) {
+ list.add(new Rating(movieID, averageRating));
+ }
+ }
+ return list;
+ }
+
+ /*
+ This method returns a double representing the average movie rating for this ID
+ if there are at least minimalRaters ratings.
+ If there are not minimalRaters ratings, then it returns 0.0.
+ */
+ Double getAverageByID(String movieID, Integer minimalRaters) {
+ long numOfRatings = myRaters.stream().filter(rater -> rater.hasRating(movieID)).count();
+
+ if (numOfRatings >= minimalRaters) {
+ return myRaters.stream()
+ .filter(rater -> rater.hasRating(movieID))
+ .mapToDouble(rating -> rating.getRating(movieID))
+ .average()
+ .orElse(0.0);
+ }
+ return 0.0;
+ }
+
+ public int getRaterSize() {
+ return myRaters.size();
+ }
+
+ public ArrayList getAverageRatingsByFilter(Integer minimalRaters, Filter filterCriteria) {
+ ArrayList rating = new ArrayList<>();
+ ArrayList movies = MovieDatabase.filterBy(filterCriteria);
+ // System.out.println(movies);
+ Rating rat;
+ for (String movie_id : movies) {
+ if (getAverageByID(movie_id, minimalRaters) != 0) {
+ rat = new Rating(movie_id, getAverageByID(movie_id, minimalRaters));
+ rating.add(rat);
+ }
+ }
+
+ Collections.sort(rating);
+ // System.out.println(rating);
+ return rating;
+ }
+} // class
diff --git a/Week3/src/TrueFilter.java b/Week3/src/TrueFilter.java
new file mode 100644
index 0000000..9a5ae07
--- /dev/null
+++ b/Week3/src/TrueFilter.java
@@ -0,0 +1,6 @@
+public class TrueFilter implements Filter {
+ @Override
+ public boolean satisfies(String id) {
+ return true;
+ }
+}
diff --git a/Week3/src/Week1.java b/Week3/src/Week1.java
new file mode 100644
index 0000000..f77bbc9
--- /dev/null
+++ b/Week3/src/Week1.java
@@ -0,0 +1,7 @@
+public class Week1 {
+ public static void main(String[] args) {
+ FirstRatings testLong = new FirstRatings("ratedmoviesfull.csv", "ratings.csv");
+ testLong.testLoadMovies();
+ testLong.testLoadRaters("193", "1798709");
+ }
+}
diff --git a/Week3/src/Week2.java b/Week3/src/Week2.java
new file mode 100644
index 0000000..d1f0eff
--- /dev/null
+++ b/Week3/src/Week2.java
@@ -0,0 +1,32 @@
+public class Week2 {
+ public static void main(String[] args) {
+ MovieRunnerAverage average = new MovieRunnerAverage();
+
+ System.out.printf(
+ "Q5. What is the rating of the movie “The Maze Runner”? - %.4f\n",
+ average.getAverageRatingOneMovie("The Maze Runner"));
+
+ System.out.printf(
+ "Q6. What is the rating of the movie “Moneyball”? - %.4f\n",
+ average.getAverageRatingOneMovie("Moneyball"));
+
+ System.out.printf(
+ "Q7. what is the rating of the movie “Vacation”? - %.4f\n",
+ average.getAverageRatingOneMovie("Vacation"));
+
+ // Q8. Using the files ratedmoviesfull.csv and ratings.csv, how many movies have 50 or more
+ // ratings?
+ average.printAverageRatings(50);
+
+ // Q9. Using the files ratedmoviesfull.csv and ratings.csv, of those movies that have at least
+ // 20 ratings,
+ // what is the name of the movie that has the lowest rating?
+
+ average.printAverageRatings(20);
+
+ // Using the files ratedmoviesfull.csv and ratings.csv,
+ // of those movies that have at least 12 ratings,
+ // what is the name of the movie that has the lowest rating?
+ average.printAverageRatings(12);
+ }
+}
diff --git a/Week3/src/Week3.java b/Week3/src/Week3.java
new file mode 100644
index 0000000..6b6655a
--- /dev/null
+++ b/Week3/src/Week3.java
@@ -0,0 +1,58 @@
+public class Week3 {
+ public static void main(String[] args) {
+ // MovieRunnerWithFilters filters = new MovieRunnerWithFilters();
+ // filters.printAverageRatingsByYear(1, 2000);
+ // filters.printAverageRatingsByGenre(1, "Crime");
+ // filters.printAverageRatingsByMinutes(1, 110, 170);
+ // filters.printAverageRatingsByDirectors(1, "Charles Chaplin,Michael Mann,Spike Jonze");
+ // filters.printAverageRatingsByYearAfterAndGenre(1, 1980, "Romance");
+ // filters.printAverageRatingsByDirectorsAndMinutes(
+ // 1, 30, 170, "Spike Jonze,Michael Mann,Charles Chaplin,Francis Ford Coppola");
+
+ MovieRunnerWithFilters quiz3 = new MovieRunnerWithFilters("ratedmoviesfull.csv", "ratings.csv");
+ System.out.print(
+ "Q.4 number of minimal raters set to 35. " + "How many rated movies are returned? ");
+ System.out.println(quiz3.getAverageRatingsNumber(35));
+
+ System.out.print(
+ "Q.5 printAverageRatingsByYearAfter. Minimal raters 20. Year 2000. How "
+ + "many rated movies are returned? ");
+ quiz3.printAverageRatingsByYear(20, 2000);
+
+ System.out.print(
+ "Q.6 printAverageRatingsByGenre. minimal raters 20. genre Comedy. How many "
+ + "rated"
+ + " movies are returned? ");
+ quiz3.printAverageRatingsByGenre(20, "Comedy");
+
+ System.out.print(
+ "Q.7 printAverageRatingsByMinutes. Minimal raters 5. Movies that take at "
+ + "least 105 minutes and at most 135 minutes. How many rated movies are returned? ");
+ quiz3.printAverageRatingsByMinutes(5, 105, 135);
+
+ System.out.println(
+ "Q.8 printAverageRatingsByDirectors. Minimal raters 4. And one of these directors:");
+ System.out.println(
+ "\"Clint Eastwood,Joel Coen,Martin Scorsese,Roman Polanski,Nora Ephron,Ridley Scott,Sydney Pollack\"");
+ System.out.print("How many rated movies are returned? ");
+ quiz3.printAverageRatingsByDirectors(
+ 4,
+ "Clint Eastwood,Joel Coen,Martin Scorsese,Roman Polanski,Nora Ephron,Ridley Scott,Sydney Pollack");
+
+ System.out.println(
+ "Q.9 printAverageRatingsByYearAfterAndGenre. Minimal raters 8, the year "
+ + "set to 1990, and the genre set to \"Drama\".");
+ System.out.print("How many rated movies are returned? ");
+ quiz3.printAverageRatingsByYearAfterAndGenre(8, 1990, "Drama");
+
+ System.out.print(
+ "Q.10 printAverageRatingsByDirectorsAndMinutes. \n"
+ + "Minimal raters 3 \n"
+ + "and the length of the film set to at least 90 minutes and no more than 180 minutes.\n"
+ + "Find all the movies that have at least one of these directors: \n"
+ + "\"Clint Eastwood,Joel Coen,Tim Burton,Ron Howard,Nora Ephron,Sydney Pollack\". \n"
+ + "How many rated movies are returned? ");
+ quiz3.printAverageRatingsByDirectorsAndMinutes(
+ 3, 90, 180, "Clint Eastwood,Joel Coen,Tim Burton,Ron Howard,Nora Ephron,Sydney Pollack");
+ }
+}
diff --git a/Week3/src/YearAfterFilter.java b/Week3/src/YearAfterFilter.java
new file mode 100644
index 0000000..ecb3e3a
--- /dev/null
+++ b/Week3/src/YearAfterFilter.java
@@ -0,0 +1,12 @@
+public class YearAfterFilter implements Filter {
+ private final int myYear;
+
+ public YearAfterFilter(int year) {
+ myYear = year;
+ }
+
+ @Override
+ public boolean satisfies(String id) {
+ return MovieDatabase.getYear(id) >= myYear;
+ }
+}