-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRecommender.cpp
149 lines (117 loc) · 5.68 KB
/
Recommender.cpp
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
#include "Recommender.h"
#include "UserDatabase.h"
#include "MovieDatabase.h"
#include "User.h"
#include "Movie.h"
#include <string>
#include <vector>
#include <unordered_set>
#include<unordered_map>
#include <algorithm>
#include <utility>
using namespace std;
Recommender::Recommender(const UserDatabase& user_database,
const MovieDatabase& movie_database)
:userdb(user_database), moviedb(movie_database)
{
}
vector<MovieAndRank> Recommender::recommend_movies(const string& user_email, int movie_count) const
{
vector<MovieAndRank> recommendations;
if (movie_count <= 0) {
return recommendations;
}
// Look up the user by email address
const User* user = userdb.get_user_from_email(user_email);
//cout << user->get_full_name() << endl;
if (!user) {
return recommendations;
}
//try methodically commenting out bits of this code and use print statements to debug where its going wrong
//unfortunately a stack overflow is preventing me from being able to run this on visual studio :(
//but it works on g32fast.
//start with checking if the watch history got properly copied.
//then check if the number for compatibity scores gets calculated. not very easy to verify but if it adds something thats good
//then check if map correctly gets compatibilty score (it should assuming everything is right so far)
//check the sorts(this will probably be the hardest to verify)
//check the shortening of the sorted movies to reccomendations
//if it stil doesnt work idk
// Get the user's watch history
vector<string> watched_movies = user->get_watch_history();
/*for (int i = 0; i < watched_movies.size(); i++)// TESTING THE WATCHEDMOVIED CAN BE ACCESSED SUCCESSFULLY
{
cout << watched_movies[i] << endl;
string copy = watched_movies[i];
Movie* movie = moviedb.get_movie_from_id(copy);
cout << movie->get_title();
}*/
// Calculate compatibility scores for each movie in the database
unordered_map<string, int> compatibility_scores;
for (int i = 0; i < watched_movies.size(); ++i) {
Movie* movie = moviedb.get_movie_from_id(watched_movies[i]);
//cout << movie->get_title();
// Calculate the compatibility score for this movie
for (const string& director : movie->get_directors()) {//iterate through every director in each movie in watched movie
for (const Movie* other_movie : moviedb.get_movies_with_director(director)) {//iterates through all movies with that director
if (watched_movies[i] != other_movie->get_id()) {
compatibility_scores[other_movie->get_id()] = +20;
}
}
}
for (const string& actor : movie->get_actors()) {//iterate through every actor in each movie in watched movie
for (const Movie* other_movie : moviedb.get_movies_with_actor(actor)) {//iterates through all movies with that actor
if (watched_movies[i] != other_movie->get_id()) {
compatibility_scores[other_movie->get_id()] += 30;
}
}
}
for (const string& genre : movie->get_genres()) {//iterate through every genre in each movie in watched movie
for (const Movie* other_movie : moviedb.get_movies_with_genre(genre)) {//iterates through each movie in database that has that genre
if (watched_movies[i] != other_movie->get_id()) {
compatibility_scores[other_movie->get_id()] += 1;
}
}
}
}
// Add this movie's compatibility score to the map
/* if (compatibility_score > 0) {
compatibility_scores[movie->get_id()] = compatibility_score;
}
}*/
/*for (unordered_map<string, int>::iterator it = compatibility_scores.begin(); it != compatibility_scores.end(); ++it)
{
Movie* m = moviedb.get_movie_from_id((*it).first);
cout << m->get_title() << ": " << (*it).second << endl;
}*/ //THIS FOR LOOP WAS TO TEST IF THE CALUCLUATION OF THE COMPATIBILITY SCORES WORKS AT ALL
// Sort the movies by compatibility score, rating, and name
vector<pair<string, int>> sorted_movies(compatibility_scores.begin(), compatibility_scores.end());// create a copy of unordered map that is a vector
std::sort(sorted_movies.begin(), sorted_movies.end(), comparePairs); // sort the vector that was created using the comparePairs function that is defined in Reccomender.h
for (int i = 0; i < sorted_movies.size() - 1; i++)
{
pair<string, int> a = sorted_movies[i];
pair<string, int> b = sorted_movies[i + 1];
const Movie* movie_a = moviedb.get_movie_from_id(a.first);
const Movie* movie_b = moviedb.get_movie_from_id(b.first);
if (a.second == b.second)//if they have the same compatibility score
{
if (movie_a->get_rating() < movie_b->get_rating()) {
swap(sorted_movies[i], sorted_movies[i + 1]);
}
else if (movie_a->get_rating() == movie_b->get_rating())
{
if (movie_a->get_title() < movie_b->get_title())
swap(sorted_movies[i], sorted_movies[i + 1]);
}
}
}
// Add the top-ranked movies to the recommendations vector
int count = 0;
for (const pair<string,int> movie : sorted_movies) {
if (count >= movie_count) {
break;
}
recommendations.emplace_back(movie.first, movie.second);
++count;
}
return recommendations;
}