ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
Course Search 選課小幫手:整合課程資料、難度指標與 AI 建議,幫助你快速找到最適合的課程。
Translation pending
EducationJavaScript · HTMLGitHub @panyuti-aiOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
這個專案提供課程搜尋、學生心得、官方課程資訊、AI 修課分析與動態課表規劃。整個網站部署在同一個 Railway 服務:Node.js/Express 提供 public/ 的前端檔案與 /api/* 後端 API,並負責 NID OAuth、資料儲存、逢甲官方資料代理與 AI 呼叫,避免把 API Key 暴露在瀏覽器。 NID API KEY 每年 7/31 到期,每年必須重新向逢甲大學申請。 申請網址請洽逢甲資訊處或 NID OAuth 服務窗口。 前端呼叫 /api/* 時使用相對網址,不需要另外設定後端網址,也沒有第二套前端部署。 上傳課表 PDF 時,前端會將 PDF 傳到後端 /api/planner-pdf,再由後端呼叫 OpenRouter 解析課程、教師、學分與節次;不會把 API key 暴露在前端。OPENROUTER_PDF_ENGINE=mistral-ocr 較適合掃描或圖片型 PDF,若要降低成本可改成 cloudflare-ai。 伺服器預設跑在 http://localhost:3000。 測試會檢查 JavaScript 語法、後端健康狀態、主要頁面、登入保護、NID 登入網址,以及三份課程資料的基本完整性。Read the full README ↗
這個專案提供課程搜尋、學生心得、官方課程資訊、AI 修課分析與動態課表規劃。整個網站部署在同一個 Railway 服務:Node.js/Express 提供 public/ 的前端檔案與 /api/* 後端 API,並負責 NID OAuth、資料儲存、逢甲官方資料代理與 AI 呼叫,避免把 API Key 暴露在瀏覽器。
NID API KEY 每年 7/31 到期,每年必須重新向逢甲大學申請。 申請網址請洽逢甲資訊處或 NID OAuth 服務窗口。
使用者瀏覽器
│
│ 同一個網域
▼
Railway:Node.js/Express(server.js)
├─ 提供 public/ 靜態前端
├─ 提供 /api/* 後端 API
├─ 呼叫逢甲 NID/官方課程資料/第三方 AI
└─ 連線 Railway PostgreSQL
前端呼叫 /api/* 時使用相對網址,不需要另外設定後端網址,也沒有第二套前端部署。
安裝依賴
npm install
設定環境變數
cp .env.example .env
# 編輯 .env,填入 ANTHROPIC_API_KEY、OPENAI_API_KEY,或 OpenRouter 的 API key
OpenRouter 使用 OpenAI-compatible API,可設定:
AI_PROVIDER=openai
OPENAI_API_KEY=sk-or-v1-xxxxxx
OPENAI_BASE_URL=https://openrouter.ai/api/v1
OPENAI_MODEL=openai/gpt-4o-mini
OPENROUTER_PDF_MODEL=openai/gpt-4o-mini
OPENROUTER_PDF_ENGINE=mistral-ocr
上傳課表 PDF 時,前端會將 PDF 傳到後端 /api/planner-pdf,再由後端呼叫 OpenRouter 解析課程、教師、學分與節次;不會把 API key 暴露在前端。OPENROUTER_PDF_ENGINE=mistral-ocr 較適合掃描或圖片型 PDF,若要降低成本可改成 cloudflare-ai。
啟動伺服器
npm start
伺服器預設跑在 http://localhost:3000。
執行測試
npm test
測試會檢查 JavaScript 語法、後端健康狀態、主要頁面、登入保護、NID 登入網址,以及課程資料的完整性與當期限制。
DATABASE_URL 需提供給網站服務。package.json 安裝依賴並執行 npm start。不需要額外的 railway.json,也不需要獨立部署前端。DATABASE_URL:Railway PostgreSQL 連線字串。ANTHROPIC_API_KEY 或 OPENAI_API_KEY:依使用的 AI 供應商擇一設定。AI_PROVIDER=openai、OPENAI_BASE_URL=https://openrouter.ai/api/v1、OPENAI_MODEL 與 OPENROUTER_PDF_MODEL。NID_CLIENT_ID、NID_CALLBACK_URL:逢甲 NID OAuth 設定。Callback 必須是網站公開網域下的 /callback,例如 https://fcu-coursesearch.com/callback。JWT_SECRET:請使用足夠長的隨機字串,不可沿用範例值。CORS_ORIGIN:可設為 Railway 公開網址或自訂網域,例如 https://fcu-coursesearch.com。目前前後端同源,不需填入另一個前端服務網址。RESEND_API_KEY、FEEDBACK_EMAIL:選填,供意見回饋寄信使用。/api/health;部署後先確認此網址回傳 {"ok":true,"service":"course-search"},再測試課程搜尋、NID 登入、收藏與課表 PDF。PORT 由 Railway 自動注入,Express 會直接使用;前端和 API 位於相同網域,因此不需要 public/config.js 或 API_BASE_URL。
GET /api/health供 Railway 健康檢查與自動化測試確認服務已啟動,不會呼叫資料庫或外部 AI。
{ "ok": true, "service": "course-search" }
POST /api/analyzeAI 分析課程是否適合修。
{
"courseName": "資料結構",
"tags": ["程式設計", "資料結構"],
"userContext": "修過 C 語言與演算法"
}
POST /api/planner-keywords從背景說明提取課程關鍵字,供排課評分使用。
{ "userContext": "我是資工系大二,想加強演算法與資料庫" }
POST /api/planner-pdf接收已登入使用者的課表 PDF,交由設定的 OpenAI-compatible/OpenRouter 模型辨識課名、教師、學分與節次。原始 PDF 不會寫入本站資料庫。
GET /api/course-grade-rules依學期與選課代碼,從逢甲公開教學大綱取得評分項目與百分比。伺服器會快取結果,
此端點保留供既有用戶端使用;目前課程詳細頁透過 /api/course-outline 取得完整大綱與配分。
/api/course-grade-rules?semester=115-1&selCode=0870
{
"items": [
{ "name": "期中考", "percentage": 30 },
{ "name": "課堂討論參與", "percentage": 40 }
],
"cached": false
}
GET /api/auth/nid-url取得逢甲 NID OAuth 登入網址,前端會將使用者導向逢甲登入頁。
POST /api/auth/nid-callback接收逢甲 OAuth 回傳的 user_code,在期限內向逢甲 API 取得使用者資料,建立或更新本站使用者並簽發 JWT。本站不會接收或儲存使用者的 NID 密碼。
GET /api/auth/me驗證現有 JWT 並回傳目前登入者資料。
網站唯一的開課來源是 public/fcu_courses.json,目前只包含校方 115-1 的 3,570 個班別。
搜尋、收藏卡片、排課候選、空堂選課與課表助理共用此清單;沒有學期的心得不能建立可選課程。
public/course_reviews.json 僅補充心得;歷史原始資料與舊合併結果保留在 data/legacy/,不對外提供。
既有個人課表仍保留,舊學期或已下架的班別會顯示提醒,不能再次加入或成為推薦。
課表助理會由後端從同一份 course_reviews.json 補入學生心得,不依賴前端或已存課表是否含有心得。
課名與教師相符時可用作業、報告、考試等文字描述比較負擔;沒有數字評分不代表沒有比較依據。
同教師其他課的心得另行標示,只供教師風格參考;沒有有效心得、描述矛盾或疑似誤歸屬時則說明限制。
心得為歷史主觀資訊,不會被換算成虛構的難度或評分,也不會讓歷史課程成為可加入的候選。
更新開課清單(換學期時指定新的學年與學期,網站各入口會一起切換):
npm run scrape-fcu -- --year 115 --sms 1
預設只抓指定學期並取代舊清單;會保留既有課程 ID,避免收藏因順序改變而遺失。
抓取為空或任何星期查詢失敗時保留原檔。歷史抓取的 --include-history 或 --merge
只能搭配 --out 寫到 public 以外;npm run merge-data 也只更新 data/legacy/courses.json。
更新後請執行測試,並以新學期重新抓取以下大綱及摘要。
搜尋卡片保留課名、教師、學分、時間及短簡介。點擊「課程詳情」可查看課程重點、 評分方式、官方大綱與學生心得;AI 修課分析、Dcard、複製與加入課表操作也集中在詳情中。 手機使用底部詳情面板,支援鍵盤分頁、Escape 關閉與回復焦點。
115-1 官方資料抓取(預設最多 2 個並行工作,可續跑):
npm run crawl-outlines -- --semester 115-1
程式依學期+選課代碼,透過 CourseOutline.aspx 取得短效 token,再呼叫
GetCourseDetail。只保存課程介紹、教學目標、每週進度、教材、官方配分及配分說明,
不保存 token、教師聯絡資訊或原始回應。會驗證回應的課程身分,逐筆原子寫入
public/course_outlines.json;失敗不刪除已完成資料,連續 3 次失敗會停止。
--limit 20 可先小批驗證,--refresh 更新既有資料,--concurrency 1 降低並行量。
停止後重跑會跳過已保存資料;不要同時啟動兩個寫入相同檔案的爬蟲。
官方資料抓取完成後,再執行 AI 整理:
npm run summarize-outlines -- --semester 115-1 --limit 20
# 確認小批內容後,移除 --limit 即可繼續完成其餘課程。
沿用 AI_PROVIDER、ANTHROPIC_API_KEY 或 OPENAI_API_KEY。也可設定專用的
COURSE_SUMMARY_PROVIDER=anthropic|openai、COURSE_SUMMARY_API_KEY、
COURSE_SUMMARY_MODEL 與 COURSE_SUMMARY_BASE_URL。
OpenRouter 可用 COURSE_SUMMARY_PROVIDER=openai,搭配
COURSE_SUMMARY_BASE_URL=https://openrouter.ai/api/v1 與相應模型。
金鑰只透過環境設定提供,不能寫入前端、資料檔或版本控制。
批次摘要會產生供應商 API 費用,可先用 --limit 控制處理量。
摘要以官方內容為依據,只整理一句短摘要、最多 5 項學習範圍與 3 個主題。
配分數字和說明直接引用官方資料,不由 AI 推估。原始大綱沒有提供學習內容時不生成摘要。
只有簡短介紹時可保留摘要,但不強制湊滿學習範圍;空白範圍會在詳情中標示。
摘要帶有來源內容雜湊;官方資料改變後,舊摘要不再顯示,需要重新整理。
課名與官方內容雜湊完全相同時,可共用已驗證的摘要,減少重複付費呼叫。
純摘要批次可用 --concurrency 6;官方抓取仍限制最多 3 個並行工作。
沒有 AI 金鑰時仍可抓取與查看官方內容,介面會標示摘要尚未完成。
GET /api/course-outlines?semester=115-1 回傳卡片用的輕量索引與實際抓取/摘要覆蓋數,
GET /api/course-outline?semester=115-1&selCode=0869 回傳單門完整資料。
一般瀏覽不會觸發付費 AI 呼叫。尚未保存的大綱會在查看詳情時查詢官方 API,
查詢具有限流、快取與同課程請求合併;失敗可重試或開啟官方原文。
本機執行:
npm test
其中:
npm run check 檢查後端與前端 JavaScript 語法。node --test 執行 API、靜態頁面、登入保護、NID OAuth 網址、課程資料及多語隱私文字測試。.github/workflows/ci.yml 會在每個 Pull Request 與推送到 main 時自動執行相同測試;全部通過後才適合合併。教師的其他課程心得會優先顯示可讀摘要;資料不足時,前端會提供已填好課名與教師的 Dcard 搜尋。若要讓使用者直接開啟原始文章:
設定 DCARD_COOKIE 後抓取公開文章索引:
npm run crawl-dcard
將文章網址、標題與公開互動數掛回心得資料:
npm run attach-review-sources
檢查 public/course_reviews.json 的差異後再提交。
scripts/dcard_raw.json 保持在 .gitignore 中,不會把完整文章與留言發布到前端;前端資料只保留最多五筆原文連結與必要的來源資訊。
CORS_ORIGIN 設為網站的 Railway 公開網址或自訂網域JWT_SECRET,不可沿用 .env.example 的範例值course-search/
├── public/ # 由 Express 提供的前端靜態檔案
│ ├── index.html
│ ├── app.js
│ ├── new_styles.css
│ └── *.json # 課程資料
├── scripts/ # 資料處理腳本
├── tests/ # Node.js 自動化測試
├── .github/workflows/ci.yml # PR 與 main 的自動測試
├── server.js # Railway 上的 Express 前後端入口
├── .env.example # 環境變數樣板
├── package.json
└── package-lock.json