diff --git a/Client/UPmovies.html b/Client/UPmovies.html new file mode 100644 index 0000000..23dc5ad --- /dev/null +++ b/Client/UPmovies.html @@ -0,0 +1,344 @@ + + + + + + + Products - StreamHub + + + + + + + + + + + + + +

Featured Movies:

+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Client/UserProfile.html b/Client/UserProfile.html index 6435c68..6dbf403 100644 --- a/Client/UserProfile.html +++ b/Client/UserProfile.html @@ -215,6 +215,7 @@
${movieInfo.title}
const userData = data.data; console.log(data.data); displayUserProfile(userData); + } else { console.error('Error:', data.message); } @@ -276,18 +277,120 @@

Movies:

const card = document.createElement('div'); card.className = 'movie-card'; card.innerHTML = ` - ${movieInfo.title} -
${movieInfo.title}
-

${movieInfo.description}

- + ${movieInfo.data.title} +
${movieInfo.data.title}
+

${movieInfo.data.description}

+ `; return card; } -function watchMovie(movieId) { - window.location.href = `/movie?id=${movieId}`; +function getUserIdFromSession() { + return new Promise((resolve, reject) => { + fetch('/profile', { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }) + .then((response) => response.json()) + .then((data) => { + if (data.success) { + const userData = data.data; + console.log("User data received:", userData); + if (userData && userData.id) { + console.log("User ID found:", userData.id); + resolve(userData.id); + } else { + console.error('User ID not found in response'); + resolve(null); + } + } else { + console.error('Error:', data.message); + resolve(null); + } + }) + .catch((error) => { + console.error('Error fetching user profile:', error); + reject(error); + }); + }); } + + + + + + +// function watchMovie(movieId) { +// const userId = getUserIdFromSession(); +// console.log("User ID: and HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", userId); +// console.log("Sending request to prepare movie:", { movieId, userId }); +// +// fetch('/prepare-movie', { +// method: 'POST', +// headers: { +// 'Content-Type': 'application/json', +// }, +// body: JSON.stringify({ movieId, userId }), +// }) +// .then(response => response.json()) +// .then(data => { +// console.log("Received response:", data); +// if (data.success) { +// setTimeout(() => { +// window.location.href = '/movie'; +// }, 1000); +// } else { +// console.error('Error preparing movie:', data.message); +// alert('Error preparing movie: ' + data.message); +// } +// }) +// .catch(error => { +// console.error('Error:', error); +// alert('An error occurred: ' + error.message); +// }); +// } + + + +async function watchMovie(movieId) { + try { + const userId = await getUserIdFromSession(); + if (!userId) { + console.error('No user ID found. User might not be logged in.'); + alert('Please log in to watch the movie.'); + return; + } + + console.log("Sending request to prepare movie:", { movieId, userId }); + + const response = await fetch('/prepare-movie', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ movieId, userId }), + }); + + const data = await response.json(); + console.log("Received response:", data); + + if (data.success) { + setTimeout(() => { + window.location.href = '/movie'; + }, 1000); + } else { + console.error('Error preparing movie:', data.message); + alert('Error preparing movie: ' + data.message); + } + } catch (error) { + console.error('Error:', error); + alert('An error occurred: ' + error.message); + } +} + + + // Initialize the page fetchUserProfileAndRecommendations(); diff --git a/Client/chat.html b/Client/chat.html new file mode 100644 index 0000000..f7a83ec --- /dev/null +++ b/Client/chat.html @@ -0,0 +1,206 @@ + + + + + Chat Page + + + + + + + + +
+

Chat

+
+
+
+ + + +
+
+
+
+
+
+
+
+
+
+ + +
+ +
+ + + diff --git a/Client/forums.html b/Client/forums.html new file mode 100644 index 0000000..0888b34 --- /dev/null +++ b/Client/forums.html @@ -0,0 +1,538 @@ + + + + + + Forum App + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + Logged in as: ${userfname} ${userlname} +
+
+
+
+
+

Enter Forum Details

+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ + + + +
+
+ + +
+ +
+
+
+
+
+
+

About

+ +
+
+
+ + + StreamHub
+

The best Streaming platform for You and your Family!

+
+
+
+
+

Copyright © 2024 StreamHub

+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+
+
+ + + + + + diff --git a/Client/movie2.html b/Client/movie2.html index 8706b46..93b2c93 100644 --- a/Client/movie2.html +++ b/Client/movie2.html @@ -5,7 +5,7 @@ - Products - StreamHub + watching - StreamHub @@ -45,29 +45,10 @@

Movies



- - - - - +
- - - -
@@ -145,11 +126,18 @@

Movies

-
-
-

+
+
+
+ + +
+ +
+ +
@@ -186,6 +174,181 @@

About

+ diff --git a/Client/styles.css b/Client/styles.css index 32646e8..15e885a 100644 --- a/Client/styles.css +++ b/Client/styles.css @@ -251,4 +251,20 @@ video { .video-container.scrubbing .timeline, .timeline-container:hover .timeline { height: 100%; +} + + +.forums-container { + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +.card { + margin: 20px; + padding: 20px; + border: 1px solid #ddd; + border-radius: 10px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + width: 300px; } \ No newline at end of file diff --git a/Client/stylesheet.css b/Client/stylesheet.css index a5e9c51..5391505 100644 --- a/Client/stylesheet.css +++ b/Client/stylesheet.css @@ -15,4 +15,19 @@ table, th, td { th, td { padding: 5px; -} \ No newline at end of file +} + +.forums-container { + display: flex; + flex-wrap: wrap; + justify-content: center; + } + + .card { + margin: 20px; + padding: 20px; + border: 1px solid #ddd; + border-radius: 10px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + width: 300px; + } \ No newline at end of file diff --git a/ReadMe Talal b/ReadMe Talal new file mode 100644 index 0000000..ccfc77c --- /dev/null +++ b/ReadMe Talal @@ -0,0 +1,4 @@ +Talals git commits +* forums comments and post +* movie recommender with js +* will make additional chatting functionality next week diff --git a/Server/movie.js b/Server/movie.js index ca95724..333c948 100644 --- a/Server/movie.js +++ b/Server/movie.js @@ -316,58 +316,58 @@ app.get('/searchMovies', async (req, res) => { // plan to start a session here, where when a user presses a mvies to watch it will be stored in the session and direct them to this page // where they can watch the video, the video path will be a variable in the session and the video info from the db too. -app.get("/video", function (req, res) { - // Ensure there is a range given for the video - const range = req.headers.range; - if (!range) { - return res.status(400).send("Requires Range header"); - } +// app.get("/video", function (req, res) { +// // Ensure there is a range given for the video +// const range = req.headers.range; +// if (!range) { +// return res.status(400).send("Requires Range header"); +// } - console.log('Range:', range); +// console.log('Range:', range); - // get video stats (about 61MB) - const videoPath = "uploads/movies/1726081504391.mp4"; +// // get video stats (about 61MB) +// const videoPath = "uploads/movies/1726081504391.mp4"; - if (!fs.existsSync(videoPath)) { - console.error(`Video file not found: ${videoPath}`); - return res.status(404).send("Video not found"); - } +// if (!fs.existsSync(videoPath)) { +// console.error(`Video file not found: ${videoPath}`); +// return res.status(404).send("Video not found"); +// } - const videoSize = fs.statSync(`${__dirname}/${videoPath}`).size; - // Parse Range - // Example: "bytes=32324-" - const CHUNK_SIZE = 10 ** 6; // 1MB - const start = Number(range.replace(/\D/g, "")); - const end = Math.min(start + CHUNK_SIZE, videoSize - 1); +// const videoSize = fs.statSync(`${__dirname}/${videoPath}`).size; +// // Parse Range +// // Example: "bytes=32324-" +// const CHUNK_SIZE = 10 ** 6; // 1MB +// const start = Number(range.replace(/\D/g, "")); +// const end = Math.min(start + CHUNK_SIZE, videoSize - 1); - console.log(`Streaming bytes ${start}-${end} of ${videoSize}`); +// console.log(`Streaming bytes ${start}-${end} of ${videoSize}`); - // Create headers - const contentLength = end - start + 1; - const headers = { - "Content-Range": `bytes ${start}-${end}/${videoSize}`, - "Accept-Ranges": "bytes", - "Content-Length": contentLength, - "Content-Type": "video/mp4", - }; +// // Create headers +// const contentLength = end - start + 1; +// const headers = { +// "Content-Range": `bytes ${start}-${end}/${videoSize}`, +// "Accept-Ranges": "bytes", +// "Content-Length": contentLength, +// "Content-Type": "video/mp4", +// }; - // HTTP Status 206 for Partial Content - res.writeHead(206, headers); +// // HTTP Status 206 for Partial Content +// res.writeHead(206, headers); - // create video read stream for this particular chunk - const videoStream = fs.createReadStream(videoPath, { start, end }); +// // create video read stream for this particular chunk +// const videoStream = fs.createReadStream(videoPath, { start, end }); - // Stream the video chunk to the client - videoStream.on('open', () => { - videoStream.pipe(res); - }); +// // Stream the video chunk to the client +// videoStream.on('open', () => { +// videoStream.pipe(res); +// }); - videoStream.on('error', (streamErr) => { - console.error('Stream Error:', streamErr); - res.end(streamErr); - }); -}); +// videoStream.on('error', (streamErr) => { +// console.error('Stream Error:', streamErr); +// res.end(streamErr); +// }); +// }); @@ -628,6 +628,467 @@ app.get('/search/:fName/:lName', async (request, response) => { }); +// app.post("/watch-movie", async (req, res) => { +// const { movieId, userId } = req.body; + +// try { +// // Fetch movie info from the database +// const movieInfo = await db.fetchMovieInfoById(movieId); + +// // Store movie info and user info in the session +// req.session.movieInfo = movieInfo; +// req.session.userId = userId; + +// // Redirect to the movie page +// res.redirect("/movie"); +// } catch (err) { +// console.log(err); +// res.status(500).json({ success: false, message: err.message }); +// } +// }); + +// // Serve the movie page +// app.get("/movie", function (req, res) { +// if (!req.session.movieInfo) { +// return res.status(400).send("No movie info in session"); +// } + +// res.sendFile(path.join(__dirname, '..', 'Client', 'movie.html')); +// }); + +// // Serve the video +// app.get("/video", function (req, res) { +// const range = req.headers.range; +// if (!range) { +// return res.status(400).send("Requires Range header"); +// } + +// const videoPath = req.session.movieInfo.videoPath; +// if (!fs.existsSync(videoPath)) { +// console.error(`Video file not found: ${videoPath}`); +// return res.status(404).send("Video not found"); +// } + +// const videoSize = fs.statSync(videoPath).size; +// const CHUNK_SIZE = 10 ** 6; // 1MB +// const start = Number(range.replace(/\D/g, "")); +// const end = Math.min(start + CHUNK_SIZE, videoSize - 1); + +// const contentLength = end - start + 1; +// const headers = { +// "Content-Range": `bytes ${start}-${end}/${videoSize}`, +// "Accept-Ranges": "bytes", +// "Content-Length": contentLength, +// "Content-Type": "video/mp4", +// }; + +// res.writeHead(206, headers); + +// const videoStream = fs.createReadStream(videoPath, { start, end }); +// videoStream.pipe(res); + +// videoStream.on('error', (streamErr) => { +// console.error('Stream Error:', streamErr); +// res.end(streamErr); +// }); +// }); + + + + + + +app.post("/prepare-movie", async (req, res) => { + const { movieId, userId } = req.body; + + console.log("Received request to prepare movie:", { movieId, userId }); + + try { + // Fetch movie info from the database + const movieInfo = await db.fetchMovieInfoById(movieId); + + console.log("Fetched movie info:", movieInfo); + + if (!movieInfo) { + console.log("No movie info found for id:", movieId); + return res.status(404).json({ success: false, message: "Movie not found" }); + } + + // Store movie info and user info in the session + req.session.movieInfo = movieInfo; + req.session.userId = userId; + + console.log('Movie info set in session:', req.session.movieInfo); + + // Save the session explicitly + req.session.save((err) => { + if (err) { + console.error("Session save error:", err); + return res.status(500).json({ success: false, message: "Error saving session" }); + } + console.log('Session saved successfully. Session data:', req.session); + res.json({ success: true, message: "Movie prepared successfully" }); + }); + } catch (err) { + console.error("Error in /prepare-movie:", err); + res.status(500).json({ success: false, message: err.message }); + } +}); + + + + + +app.get("/movie", function (req, res) { + console.log("Session in /movie:", req.session); + if (!req.session.movieInfo) { + console.log("No movie info found in session"); + return res.status(400).send("No movie info in session. Please select a movie first."); + } + + console.log("Movie info found:", req.session.movieInfo); + res.sendFile(path.join(__dirname, '..', 'Client', 'UPmovie.html')); +}); + + +app.get("/movie-info", (req, res) => { + console.log("Session in /movie-info:", req.session); + if (!req.session.movieInfo) { + console.log("No movie info found in /movie-info"); + return res.status(400).json({ success: false, message: "No movie info in session" }); + } + + console.log("Sending movie info:", req.session.movieInfo); + res.json({ + success: true, + movieInfo: req.session.movieInfo, + userId: req.session.userId + }); +}); + + + + + +app.use((req, res, next) => { + console.log('Session ID:', req.sessionID); + console.log('Session Data:', req.session); + next(); +}); + + + + + + + + + +app.post("/watch-movie", async (req, res) => { + const { movieId, userId } = req.body; + + try { + // Fetch movie info from the database + const movieInfo = await db.fetchMovieInfoById(movieId); + + // Store movie info and user info in the session + req.session.movieInfo = movieInfo; + req.session.userId = userId; + + // Redirect to the movie page + res.redirect("/movie"); + } catch (err) { + console.log(err); + res.status(500).json({ success: false, message: err.message }); + } +}); + +// app.get("/movie", function (req, res) { +// if (!req.session.movieInfo) { +// return res.status(400).send("No movie info in session"); +// } + +// res.sendFile(path.join(__dirname, '..', 'Client', 'UPmovie.html')); +// }); + +app.get("/video", function (req, res) { + const range = req.headers.range; + if (!range) { + return res.status(400).send("Requires Range header"); + } + + const videoPath = req.session.movieInfo.filepath; + if (!fs.existsSync(videoPath)) { + console.error(`Video file not found: ${videoPath}`); + return res.status(404).send("Video not found"); + } + + const videoSize = fs.statSync(videoPath).size; + const CHUNK_SIZE = 10 ** 6; // 1MB + const start = Number(range.replace(/\D/g, "")); + const end = Math.min(start + CHUNK_SIZE, videoSize - 1); + + const contentLength = end - start + 1; + const headers = { + "Content-Range": `bytes ${start}-${end}/${videoSize}`, + "Accept-Ranges": "bytes", + "Content-Length": contentLength, + "Content-Type": "video/mp4", + }; + + res.writeHead(206, headers); + + const videoStream = fs.createReadStream(videoPath, { start, end }); + videoStream.pipe(res); + + videoStream.on('error', (streamErr) => { + console.error('Stream Error:', streamErr); + res.end(streamErr); + }); +}); + + +// app.get("/movie-info", (req, res) => { +// if (!req.session.movieInfo) { +// return res.status(400).json({ success: false, message: "No movie info in session" }); +// } + +// res.json({ +// success: true, +// movieInfo: req.session.movieInfo, +// userId: req.session.userId +// }); +// }); + + + + + + + + + + + +app.get('/movie-info/:title', async (request, response) => { + try { + const { title } = request.params; + const result = await db.fetchMovieInfo(title); + response.json({ data: result }); + } catch (err) { + console.log(err); + response.status(500).json({ success: false, message: err.message }); + } +}); + + +// forums api + +// Middleware to check if user is logged in +function isLoggedIn(req, res, next) { + if (req.headers['user-id']) { + req.user = { id: req.headers['user-id'] }; + next(); + } else { + next(); + } +} +// Create a new forum +app.post('/forums', isLoggedIn, (req, res) => { + if (!req.user) return res.status(403).send('Login required'); + + const { title, content } = req.body; + const user_id = req.user.id; + db.query('INSERT INTO forums (title, content, user_id) VALUES (?, ?, ?)', [title, content, user_id], (err, result) => { + if (err) throw err; + res.send('Forum created'); + }); +}); + + +// Get all forums +app.get('/forums', (req, res) => { + db.query('SELECT * FROM forums', (err, result) => { + if (err) throw err; + res.send(result); + }); +}); + + +// Delete a forum +app.delete('/forums/:id', isLoggedIn, (req, res) => { + if (!req.user) return res.status(403).send('Login required'); + + const forum_id = req.params.id; + db.query('DELETE FROM forums WHERE id = ? AND user_id = ?', [forum_id, req.user.id], (err, result) => { + if (err) throw err; + res.send('Forum deleted'); + }); +}); + +// Create a new comment +app.post('/forums/:forumId/comments', isLoggedIn, (req, res) => { + if (!req.user) return res.status(403).send('Login required'); + + const { content } = req.body; + const forum_id = req.params.forumId; + const user_id = req.user.id; + db.query('INSERT INTO comments (forum_id, user_id, content) VALUES (?, ?, ?)', [forum_id, user_id, content], (err, result) => { + if (err) throw err; + res.send('Comment created'); + }); +}); + +// Get all comments +app.get('/forums/:id/comments', async (req, res) => { + try { + const forumId = req.params.id; + if (!forumId) { + return res.status(400).send({ error: 'Forum ID is required' }); + } + + const comments = await db.query('SELECT * FROM comments WHERE forum_id = ?', [forumId]); + if (comments.length === 0) { + return res.status(404).send({ message: 'No comments found for this forum' }); + } + + res.send(comments); + } catch (err) { + console.error(err); + res.status(500).send({ error: 'Database query failed' }); + } +}); + +// Delete a comment + +app.delete('/comments/:id', isLoggedIn, (req, res) => { + if (!req.user) return res.status(403).send('Login required'); + + const comment_id = req.params.id; + db.query('DELETE FROM comments WHERE id = ? AND user_id = ?', [comment_id, req.user.id], (err, result) => { + if (err) throw err; + res.send('Comment deleted'); + }); +}); + + + +//code for chatting + +// Send message +app.post('/send', (req, res) => { + const { from_user_id, to_user_id, message } = req.body; + if (!from_user_id) { + res.status(401).json({ success: false, error: "You must be logged in to send a message" }); + return; + } + + db.query("INSERT INTO messages (from_user_id, to_user_id, message) VALUES (?, ?, ?)", [from_user_id, to_user_id, message], (err, result) => { + if (err) { + res.status(500).json({ success: false, error: err.message }); + } else { + res.status(200).json({ success: true }); + } + }); +}); + +// Get messages for user +// Get messages for user +app.get('/messages/:user_id', (req, res) => { + const user_id = req.params.user_id; + console.log(`Received request for messages for user ${user_id}`); + console.log('Request headers:', req.headers); + console.log('Request query:', req.query); + console.log('About to execute database query...'); + + const queries = [ + db.query("SELECT * FROM messages WHERE to_user_id = ?", [user_id]), + db.query("SELECT * FROM messages WHERE from_user_id = ?", [user_id]) + ]; + + Promise.all(queries) + .then(([receivedMessages, sentMessages]) => { + const allMessages = receivedMessages.concat(sentMessages); + console.log(`Fetched ${allMessages.length} messages for user ${user_id}`); + console.log(`Preparing response...`); + console.log('Response data:', allMessages); + res.json({ messages: allMessages }); + console.log(`Response sent.`); + }) + .catch(err => { + console.error(`Error fetching messages: ${err.message}`); + res.status(500).json({ error: err.message }); + }); +}); + + + + app.get('/searchUser/:id', async (req, res) => { + const id = req.params.id; + console.log('Received request to search user with id:', id); + + if (!id) { + console.error('No ID provided'); + return res.status(400).json({ success: false, error: 'No ID provided' }); + } + + try { + const result = await db.query("SELECT * FROM user WHERE id = ?", [id]); + if (result.length > 0) { + const user = result[0]; + return res.status(200).json({ user }); + } else { + return res.status(404).json({ success: false, error: 'User not found' }); + } + } catch (err) { + console.error('Database error:', err); + return res.status(500).json({ success: false, error: err.message }); + } + }); +// get names for forum +app.get('/api/users/:userid', async (req, res) => { + const userId = req.params.userid; + const query = `SELECT fname, lname FROM user WHERE id = ?`; + const user = await db.query(query, [userId]); + console.log(user[0].fname, user[0].lname); + res.json({ fname: user[0].fname, lname: user[0].lname }); +}); + + + +// Send message +/* +const defaultUserId = 1; + app.post('/send', (req, res) => { + const { to_user_id, message } = req.body; + const stmt = db.prepare("INSERT INTO messages (from_user_id, to_user_id, message) VALUES (?, ?, ?)"); + stmt.run(defaultUserId, to_user_id, message); + stmt.finalize(); + res.status(200).json({ success: true }); +});*/ + +// Get messages for user +/*app.get('/messages/:user_id', (req, res) => { + const user_id = req.params.user_id; + db.all("SELECT * FROM messages WHERE to_user_id = ?", [user_id], (err, rows) => { + if (err) { + res.status(500).json({ success: false, error: err.message }); + return; + } + res.status(200).json({ success: true, messages: rows }); + }); +});*/ + + + + + + + + + + + app.get("/signup.html", (req, res) => { res.sendFile(path.join(__dirname, '..', 'Client', 'signup.html')); @@ -681,6 +1142,16 @@ app.get("/UserProfile.html", (req, res) => { res.sendFile(path.join(__dirname, '..', 'Client', 'UserProfile.html')); }); +// forums link +app.get("/forums.html", (req, res) => { + res.sendFile(path.join(__dirname, '..', 'Client', 'forums.html')); +}); + + +// chat link +app.get("/chat.html", (req, res) => { + res.sendFile(path.join(__dirname, '..', 'Client', 'chat.html')); +}); app.get("*", (req, res) => { res.status(404).send("Page not found"); }); diff --git a/recommender.js b/recommender.js new file mode 100644 index 0000000..d6f7d37 --- /dev/null +++ b/recommender.js @@ -0,0 +1,126 @@ +const express = require('express'); +const mysql = require('mysql'); +const app = express(); +const port = 3000; +const path = require("path"); +//this helps with differemt file paths +app.use('/assets', express.static(path.join(__dirname, 'assets'))); +app.use('/images', express.static(path.join(__dirname, 'images'))); + + + + +const connection = mysql.createConnection({ + host: 'localhost', + user: 'root', + password: '', + database: 'MovieDB' +}); + +connection.connect(); + +app.use(express.static('public')); + +app.get('/get_movies', (req, res) => { + connection.query('SELECT movie_id, title, genre, plot FROM movies', (error, results) => { + if (error) throw error; + res.json(results); + }); +}); + +app.get('/get_movie', (req, res) => { + const movieId = req.query.movie_id; + connection.query('SELECT * FROM movies WHERE movie_id = ?', [movieId], (error, results) => { + if (error) throw error; + if (results.length === 0) { + res.status(404).json({ message: 'Movie not found' }); + } else { + res.json(results[0]); + } + }); + }); + +app.get('/get_recommendations', (req, res) => { + const movieId = req.query.movie_id; + connection.query('SELECT * FROM movies WHERE movie_id = ?', [movieId], (error, results) => { + if (error) throw error; + const selectedMovie = results[0]; + connection.query('SELECT * FROM movies', (error, allMovies) => { + if (error) throw error; + const recommendations = getRecommendations(selectedMovie, allMovies); + res.json(recommendations); + }); + }); +}); + +function getRecommendations(selectedMovie, allMovies) { + const tfidf = calculateTFIDF(allMovies); + const selectedMovieIndex = allMovies.findIndex(movie => movie.movie_id == selectedMovie.movie_id); + const cosineSim = calculateCosineSimilarity(tfidf, selectedMovieIndex); + return cosineSim + .map((score, index) => ({ movie: allMovies[index], score })) + .sort((a, b) => b.score - a.score) + .slice(1, 6); // Get top 5 recommendations +} + +function calculateTFIDF(movies) { + const tfidf = []; + const documentCount = movies.length; + const termFrequency = movies.map(movie => { + const terms = (movie.genre + ' ' + movie.plot).toLowerCase().split(/\W+/); + const termCount = {}; + terms.forEach(term => { + termCount[term] = (termCount[term] || 0) + 1; + }); + return termCount; + }); + + const documentFrequency = {}; + termFrequency.forEach(termCount => { + Object.keys(termCount).forEach(term => { + documentFrequency[term] = (documentFrequency[term] || 0) + 1; + }); + }); + + termFrequency.forEach(termCount => { + const tfidfVector = {}; + Object.keys(termCount).forEach(term => { + const tf = termCount[term] / Object.keys(termCount).length; + const idf = Math.log(documentCount / (1 + documentFrequency[term])); + tfidfVector[term] = tf * idf; + }); + tfidf.push(tfidfVector); + }); + + return tfidf; +} + +function calculateCosineSimilarity(tfidf, selectedMovieIndex) { + const selectedVector = tfidf[selectedMovieIndex]; + return tfidf.map(vector => { + const dotProduct = Object.keys(selectedVector).reduce((sum, term) => { + return sum + (selectedVector[term] * (vector[term] || 0)); + }, 0); + const magnitudeA = Math.sqrt(Object.values(selectedVector).reduce((sum, val) => sum + val * val, 0)); + const magnitudeB = Math.sqrt(Object.values(vector).reduce((sum, val) => sum + val * val, 0)); + return dotProduct / (magnitudeA * magnitudeB); + }); +} +app.get('/r', (req, res) => { + res.sendFile(__dirname + '/recom.html'); + }); + + app.get('/', (req, res) => { + res.sendFile(__dirname + '/mRecom.html'); + }); + + app.get('/t', (req, res) => { + res.sendFile(__dirname + '/test.html'); + }); + + app.get('/recommended-movies.html', (req, res) => { + res.sendFile(__dirname + '/recommended-movies.html'); + }); +app.listen(port, () => { + console.log(`Server running at http://localhost:${port}`); +}); diff --git a/streamhubdb_2.sql b/streamhubdb_2.sql new file mode 100644 index 0000000..0cf13ff --- /dev/null +++ b/streamhubdb_2.sql @@ -0,0 +1,246 @@ +-- phpMyAdmin SQL Dump +-- version 5.2.1 +-- https://www.phpmyadmin.net/ +-- +-- Host: 127.0.0.1 +-- Generation Time: Oct 12, 2024 at 01:20 PM +-- Server version: 10.4.32-MariaDB +-- PHP Version: 8.0.30 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Database: `streamhubdb` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `comments` +-- + +CREATE TABLE `comments` ( + `id` int(11) NOT NULL, + `forum_id` int(11) DEFAULT NULL, + `user_id` int(11) DEFAULT NULL, + `content` text DEFAULT NULL, + `image_url` varchar(255) DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Dumping data for table `comments` +-- + +INSERT INTO `comments` (`id`, `forum_id`, `user_id`, `content`, `image_url`, `created_at`) VALUES +(1, 1, 1, 'hello', NULL, '2024-10-11 13:25:03'), +(2, 1, 3, 'wow this is epic', NULL, '2024-10-12 09:25:22'), +(11, 7, 8, 'nah it was greate', NULL, '2024-10-12 10:53:35'), +(12, 1, 8, 'i agree with 3 it was epic', NULL, '2024-10-12 10:54:39'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `forums` +-- + +CREATE TABLE `forums` ( + `id` int(11) NOT NULL, + `title` varchar(255) NOT NULL, + `content` text DEFAULT NULL, + `user_id` int(11) DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Dumping data for table `forums` +-- + +INSERT INTO `forums` (`id`, `title`, `content`, `user_id`, `created_at`) VALUES +(1, 'scifi', 'helllo i love movie', 1, '2024-10-11 12:38:41'), +(2, 'action movie', 'this was ggreate', 1, '2024-10-12 09:56:44'), +(6, 'interstller', 'i love this movie', 8, '2024-10-12 10:22:05'), +(7, 'fnaf', 'mid horror mobie', 3, '2024-10-12 10:50:34'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `movies` +-- + +CREATE TABLE `movies` ( + `mid` int(10) NOT NULL, + `title` varchar(30) NOT NULL, + `genre` varchar(20) NOT NULL, + `rdate` varchar(5) NOT NULL, + `runtime` varchar(4) NOT NULL, + `description` varchar(100) NOT NULL, + `viewers` int(10) DEFAULT 1, + `imgpath` text NOT NULL, + `filepath` text NOT NULL, + `trailer_url` varchar(255) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Dumping data for table `movies` +-- + +INSERT INTO `movies` (`mid`, `title`, `genre`, `rdate`, `runtime`, `description`, `viewers`, `imgpath`, `filepath`, `trailer_url`) VALUES +(1, 'Oz the Great and Powerful', 'Adventure', '2013-', '130', 'A small-time magician is swept away to an enchanted land and is forced into a power struggle between', 1, 'uploads\\posters\\1726081513616.jpg', 'uploads\\movies\\1726081504391.mp4', 'https://www.youtube.com/results?search_query=oz+the+great+and+powerful+trailer'), +(3, 'My Man Godfrey', 'Comedy', '1936-', '94', 'A scatterbrained socialite hires a vagrant as a family butler - but there\'s more to Godfrey than mee', 1, 'uploads\\posters\\1726082269866.jpg', 'uploads\\movies\\1726082265639.mp4', 'https://www.imdb.com/video/vi3249931545/?ref_=ext_shr_lnk'), +(5, 'His Girl Friday', 'Romance', '1940-', '93', 'A newspaper editor uses every trick in the book to keep his ace reporter ex-wife from quitting and r', 1, 'uploads\\posters\\1726137862535.jpg', 'uploads\\movies\\1726137861727.mp4', 'https://www.imdb.com/video/vi4108846105/?playlistId=tt0032599&ref_=ext_shr_lnk'), +(7, 'Disorder in the Court', 'Comedy', '1936-', '16', 'The stooges are witnesses at a trial where their friend, a dancer at a nightclub where they are musi', 1, 'uploads\\posters\\1726139019012.jpg', 'uploads\\movies\\1726139004943.mp4', 'https://www.youtube.com/watch?v=E33qzW4Qvr8'), +(53, 'Big Duck update test', 'Adventure', '2020-', '15', 'Lmaoooo!', 1, 'uploads\\posters\\1726396270555.jpeg', 'uploads\\movies\\1726396268948.mp4', 'https://www.imdb.com/video/vi3249931545/?ref_=ext_shr_lnk'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `user` +-- + +CREATE TABLE `user` ( + `id` int(255) NOT NULL, + `fName` varchar(255) NOT NULL, + `lName` varchar(255) NOT NULL, + `Email` varchar(255) NOT NULL, + `Password` varchar(255) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Dumping data for table `user` +-- + +INSERT INTO `user` (`id`, `fName`, `lName`, `Email`, `Password`) VALUES +(1, 'The', 'Admin', 'admin@boss.com', '123'), +(3, 'TheTop', 'G', 'TheTopG@nice.com', '555'), +(6, 'Supa', 'HotFire', 'BoomPow@gmail.com', '987'), +(8, 'jack', 'sam', 'hossam@powpow.com', '573985738'), +(11, 'TheMan', 'TheMyth', 'TheLegend@me.com', '9001'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `user_movie_interaction` +-- + +CREATE TABLE `user_movie_interaction` ( + `interaction_id` int(11) NOT NULL, + `user_id` int(11) DEFAULT NULL, + `movie_id` int(11) DEFAULT NULL, + `viewed` tinyint(1) DEFAULT 0, + `liked` tinyint(1) DEFAULT 0, + `rated` tinyint(1) DEFAULT 0, + `rating` decimal(2,1) DEFAULT NULL CHECK (`rating` between 0 and 5), + `added_to_watchlist` tinyint(1) DEFAULT 0, + `picked_during_signup` tinyint(1) DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `comments` +-- +ALTER TABLE `comments` + ADD PRIMARY KEY (`id`), + ADD KEY `forum` (`forum_id`), + ADD KEY `user` (`user_id`); + +-- +-- Indexes for table `forums` +-- +ALTER TABLE `forums` + ADD PRIMARY KEY (`id`), + ADD KEY `users` (`user_id`); + +-- +-- Indexes for table `movies` +-- +ALTER TABLE `movies` + ADD PRIMARY KEY (`mid`); + +-- +-- Indexes for table `user` +-- +ALTER TABLE `user` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `user_movie_interaction` +-- +ALTER TABLE `user_movie_interaction` + ADD PRIMARY KEY (`interaction_id`), + ADD KEY `midf` (`movie_id`), + ADD KEY `uidf` (`user_id`); + +-- +-- AUTO_INCREMENT for dumped tables +-- + +-- +-- AUTO_INCREMENT for table `comments` +-- +ALTER TABLE `comments` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13; + +-- +-- AUTO_INCREMENT for table `forums` +-- +ALTER TABLE `forums` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8; + +-- +-- AUTO_INCREMENT for table `movies` +-- +ALTER TABLE `movies` + MODIFY `mid` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=54; + +-- +-- AUTO_INCREMENT for table `user` +-- +ALTER TABLE `user` + MODIFY `id` int(255) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13; + +-- +-- AUTO_INCREMENT for table `user_movie_interaction` +-- +ALTER TABLE `user_movie_interaction` + MODIFY `interaction_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- Constraints for dumped tables +-- + +-- +-- Constraints for table `comments` +-- +ALTER TABLE `comments` + ADD CONSTRAINT `forum` FOREIGN KEY (`forum_id`) REFERENCES `forums` (`id`), + ADD CONSTRAINT `user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`); + +-- +-- Constraints for table `forums` +-- +ALTER TABLE `forums` + ADD CONSTRAINT `users` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`); + +-- +-- Constraints for table `user_movie_interaction` +-- +ALTER TABLE `user_movie_interaction` + ADD CONSTRAINT `midf` FOREIGN KEY (`movie_id`) REFERENCES `movies` (`mid`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `uidf` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/streamhubdb_3.sql b/streamhubdb_3.sql new file mode 100644 index 0000000..20978ea --- /dev/null +++ b/streamhubdb_3.sql @@ -0,0 +1,257 @@ +-- phpMyAdmin SQL Dump +-- version 5.2.1 +-- https://www.phpmyadmin.net/ +-- +-- Host: 127.0.0.1 +-- Generation Time: Oct 20, 2024 at 03:21 PM +-- Server version: 10.4.28-MariaDB +-- PHP Version: 8.0.28 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Database: `streamhubdb` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `comments` +-- + +CREATE TABLE `comments` ( + `id` int(11) NOT NULL, + `forum_id` int(11) DEFAULT NULL, + `user_id` int(11) DEFAULT NULL, + `content` text DEFAULT NULL, + `image_url` varchar(255) DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Dumping data for table `comments` +-- + +INSERT INTO `comments` (`id`, `forum_id`, `user_id`, `content`, `image_url`, `created_at`) VALUES +(2, 1, 3, 'wow this is epic', NULL, '2024-10-12 09:25:22'), +(12, 1, 8, 'i agree with 3 it was epic', NULL, '2024-10-12 10:54:39'), +(13, 1, 1, 'no stfu', NULL, '2024-10-12 12:34:06'), +(14, 9, 1, 'agree', NULL, '2024-10-12 20:10:08'), +(18, 1, 8, 'u speak no', NULL, '2024-10-15 18:03:14'), +(19, 1, 1, 'i speakl yes', NULL, '2024-10-15 18:08:23'), +(21, 1, 3, 'yoyo', NULL, '2024-10-15 18:38:33'), +(23, 1, 8, 'sup', NULL, '2024-10-15 19:01:30'), +(54, 11, 1, 'gg', NULL, '2024-10-18 14:54:14'), +(57, 6, 6, 'woowoowow', NULL, '2024-10-19 17:21:36'), +(60, 1, 6, 'idk', NULL, '2024-10-19 17:31:11'), +(62, 30, 6, 'do the comments work', NULL, '2024-10-19 18:00:18'), +(72, 36, 8, 'does it work', NULL, '2024-10-20 12:54:36'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `forums` +-- + +CREATE TABLE `forums` ( + `id` int(11) NOT NULL, + `title` varchar(255) NOT NULL, + `content` text DEFAULT NULL, + `user_id` int(11) DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Dumping data for table `forums` +-- + +INSERT INTO `forums` (`id`, `title`, `content`, `user_id`, `created_at`) VALUES +(1, 'scifi', 'helllo i love movie', 1, '2024-10-11 12:38:41'), +(6, 'interstller', 'i love this movie', 8, '2024-10-12 10:22:05'), +(9, 'martian', 'goated movie', 6, '2024-10-12 20:09:53'), +(11, 'ASDS', 'SDSA', 3, '2024-10-16 10:11:50'), +(30, 'test forum', 'hello this work', 6, '2024-10-19 18:00:05'), +(36, 'fast and furious', 'i dont like them ', 8, '2024-10-20 12:37:43'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `movies` +-- + +CREATE TABLE `movies` ( + `mid` int(10) NOT NULL, + `title` varchar(30) NOT NULL, + `genre` varchar(20) NOT NULL, + `rdate` varchar(5) NOT NULL, + `runtime` varchar(4) NOT NULL, + `description` varchar(100) NOT NULL, + `viewers` int(10) DEFAULT 1, + `imgpath` text NOT NULL, + `filepath` text NOT NULL, + `trailer_url` varchar(255) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Dumping data for table `movies` +-- + +INSERT INTO `movies` (`mid`, `title`, `genre`, `rdate`, `runtime`, `description`, `viewers`, `imgpath`, `filepath`, `trailer_url`) VALUES +(1, 'Oz the Great and Powerful', 'Adventure', '2013-', '130', 'A small-time magician is swept away to an enchanted land and is forced into a power struggle between', 1, 'uploads\\posters\\1726081513616.jpg', 'uploads\\movies\\1726081504391.mp4', 'https://www.youtube.com/results?search_query=oz+the+great+and+powerful+trailer'), +(3, 'My Man Godfrey', 'Comedy', '1936-', '94', 'A scatterbrained socialite hires a vagrant as a family butler - but there\'s more to Godfrey than mee', 1, 'uploads\\posters\\1726082269866.jpg', 'uploads\\movies\\1726082265639.mp4', 'https://www.imdb.com/video/vi3249931545/?ref_=ext_shr_lnk'), +(5, 'His Girl Friday', 'Romance', '1940-', '93', 'A newspaper editor uses every trick in the book to keep his ace reporter ex-wife from quitting and r', 1, 'uploads\\posters\\1726137862535.jpg', 'uploads\\movies\\1726137861727.mp4', 'https://www.imdb.com/video/vi4108846105/?playlistId=tt0032599&ref_=ext_shr_lnk'), +(7, 'Disorder in the Court', 'Comedy', '1936-', '16', 'The stooges are witnesses at a trial where their friend, a dancer at a nightclub where they are musi', 1, 'uploads\\posters\\1726139019012.jpg', 'uploads\\movies\\1726139004943.mp4', 'https://www.youtube.com/watch?v=E33qzW4Qvr8'), +(53, 'Big Duck update test', 'Adventure', '2020-', '15', 'Lmaoooo!', 1, 'uploads\\posters\\1726396270555.jpeg', 'uploads\\movies\\1726396268948.mp4', 'https://www.imdb.com/video/vi3249931545/?ref_=ext_shr_lnk'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `user` +-- + +CREATE TABLE `user` ( + `id` int(255) NOT NULL, + `fName` varchar(255) NOT NULL, + `lName` varchar(255) NOT NULL, + `Email` varchar(255) NOT NULL, + `Password` varchar(255) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Dumping data for table `user` +-- + +INSERT INTO `user` (`id`, `fName`, `lName`, `Email`, `Password`) VALUES +(1, 'The', 'Admin', 'admin@boss.com', '123'), +(3, 'TheTop', 'G', 'TheTopG@nice.com', '555'), +(6, 'Supa', 'HotFire', 'BoomPow@gmail.com', '987'), +(8, 'jack', 'sam', 'hossam@powpow.com', '573985738'), +(11, 'TheMan', 'TheMyth', 'TheLegend@me.com', '9001'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `user_movie_interaction` +-- + +CREATE TABLE `user_movie_interaction` ( + `interaction_id` int(11) NOT NULL, + `user_id` int(11) DEFAULT NULL, + `movie_id` int(11) DEFAULT NULL, + `viewed` tinyint(1) DEFAULT 0, + `liked` tinyint(1) DEFAULT 0, + `rated` tinyint(1) DEFAULT 0, + `rating` decimal(2,1) DEFAULT NULL CHECK (`rating` between 0 and 5), + `added_to_watchlist` tinyint(1) DEFAULT 0, + `picked_during_signup` tinyint(1) DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `comments` +-- +ALTER TABLE `comments` + ADD PRIMARY KEY (`id`), + ADD KEY `forum` (`forum_id`), + ADD KEY `user` (`user_id`); + +-- +-- Indexes for table `forums` +-- +ALTER TABLE `forums` + ADD PRIMARY KEY (`id`), + ADD KEY `users` (`user_id`); + +-- +-- Indexes for table `movies` +-- +ALTER TABLE `movies` + ADD PRIMARY KEY (`mid`); + +-- +-- Indexes for table `user` +-- +ALTER TABLE `user` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `user_movie_interaction` +-- +ALTER TABLE `user_movie_interaction` + ADD PRIMARY KEY (`interaction_id`), + ADD KEY `midf` (`movie_id`), + ADD KEY `uidf` (`user_id`); + +-- +-- AUTO_INCREMENT for dumped tables +-- + +-- +-- AUTO_INCREMENT for table `comments` +-- +ALTER TABLE `comments` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=77; + +-- +-- AUTO_INCREMENT for table `forums` +-- +ALTER TABLE `forums` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=38; + +-- +-- AUTO_INCREMENT for table `movies` +-- +ALTER TABLE `movies` + MODIFY `mid` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=54; + +-- +-- AUTO_INCREMENT for table `user` +-- +ALTER TABLE `user` + MODIFY `id` int(255) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13; + +-- +-- AUTO_INCREMENT for table `user_movie_interaction` +-- +ALTER TABLE `user_movie_interaction` + MODIFY `interaction_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- Constraints for dumped tables +-- + +-- +-- Constraints for table `comments` +-- +ALTER TABLE `comments` + ADD CONSTRAINT `forum` FOREIGN KEY (`forum_id`) REFERENCES `forums` (`id`) ON DELETE CASCADE, + ADD CONSTRAINT `user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`); + +-- +-- Constraints for table `forums` +-- +ALTER TABLE `forums` + ADD CONSTRAINT `users` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`); + +-- +-- Constraints for table `user_movie_interaction` +-- +ALTER TABLE `user_movie_interaction` + ADD CONSTRAINT `midf` FOREIGN KEY (`movie_id`) REFERENCES `movies` (`mid`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `uidf` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;