### 專題題目: 政大課程評價網

----
### 組長及組員姓名學號與系級
資科三 108703051 謝惟寧
資科三 108703023 李順斌
資科三 108703006 郭沛澐
資科四 107703001 鄭家宇
金融四 107302027 陳冠全
資科四 107703034 張昱威
資科四 107703044 陶亮清
----
## 專案主題
#### 政大課程評價網

----
## 需求分析
#### 為什麼想開發課程評價網站:
1. 降低同學發修課評價的成本,不需要再到論壇上發文,而是可直接填表上傳
2. 集合所有政大課程到一個網站,找課程資料不需要再到處google
3. 考古題跟筆記分享+留言系統,使用者不需要再到考古題分享社團考古
----
## 系統功能
#### 政大課程評價網有什麼功能:
1. 瀏覽/上傳/修改/刪除課程評價跟課程資源
2. 快速查詢想要找的課程
3. 將課程依照評價/甜度/涼度/收藏數排序
4. 使用者可以收藏課程
5. 使用者貼文/留言設定暱稱
----
### 專案成品
https://course-nccu.com
---
#### 目錄
1. ER Model
2. Relational Schema
3. #### 資料庫規劃
3-a. 課程 course
3-b. 使用者 user
3-c. 課程評價 courseFeedBack
3-d. 課程資源 courseResource
3-e. 系所 department
3-f. 教授 professor
3-g. 使用者發文 userPost
4. #### 前後端開發
4-a. 前端
4-b. 後端
---
###### ER Model

---
### Relational Schema

---
### 選擇DBMS
##### mongoDb (atlas)
https://cloud.mongodb.com/v2/60a7c3d75e0deb0e308f05fe#metrics/replicaSet/61ab7064edd14f61f070a2af/explorer/nccu-course-guide/coursefeedbacks/find
----
# 資料庫規劃
----
## 規劃資料庫(1)-course

----
### 處理課程資料
我們觀察這份政大課程查詢下載的excel檔

我們發現科目代碼得編碼是有規則的
從前3碼可以看出這堂課是哪一大分類的
中間3碼則表是子分類
----
科目代碼編碼規則整理
| 課程類別 | 前3碼 |
| ---- | ----- |
| 整開 | 000 |
| 中文通識 | 031 |
| 英文通識 | 032 |
| 書院 | 045 |
| 資訊 | 046 |
| 人文 | 041 |
| 社會 | 042 |
| 自然 | 043 |
| 跨領域 | 044 / 090 / 993 |
| 體育 | 002 |
| 備註: | 子類別看中間3碼 |
----
### course id:
###### course id是一個composite attribute
一堂課的id(Primary Key)=
學年(3碼)+ 學期(1碼) + 科目代碼(9碼)
共13碼
----
### 以 110 上學期的微積分為例
他的id是
1101000713001
拆解如下:
| 學年(3碼) | 學期(1碼) | 科目代碼(9碼)
| ---- | ----- | ----- |
| 110 | 1 | 000713001 |
----
### 處理課程資料
我們將excel檔轉成csv檔,
並按照科目代碼幫課程進行分類後,
直接import到我們的資料庫,
然後對每堂課加上type跟subtype
還有一些必要的attribute,
就這樣把課程資料搞定了
----
## course的schema
``` javascript [2|3|4|5|6-7|8-9|10-11|12-13|14-19|20|21-24|25-26|27-28]
const courseSchema = mongoose.Schema({
id: { type: String ,unique:true //primary key()
semester: String //學期(共四碼:)e.g. "1101"代表110學年上學期 前三碼代表學年 第四碼代表上或下學期
code: String //由政大編碼的九碼課程id (取自課程查詢下載的excel檔)
point: Number, //學分 (取自課程查詢下載的excel檔)
courseNameZH_TW: String //課程名稱(中文) (取自課程查詢下載的excel檔)
courseName: String //課程名稱 (取自課程查詢下載的excel檔)
instructorZH_TW: String //教師名稱 (取自課程查詢下載的excel檔)
instructor: String //教師名稱 (取自課程查詢下載的excel檔)
departmentZH_TW: String //開課單位 (取自課程查詢下載的excel檔)
department: String //開課單位 (取自課程查詢下載的excel檔)
sessionZH_TW: String //上課時段 (取自課程查詢下載的excel檔)
session: String ////上課時段 (取自課程查詢下載的excel檔)
classroom: String //上課教室 (取自課程查詢下載的excel檔)
typeOfCredit: String // (取自課程查詢下載的excel檔)
lectureLanguage: String //教學使用語言 (取自課程查詢下載的excel檔)
isCoreGeneral: String //是否為核心通識 (取自課程查詢下載的excel檔)
information: String //詳細資訊 (取自課程查詢下載的excel檔)
note: String //課程註解 (取自課程查詢下載的excel檔)
comments: [String], default: [] //此課程的評價陣列
avg_rate:Number, //此課程的平均評價
avg_sweet:Number, //此課程的平均甜度
avg_loading:Number, //此課程的平均涼度
avg_gain:Number, //此課程的平均收穫
num_of_feedback:Number, //此課程的評價數
num_of_like:Number, //此課程的評價數
type: String //此課程的種類:有以下幾種["DEPARTMENT","GENERAL","INTEGRATED","PE","ND"]
subType: String //此課程的子種類 列舉如下
// type為"DEPARTMENT" 的有以下幾種subtype:["CHINESE","COMPUTER_SCIENCE"...]
// type為"GENERAL" 有以下幾種subtype:["SOCIAL","HUMANITY","ENGLISH"...]
// type為"INTEGRATED" 有以下幾種subtype:["CALCULUS","CIVIL_LAW"...]
// type為"PE"(體育) 目前沒有subtype subtype值為""
// type為"ND"(國防) 目前沒有subtype subtype值為""
short_code: String //此課程的短id code的前三碼
})
```
---
## 規劃資料庫(2)-user

----
## 處理使用者登入/登出
為了確認使用者是否是真的政大的學生,
我們的使用者登入登出系統使用了google auth
第三方登入驗證
----
## 登入架構流程圖

----
## 登入架構
使用者在跟google登入驗證成功後,再將拿到的token傳到我們的server,
然後我們server再拿此token跟google確認,
確認成功後,google就會回傳這個使用者的資料供我們寫入我們資料庫(使用upsert)
----
## 登入demo

----
## 驗證使用者是否為政大學生 done
使用google第三方登入驗證系統得好處就是
我們可以驗證使用者是否使用@g.nccu.edu.tw登入我們的系統
因為我們希望只有政大的學生能上傳評價
----
## user的schema
``` javascript [3-6]
const userSchema = mongoose.Schema({
id: { type: String ,unique:true}, //primary key
token: { type: String ,unique:true}, //google api 回傳的此使用者的代碼(驗證用)
name: { type: String, required: true }, // (取自google api)
email: { type: String, required: true }, // (取自google api)
picture: { type: String }, // 人物頭像圖(取自google api)
nickname: { type: String },// 暱稱
loginChannel: { type: String }, //使用者的登入管道
isValid: { type: String }, //是否通過信箱驗證
isBanned: { type: String }, //是否被ban
likes:[String], //使用者收藏的課程id陣列
thumbups:[String], //使用者按讚的評價(feedback)id陣列
},{timestamps: true});
```
----
## user跟course之間的三張table

----
## 規劃資料庫(3)-courseFeedBack

----
## course/user/courseFeedBack relation

----
## courseFeedBack的schema
``` javascript [2|3-6|7-8|9|11]
const courseFeedBackSchema = mongoose.Schema({
id:String, //(PK)
rate: Number, //評價
sweet: Number, //甜度
loading: Number, //涼度
gain: String, //收獲
introduction: String, //懶人包
description: String, //評價內容
user: String, //使用者id
user_nickname: String, //使用者暱稱
course: String, //課程id (FK)
course_semester: String, //e.g. "1101"
course_code: String, //由政大編碼的九碼課程id
num_of_thumbsup: Number, //按讚數
})
```
----
## 課程資源

----
## courseResource的schema
``` javascript [2|3-6|7-8|9|11]
const CourseResourceSchema = mongoose.Schema({
id:String, // (PK)
introduction: String, //懶人包
description: String, //課程資源描述
user: String,//使用者id (FK)
user_nickname: String, //使用者暱稱
file_photo:String, //封面照
file: String,
file_name: String,
course: String, //課程id (FK)
course_semester: String, //學期(4碼) e.g."1101"
course_code: String, //科目代碼
num_of_thumbsup: Number, //按讚數
},{timestamps: true})
```
----
## textBook的schema
``` javascript [2|3-6|7-8|9|11]
const textBook = mongoose.Schema({
id:String, //(PK)
ISBN:String, //國際標準書號
introduction: String, //懶人包
description: String, //評價內容
price: Number, //定價
user: String, //使用者id
user_nickname: String, //使用者暱稱
course: [String], //課程id (FK)
course_semester: String, //e.g. "1101"
},{timestamps: true})
```
----
## department跟professor

----
## department的schema
``` javascript [2|3-6|7-8|9|11]
const department = mongoose.Schema({
id:String, //(PK)
name: String, //名稱
short: String, //短名稱
chinese_name: String, //中文名稱
note: String, //備註
logo_img_url: String, //logo網址
official_website_url: String, //官方網站網址
},{timestamps: true})
```
----
## professor的schema
``` javascript [2|3-6|7-8|9|11]
const professor = mongoose.Schema({
professor: String, //(PK)
department: String, //所屬科系(FK)
type: String, //職位 (教授/副教授/助理教授)
email: String, //電子信箱
extension_number: String, //校內分機號碼
education: String, //學歷
person_website_url: String, //個人網站網址
lab_website_url: String //實驗室網址
},{timestamps: true})
```
----
## userPost的schema
``` javascript [2|3-6|7-8|9|11]
//使用者table
const postSchema = mongoose.Schema({
title: String, //標題
message: String, //內文
name: String, //使用者名稱
creator: String, //使用者id (FK)
tags: [String], //標籤
selectedFile: String, //貼文圖(只有一張)(<16mb的檔案在mongodb裡可用字串存)
likes: { type: [String], default: [] }, //讚數
comments: { type: [String], default: [] }, //留言陣列
},{timestamps: true})
```
---
### 前端、後端架構
----
### 專案架構圖

----
### 前端使用工具(1)
#### React.js

----
#### 為什麼我們前端要用React.js

----
### 前端使用工具(2)
#### material UI

----
### 為什麼我們前端要用Material UI
github 星星數第三的React library
Next.js ( ⭐ 79K)
Ant Design ( ⭐ 77K)
Material-UI(⭐ 74K) 開發快/好看/客製化
Tailewind CSS(⭐ 52K) 開發慢/好看/客製化
Bootstrap React(⭐ 20K) 開發快/不好看/制式化
---
### 後端架構圖

----
## DEMO
https://course-nccu.com
----
## 心得
在開發課程評價網遇到最大的困難就是資料搜集,
我們嘗試透過學生會跟電算中心請求API,不過因為安全問題
最後只有拿到系所的Excel檔,
所以我們目前的資料是不齊全的(沒有教授的資料),
好在我們有遇到熱心的有政大的學生,願意提供他自己整理關於Dcard上的資料,
另外,為了增加課程評價數,我們也使用了google表單,讓通學可以輕鬆上傳評價
關於學校官方整理的評價,我們也開始寫爬蟲去抓取資料
關於DCARD上的課程相關資料,我們有整理出關於志願序回報的資料
最後,希望我們的專案能幫助政大學生選到他想選的課。
----
### 每位成員負責之任務分工
每人:資料庫、API規劃與設計、功能設計
資科三 惟寧: 前端 + 功能設計
資科三 順斌: course + 功能設計
資科三 沛澐: post
資科四 亮清: courseFeedBack
資科四 昱威: courseResource
資科四 家宇: csv
金融四 冠全: user
---
### 每位成員貢獻百分比
惟寧: 前端+code實作+報告 35%
順斌: 小組分工,簡報,course 15%
亮清: courseFeedBack 10%
昱威: courseResource 10%
冠全: user 10%
沛澐: post 10%
家宇: csv 10%
----
## 感謝撥空觀賞
https://course-nccu.com
{"metaMigratedAt":"2023-06-16T18:15:36.561Z","metaMigratedFrom":"YAML","title":"資料庫規劃","breaks":true,"slideOptions":"{\"transition\":\"slide\",\"slideOptions\":null}","contributors":"[{\"id\":\"fd8753d8-d3f1-42d1-9d9c-3068882df242\",\"add\":13363,\"del\":4003}]"}