-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathFourthRatings.java
196 lines (159 loc) · 7.38 KB
/
FourthRatings.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/**
* FourthRatings class contains various methods that can be used to get average ratings
* (with/without filters) as well as additional helper methods:
*
* * getAverageRatings and getAverageRatingsByFilter are used to find movies that have required
* * number of ratings, and in case with getAverageRatingsByFilter can be filtered using a range
* * of filters provided in this program.
*
* * getSimilarRatings and getSimilarRatingsByFilter work similarly to the methods mentioned
* * above but additionally ratings are provided using weighted averages. A user will get more
* * personalized recommendations because movies that were highly rated by only similar raters
* * will be returned. numSimilarRaters method parameter can be changed in order to modify
* * the precision of the provided recommendations.
*
* @ Konstantin Krumin
* @ Version: 1.0 (February 20, 2020)
*/
import java.util.*;
public class FourthRatings {
public FourthRatings () {
// default constructor
this("ratings.csv");
}
public FourthRatings (String ratingsfile) {
RaterDatabase.initialize(ratingsfile);
}
private double getAverageByID (String id, int minimalRaters) {
double sum = 0.0;
int count = 0;
for (Rater rater : RaterDatabase.getRaters()) {
if (rater.hasRating(id)) {
sum += rater.getRating(id);
count += 1;
}
}
if (count >= minimalRaters) {
return sum / count;
} else {
return 0.0;
}
}
public ArrayList<Rating> getAverageRatings (int minimalRaters) {
ArrayList<Rating> averageRatings = new ArrayList<Rating> ();
ArrayList<String> movies = MovieDatabase.filterBy(new TrueFilter());
for (String movieID : movies) {
double average = Math.round(getAverageByID(movieID, minimalRaters) * 100.0) / 100.0;
if (average != 0.0) {
Rating rating = new Rating (movieID, average);
averageRatings.add(rating);
}
}
return averageRatings;
}
public ArrayList<Rating> getAverageRatingsByFilter (int minimalRaters, Filter filterCriteria) {
ArrayList<Rating> averageRatings = new ArrayList<Rating> ();
ArrayList<String> filteredMovies = MovieDatabase.filterBy(filterCriteria);
for (String movieID : filteredMovies) {
double average = Math.round(getAverageByID(movieID, minimalRaters) * 100.0) / 100.0;
if (average != 0.0) {
Rating rating = new Rating (movieID, average);
averageRatings.add(rating);
}
}
return averageRatings;
}
private double dotProduct (Rater me, Rater r) {
double dotProduct = 0.0;
ArrayList<String> itemsRatedMe = me.getItemsRated();
for (String item : itemsRatedMe) {
if (r.getItemsRated().contains(item)) {
double currRatingR = r.getRating(item);
double currRatingMe = me.getRating(item);
dotProduct += (currRatingR - 5.0) * (currRatingMe - 5.0);
}
}
return dotProduct;
}
private ArrayList<Rating> getSimilarities (String id) {
ArrayList<Rating> similarities = new ArrayList<Rating> ();
Rater me = RaterDatabase.getRater(id);
for (Rater currRater : RaterDatabase.getRaters()) {
if (! currRater.getID().equals(id)) {
double dotProduct = dotProduct(me, currRater);
if (dotProduct >= 0) {
similarities.add(new Rating(currRater.getID(), dotProduct));
}
}
}
Collections.sort(similarities, Collections.reverseOrder());
return similarities;
}
public ArrayList<Rating> getSimilarRatings (String id, int numSimilarRaters, int minimalRaters) {
ArrayList<Rating> weightedRatings = new ArrayList<Rating> ();
ArrayList<Rating> similarRaters = getSimilarities(id);
ArrayList<String> movies = MovieDatabase.filterBy(new TrueFilter());
HashMap<String,Double> accumulatedRating = new HashMap<String,Double> ();
HashMap<String,Integer> accumulatedCount = new HashMap<String,Integer> ();
for (String movieID : movies) {
double currRating = 0.0;
int currCount = 0;
for (int k=0; k < numSimilarRaters; k++) {
Rating r = similarRaters.get(k);
String raterID = r.getItem();
double weight = r.getValue();
Rater rater = RaterDatabase.getRater(raterID);
if (rater.hasRating(movieID)) {
double rating = rater.getRating(movieID) * weight;
currRating += rating;
currCount += 1;
}
}
if (currCount >= minimalRaters) {
accumulatedRating.put(movieID, currRating);
accumulatedCount.put(movieID, currCount);
}
}
for (String movieID : accumulatedRating.keySet()) {
double weightedRating = Math.round((accumulatedRating.get(movieID) / accumulatedCount.get(movieID)) * 100.0) / 100.0;
Rating rating = new Rating (movieID, weightedRating);
weightedRatings.add(rating);
}
Collections.sort(weightedRatings, Collections.reverseOrder());
return weightedRatings;
}
public ArrayList<Rating> getSimilarRatingsByFilter
(String id, int numSimilarRaters, int minimalRaters, Filter filterCriteria) {
ArrayList<Rating> weightedRatings = new ArrayList<Rating> ();
ArrayList<Rating> similarRaters = getSimilarities(id);
ArrayList<String> filteredMovies = MovieDatabase.filterBy(filterCriteria);
HashMap<String,Double> accumulatedRating = new HashMap<String,Double> ();
HashMap<String,Integer> accumulatedCount = new HashMap<String,Integer> ();
for (String movieID : filteredMovies) {
double currRating = 0.0;
int currCount = 0;
for (int k=0; k < numSimilarRaters; k++) {
Rating r = similarRaters.get(k);
String raterID = r.getItem();
double weight = r.getValue();
Rater rater = RaterDatabase.getRater(raterID);
if (rater.hasRating(movieID)) {
double rating = rater.getRating(movieID) * weight;
currRating += rating;
currCount += 1;
}
}
if (currCount >= minimalRaters) {
accumulatedRating.put(movieID, currRating);
accumulatedCount.put(movieID, currCount);
}
}
for (String movieID : accumulatedRating.keySet()) {
double weightedRating = Math.round((accumulatedRating.get(movieID) / accumulatedCount.get(movieID)) * 100.0) / 100.0;
Rating rating = new Rating (movieID, weightedRating);
weightedRatings.add(rating);
}
Collections.sort(weightedRatings, Collections.reverseOrder());
return weightedRatings;
}
}