<100 subscribers
Day 6:JavaScript 程式碼執行排序:遞迴函數、Call Stack、Task Queue
Call Stack;遞迴函數與 call stack 的關係;Task Queue(非同步的概念再釐清)
Day 9:「修煉圈圈 Practice Rings」Web app 開發日誌 - 2025 六角 AI Vibe Coding 體驗營期末大魔王作業
這份筆記旨在記錄 2025 六角 Vibe Coding 體驗營每日作業 Day 21 的期末專案成果,從一個簡單的個人痛點出發,透過與 AI(在我這個情境中是 Perplexity)協作,在一天內完成了一個包含前後端的全端網頁小工具:「修煉圈圈 Practice Rings」。
2025 六角學院 Vibe Coding 體驗營完課心得
透過 2025 六角 Vibe Coding 體驗營,我學會先釐清需求、再和 AI 合作實作,用 SDD 與規格和自己對話,也透過實作看見技術底子哪些地方還需要補強。
Day 6:JavaScript 程式碼執行排序:遞迴函數、Call Stack、Task Queue
Call Stack;遞迴函數與 call stack 的關係;Task Queue(非同步的概念再釐清)
Day 9:「修煉圈圈 Practice Rings」Web app 開發日誌 - 2025 六角 AI Vibe Coding 體驗營期末大魔王作業
這份筆記旨在記錄 2025 六角 Vibe Coding 體驗營每日作業 Day 21 的期末專案成果,從一個簡單的個人痛點出發,透過與 AI(在我這個情境中是 Perplexity)協作,在一天內完成了一個包含前後端的全端網頁小工具:「修煉圈圈 Practice Rings」。
2025 六角學院 Vibe Coding 體驗營完課心得
透過 2025 六角 Vibe Coding 體驗營,我學會先釐清需求、再和 AI 合作實作,用 SDD 與規格和自己對話,也透過實作看見技術底子哪些地方還需要補強。
這個小工具把跨課程模組的影音進度,收斂到同一張試算表中追蹤,如果你是:
同時在上兩門以上線上課
想在同一個管理面板確認「全部買的課總共有多少影片、自己看到哪」
不想被各家平台的「學習進度條」綁死,想用自己的規則管理進度
那你就可以用這個小工具管理自己的學習進度!
一開始需要在終端機執行指令處理一些資料,後續管理都在 Google Sheet 視覺化呈現。 雖然我是為了解決跨課程模組重複章節而開發,就算你的課程之間沒有重複章節,也可以單純把它當成「所有已購買線上課程的集中版進度面板」來用。 詳細操作步驟可以參考 GitHub 專案說明:


會起心動念開始做這個小工具,起點其實很單純:我在六角學院的正課(無限期不限次數的錄影課)與體驗營(直播型課程,有附補充錄影教材)常常出現「內容相同、章節被重新編排」的情況,導致學習時得在兩個課程頁面之間反覆切換,才能確認「這一段我到底在哪一門課看過了」。
尤其當體驗營需要跟上實作節奏、同時又想用沒有觀看期限的正課把基礎知識補齊時,這種來回比對就變成很高頻的痛點:不只浪費時間,還很容易因為名稱差異而判斷錯誤。
所以我的目標很明確:在同一個介面管理整體學習進度,把「要看的影片」和「看完打勾」這件事做得像任務管理一樣順手。
第一步是把「課程影片列表」變成可以處理的資料,而不是只能用眼睛看網頁上的文字內容。
我最後採取的方式是:直接在課程頁開 DevTools,把章節與小節的文字抓下來輸出成 CSV,讓每一列都有 course / section / lecture / duration 這些欄位。
當時也遇到六角課程頁面在「個人 Dashboard / 繼續觀課」狀態的 DOM 結構不同,需要調整 selector(例如章節 class、影片標題 class),這讓我一開始就把「01 抓取腳本要可調整 selector」列為設計重點。
一開始我對「同內容不同名字」的處理方式,其實很傳統:先用標題相似度找候選,再人工確認,最後把結果寫進 rename map(例如把「同一支影片在不同課程模組的標題」統一成 canonical_title)。
這方法可行,但只要課程一多,就會進入一種「每次更新都要再人工審一次」的循環:新增一門課要審、體驗營更新要審、章節標題改幾個字也要審,流程很難真正自動化。
後來我發現一個關鍵訊號:時長(duration)在這個情境非常有辨識度。很多重複影片即使標題略改、甚至章節歸類不同,影片長度往往完全一致(或差距非常小),這讓「只靠文字」的 fuzzy match 變成「文字 + 時長」的雙因子判斷。
也就是說,我不需要再把所有疑似重複都丟回人工決策,而是讓程式用 duration 先分桶縮小候選集合,再用字串相似度(例如 Levenshtein)做最後判斷,符合閾值就直接視為同一支影片。
這個轉變帶來的差異非常明顯:
人工 rename map(早期)
優點:準確、可控,遇到特例能硬解。
缺點:維護成本高,資料每次更新就要再審一次,工作流很難「一鍵重跑」。
duration + similarity 全自動(現在)
優點:新增課程或重新匯出清單後,直接跑腳本就能產出穩定的 canonical_key 與 watch_from,Google Sheets 只管顯示與完成觀課後勾選,整體流程變成「可重跑、可擴充」。
缺點:本質是 heuristic(啟發式)規則,仍有極少數情況可能誤判,需要保留報表或抽樣檢查的出口。
對我自己來說,這就是整個專案「最有感」的一步:把原本的人工判斷,收斂成可以被程式穩定重複執行的規則,讓新增課程模組不再是一個要花半天人工對照的任務,而是幾分鐘內可完成的自動化流程。
資料處理自動化之後,下一個挑戰是「怎麼管理進度」。 我選擇 Google Sheets 的原因很務實:
進度管理本質就是表格與勾選。
我想要能快速篩選、可視化完成度、又能在手機上看。
但我其實一開始對 Sheets 公式很不熟,特別是要讓一整張表「自動長出來」,一開始寫公式會卡在拖拉、填滿、引用錯位。
後來真正救我的關鍵是理解 陣列公式(ARRAYFORMULA) 的思維:讓 tasks 由 raw_all 自動生成,資料更新時只要取代匯入 raw_all,面板就能跟著更新。
需要時我只要匯入新的 raw_all.canonical.csv,tasks 這張表就會自動長出所有唯一影片、對應的 watch_from,並保留之前打勾過的完成狀態,完全不用再手動調整公式或範圍。
我的面板需求之一是:能夠「只看某個 section 的影片」,不然整張表太長。 我第一次用 Sheets 的資料驗證做下拉式選單,讓 section 清單自動從 raw_all 產生,再用下拉選單選要看的 section。
接著我第一次寫 Apps Script,想把「切換 section → 自動只顯示該 section」做成一鍵操作。
目前的成果是:切換 section 後,visible 欄位會自動更新,確實大幅減少手動操作;但還沒做到完全無感的 UI(我現在仍需要手動在篩選器再點一次 TRUE 才會刷新顯示)。
即便如此,它已經把最煩的「一直捲、一直找、一直比對」替換成「選 section → 勾完成」的流程,實際使用體感差很多。
回頭看這段開發,很多問題其實都在「讓流程可重跑、可驗證」:
一開始我同時做「全課程重複」和「體驗營子集重複」兩種報表,才把需求界線釐清:哪些是要用來決策 watch_from,哪些只是用來 debug。
也曾經為了少數特例寫 patch 腳本,但最後都被更通用的 canonical_key + watch_from 規則取代,整體 pipeline 變得更乾淨。
目前我已經把流程收斂成:
01:在課程頁 DevTools 抓清單(CSV)。
02:合併成 raw_all.csv(若分多課程檔)。
03:自動產生 raw_all.canonical.csv(包含 canonical_key 與 watch_from)。
匯入 Google Sheets 的 raw_all 工作表(取代內容),tasks 面板自動更新。
對我來說,這個小工具最有價值的不是「資料分析」,而是把學習流程變得像產品一樣:一個介面看全局、知道下一步要看什麼、看完就打勾。
這次算是我第一次用 JavaScript 認真寫一套「自動化工具腳本+資料處理 pipeline」,因為過去如果要做資料整理、批次處理、或是類似的自動化任務,我比較習慣用 Python 來完成。
有趣的是,不管是以前用 Python,或是這次改用 JS(尤其是 Node.js + 瀏覽器 DevTools 這種組合),在 AI 的協助下開發體驗其實很相似:先把需求描述清楚,快速產出一個可跑的版本,再透過「反覆跑、反覆驗證輸入輸出、反覆釐清操作步驟」去收斂到穩定可用的流程。
幾週前開始系統性地學前端開發之後,慢慢熟悉 JS 的語感與生態(例如直接在瀏覽器對 DOM 做處理、再用 Node 接後續 pipeline),才發現 兩種語言都能做出幾乎一樣的工具,只是切入點不同:Python 很適合快速做資料處理與整理,而 JavaScript 在「直接貼到課程頁 DevTools 抓資料」這件事上因為是瀏覽器原生語言就超級方便,不用再透過 Python 寫爬蟲。
最後把功能做完、流程跑順、文件補齊並真的開始拿來追課,那種「從混亂到可控」的成就感,不管用哪一種語言完成,體驗都非常接近,也讓我更確定:語言只是工具,真正的差異在於能不能把問題拆清楚、把流程做成可重跑的系統。
做到最後才突然意識到:這個專案從頭到尾其實都是用 JavaScript 在寫自動化,只是跑在不同的執行環境。
在課程頁面上,我用瀏覽器 DevTools 直接操作 DOM 把章節/小節抓成 CSV;回到本機後,用 Node.js 在終端機跑腳本做合併、去重與產生 canonical_key / watch_from;最後在 Google Sheets 端,Apps Script 也是用 JavaScript 寫 onEdit 來處理下拉篩選、同步勾選狀態。
更有趣的是,Google Apps Script 現在同樣是跑在 V8 runtime(也就是 Chrome 與 Node.js 使用的那個 JavaScript 引擎)上,所以可以用相對現代的 JS 語法來寫自動化邏輯。
這讓我對「JavaScript 不只是拿來寫網頁互動」有了更具體的體感:同一個語言可以在瀏覽器、命令列、雲端腳本這三個地方各司其職,把一個原本很瑣碎的人工流程串成可重跑的工具鏈。
這個小工具把跨課程模組的影音進度,收斂到同一張試算表中追蹤,如果你是:
同時在上兩門以上線上課
想在同一個管理面板確認「全部買的課總共有多少影片、自己看到哪」
不想被各家平台的「學習進度條」綁死,想用自己的規則管理進度
那你就可以用這個小工具管理自己的學習進度!
一開始需要在終端機執行指令處理一些資料,後續管理都在 Google Sheet 視覺化呈現。 雖然我是為了解決跨課程模組重複章節而開發,就算你的課程之間沒有重複章節,也可以單純把它當成「所有已購買線上課程的集中版進度面板」來用。 詳細操作步驟可以參考 GitHub 專案說明:


會起心動念開始做這個小工具,起點其實很單純:我在六角學院的正課(無限期不限次數的錄影課)與體驗營(直播型課程,有附補充錄影教材)常常出現「內容相同、章節被重新編排」的情況,導致學習時得在兩個課程頁面之間反覆切換,才能確認「這一段我到底在哪一門課看過了」。
尤其當體驗營需要跟上實作節奏、同時又想用沒有觀看期限的正課把基礎知識補齊時,這種來回比對就變成很高頻的痛點:不只浪費時間,還很容易因為名稱差異而判斷錯誤。
所以我的目標很明確:在同一個介面管理整體學習進度,把「要看的影片」和「看完打勾」這件事做得像任務管理一樣順手。
第一步是把「課程影片列表」變成可以處理的資料,而不是只能用眼睛看網頁上的文字內容。
我最後採取的方式是:直接在課程頁開 DevTools,把章節與小節的文字抓下來輸出成 CSV,讓每一列都有 course / section / lecture / duration 這些欄位。
當時也遇到六角課程頁面在「個人 Dashboard / 繼續觀課」狀態的 DOM 結構不同,需要調整 selector(例如章節 class、影片標題 class),這讓我一開始就把「01 抓取腳本要可調整 selector」列為設計重點。
一開始我對「同內容不同名字」的處理方式,其實很傳統:先用標題相似度找候選,再人工確認,最後把結果寫進 rename map(例如把「同一支影片在不同課程模組的標題」統一成 canonical_title)。
這方法可行,但只要課程一多,就會進入一種「每次更新都要再人工審一次」的循環:新增一門課要審、體驗營更新要審、章節標題改幾個字也要審,流程很難真正自動化。
後來我發現一個關鍵訊號:時長(duration)在這個情境非常有辨識度。很多重複影片即使標題略改、甚至章節歸類不同,影片長度往往完全一致(或差距非常小),這讓「只靠文字」的 fuzzy match 變成「文字 + 時長」的雙因子判斷。
也就是說,我不需要再把所有疑似重複都丟回人工決策,而是讓程式用 duration 先分桶縮小候選集合,再用字串相似度(例如 Levenshtein)做最後判斷,符合閾值就直接視為同一支影片。
這個轉變帶來的差異非常明顯:
人工 rename map(早期)
優點:準確、可控,遇到特例能硬解。
缺點:維護成本高,資料每次更新就要再審一次,工作流很難「一鍵重跑」。
duration + similarity 全自動(現在)
優點:新增課程或重新匯出清單後,直接跑腳本就能產出穩定的 canonical_key 與 watch_from,Google Sheets 只管顯示與完成觀課後勾選,整體流程變成「可重跑、可擴充」。
缺點:本質是 heuristic(啟發式)規則,仍有極少數情況可能誤判,需要保留報表或抽樣檢查的出口。
對我自己來說,這就是整個專案「最有感」的一步:把原本的人工判斷,收斂成可以被程式穩定重複執行的規則,讓新增課程模組不再是一個要花半天人工對照的任務,而是幾分鐘內可完成的自動化流程。
資料處理自動化之後,下一個挑戰是「怎麼管理進度」。 我選擇 Google Sheets 的原因很務實:
進度管理本質就是表格與勾選。
我想要能快速篩選、可視化完成度、又能在手機上看。
但我其實一開始對 Sheets 公式很不熟,特別是要讓一整張表「自動長出來」,一開始寫公式會卡在拖拉、填滿、引用錯位。
後來真正救我的關鍵是理解 陣列公式(ARRAYFORMULA) 的思維:讓 tasks 由 raw_all 自動生成,資料更新時只要取代匯入 raw_all,面板就能跟著更新。
需要時我只要匯入新的 raw_all.canonical.csv,tasks 這張表就會自動長出所有唯一影片、對應的 watch_from,並保留之前打勾過的完成狀態,完全不用再手動調整公式或範圍。
我的面板需求之一是:能夠「只看某個 section 的影片」,不然整張表太長。 我第一次用 Sheets 的資料驗證做下拉式選單,讓 section 清單自動從 raw_all 產生,再用下拉選單選要看的 section。
接著我第一次寫 Apps Script,想把「切換 section → 自動只顯示該 section」做成一鍵操作。
目前的成果是:切換 section 後,visible 欄位會自動更新,確實大幅減少手動操作;但還沒做到完全無感的 UI(我現在仍需要手動在篩選器再點一次 TRUE 才會刷新顯示)。
即便如此,它已經把最煩的「一直捲、一直找、一直比對」替換成「選 section → 勾完成」的流程,實際使用體感差很多。
回頭看這段開發,很多問題其實都在「讓流程可重跑、可驗證」:
一開始我同時做「全課程重複」和「體驗營子集重複」兩種報表,才把需求界線釐清:哪些是要用來決策 watch_from,哪些只是用來 debug。
也曾經為了少數特例寫 patch 腳本,但最後都被更通用的 canonical_key + watch_from 規則取代,整體 pipeline 變得更乾淨。
目前我已經把流程收斂成:
01:在課程頁 DevTools 抓清單(CSV)。
02:合併成 raw_all.csv(若分多課程檔)。
03:自動產生 raw_all.canonical.csv(包含 canonical_key 與 watch_from)。
匯入 Google Sheets 的 raw_all 工作表(取代內容),tasks 面板自動更新。
對我來說,這個小工具最有價值的不是「資料分析」,而是把學習流程變得像產品一樣:一個介面看全局、知道下一步要看什麼、看完就打勾。
這次算是我第一次用 JavaScript 認真寫一套「自動化工具腳本+資料處理 pipeline」,因為過去如果要做資料整理、批次處理、或是類似的自動化任務,我比較習慣用 Python 來完成。
有趣的是,不管是以前用 Python,或是這次改用 JS(尤其是 Node.js + 瀏覽器 DevTools 這種組合),在 AI 的協助下開發體驗其實很相似:先把需求描述清楚,快速產出一個可跑的版本,再透過「反覆跑、反覆驗證輸入輸出、反覆釐清操作步驟」去收斂到穩定可用的流程。
幾週前開始系統性地學前端開發之後,慢慢熟悉 JS 的語感與生態(例如直接在瀏覽器對 DOM 做處理、再用 Node 接後續 pipeline),才發現 兩種語言都能做出幾乎一樣的工具,只是切入點不同:Python 很適合快速做資料處理與整理,而 JavaScript 在「直接貼到課程頁 DevTools 抓資料」這件事上因為是瀏覽器原生語言就超級方便,不用再透過 Python 寫爬蟲。
最後把功能做完、流程跑順、文件補齊並真的開始拿來追課,那種「從混亂到可控」的成就感,不管用哪一種語言完成,體驗都非常接近,也讓我更確定:語言只是工具,真正的差異在於能不能把問題拆清楚、把流程做成可重跑的系統。
做到最後才突然意識到:這個專案從頭到尾其實都是用 JavaScript 在寫自動化,只是跑在不同的執行環境。
在課程頁面上,我用瀏覽器 DevTools 直接操作 DOM 把章節/小節抓成 CSV;回到本機後,用 Node.js 在終端機跑腳本做合併、去重與產生 canonical_key / watch_from;最後在 Google Sheets 端,Apps Script 也是用 JavaScript 寫 onEdit 來處理下拉篩選、同步勾選狀態。
更有趣的是,Google Apps Script 現在同樣是跑在 V8 runtime(也就是 Chrome 與 Node.js 使用的那個 JavaScript 引擎)上,所以可以用相對現代的 JS 語法來寫自動化邏輯。
這讓我對「JavaScript 不只是拿來寫網頁互動」有了更具體的體感:同一個語言可以在瀏覽器、命令列、雲端腳本這三個地方各司其職,把一個原本很瑣碎的人工流程串成可重跑的工具鏈。
Share Dialog
Share Dialog
No comments yet