From 68891e8e5b73bd065ab5cb8b9de0c1b9a4764b79 Mon Sep 17 00:00:00 2001 From: huythai855 Date: Tue, 8 Aug 2023 23:57:24 +0700 Subject: [PATCH] feat: add .env to get api keys --- .env.example | 4 ++ rec_from_one.js | 103 ------------------------------------- rec_from_one.py | 63 ----------------------- rec_from_some.js | 80 ---------------------------- rec_from_some.py | 45 ---------------- server/big_query_client.js | 13 +++-- server/helper.js | 10 +--- server/index.js | 20 ------- server/server.js | 103 ------------------------------------- 9 files changed, 14 insertions(+), 427 deletions(-) create mode 100644 .env.example delete mode 100644 rec_from_one.js delete mode 100644 rec_from_one.py delete mode 100644 rec_from_some.js delete mode 100644 rec_from_some.py delete mode 100644 server/server.js diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..f0d93569b --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# .env +PROJECT_ID= +CLIENT_EMAIL= +PRIVATE_KEY= diff --git a/rec_from_one.js b/rec_from_one.js deleted file mode 100644 index f84f1158e..000000000 --- a/rec_from_one.js +++ /dev/null @@ -1,103 +0,0 @@ -class Courses { - /* - difficulty: grading the course's hardness from 1 to 3 (easy, medium, hard) - science_ness: grading the science-ness from (-2 to 1) (Biology, Physics, Chemistry, Math) - duration: the course's duration in seconds - total_users: the total number of users who have taken the course - */ - constructor(course_id, course_name, difficulty, science_ness, duration, total_users) { - this.course_id = course_id; - this.course_name = course_name; - this.difficulty = difficulty; - this.science_ness = science_ness; - this.duration = duration / 1000; - this.total_users = total_users / 1000; - } -} - -function euclid_distance(course1, course2, science_ness_weight = 0.2, duration_weight = 0.4) { - console.log( - Math.sqrt( - (course1.difficulty - course2.difficulty) ** 2 + - science_ness_weight * (course1.science_ness - course2.science_ness) ** 2 + - duration_weight * (course1.duration - course2.duration) ** 2 + - (course1.total_users - course2.total_users) ** 2 - ) - ); - return Math.sqrt( - (course1.difficulty - course2.difficulty) ** 2 + - science_ness_weight * (course1.science_ness - course2.science_ness) ** 2 + - duration_weight * (course1.duration - course2.duration) ** 2 + - (course1.total_users - course2.total_users) ** 2 - ); -} - -function cosine_similarity(course1, course2, science_ness_weight = 0.2, duration_weight = 0.4) { - const len1 = Math.sqrt( - course1.difficulty ** 2 + - science_ness_weight * course1.science_ness ** 2 + - duration_weight * course1.duration ** 2 + - course1.total_users ** 2 - ); - - const len2 = Math.sqrt( - course2.difficulty ** 2 + - science_ness_weight * course2.science_ness ** 2 + - duration_weight * course2.duration ** 2 + - course2.total_users ** 2 - ); - - const dot_product = - course1.difficulty * course2.difficulty + - science_ness_weight * course1.science_ness * course2.science_ness + - duration_weight * course1.duration * course2.duration + - course1.total_users * course2.total_users; - - console.log(dot_product / (len1 * len2)); - return dot_product / (len1 * len2); -} - -function recommend_courses(course, k, distance_func) { - if (course.course_id < 0 || course.course_id >= courses.length) { - return null; - } - - let sorted_courses; - if (distance_func === euclid_distance) { - sorted_courses = courses.sort((a, b) => euclid_distance(course, a, 0.2, 0.4) - euclid_distance(course, b, 0.2, 0.4)); - } else if (distance_func === cosine_similarity) { - sorted_courses = courses.sort((a, b) => cosine_similarity(course, a, 0.2, 0.4) - cosine_similarity(course, b, 0.2, 0.4)); - } - - return sorted_courses.slice(0, k); -} - -// test -const courses = [ - new Courses(1, "Ly 2", 2, -1, 30000, 600), - new Courses(2, "Ly 3", 3, -1, 30000, 200), - new Courses(3, "Hoa 1", 1, 0, 28000, 402), - new Courses(4, "Hoa 3", 3, 0, 50000, 120), - new Courses(5, "Toan 3", 3, 1, 10000, 500), - new Courses(6, "Sinh 2", 2, -2, 30000, 600), -]; - -if (typeof module !== 'undefined' && module.exports) { - // Export the necessary functions and classes, if you wanna use it in another file - module.exports = { - Courses, - euclid_distance, - cosine_similarity, - recommend_courses, - courses, - }; -} - -// If using Node.js in another file, import the necessary functions and classes: -// const { Courses, euclid_distance, recommend_courses, courses } = require('./filename.js'); - -const courseA = new Courses(0, "Ly 1", 1, -1, 35000, 800); -const recommended = recommend_courses(courseA, 3, euclid_distance); -for (const course of recommended) { - console.log(course.course_name); -} \ No newline at end of file diff --git a/rec_from_one.py b/rec_from_one.py deleted file mode 100644 index b2c380ad9..000000000 --- a/rec_from_one.py +++ /dev/null @@ -1,63 +0,0 @@ -import math - -class Courses: - """ - difficulty: 1 - 3 - science_ness: -2 - 1 (Sinh, Ly, Hoa, Toan) - duration: - total_users: - chosen: da hoc truoc do chua - """ - def __init__(self, course_id, course_name, difficulty, science_ness, duration, total_users, chosen = False): - self.course_id = course_id - self.course_name = course_name - self.difficulty = difficulty - self.science_ness = science_ness - self.duration = duration / 100 - self.total_users = total_users / 100 - self.chosen = chosen - -def euclid_distance(course1, course2, science_ness_weight, duration_weight): - if course2.chosen == True: - return math.inf - #print(math.sqrt((course1.difficulty - course2.difficulty) **2 + science_ness_weight * (course1.science_ness - course2.science_ness) **2 + duration_weight * (course1.duration - course2.duration) **2 + (course1.total_users - course2.total_users) ** 2)) - return math.sqrt((course1.difficulty - course2.difficulty) **2 + science_ness_weight * (course1.science_ness - course2.science_ness) **2 + duration_weight * (course1.duration - course2.duration) **2 + (course1.total_users - course2.total_users) ** 2) - -def cosine_similarity(course1, course2, science_ness_weight = 0.2, duration_weight = 0.2): - if course2.chosen == True: - return -math.inf - len1 = math.sqrt(course1.difficulty **2 + science_ness_weight * course1.science_ness **2 + duration_weight * course1.duration **2 + course1.total_users **2) - - len2 = math.sqrt(course2.difficulty **2 + science_ness_weight * course2.science_ness **2 + duration_weight * course2.duration **2 + course2.total_users **2) - - dot_product = course1.difficulty * course2.difficulty + science_ness_weight * course1.science_ness * course2.science_ness + duration_weight * course1.duration * course2.duration + course1.total_users * course2.total_users - - print(dot_product / (len1 * len2)) - return dot_product / (len1 * len2) - -def recommend_courses(courseA, course_list, k, distance_func): - if (courseA.course_id < 0 or courseA.course_id >= len(courses)): - return None - sorted_courses = [] - if distance_func == euclid_distance: - sorted_courses = sorted(course_list, key=lambda x: euclid_distance(courseA, x, 0.2, 0.2)) - elif distance_func == cosine_similarity: - sorted_courses = sorted(course_list, key = lambda x: cosine_similarity(courseA, x, 0.2, 0.2)) - return sorted_courses[:k] - - -# test -courses = [ - Courses(1, "Ly 2", 2, -1, 300, 600, False), - Courses(2, "Ly 3", 3, -1, 300, 200, False), - Courses(3, "Hoa 1", 1, 0, 280, 402, False), - Courses(4, "Hoa 3", 3, 0, 500, 120, False), - Courses(5, "Toan 3", 3, 1, 1000, 500, False), - Courses(6, "Sinh 2", 2, -2, 300, 600, False), -] - -if __name__ == "__main__": - courseA = Courses(0, "Ly 1", 1, -1, 350, 800, True) - recommended = recommend_courses(courseA, courses, 3, euclid_distance) - for course in recommended: - print(course.course_name) \ No newline at end of file diff --git a/rec_from_some.js b/rec_from_some.js deleted file mode 100644 index 6e4bf7b39..000000000 --- a/rec_from_some.js +++ /dev/null @@ -1,80 +0,0 @@ -class Courses { - /* - difficulty: grading the course's hardness from 1 to 3 (easy, medium, hard) - science_ness: grading the science-ness from (-2 to 1) (Biology, Physics, Chemistry, Math) - duration: the course's duration in seconds - total_users: the total number of users who have taken the course - */ - constructor(course_id, name, difficulty, science_ness, duration, total_users) { - this.course_id = course_id; - this.name = name; - this.difficulty = difficulty; - this.science_ness = science_ness; - this.duration = duration / 1000; - this.total_users = total_users /100; - } -} - - -function recommendSimilarCourses(currentCourses, allCourses, k) { - function euclid_distance(course1, course2, science_ness_weight = 0.2, duration_weight = 0.4) { - // console.log( - // Math.sqrt( - // (course1.difficulty - course2.difficulty) ** 2 + - // science_ness_weight * (course1.science_ness - course2.science_ness) ** 2 + - // duration_weight * (course1.duration - course2.duration) ** 2 + - // (course1.total_users - course2.total_users) ** 2 - // ) - // ); - return Math.sqrt( - (course1.difficulty - course2.difficulty) ** 2 + - science_ness_weight * (course1.science_ness - course2.science_ness) ** 2 + - duration_weight * (course1.duration - course2.duration) ** 2 + - (course1.total_users - course2.total_users) ** 2 - ); - } - - let recommendations = []; - for (let i = 0; i < allCourses.length; i++) { - const course = allCourses[i]; - if (!currentCourses.includes(course)) { - for (let j = 0; j < currentCourses.length; j++) { - const currentCourse = currentCourses[j]; - recommendations.push([euclid_distance(currentCourse, course, 0.2, 0.4), course]); - } - } - } - - let idx = 1; - let sum = 0; - let finalRecommendations = []; - for (let i = 0; i < recommendations.length; i++) { - const [distance, course] = recommendations[i]; - sum += distance; - if (idx % currentCourses.length === 0) { - finalRecommendations.push([sum / currentCourses.length, course]); - sum = 0; - } - idx += 1; - } - - finalRecommendations.sort((a, b) => a[0] - b[0]); // Sắp xếp theo khoảng cách - return finalRecommendations.slice(0, k); -} - -const courses = [ - new Courses(1, "Ly 2", 2, -1, 3000, 600), - new Courses(2, "Ly 3", 3, -1, 3000, 200), - new Courses(3, "Hoa 1", 1, 0, 2800, 400), - new Courses(4, "Hoa 2", 3, 0, 4000, 120), - new Courses(5, "Toan 3", 3, 1, 8000, 500), - new Courses(6, "Sinh 2", 2, -2, 3000, 180), -]; - -const currentCourses = [courses[0], courses[1]]; - -recommended = recommendSimilarCourses(currentCourses, courses, 3); -for (let i = 0; i < recommended.length; i++) { - const [distance, course] = recommended[i]; - console.log(distance, course.name); -} diff --git a/rec_from_some.py b/rec_from_some.py deleted file mode 100644 index 71f0a36c1..000000000 --- a/rec_from_some.py +++ /dev/null @@ -1,45 +0,0 @@ -# import math -from rec_from_one import Courses, euclid_distance - -def recommend_similar_courses(current_courses, all_courses, k): - recommendations = [] # luu lai kc tu tung course dang hoc den cac course con lai - for course in all_courses: - if course not in current_courses: - for current_course in current_courses: - recommendations.append((euclid_distance(current_course, course, 0.2, 0.2), course)) - - # for (distance, course) in recommendations: - # print((distance, course.course_name)) - - idx = 1 - sum = 0 - final_recommendations = [] # luu trung binh kc tu courseA den cac course hien tai va courseA - for (distance, course) in recommendations: - sum += distance - if idx % len(current_courses) == 0: - final_recommendations.append((sum / len(current_courses), course)) - sum = 0 - idx += 1 - final_recommendations = sorted(final_recommendations, key = lambda x: x[0]) # sort theo khoang cach - return final_recommendations[:k] - - - -## TEST -# tat ca course cua he thong -courses = [ - Courses(1, "Ly 2", 2, -1, 300, 600, True), - Courses(2, "Ly 3", 3, -1, 300, 200, True), - Courses(3, "Hoa 1", 1, 0, 280, 402, False), - Courses(4, "Sinh 1", 1, -2, 500, 420, False), - Courses(5, "Toan 1", 1, 1, 600, 500, False), - Courses(6, "Sinh 2", 2, -2, 600, 100, False), -] - -# course dang hoc -current_courses = [courses[0], courses[1]] - -if __name__ == "__main__": - ans = recommend_similar_courses(current_courses, courses, 3) - for val in ans: - print((val[0], val[1].course_name)) \ No newline at end of file diff --git a/server/big_query_client.js b/server/big_query_client.js index 78c690432..a463146c0 100644 --- a/server/big_query_client.js +++ b/server/big_query_client.js @@ -1,15 +1,20 @@ +const dotenv = require('dotenv'); const { BigQuery } = require('@google-cloud/bigquery'); +// Load environment variables from .env file +dotenv.config(); + // Credentials to connect to BigQuery. -const credentials = require('../api_keys/sciplay-5a03294800fe.json'); +// const credentials = require('../api_keys/sciplay-5a03294800fe.json'); // Create a BigQuery client const bigqueryClient = new BigQuery({ - projectId: credentials.project_id, + projectId: process.env.PROJECT_ID, credentials: { - client_email: credentials.client_email, - private_key: credentials.private_key, + client_email: process.env.CLIENT_EMAIL, + private_key: process.env.PRIVATE_KEY, }, }); + module.exports.bigqueryClient = bigqueryClient; \ No newline at end of file diff --git a/server/helper.js b/server/helper.js index 8e5b0c4f0..4910af09e 100644 --- a/server/helper.js +++ b/server/helper.js @@ -2,9 +2,8 @@ const { getDataFromBigQuery } = require('./big_query/query.js'); const { insertDataToBigQuery } = require('./big_query/insert.js'); const { updateDataInBigQuery } = require('./big_query/update.js'); const { bigqueryClient } = require('./big_query_client.js'); -// const { get } = require('mongoose'); -// Student informations + async function getStudent(user_id) { const [rows] = await getDataFromBigQuery(bigqueryClient, { datasetId: 'sciplay_dataset', @@ -13,10 +12,8 @@ async function getStudent(user_id) { conditions: [`student_id = ${user_id}`], limit: 1, }); - // console.log(rows); let name = rows.fullname.split(/\s+/); - console.log(name); const nameArray = name.slice(-2).join(' '); name = nameArray const year = rows.date_of_birth.value.split('-'); @@ -66,7 +63,6 @@ async function getStudentCourses(user_id) { conditions: [`student_id=${user_id}`], limit: 4, }); - // console.log(rows); for (let i = 0; i < rows.length; i++) { const { course_id } = rows[i]; @@ -85,7 +81,6 @@ async function getFinishedCourses(user_id) { limit: 5, }); - // console.log(rows); for (let i = 0; i < rows.length; i++) { const { course_id } = rows[i]; rows[i] = await getCourse(course_id); @@ -138,7 +133,6 @@ async function getStudentLessons(user_id) { conditions: [`student_id=${user_id}`], limit: 3, }); - // console.log(rows); // rows = [{lesson_id : '1'}, {lesson_id : '2'}, {lesson_id : '3'}, {lesson_id : '4'}] for (let i = 0; i < rows.length; i++) { @@ -147,7 +141,6 @@ async function getStudentLessons(user_id) { rows[i] = lesson; } - // console.log(rows); return rows; } // Lesson inside a topic @@ -207,7 +200,6 @@ async function getThread(thread_id){ conditions: [`thread_id = ${thread_id}`], limit: 1, }); - console.log(row.date_time.value.toString().slice('T')); const [date, time] = row.date_time.value.slice('-'); row.time = time; row.date = date; diff --git a/server/index.js b/server/index.js index 8a3cc8a7f..f5fe9ca63 100644 --- a/server/index.js +++ b/server/index.js @@ -18,32 +18,17 @@ app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(cors()); -// async function Test () { -// const stu = await getRanking('current_level', '10'); -// console.log(stu); -// } -// Test(); app.get('/api/login', async (req, res) => { - console.log("Login API triggered"); - console.log(req.query); const email = req.query.email; const password = req.query.password; const user = await getUser(email, password); - - console.log(email); - console.log(password); - console.log(user); - try { const email = req.query.email; const password = req.query.password; const user = await getUser(email, password); - // console.log(email); - // console.log(password); - console.log("User: ", user); if (user === undefined) { res.json({ "error": true, "student_id" : undefined}); @@ -68,7 +53,6 @@ app.get('/api/homepage', async (req, res) => { courses, lessons } - // console.log(data); res.json(data); } catch (err) { res.status(500).json({ message: 'Cannot fetch data' }); @@ -90,7 +74,6 @@ app.get('/api/course', async (req, res) => { courses, recommend } - console.log(data) res.json(data); } else { if (course_path_id === undefined) { @@ -100,7 +83,6 @@ app.get('/api/course', async (req, res) => { student, topics, }; - // console.log(data); res.json(data); } else { @@ -129,7 +111,6 @@ app.get('/api/lesson', async (req, res) => { student, lesson, } - // console.log(data); res.json(data); } catch (err) { res.status(500).json({ message: 'Cannot fetch data' }); @@ -146,7 +127,6 @@ app.get('/api/user', async (req, res) => { student, fin_courses, } - // console.log(data); res.json(data); } catch (err) { res.status(500).json({ message: 'Cannot fetch data' }); diff --git a/server/server.js b/server/server.js deleted file mode 100644 index 1bd3ef5db..000000000 --- a/server/server.js +++ /dev/null @@ -1,103 +0,0 @@ -const express = require('express'); -const bodyParser = require('body-parser'); -const { BigQuery } = require('@google-cloud/bigquery'); -const { Storage } = require('@google-cloud/storage'); -const cors = require('cors'); - -const app = express(); -const port = 3000; // Chọn cổng mà bạn muốn sử dụng - - -// Credentials to connect to BigQuery. -const credentials = require('./../api_keys/sciplay-5a03294800fe.json'); - -// Create a BigQuery client -const bigqueryClient = new BigQuery({ - projectId: credentials.project_id, - credentials: { - client_email: credentials.client_email, - private_key: credentials.private_key, - }, -}); - -const keyFilename = './api_keys/sciplay-5a03294800fe.json'; -const storageClient = new Storage({ keyFilename }); - -const bucketName = 'sciplay'; // Thay 'your-bucket-name' bằng tên của Bucket GCS của bạn -const gifFileName = 'course-header-image/1.gif'; - - - -// Sử dụng body-parser để phân tích các yêu cầu gửi từ phía client -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({ extended: true })); -app.use(cors()); - -// Định nghĩa các route -app.get('/api/data', async (req, res) => { - try { - // Truy vấn dữ liệu từ BigQuery - const query = 'SELECT * FROM `sciplay_dataset.lesson`'; - const options = { - query: query, - location: 'US', // Thay đổi địa điểm nếu dữ liệu của bạn lưu trữ ở nơi khác - }; - - const [rows] = await bigqueryClient.query(options); - - const [url] = await storageClient.bucket(bucketName).file(gifFileName).getSignedUrl({ - action: 'read', - expires: Date.now() + 15 * 60 * 1000, // URL hết hạn sau 15 phút - }); - - const rowName = rows.map(item => ({ name: item.name, lesson_id: item.lesson_id, url: url })); - console.log('rowName: ', rowName); - res.json(rowName); - } catch (error) { - console.error('Error executing BigQuery query:', error); - res.status(500).json({ message: 'Something went wrong' }); - } -}); - - - -// Route mới để xử lý việc routing dựa trên thông tin name từ frontend -app.post('/api/routing', (req, res) => { - const { name } = req.body; - // Xử lý logic dựa trên thông tin name ở đây (nếu cần) - - // console.log('Clicked on:', name) - - // Ví dụ: Nếu name là 'namePage', chuyển hướng đến trang '/namePage' - if (true) { // (name === 'namePage') { - res.redirect('/login'); - } else { - res.status(404).json({ message: 'Page not found' }); - } -}); - - -// Lấý nội dung lesson -app.get('/api/lesson', async (req, res) => { - // Xử lý logic cho trang /namePage ở đây - const lesson_id = req.query.id; - - console.log('Lesson_ID: ', lesson_id); - - const query = 'SELECT * FROM `sciplay_dataset.lesson` WHERE lesson_id = ' + lesson_id + ';'; - const options = { - query: query, - location: 'US', - }; - - const [rows] = await bigqueryClient.query(options); - console.log('Rows:', rows); - - console.log(lesson_id); - res.json(rows); -}); - -// Khởi động server -app.listen(port, () => { - console.log(`Server is running on http://localhost:${port}`); -});