#include <algorithm>
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <vector>
#include "MovieRecommender.h"
using std::list; using std::vector;
struct RatingInformation {
int userId, movieId, rating;
RatingInformation(int u, int m, int r) : userId(u), movieId(m), rating(r) {};
// overloading operator to make calls to sort simpler
bool operator<(const RatingInformation& rhs) const {
return (this->movieId < rhs.movieId);
}
};
int main() {
return 0;
}
list<RatingInformation> readFromFile(char* file) {
// assumption: input is properly formatted with 3 integer values per line
list<RatingInformation> ratings;
std::ifstream in(file);
if (in) {
int userId, movieId, rating;
while (in >> userId >> movieId >> rating) {
ratings.push_back(RatingInformation(userId, movieId, rating));
}
} else {
std::cerr << "Cannot open file " << file << std::endl;
}
in.close();
return ratings;
}
template<class InputIterator>
void print(InputIterator start, InputIterator end) {
for (InputIterator i = start; i != end; i++) {
std::cout << "UserId is " << i->userId
<< ", MovieId is " << i->movieId
<< ", and Rating is " << i->rating
<< std::endl;
}
}
void transform(vector<RatingInformation>& user, int shift) {
for (int i = 0, n = user.size(); i < n; i++) {
user[i].rating += shift;
}
}
int dotProduct(vector<RatingInformation>& a, vector<RatingInformation>& b) {
// Assumptions:
// - size of both vectors is the same
// - vectors are sorted according to movie id
// - vectors contain same movie collections
int dotProduct = 0;
for (int i = 0, n = a.size(); i < n; i++) {
dotProduct += a[i].rating * b[i].rating;
}
return dotProduct;
}
template<class InputIterator>
bool containsMovie(InputIterator start, InputIterator finish, int movieId) {
for (InputIterator i = start; i != finish; i++) {
if (i->movieId == movieId) return true;
}
return false;
}
template<class InputIterator>
vector<RatingInformation> getSubset(InputIterator user1Start, InputIterator user1Finish,
InputIterator user2Start, InputIterator user2Finish) {
vector<RatingInformation> subset;
for (InputIterator i = user1Start; i != user1Finish; i++) {
if (containsMovie(user2Start, user2Finish, i->movieId)) {
subset.push_back(*i);
}
}
return subset;
}
int guser = 0;
bool userSeparation(RatingInformation set1) {
return (set1.userId != guser);
}
int computeSimilarity(list<RatingInformation> ratings, int userId1, int userId2) {
list<RatingInformation> user1, user2;
// yank ratings associated with user 1 and user 2 from input RatingInformation list
guser = userId1;
std::remove_copy_if(ratings.begin(), ratings.end(), user1.begin(), userSeparation);
guser = userId2;
std::remove_copy_if(ratings.begin(), ratings.end(), user2.begin(), userSeparation);
// determined overlap regions between two users based on movieIds
vector<RatingInformation> ratings1 = getSubset(user1.begin(), user1.end(),
user2.begin(), user2.end());
vector<RatingInformation> ratings2 = getSubset(user2.begin(), user2.end(),
user1.begin(), user1.end());
transform(ratings1, -5);
transform(ratings2, -5);
// note, < operator is overloaded
std::sort(ratings1.begin(), ratings1.end());
std::sort(ratings2.begin(), ratings2.end());
return dotProduct(ratings1, ratings2);
}