ArchitSharma commited on
Commit
1f6053d
1 Parent(s): d2bd828

Upload 12 files

Browse files
main.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pandas as pd
3
+ from flask import Flask, render_template, request
4
+ from sklearn.feature_extraction.text import CountVectorizer
5
+ from sklearn.metrics.pairwise import cosine_similarity
6
+ import json
7
+ import bs4 as bs
8
+ import urllib.request
9
+ import pickle
10
+ import requests
11
+ from datetime import date, datetime
12
+
13
+ # load the nlp model and tfidf vectorizer from disk
14
+ filename = 'nlp_model.pkl'
15
+ clf = pickle.load(open(filename, 'rb'))
16
+ vectorizer = pickle.load(open('tranform.pkl','rb'))
17
+
18
+ # converting list of string to list (eg. "["abc","def"]" to ["abc","def"])
19
+ def convert_to_list(my_list):
20
+ my_list = my_list.split('","')
21
+ my_list[0] = my_list[0].replace('["','')
22
+ my_list[-1] = my_list[-1].replace('"]','')
23
+ return my_list
24
+
25
+ # convert list of numbers to list (eg. "[1,2,3]" to [1,2,3])
26
+ def convert_to_list_num(my_list):
27
+ my_list = my_list.split(',')
28
+ my_list[0] = my_list[0].replace("[","")
29
+ my_list[-1] = my_list[-1].replace("]","")
30
+ return my_list
31
+
32
+ def get_suggestions():
33
+ data = pd.read_csv('main_data.csv')
34
+ return list(data['movie_title'].str.capitalize())
35
+
36
+ app = Flask(__name__)
37
+
38
+ @app.route("/")
39
+ @app.route("/home")
40
+ def home():
41
+ suggestions = get_suggestions()
42
+ return render_template('home.html',suggestions=suggestions)
43
+
44
+
45
+ @app.route("/recommend",methods=["POST"])
46
+ def recommend():
47
+ # getting data from AJAX request
48
+ title = request.form['title']
49
+ cast_ids = request.form['cast_ids']
50
+ cast_names = request.form['cast_names']
51
+ cast_chars = request.form['cast_chars']
52
+ cast_bdays = request.form['cast_bdays']
53
+ cast_bios = request.form['cast_bios']
54
+ cast_places = request.form['cast_places']
55
+ cast_profiles = request.form['cast_profiles']
56
+ imdb_id = request.form['imdb_id']
57
+ poster = request.form['poster']
58
+ genres = request.form['genres']
59
+ overview = request.form['overview']
60
+ vote_average = request.form['rating']
61
+ vote_count = request.form['vote_count']
62
+ rel_date = request.form['rel_date']
63
+ release_date = request.form['release_date']
64
+ runtime = request.form['runtime']
65
+ status = request.form['status']
66
+ rec_movies = request.form['rec_movies']
67
+ rec_posters = request.form['rec_posters']
68
+ rec_movies_org = request.form['rec_movies_org']
69
+ rec_year = request.form['rec_year']
70
+ rec_vote = request.form['rec_vote']
71
+
72
+ # get movie suggestions for auto complete
73
+ suggestions = get_suggestions()
74
+
75
+ # call the convert_to_list function for every string that needs to be converted to list
76
+ rec_movies_org = convert_to_list(rec_movies_org)
77
+ rec_movies = convert_to_list(rec_movies)
78
+ rec_posters = convert_to_list(rec_posters)
79
+ cast_names = convert_to_list(cast_names)
80
+ cast_chars = convert_to_list(cast_chars)
81
+ cast_profiles = convert_to_list(cast_profiles)
82
+ cast_bdays = convert_to_list(cast_bdays)
83
+ cast_bios = convert_to_list(cast_bios)
84
+ cast_places = convert_to_list(cast_places)
85
+
86
+ # convert string to list (eg. "[1,2,3]" to [1,2,3])
87
+ cast_ids = convert_to_list_num(cast_ids)
88
+ rec_vote = convert_to_list_num(rec_vote)
89
+ rec_year = convert_to_list_num(rec_year)
90
+
91
+ # rendering the string to python string
92
+ for i in range(len(cast_bios)):
93
+ cast_bios[i] = cast_bios[i].replace(r'\n', '\n').replace(r'\"','\"')
94
+
95
+ for i in range(len(cast_chars)):
96
+ cast_chars[i] = cast_chars[i].replace(r'\n', '\n').replace(r'\"','\"')
97
+
98
+ # combining multiple lists as a dictionary which can be passed to the html file so that it can be processed easily and the order of information will be preserved
99
+ movie_cards = {rec_posters[i]: [rec_movies[i],rec_movies_org[i],rec_vote[i],rec_year[i]] for i in range(len(rec_posters))}
100
+
101
+ casts = {cast_names[i]:[cast_ids[i], cast_chars[i], cast_profiles[i]] for i in range(len(cast_profiles))}
102
+
103
+ cast_details = {cast_names[i]:[cast_ids[i], cast_profiles[i], cast_bdays[i], cast_places[i], cast_bios[i]] for i in range(len(cast_places))}
104
+
105
+ # web scraping to get user reviews from IMDB site
106
+ sauce = urllib.request.urlopen('https://www.imdb.com/title/{}/reviews?ref_=tt_ov_rt'.format(imdb_id)).read()
107
+ soup = bs.BeautifulSoup(sauce,'lxml')
108
+ soup_result = soup.find_all("div",{"class":"text show-more__control"})
109
+
110
+ reviews_list = [] # list of reviews
111
+ reviews_status = [] # list of comments (good or bad)
112
+ for reviews in soup_result:
113
+ if reviews.string:
114
+ reviews_list.append(reviews.string)
115
+ # passing the review to our model
116
+ movie_review_list = np.array([reviews.string])
117
+ movie_vector = vectorizer.transform(movie_review_list)
118
+ pred = clf.predict(movie_vector)
119
+ reviews_status.append('Positive' if pred else 'Negative')
120
+
121
+ # getting current date
122
+ movie_rel_date = ""
123
+ curr_date = ""
124
+ if(rel_date):
125
+ today = str(date.today())
126
+ curr_date = datetime.strptime(today,'%Y-%m-%d')
127
+ movie_rel_date = datetime.strptime(rel_date, '%Y-%m-%d')
128
+
129
+ # combining reviews and comments into a dictionary
130
+ movie_reviews = {reviews_list[i]: reviews_status[i] for i in range(len(reviews_list))}
131
+
132
+ # passing all the data to the html file
133
+ return render_template('recommend.html',title=title,poster=poster,overview=overview,vote_average=vote_average,
134
+ vote_count=vote_count,release_date=release_date,movie_rel_date=movie_rel_date,curr_date=curr_date,runtime=runtime,status=status,genres=genres,movie_cards=movie_cards,reviews=movie_reviews,casts=casts,cast_details=cast_details)
135
+
136
+ if __name__ == '__main__':
137
+ app.run(debug=True)
nlp_model.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d7f74f92a7c9fc61fc323aa41fc8485b5c76d5c6e6b5d6382eab91d3e2fa7629
3
+ size 64953
requirements.txt ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Flask==1.1.1
2
+ gunicorn==19.9.0
3
+ Jinja2==2.10.1
4
+ MarkupSafe==1.1.1
5
+ Werkzeug==0.15.5
6
+ numpy>=1.9.2
7
+ scipy>=0.15.1
8
+ nltk==3.5
9
+ scikit-learn>=0.18
10
+ pandas>=0.19
11
+ beautifulsoup4==4.9.1
12
+ jsonschema==3.2.0
13
+ tmdbv3api==1.6.1
14
+ lxml==4.6.2
15
+ urllib3==1.25.9
16
+ requests==2.23.0
17
+ pickleshare==0.7.5
static/autocomplete.js ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ new autoComplete({
2
+ data: { // Data src [Array, Function, Async] | (REQUIRED)
3
+ src: films,
4
+ },
5
+ selector: "#autoComplete", // Input field selector | (Optional)
6
+ threshold: 2, // Min. Chars length to start Engine | (Optional)
7
+ debounce: 100, // Post duration for engine to start | (Optional)
8
+ searchEngine: "strict", // Search Engine type/mode | (Optional)
9
+ resultsList: { // Rendered results list object | (Optional)
10
+ render: true,
11
+ container: source => {
12
+ source.setAttribute("id", "food_list");
13
+ },
14
+ destination: document.querySelector("#autoComplete"),
15
+ position: "afterend",
16
+ element: "ul"
17
+ },
18
+ maxResults: 5, // Max. number of rendered results | (Optional)
19
+ highlight: true, // Highlight matching results | (Optional)
20
+ resultItem: { // Rendered result item | (Optional)
21
+ content: (data, source) => {
22
+ source.innerHTML = data.match;
23
+ },
24
+ element: "li"
25
+ },
26
+ noResults: () => { // Action script on noResults | (Optional)
27
+ const result = document.createElement("li");
28
+ result.setAttribute("class", "no_result");
29
+ result.setAttribute("tabindex", "1");
30
+ result.innerHTML = "No Results";
31
+ document.querySelector("#autoComplete_list").appendChild(result);
32
+ },
33
+ onSelection: feedback => { // Action script onSelection event | (Optional)
34
+ document.getElementById('autoComplete').value = feedback.selection.value;
35
+ }
36
+ });
static/default.jpg ADDED
static/image.jpg ADDED
static/loader.gif ADDED
static/recommend.js ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ $(function() {
2
+ // Button will be disabled until we type something inside the input field
3
+ const source = document.getElementById('autoComplete');
4
+ const inputHandler = function(e) {
5
+ if(e.target.value==""){
6
+ $('.movie-button').attr('disabled', true);
7
+ }
8
+ else{
9
+ $('.movie-button').attr('disabled', false);
10
+ }
11
+ }
12
+ source.addEventListener('input', inputHandler);
13
+
14
+ $('.fa-arrow-up').click(function(){
15
+ $('html, body').animate({scrollTop:0}, 'slow');
16
+ });
17
+
18
+ $('.app-title').click(function(){
19
+ window.location.href = '/';
20
+ })
21
+
22
+ $('.movie-button').on('click',function(){
23
+ var my_api_key = '5492165c61b1a21c06eb3a3b578a6339';
24
+ var title = $('.movie').val();
25
+ if (title=="") {
26
+ $('.results').css('display','none');
27
+ $('.fail').css('display','block');
28
+ }
29
+
30
+ if (($('.fail').text() && ($('.footer').css('position') == 'absolute'))) {
31
+ $('.footer').css('position', 'fixed');
32
+ }
33
+
34
+ else{
35
+ load_details(my_api_key,title);
36
+ }
37
+ });
38
+ });
39
+
40
+ // will be invoked when clicking on the recommended movie cards
41
+ function recommendcard(e){
42
+ $("#loader").fadeIn();
43
+ var my_api_key = '5492165c61b1a21c06eb3a3b578a6339';
44
+ var title = e.getAttribute('title');
45
+ load_details(my_api_key,title);
46
+ }
47
+
48
+
49
+ // get the details of the movie from the API (based on the name of the movie)
50
+ function load_details(my_api_key,title){
51
+ $.ajax({
52
+ type: 'GET',
53
+ url:'https://api.themoviedb.org/3/search/movie?api_key='+my_api_key+'&query='+title,
54
+ async: false,
55
+ success: function(movie){
56
+ if(movie.results.length<1){
57
+ $('.fail').css('display','block');
58
+ $('.results').css('display','none');
59
+ $("#loader").delay(500).fadeOut();
60
+ }
61
+ else if(movie.results.length==1) {
62
+ $("#loader").fadeIn();
63
+ $('.fail').css('display','none');
64
+ $('.results').delay(1000).css('display','block');
65
+ var movie_id = movie.results[0].id;
66
+ var movie_title = movie.results[0].title;
67
+ var movie_title_org = movie.results[0].original_title;
68
+ get_movie_details(movie_id,my_api_key,movie_title,movie_title_org);
69
+ }
70
+ else{
71
+ var close_match = {};
72
+ var flag=0;
73
+ var movie_id="";
74
+ var movie_title="";
75
+ var movie_title_org="";
76
+ $("#loader").fadeIn();
77
+ $('.fail').css('display','none');
78
+ $('.results').delay(1000).css('display','block');
79
+ for(var count in movie.results){
80
+ if(title==movie.results[count].original_title){
81
+ flag = 1;
82
+ movie_id = movie.results[count].id;
83
+ movie_title = movie.results[count].title;
84
+ movie_title_org = movie.results[count].original_title;
85
+ break;
86
+ }
87
+ else{
88
+ close_match[movie.results[count].title] = similarity(title, movie.results[count].title);
89
+ }
90
+ }
91
+ if(flag==0){
92
+ movie_title = Object.keys(close_match).reduce(function(a, b){ return close_match[a] > close_match[b] ? a : b });
93
+ var index = Object.keys(close_match).indexOf(movie_title)
94
+ movie_id = movie.results[index].id;
95
+ movie_title_org = movie.results[index].original_title;
96
+ }
97
+ get_movie_details(movie_id,my_api_key,movie_title,movie_title_org);
98
+ }
99
+ },
100
+ error: function(error){
101
+ alert('Invalid Request - '+error);
102
+ $("#loader").delay(500).fadeOut();
103
+ },
104
+ });
105
+ }
106
+
107
+ // getting closest match to the requested movie name using Levenshtein distance
108
+ function similarity(s1, s2) {
109
+ var longer = s1;
110
+ var shorter = s2;
111
+ if (s1.length < s2.length) {
112
+ longer = s2;
113
+ shorter = s1;
114
+ }
115
+ var longerLength = longer.length;
116
+ if (longerLength == 0) {
117
+ return 1.0;
118
+ }
119
+ return (longerLength - editDistance(longer, shorter)) / parseFloat(longerLength);
120
+ }
121
+
122
+ function editDistance(s1, s2) {
123
+ s1 = s1.toLowerCase();
124
+ s2 = s2.toLowerCase();
125
+
126
+ var costs = new Array();
127
+ for (var i = 0; i <= s1.length; i++) {
128
+ var lastValue = i;
129
+ for (var j = 0; j <= s2.length; j++) {
130
+ if (i == 0)
131
+ costs[j] = j;
132
+ else {
133
+ if (j > 0) {
134
+ var newValue = costs[j - 1];
135
+ if (s1.charAt(i - 1) != s2.charAt(j - 1))
136
+ newValue = Math.min(Math.min(newValue, lastValue),
137
+ costs[j]) + 1;
138
+ costs[j - 1] = lastValue;
139
+ lastValue = newValue;
140
+ }
141
+ }
142
+ }
143
+ if (i > 0)
144
+ costs[s2.length] = lastValue;
145
+ }
146
+ return costs[s2.length];
147
+ }
148
+
149
+ // get all the details of the movie using the movie id.
150
+ function get_movie_details(movie_id,my_api_key,movie_title,movie_title_org) {
151
+ $.ajax({
152
+ type:'GET',
153
+ url:'https://api.themoviedb.org/3/movie/'+movie_id+'?api_key='+my_api_key,
154
+ success: function(movie_details){
155
+ show_details(movie_details,movie_title,my_api_key,movie_id,movie_title_org);
156
+ },
157
+ error: function(error){
158
+ alert("API Error! - "+error);
159
+ $("#loader").delay(500).fadeOut();
160
+ },
161
+ });
162
+ }
163
+
164
+ // passing all the details to python's flask for displaying and scraping the movie reviews using imdb id
165
+ function show_details(movie_details,movie_title,my_api_key,movie_id,movie_title_org){
166
+ var imdb_id = movie_details.imdb_id;
167
+ var poster;
168
+ if(movie_details.poster_path){
169
+ poster = 'https://image.tmdb.org/t/p/original'+movie_details.poster_path;
170
+ }
171
+ else {
172
+ poster = 'static/default.jpg';
173
+ }
174
+ var overview = movie_details.overview;
175
+ var genres = movie_details.genres;
176
+ var rating = movie_details.vote_average;
177
+ var vote_count = movie_details.vote_count;
178
+ var release_date = movie_details.release_date;
179
+ var runtime = parseInt(movie_details.runtime);
180
+ var status = movie_details.status;
181
+ var genre_list = []
182
+ for (var genre in genres){
183
+ genre_list.push(genres[genre].name);
184
+ }
185
+ var my_genre = genre_list.join(", ");
186
+ if(runtime%60==0){
187
+ runtime = Math.floor(runtime/60)+" hour(s)"
188
+ }
189
+ else {
190
+ runtime = Math.floor(runtime/60)+" hour(s) "+(runtime%60)+" min(s)"
191
+ }
192
+
193
+ // calling `get_movie_cast` to get the top cast for the queried movie
194
+ movie_cast = get_movie_cast(movie_id,my_api_key);
195
+
196
+ // calling `get_individual_cast` to get the individual cast details
197
+ ind_cast = get_individual_cast(movie_cast,my_api_key);
198
+
199
+ // calling `get_recommendations` to get the recommended movies for the given movie id from the TMDB API
200
+ recommendations = get_recommendations(movie_id, my_api_key);
201
+
202
+ details = {
203
+ 'title':movie_title,
204
+ 'cast_ids':JSON.stringify(movie_cast.cast_ids),
205
+ 'cast_names':JSON.stringify(movie_cast.cast_names),
206
+ 'cast_chars':JSON.stringify(movie_cast.cast_chars),
207
+ 'cast_profiles':JSON.stringify(movie_cast.cast_profiles),
208
+ 'cast_bdays':JSON.stringify(ind_cast.cast_bdays),
209
+ 'cast_bios':JSON.stringify(ind_cast.cast_bios),
210
+ 'cast_places':JSON.stringify(ind_cast.cast_places),
211
+ 'imdb_id':imdb_id,
212
+ 'poster':poster,
213
+ 'genres':my_genre,
214
+ 'overview':overview,
215
+ 'rating':rating,
216
+ 'vote_count':vote_count.toLocaleString(),
217
+ 'rel_date':release_date,
218
+ 'release_date':new Date(release_date).toDateString().split(' ').slice(1).join(' '),
219
+ 'runtime':runtime,
220
+ 'status':status,
221
+ 'rec_movies':JSON.stringify(recommendations.rec_movies),
222
+ 'rec_posters':JSON.stringify(recommendations.rec_posters),
223
+ 'rec_movies_org':JSON.stringify(recommendations.rec_movies_org),
224
+ 'rec_year':JSON.stringify(recommendations.rec_year),
225
+ 'rec_vote':JSON.stringify(recommendations.rec_vote)
226
+ }
227
+
228
+ $.ajax({
229
+ type:'POST',
230
+ data:details,
231
+ url:"/recommend",
232
+ dataType: 'html',
233
+ complete: function(){
234
+ $("#loader").delay(500).fadeOut();
235
+ },
236
+ success: function(response) {
237
+ $('.results').html(response);
238
+ $('#autoComplete').val('');
239
+ $('.footer').css('position','absolute');
240
+ if ($('.movie-content')) {
241
+ $('.movie-content').after('<div class="gototop"><i title="Go to Top" class="fa fa-arrow-up"></i></div>');
242
+ }
243
+ $(window).scrollTop(0);
244
+ }
245
+ });
246
+ }
247
+
248
+ // getting the details of individual cast
249
+ function get_individual_cast(movie_cast,my_api_key) {
250
+ cast_bdays = [];
251
+ cast_bios = [];
252
+ cast_places = [];
253
+ for(var cast_id in movie_cast.cast_ids){
254
+ $.ajax({
255
+ type:'GET',
256
+ url:'https://api.themoviedb.org/3/person/'+movie_cast.cast_ids[cast_id]+'?api_key='+my_api_key,
257
+ async:false,
258
+ success: function(cast_details){
259
+ cast_bdays.push((new Date(cast_details.birthday)).toDateString().split(' ').slice(1).join(' '));
260
+ if(cast_details.biography){
261
+ cast_bios.push(cast_details.biography);
262
+ }
263
+ else {
264
+ cast_bios.push("Not Available");
265
+ }
266
+ if(cast_details.place_of_birth){
267
+ cast_places.push(cast_details.place_of_birth);
268
+ }
269
+ else {
270
+ cast_places.push("Not Available");
271
+ }
272
+ }
273
+ });
274
+ }
275
+ return {cast_bdays:cast_bdays,cast_bios:cast_bios,cast_places:cast_places};
276
+ }
277
+
278
+ // getting the details of the cast for the requested movie
279
+ function get_movie_cast(movie_id,my_api_key){
280
+ cast_ids= [];
281
+ cast_names = [];
282
+ cast_chars = [];
283
+ cast_profiles = [];
284
+ top_10 = [0,1,2,3,4,5,6,7,8,9];
285
+ $.ajax({
286
+ type:'GET',
287
+ url:"https://api.themoviedb.org/3/movie/"+movie_id+"/credits?api_key="+my_api_key,
288
+ async:false,
289
+ success: function(my_movie){
290
+ if(my_movie.cast.length>0){
291
+ if(my_movie.cast.length>=10){
292
+ top_cast = [0,1,2,3,4,5,6,7,8,9];
293
+ }
294
+ else {
295
+ top_cast = [0,1,2,3,4];
296
+ }
297
+ for(var my_cast in top_cast){
298
+ cast_ids.push(my_movie.cast[my_cast].id)
299
+ cast_names.push(my_movie.cast[my_cast].name);
300
+ cast_chars.push(my_movie.cast[my_cast].character);
301
+ if(my_movie.cast[my_cast].profile_path){
302
+ cast_profiles.push("https://image.tmdb.org/t/p/original"+my_movie.cast[my_cast].profile_path);
303
+ }
304
+ else {
305
+ cast_profiles.push("static/default.jpg");
306
+ }
307
+ }
308
+ }
309
+ },
310
+ error: function(error){
311
+ alert("Invalid Request! - "+error);
312
+ $("#loader").delay(500).fadeOut();
313
+ }
314
+ });
315
+
316
+ return {cast_ids:cast_ids,cast_names:cast_names,cast_chars:cast_chars,cast_profiles:cast_profiles};
317
+ }
318
+
319
+ // getting recommendations
320
+ function get_recommendations(movie_id, my_api_key) {
321
+ rec_movies = [];
322
+ rec_posters = [];
323
+ rec_movies_org = [];
324
+ rec_year = [];
325
+ rec_vote = [];
326
+
327
+ $.ajax({
328
+ type: 'GET',
329
+ url: "https://api.themoviedb.org/3/movie/"+movie_id+"/recommendations?api_key="+my_api_key,
330
+ async: false,
331
+ success: function(recommend) {
332
+ for(var recs in recommend.results) {
333
+ rec_movies.push(recommend.results[recs].title);
334
+ rec_movies_org.push(recommend.results[recs].original_title);
335
+ rec_year.push(new Date(recommend.results[recs].release_date).getFullYear());
336
+ rec_vote.push(recommend.results[recs].vote_average);
337
+ if(recommend.results[recs].poster_path){
338
+ rec_posters.push("https://image.tmdb.org/t/p/original"+recommend.results[recs].poster_path);
339
+ }
340
+ else {
341
+ rec_posters.push("static/default.jpg");
342
+ }
343
+ }
344
+ },
345
+ error: function(error) {
346
+ alert("Invalid Request! - "+error);
347
+ $("#loader").delay(500).fadeOut();
348
+ }
349
+ });
350
+ return {rec_movies:rec_movies,rec_movies_org:rec_movies_org,rec_posters:rec_posters,rec_year:rec_year,rec_vote:rec_vote};
351
+ }
static/style.css ADDED
@@ -0,0 +1,310 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* width */
2
+ ::-webkit-scrollbar {
3
+ width: 15px;
4
+ }
5
+
6
+ /* Track */
7
+ ::-webkit-scrollbar-track {
8
+ border-radius: 10px;
9
+ }
10
+
11
+ /* Handle */
12
+ ::-webkit-scrollbar-thumb {
13
+ background: #e50914;
14
+ border-radius: 10px;
15
+ }
16
+
17
+ /* Handle on hover */
18
+ ::-webkit-scrollbar-thumb:hover {
19
+ background: #b30000;
20
+ }
21
+
22
+ .movie {
23
+ color: #fff;
24
+ margin-left: auto;
25
+ margin-right: auto;
26
+ resize: none;
27
+ }
28
+
29
+ .movie-content {
30
+ display: flex;
31
+ flex-wrap: wrap;
32
+ justify-content:center;
33
+ }
34
+
35
+ .movie-content > div {
36
+ margin:20px;
37
+ }
38
+
39
+ .btn-block{
40
+ width: 15%;
41
+ text-align: center;
42
+ margin-left: auto;
43
+ margin-right: auto;
44
+ color: #e4e0e0;
45
+ }
46
+
47
+ #content {
48
+ background-image: url("../static/image.jpg");
49
+ background-color: #181818;
50
+ font-family: 'Noto Sans JP', sans-serif;
51
+ }
52
+
53
+ #details {
54
+ margin-left: 50px;
55
+ }
56
+
57
+ .body-content {
58
+ position: relative;
59
+ min-height: 100%;
60
+ }
61
+
62
+ .footer {
63
+ color: #e4e0e0;
64
+ background-color: #e50914d1;
65
+ text-align:center;
66
+ position: fixed;
67
+ bottom: 0;
68
+ width: 100%;
69
+ }
70
+
71
+ .social-icons {
72
+ margin-left: 15px;
73
+ }
74
+
75
+ h1 {
76
+ font-family: 'Netflix Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
77
+ color: #e50914;
78
+ font-weight: bold;
79
+ margin-top: 30px;
80
+ text-shadow: #000000 0px 0px 13px;
81
+ }
82
+
83
+ .github-corner:hover .octo-arm {
84
+ animation: octocat-wave 560ms ease-in-out;
85
+ }
86
+
87
+ .fa-arrow-up {
88
+ font-size: 1.5em;
89
+ color: #ffffff;
90
+ background: #e50914;
91
+ padding: 10px;
92
+ border-radius: 50%;
93
+ float: right;
94
+ bottom: 25px;
95
+ position: relative;
96
+ }
97
+
98
+ .fa-arrow-up:hover {
99
+ cursor: pointer;
100
+ }
101
+
102
+ .app-title:hover {
103
+ cursor: pointer;
104
+ }
105
+
106
+ @keyframes octocat-wave {
107
+ 0%,
108
+ 100% {
109
+ transform: rotate(0)
110
+ }
111
+
112
+ 20%,
113
+ 60% {
114
+ transform: rotate(-25deg)
115
+ }
116
+
117
+ 40%,
118
+ 80% {
119
+ transform: rotate(10deg)
120
+ }
121
+ }
122
+
123
+ #autoComplete {
124
+ background-position: 98% ;
125
+ }
126
+
127
+ #name {
128
+ color: white;
129
+ padding: 1px;
130
+ }
131
+
132
+ h6 {
133
+ margin-bottom: 20px;
134
+ }
135
+
136
+ @media only screen and (max-width: 650px) {
137
+ #mcontent {
138
+ display: block;
139
+ }
140
+ .poster-lg {
141
+ display: none;
142
+ }
143
+ #details {
144
+ margin-left: 30px;
145
+ }
146
+ #loader {
147
+ display: none;
148
+ position: fixed;
149
+ z-index: 100;
150
+ left: 0;
151
+ top:0;
152
+ width: 100%;
153
+ height: 100%;
154
+ background-image: url("../static/loader.gif");
155
+ background-size: 40%;
156
+ background-position: 50% 50%;
157
+ background-color: rgba(255, 255, 255, 1);
158
+ background-repeat: no-repeat;
159
+ -webkit-transition: background-image 0.2s ease-in-out;
160
+ transition: background-image 0.2s ease-in-out;
161
+ }
162
+
163
+ #loader-text {
164
+ vertical-align: middle;
165
+ color:white;
166
+ }
167
+
168
+ #autoComplete {
169
+ background-position: 97% ;
170
+ }
171
+
172
+ svg[data-toggle=tooltip] {
173
+ width: 50px;
174
+ height: 50px;
175
+ }
176
+
177
+ .fa-arrow-up{
178
+ font-size: 1em;
179
+ color: #ffffff;
180
+ background: #e50914;
181
+ padding: 10px;
182
+ border-radius: 50%;
183
+ float: right;
184
+ bottom: 10px;
185
+ position: relative;
186
+ }
187
+ }
188
+
189
+ @media only screen and (max-width: 991px) {
190
+ .modal-body{
191
+ display: block;
192
+ }
193
+ .profile-pic {
194
+ margin-left: auto;
195
+ margin-right: auto;
196
+ display: block;
197
+ margin-bottom: 20px;
198
+ }
199
+ }
200
+ @media only screen and (min-width: 992px) {
201
+ .modal-body {
202
+ display: flex;
203
+ }
204
+ }
205
+
206
+ @media only screen and (min-width: 651px) {
207
+ .poster-sm {
208
+ display: none;
209
+ }
210
+
211
+ #mcontent {
212
+ display: flex;
213
+ flex-wrap: nowrap;
214
+ }
215
+
216
+ #loader {
217
+ display: none;
218
+ position: fixed;
219
+ z-index: 100;
220
+ left: 0;
221
+ top:0;
222
+ width: 100%;
223
+ height: 100%;
224
+ background-image: url("../static/loader.gif");
225
+ background-size: 20%;
226
+ background-position: 50% 50%;
227
+ background-color: rgba(255, 255, 255, 1);
228
+ background-repeat: no-repeat;
229
+ -webkit-transition: background-image 0.2s ease-in-out;
230
+ transition: background-image 0.2s ease-in-out;
231
+ }
232
+
233
+ #loader-text {
234
+ vertical-align: middle;
235
+ color:white;
236
+ }
237
+
238
+ }
239
+
240
+ .poster{
241
+ -webkit-box-shadow: 0px 1px 15px 4px rgba(250,250,250,1);
242
+ -moz-box-shadow: 0px 1px 15px 4px rgba(250,250,250,1);
243
+ box-shadow: 0px 1px 15px 4px rgba(250,250,250,1);
244
+ }
245
+
246
+ .card:hover {
247
+ cursor: pointer;
248
+ }
249
+
250
+ .castcard:hover {
251
+ cursor: pointer;
252
+ }
253
+
254
+ .cast-img {
255
+ filter: brightness(100%);
256
+ -moz-transition: all 0.75s ease;
257
+ -webkit-transition: all 0.75s ease;
258
+ transition: all 0.75s ease;
259
+ }
260
+
261
+
262
+ .cast-img:hover {
263
+ filter: brightness(50%);
264
+ -moz-transition: all 0.75s ease;
265
+ -webkit-transition: all 0.75s ease;
266
+ transition: all 0.75s ease;
267
+ }
268
+
269
+ .fig {
270
+ display: flex;
271
+ align-items: center;
272
+ justify-content: center;
273
+ backdrop-filter: brightness(50%);
274
+ position: absolute;
275
+ bottom: 0px;
276
+ top: 0px;
277
+ right: 0px;
278
+ left: 0px;
279
+ opacity: 0;
280
+ -moz-transition: all 0.75s ease;
281
+ -webkit-transition: all 0.75s ease;
282
+ transition: all 0.75s ease;
283
+ }
284
+
285
+ .fig:hover {
286
+ opacity: 1;
287
+ backdrop-filter:br;
288
+ -moz-transition: all 0.75s ease;
289
+ -webkit-transition: all 0.75s ease;
290
+ transition: all 0.75s ease;
291
+ }
292
+
293
+ .card-btn {
294
+ border-radius: 20px;
295
+ }
296
+
297
+ .imghvr {
298
+ position: relative;
299
+ }
300
+
301
+ .table td {
302
+ border-color: white;
303
+ border-style:solid;
304
+ border-width:1px;
305
+ }
306
+
307
+ .fail {
308
+ display: none;
309
+ color: white;
310
+ }
templates/home.html ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Movie Recommendation System</title>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7
+
8
+ <!-- Google Fonts -->
9
+ <link href="https://fonts.googleapis.com/css?family=IBM+Plex+Sans&display=swap" rel="stylesheet">
10
+ <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
11
+
12
+ <!-- Font Awesome -->
13
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
14
+
15
+ <!-- Bootstrap -->
16
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
17
+
18
+ <!-- jQuery -->
19
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
20
+
21
+ <!-- Auto Complete -->
22
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@7.2.0/dist/css/autoComplete.min.css">
23
+
24
+ <!-- External CSS -->
25
+ <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='style.css') }}">
26
+
27
+ <script type="text/javascript">
28
+ var films = {{suggestions|tojson}};
29
+ $(document).ready(function(){
30
+ $("#myModal").modal('show');
31
+ });
32
+ </script>
33
+
34
+ </head>
35
+
36
+ <body id="content" style="font-family: 'Noto Sans JP', sans-serif;">
37
+ <div class="body-content">
38
+ <div class="ml-container" style="display: block;">
39
+ <a href="https://github.com/ArchitSharma21/Movie-Recommendation-System-With-Deployment-Using-Heroku" target="_blank" class="github-corner" title="View source on GitHub">
40
+ <svg data-toggle="tooltip"
41
+ data-placement="left" width="80" height="80" viewBox="0 0 250 250"
42
+ style="fill:#e50914; color:#fff; position: fixed;z-index:100; top: 0; border: 0; right: 0;" aria-hidden="true">
43
+ <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
44
+ <path
45
+ d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
46
+ fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
47
+ <path
48
+ d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
49
+ fill="currentColor" class="octo-body"></path>
50
+ </svg>
51
+ </a>
52
+ <center><h1 class="app-title">Movie Recommendation System</h1></center>
53
+ <div class="form-group shadow-textarea" style="margin-top: 30px;text-align: center;color: white;">
54
+ <input type="text" name="movie" class="movie form-control" id="autoComplete" autocomplete="off" placeholder="Enter the Movie Name" style="background-color: #ffffff;border-color:#ffffff;width: 60%;color: #181818" required="required" />
55
+ <br>
56
+ </div>
57
+
58
+ <div class="form-group" style="text-align: center;">
59
+ <button class="btn btn-primary btn-block movie-button" style="background-color: #e50914;text-align: center;border-color: #e50914;width:120px;" disabled="true" >Enter</button><br><br>
60
+ </div>
61
+ </div>
62
+
63
+ <div id="loader" class="text-center">
64
+ </div>
65
+
66
+ <div class="fail">
67
+ <center><h3>Sorry! The movie you requested is not in our database.
68
+ Please check the spelling or try with other movies!</h3></center>
69
+ </div>
70
+
71
+ <div class="results">
72
+ <center>
73
+ <h2 id="name" class="text-uppercase"></h2>
74
+ </center>
75
+ </div>
76
+
77
+ <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel3" aria-hidden="true">
78
+ <div class="modal-dialog modal-md" role="document">
79
+ <div class="modal-content">
80
+ <div class="modal-header" style="background-color: #e50914;color: white;">
81
+ <h5 class="modal-title" id="exampleModalLabel3">Hey there!</h5>
82
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
83
+ <span aria-hidden="true" style="color: white">&times;</span>
84
+ </button>
85
+ </div>
86
+ <div class="modal-body">
87
+ <p>Don't worry if the movie that you are looking for is not auto-suggested while typing. Just type the movie name and click on "enter". You will be good to go even though if you made some typo errors.</p>
88
+ </div>
89
+ <div class="modal-footer" style="text-align: center;">
90
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">Let's go!</button>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </div>
95
+
96
+ <footer class="footer">
97
+ <br/>
98
+ <div class="social" style="margin-bottom: 8px">
99
+ <a class="social-icons" href="https://github.com/ArchitSharma21" target="_blank"><i class="fa fa-github-alt" style="font-size:24px;color: #e4e0e0"></i></a>
100
+ </div>
101
+ </footer>
102
+ </div>
103
+
104
+ <script src="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@7.2.0/dist/js/autoComplete.min.js"></script>
105
+ <script type="text/javascript" src="{{url_for('static', filename='autocomplete.js')}}"></script>
106
+
107
+ <script type="text/javascript" src="{{url_for('static', filename='recommend.js')}}"></script>
108
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
109
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
110
+
111
+ </body>
112
+ </html>
templates/recommend.html ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>NEW</title>
5
+
6
+ <meta charset="UTF-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
8
+
9
+ <!-- Google Fonts -->
10
+ <link href="https://fonts.googleapis.com/css?family=IBM+Plex+Sans&display=swap" rel="stylesheet">
11
+ <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
12
+ <link href="https://fonts.googleapis.com/css2?family=Rowdies:wght@300&display=swap" rel="stylesheet">
13
+
14
+ <!-- Font Awesome -->
15
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
16
+
17
+ <!-- Bootstrap -->
18
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
19
+
20
+ <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='style.css') }}">
21
+
22
+ </head>
23
+
24
+ <body id="content">
25
+
26
+ <div class="results">
27
+ <center>
28
+ <h2 id="name" class="text-uppercase" style="font-family: 'Rowdies', cursive;">{{title}}</h2>
29
+ </center>
30
+ </div>
31
+ <br/>
32
+
33
+ <div id="mycontent">
34
+ <div id="mcontent">
35
+ <div class="poster-lg">
36
+ <img class="poster" style="border-radius: 40px;margin-left: 90px;" height="400" width="250" src={{poster}}>
37
+ </div>
38
+ <div class="poster-sm text-center">
39
+ <img class="poster" style="border-radius: 40px;margin-bottom: 5%;" height="400" width="250" src={{poster}}>
40
+ </div>
41
+ <div id="details">
42
+ <br/>
43
+ <h6 id="title" style="color:white;">TITLE: &nbsp;{{title}}</h6>
44
+ <h6 id="overview" style="color:white;max-width: 85%">OVERVIEW: <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{overview}}</h6>
45
+ <h6 id="vote_average" style="color:white;">RATING: &nbsp;{{vote_average}}/10 ({{vote_count}} votes)</h6>
46
+ <h6 id="genres" style="color:white;">GENRE: &nbsp;{{genres}}</h6>
47
+ <h6 id="date" style="color:white;">RELEASE DATE: &nbsp;{{release_date}}</h6>
48
+ <h6 id="runtime" style="color:white;">RUNTIME: &nbsp;{{runtime}}</h6>
49
+ <h6 id="status" style="color:white;">STATUS: &nbsp;{{status}}</h6>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ <br/>
54
+
55
+ {% for name, details in cast_details.items() if not cast_details.hidden %}
56
+ <div class="modal fade" id="{{details[0]}}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel3" aria-hidden="true">
57
+ <div class="modal-dialog modal-lg" role="document">
58
+ <div class="modal-content">
59
+ <div class="modal-header" style="background-color: #e50914;color: white;">
60
+ <h5 class="modal-title" id="exampleModalLabel3">{{name}}</h5>
61
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
62
+ <span aria-hidden="true" style="color: white">&times;</span>
63
+ </button>
64
+ </div>
65
+
66
+ <div class="modal-body">
67
+ <img class="profile-pic" src="{{details[1]}}" alt="{{name}} - profile" style="width: 250px;height:400px;border-radius: 10px;" />
68
+ <div style="margin-left: 20px">
69
+ <p><strong>Birthday:</strong> {{details[2]}} </p>
70
+ <p><strong>Place of Birth:</strong> {{details[3]}} </p>
71
+ <p>
72
+ <p><strong>Biography:</strong><p>
73
+ {{details[4]}}
74
+ </p>
75
+ </div>
76
+ </div>
77
+ <div class="modal-footer">
78
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
79
+ </div>
80
+ </div>
81
+ </div>
82
+ </div>
83
+ {% endfor %}
84
+
85
+ <div class="container">
86
+
87
+ {% if casts|length > 1 %}
88
+ <div class="movie" style="color: #E8E8E8;">
89
+ <center>
90
+ <h2 style="font-family: 'Rowdies', cursive;">TOP CAST</h2>
91
+ <h5>(Click on the cast to know more)</h5>
92
+ </center>
93
+ </div>
94
+
95
+
96
+ <div class="movie-content">
97
+ {% for name, details in casts.items() if not casts.hidden %}
98
+ <div class="castcard card" style="width: 14rem;" title="Click to know more about {{name}}" data-toggle="modal" data-target="#{{details[0]}}">
99
+ <div class="imghvr">
100
+ <img class="card-img-top cast-img" id="{{details[0]}}" height="360" width="240" alt="{{name}} - profile" src="{{details[2]}}">
101
+ <figcaption class="fig">
102
+ <button class="card-btn btn btn-danger"> Know More </button>
103
+ </figcaption>
104
+ </div>
105
+ <div class="card-body" style="font-family: 'Rowdies', cursive;font-size: 18px;">
106
+ <h5 class="card-title">{{name|upper}}</h5>
107
+ <h5 class="card-title" style="font-size: 18px"><span style="color:#756969;font-size: 18px;">AS {{details[1]|upper}}</span></h5>
108
+ </div>
109
+ </div>
110
+ {% endfor %}
111
+ </div>
112
+ {% endif %}
113
+ <br/>
114
+
115
+ <center>
116
+ {% if reviews %}
117
+ <h2 style="font-family: 'Rowdies', cursive;color:white">USER REVIEWS</h2>
118
+ <div class="col-md-12" style="margin: 0 auto; margin-top:25px;">
119
+ <table class="table table-bordered" bordercolor="white" style="color:white">
120
+ <thead>
121
+ <tr>
122
+ <th class="text-center" scope="col" style="width: 75%">Comments</th>
123
+ <th class="text-center" scope="col">Sentiments</th>
124
+ </tr>
125
+ </thead>
126
+
127
+ <tbody>
128
+ {% for review, status in reviews.items() if not reviews.hidden %}
129
+ <tr style="background-color:#e5091485;">
130
+ <td>{{review}}</td>
131
+ <td>
132
+ <center>
133
+ {{status}} :
134
+ {% if status =='Positive' %}
135
+ &#128515;
136
+ {% else %}
137
+ &#128534;
138
+ {% endif %}
139
+ </center>
140
+ </td>
141
+ </tr>
142
+ {% endfor %}
143
+ </tbody>
144
+ </table>
145
+ </div>
146
+
147
+ {% if (curr_date) and (movie_rel_date) %}
148
+ {% elif curr_date < movie_rel_date %}
149
+ <div style="color:white;">
150
+ <h1 style="color:white"> This movie is not released yet. Stay tuned! </h1>
151
+ </div>
152
+ {% else %}
153
+ <div style="color:white;">
154
+ <h1 style="color:white"> Sorry, the reviews for this movie are not available! :( </h1>
155
+ </div>
156
+ {% endif %}
157
+ {% else %}
158
+ <div style="color:white;">
159
+ <h1 style="color:white"> Sorry, the reviews for this movie are not available! :( </h1>
160
+ </div>
161
+ {% endif %}
162
+ </center>
163
+ <br/>
164
+
165
+
166
+ {% if movie_cards|length > 1 %}
167
+
168
+ <div class="movie" style="color: #E8E8E8;">
169
+ <center><h2 style="font-family: 'Rowdies', cursive;">RECOMMENDED MOVIES FOR YOU</h2><h5>(Click any of the movies to get recommendation)</h5></center>
170
+ </div>
171
+
172
+ <div class="movie-content">
173
+ {% for poster, details in movie_cards.items() if not movie_cards.hidden %}
174
+ <div class="card" style="width: 14rem;" title="{{details[1]}}" onclick="recommendcard(this)">
175
+ <div class="imghvr">
176
+ <img class="card-img-top" height="360" width="240" alt="{{details[0]}} - poster" src={{poster}}>
177
+ <div class="card-img-overlay" >
178
+ <span class="card-text" style="font-size:15px;background: #000000b8;color:white;padding:2px 5px;border-radius: 10px;"><span class="fa fa-star checked">&nbsp; {{details[2]}}/10</span></span>
179
+ </div>
180
+ <div class=".card-img-overlay" style="position: relative;">
181
+ <span class="card-text" style="font-size:15px;position:absolute;bottom:20px;left:15px;background: #000000b8;color:white;padding: 5px;border-radius: 10px;">{{details[3]}}</span>
182
+ </div>
183
+ <figcaption class="fig">
184
+ <button class="card-btn btn btn-danger"> Click Me </button>
185
+ </figcaption>
186
+ </div>
187
+ <div class="card-body">
188
+ <h5 class="card-title" style="font-family: 'Rowdies', cursive;font-size: 17px;">{{details[0]|upper}}</h5>
189
+ </div>
190
+ </div>
191
+ {% endfor %}
192
+ </div>
193
+ {% endif %}
194
+ <br/><br/><br/><br/>
195
+ </div>
196
+
197
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
198
+ <script type="text/javascript" src="{{url_for('static', filename='recommend.js')}}"></script>
199
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
200
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
201
+
202
+ </body>
203
+ </html>
tranform.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:60040ccfcec04b8e9f6b763fad7166f688ae4451a9e13e058ee40193c1e3b628
3
+ size 58563