聽力練習模式|工作報告
案子期間 2026-10-04~10-05|案子資料夾 docs\work\2026-10-04-listening-mode\|本案不在 git 版控,以鎖定檔 02-contract.locked.md 為準
一句話結論
把多益題庫做成一個「照正確方法練聽力」的網站,放在實驗室電腦當 server(一直開著、負責存進度和送網頁的那台電腦),手機、電腦都能接著學。
驗收全過:自動測試 plan 52、sync 8、server 11、e2e 77 全部通過;第 3 關(找人實際試用)最後一輪沒有低於 3 分的格子;最後一次監工(沒參與製作的獨立檢查者)在正常使用下找到 0 個高、0 個中的問題。
原本有 4 件事等你決定,2026-10-05 已全部定案(見第 1 節)。
做了什麼
| 項目 | 白話 |
|---|---|
| 打開就知道這次做什麼 | 每次分三區:① 複習 → ② 新學(一組 5 個新字+10 題)→ ③ 連續聽。做完按「這次完成」。 |
| 每一題教你怎麼聽 | 先聽再看、只抓聲音不翻譯;句子裡每個字都能點,點了=「剛剛沒聽出來」。 |
| 自動排複習 | 點過字的句子,下一次會回來複習。連續 2 次「這次都聽出來了」就算學會。 |
| 到哪裡都接得上 | 進度存在實驗室電腦。電腦做到一半,手機打開就停在同一題。 |
| 學習方法手冊 | 網站裡有一個子頁 guide.html,隨時能打開看「為什麼要這樣練」。 |
驗收結果出處
| 說法 | 出處 |
|---|---|
| 四組測試 plan 52、sync 8、server 11、e2e 77 全過 | 04-implementation.md 最後一節(製作者自己跑,e2e 連跑 2 次)。最後一位監工(05k)自己重跑時是 plan 52、sync 8、server 11、e2e 75,也全過;那之後新加的 2 個 e2e 只有製作者跑過。 |
| 第 3 關最後一輪沒有低於 3 分 | 05d-gate3-r5.md 分數表 |
| 最後一次監工 0 高 0 中 | 05k-review-r7.md(正常使用下 0 高、0 中、3 低) |
左邊點一節看一節(手機點左上角 ☰)。每節開頭都有一句結論,趕時間只讀那一句就好。
最重要的是「1 還需要你決定的事」和「B 驗收對照表」。
1 還需要你決定的事
結論:有 4 題等你決定,都不擋上線。我的建議是:前 3 題都「先照現在的用一週,再決定」,第 4 題另開小案子處理。
你說「你決定就好,用了有問題會說」,所以 4 題都由我定案:
1. 新文字:照現在的用。哪句讀起來卡再改。
2. 複習卡上次的選項和對錯:不收起來(改變了原本的建議)。理由:你 10/4 定過「題目和選項都不蓋住,我自己不要去看就好」,收起來等於蓋住,跟你自己的原則衝突。
3. 複習先堆起來:接受。每次分量不變;真的有壓力再改面板說法。
4. 課綱:已經改了,不另開案子(只改兩句話)。看過原文後發現那段在講「單字」練習,不是整句。改成「每遍只抓聲音、聽出是哪個字(不把整句翻成中文)」和「聽到 → 一秒內懂意思(腦中出現畫面或意思就算,不用說出中文)」。改之前的檔案備份在 scratchpad。
第 1 題:新加的畫面文字,要不要換說法?
問題:最後兩輪照試用者的建議加了幾句新文字。你授權我先做(04 寫明「字眼照試用者建議先做」),但字眼本來是你要拍板的事。
| 出現在哪 | 現在的文字 | 出處 |
|---|---|---|
| 複習卡題號旁(一句剛學會時) | 「· 學會了 ✓(之後不再複習)」 | 第 3 關 r5 M1 |
| 按完「這次完成」的畫面 | 「這次有 N 句學會了,之後不用再複習 ✓」 | 第 3 關 r5 M1 |
| 「今天只複習」框裡的按鈕 | 「▶ 先連續聽複習的 N 句」 | 第 3 關 r5 L6 |
| 面板「之後還會再出現 N 句」後面的括號 | 「(裡面有還沒聽出來的字)」 | 第 3 關 r5 L1 |
| 同一顆連續聽按鈕播放中/播完 | 「■ 停止(正在播第 k / n 句)」→「✓ 已聽完 · 再聽一次」 | 05k 低 2 |
我推薦:先用,用一週再說。
為什麼:前四句是第 3 關試用者建議的說法,最後一句是監工建議的;監工(05k)在手機上看過實際樣子,不會擠爛版面。字眼好不好,要你自己累的晚上用過才知道。哪句讀起來卡,直接告訴我改哪句就好。
第 2 題:複習卡要不要把「上次的選項和對錯」收起來?
問題:複習卡現在還顯示上次的 5 個選項、上次的對錯(例如紅色「✗ 錯誤 · 正解:…」)。手機上一張卡約 899 px 高。
我推薦:要收(預設收起,點「看上次的題目」才展開),但不急:先用一週,覺得礙眼再開一個小案子做。
為什麼:
- 複習是在驗耳朵,舊的對錯跟耳朵無關,還讓手機多滑好幾個畫面。第 3 關 5 輪試用者每輪都提(r1 L2、r2 L2、r3 L3、r4 L3、r5 L3)。
- 但它一直被評為「低」,不影響做完一次。04 記錄不改的原因是「要動版面較大」。
第 3 題:學新題那段時間,複習會先堆起來,能接受嗎?
問題:這是 D6 規則(到期超過 10 句時,先排最難的)的必然結果。監工用模擬算出來的樣子(05j 低 3):
- 第 5~25 次,每次到期的句子都超過 10 句,最多 44 句(第 11 次)。
- 面板的「之後還會再出現 N 句」會先漲到 50~60 句,才開始下降。
- 「只點過 1 個字」的句子會一直被更難的擠到後面,最多等 16 次才輪到。
- 新題全部學完後約 15 次(第 26 次)清空。
- 每一次都還是「複習 10+新學 10」,做得完,不會卡住。
注意:這是模擬,假設「新題 70% 會點 1~3 個字、複習 60% 按都聽出來」。這兩個比例是監工假設的,不是你的實際資料。
我推薦:接受,先照現在的用。
為什麼:
- 每次的分量不變,1.5 小時內做得完。
- 先練最難的,符合你 10/5 說的「學會的字之後會在新題目裡自然重複,舊題目只要把真正難的磨到聽得出來」。
- 真的覺得「數字一直漲」有壓力,還有兩條退路:改面板的說法,或改用停車場 P3 原本的推薦(複習多時新題少排幾題,總量不變)。
第 4 題:文法課綱裡「每遍試說中文」那段,要不要另案改掉?
問題:課綱的聽力格式寫「先聽三遍不看字,每遍試說中文」。這跟本案的新方法「只抓聲音、不翻成中文」相反。你 10/5 決定本案不做「每遍試說中文」(停車場 P1),但課綱檔本身沒改。
我推薦:另開一個小案子,把課綱那段改成「聽到→一秒內出現畫面或懂意思」。
為什麼:合約第 41 條規定之後出第 2 冊要照課綱的規則。兩份文件說法相反,之後出題或複習課綱時會混淆。
停車場 P1~P4 與差異 D1~D6 都在 2026-10-05 處理完:P1 是你親自決定;P2~P4、D1~D6 是你授權我照「① 長期目標 ② 方便持續用下去」代為裁決(
01-decisions.md 最後一節)。A 合約原文
結論:合約動工前就鎖定了,收工時一個字都沒改;後來只追加了第 42、43 條(手冊放上網站)。
以下為動工前鎖定之合約原文(檔案
02-contract.locked.md;本案不在 git),收工時未經任何改寫。現存的
02-contract.md 與鎖定檔大小相同(10,189 bytes),主理人已逐位元組比對過。02 合約:聽力練習模式(2026-10-04)
1. 想解決什麼(點開看原文)
主理人原話:
「我在看這些題目的時候,通常聽了兩三遍,只能抓出部分的關鍵詞……然後翻譯成中文,然後去理解。這種方式感覺太慢了。」
「明明知道意思,但是我聽不懂,我用聽的完全不知道是什麼意思。」
「因為我知道中文意思……就可以推敲出來那一塊是在講哪一個內容,然後就會沒這麼的仔細。」
「這個網頁可以漸進式引導我去學會,而不是讓我有偷懶的這個機會。」
「最重要的重點是,我要知道那個邏輯,才去學習……規則啊、制約啊、評分啊、麥克風錄製聲音這種東西可能會有點太多餘了,所以要抓一下分寸。」
「我只要上來學英文,我不用管今天必須要做到什麼事情……直接無腦學習。」
白話目標:
讓這個題庫網頁一打開,就告訴我這一次要做什麼;並且在每一題裡,用輕量的步驟引導我照正確的方法練聽力:先聽再看、只抓聲音不翻譯、看原文時找出沒聽出來的字、之後反覆聽已經懂的句子。我先讀懂這套方法的道理,再開始練。
2. 查了什麼、發現什麼(點開看原文)
- 題庫現在有 10 組、每組 5 個新字和 10 題。每一題都有整句錄音、翻譯、詳解、句子拆解(每一塊都能單獨播放)。單字也能播放。
- 一打開,所有題目和英文句子都直接顯示。所以很難做到「先聽再看」。
- 主理人現在的聽法:先不看字聽,邊聽邊找認得的字翻成中文;聽三遍大約抓到七、八個字;接著看原文才看懂;再聽時腦中已經有中文,變成在找哪個中文對到哪個英文。
- 主要缺口有兩個:
- 認得字的拼法,卻認不出它實際念出來的聲音(字會黏在一起、小字念得很輕)。
- 知道意思之後,會用猜的代替真的聽到。
- 實測語速:網頁的 100% 約等於多益官方範例的速度;主理人目前練 70%。
- 主理人每天學英文大約 2 小時,扣掉恍神,每次的目標要在 1.5 小時內做得完。
- 之後網頁會放到 server 上,要在任何地方都能用。
3. 考慮過哪些做法、為什麼選這個(點開看原文)
| 主題 | 選的做法 | 放棄的做法與理由 |
|---|---|---|
| 擋偷懶的程度 | 靠理解目的+提示「什麼時候可以看」,不蓋任何東西 | 強制鎖定、計分、懲罰:太多。預設蓋住句子和選項:主理人選擇自己不看就好 |
| 記下沒聽出來的字 | 句子打開後點字標記 | 聽寫框自動比對:每句都要打字,太重 |
| 第一眼看到什麼 | 只顯示這一次要做的東西 | 顯示全部題目:每次都要自己找位置 |
| 怎麼算一天 | 用「次」:開始做算一次,按完成才結束 | 用日曆天數:休息幾天,複習會堆成一大疊 |
| 複習間隔 | 隔 1、3、7 次 | — |
| 每次分量 | 新題最多 10 題、複習最多 10 句 | 複習最多 20 句:主理人改成 10 |
| 進度存哪 | server 上的那份為唯一進度,任何裝置打開都接著學;另有匯出/匯入 | 只存瀏覽器:換地方就看不到。「兩邊比較、較新的蓋掉較舊的」:可能讓進度不見。server 上的程式由主理人自己處理 |
| 範圍 | 在現有每一題裡加步驟 | 另做「只練聽力」頁面:這次先不做,下一案 |
| 不做 | 麥克風錄音、發音打分、新題目、聽寫 | 主理人認為多餘 |
| 手機 | 響應式,手機也能完整使用 | 只在電腦用:主理人要在任何地方都能用 |
4. 可驗證的行為規格
方法說明
1. 當使用者第一次打開網頁,最上方應出現「聽力的底層邏輯」說明。
2. 當使用者按「我懂了」,說明應收起來,之後打開網頁都不會再自動展開。
3. 說明收起後,畫面上應一直有「重看方法」可以點;點了就重新展開說明。
這一次要做什麼
4. 當使用者打開網頁,應直接只看到「這一次」要做的三區,依序是:① 複習、② 新學、③ 連續聽。其他組的題目不顯示。
5. 當使用者按「看全部題目」,應看到原本的全部 10 組;再按「回到這次的內容」,應回到三區畫面。
6. 當使用者在這一次第一次做任何操作(播放、作答、點字),網頁應記下「第 N 次學習開始」。
7. 當使用者沒按「這次完成」就關掉網頁,下次打開應仍是同一次,而且做到哪裡就停在哪裡。
8. 當使用者按「這次完成」,這一次就結束;下次打開應是新的一次,三區內容重新排好。
9. 日曆日期不應影響任何安排;沒有打開網頁的日子,不算一次。
② 新學
10. 新學區應從第 6 組第 1 題開始,依序往後;第 1~5 組不排入新學(在「看全部題目」裡仍可做)。顯示那組的 5 個新字和還沒用新方法做過的題目;上一次做到一半的,從下一題接著做。第 10 組學完後,接著用新方法學第 1~5 組(待拍板卡確認,見停車場 P2)。
11. 一次最多新學 10 題(一組)。這一組都作答後,新學區應顯示已完成。
12. 所有組都用新方法學完時,新學區應顯示「第 1 冊的新題都學完了」,並算作完成。
① 複習
13. 複習區應列出這一次到期的句子,最多 10 句,先到期的排前面;超過的留到下一次。
14. 這一次沒有到期的句子時,複習區應顯示「這次沒有要複習的」,並算作完成。
15. 作答後,只要這一題有點過「沒聽出來」的字,這句應排進複習,在下一次到期。
16. 複習時,當使用者按「這次都聽出來了」,下一次到期的間隔應依序變成 1 → 3 → 7 次;隔 7 次那輪也按了「這次都聽出來了」,這句就算學會,不再出現在複習。
17. 複習時,當使用者按「還是有沒聽出來的」,可以重新點字,而且這句應在下一次再到期。
18. 複習時,上次點過的字應用淡色標出來。
③ 連續聽
19. 當使用者按連續聽的播放鍵,應依序連續播完這一次新學的句子(完整句),中間不停、不顯示句子;播完算作完成。
20. 這一次沒有新學的句子時,連續聽應改播這一次複習的句子;兩者都沒有時,算作完成。
完成與進度
21. 三區都完成時,應出現明顯的「這次完成 ✓」按鈕。三區還沒都完成時,也應能按「這次完成」(比較不顯眼);沒做完的留到下一次。
22. 左側面板應顯示這一次的進度:複習 x/y、新學 x/10、連續聽是否完成、這一次已練幾分鐘。
23. 「已練幾分鐘」只在網頁正在被看的時候累計;切到別的視窗就暫停。
24. 每一區完成時,應有清楚的「已完成」標示,一眼看得出做到哪、還剩什麼。
每一題的聽力步驟
25. 題目句子和選項應照原樣顯示,不蓋住。是否先不看,由使用者自己決定。
26. 每一題的播放鍵旁應有一行提示,告訴使用者「什麼時候可以看」(文字照預告頁)。
27. 方法說明裡應有一張完整的「什麼時候可以看」表:看句子、看選項、看句子拆解、看翻譯,各在什麼時機(文字照預告頁)。
28. 句子裡每個英文字都應可以點;點一下變色,代表「剛剛沒聽出來」;再點一下取消。
29. 每一個聽力步驟旁邊,應有一句話說明這一步在練什麼、為什麼(文字照預告頁)。
30. 網頁應有「耳朵缺口清單」,列出點過「沒聽出來」的字和次數;點清單裡的字,可以播放那個字出現的句子。
進度保存與搬家
31. 所有進度(作答、標記、點字、複習安排、次數、語速、開關)應自動保存。設定好 server 後,進度以 server 上的那份為準,每做一個動作就存到 server。
32. 現在已經有的作答紀錄應保留,不會因為這次改版而消失。
33. 當使用者按「匯出進度」,應下載一個進度檔;當使用者按「匯入進度」並選擇這個檔,進度應換成檔案裡的內容(換之前先確認)。
34. 當使用者在任何一台裝置打開網頁,應從 server 讀取進度,接著上次停下的地方繼續(例如讀到一半被打斷,換一台裝置、換一個時間接著讀)。
35. 連不上 server 時,網頁應明顯顯示「連不上 server」;這段期間做的事先暫存在這台裝置,連上後應自動補存到 server,不會不見。
37. 兩台裝置同時開著網頁時,比較舊的那一頁要存進度前,應先提示「另一台裝置有比較新的進度」並重新載入,不能蓋掉比較新的進度。
38. 還沒設定 server 時(例如現在在自己電腦上用),進度應存在這台瀏覽器;之後可以用「匯出進度」再「匯入進度」,把現在的紀錄搬上 server。
手機
39. 在手機寬度下,所有功能都應能用、畫面不跑版;左側面板在手機上應收成畫面底部的一條,點開才看到完整的進度與設定。
不能弄壞的
36. 在「看全部題目」裡,原本的功能都應照常可用:文法作答、統計、篩選、翻譯、詳解、句子拆解、單字表、字族、各種播放、語速。
不變的規則(題目內容)
40. 本案不應改動任何題目內容:題目句子、選項、正確答案、翻譯、詳解、句子拆解、考點標籤、單字表與字族都維持原樣。
41. 之後新增的題目(例如第 2 冊),應照文法課綱(english-grammar-curriculum__21_.html)定下的出題規則:只考教過的內容(題幹、選項、例句都算)、句子長度照多益(約 20~30 字)、多用之前背過的字、教學用過的例句不拿來當考題、正確答案位置要打散、考點標籤對到課綱的觀念編號、每組 5 個新字+10 題、不出造句題。
合約原文的條號順序就是 35、37、38、39、36、40、41(第 36 條放在「不能弄壞的」底下),照原樣保留。
合約增補 1(第 42、43 條)
檔案 02-contract-amend-1.md。主理人 2026-10-04 提出並同意;是追加,不改動原文。
主理人原話:
「這一個重點要求的說明就是教我怎麼去學習的文章也要把它一起加在這個 Server 上面,這是隨時隨地我可以點開來看應該要怎麼學,然後可能就是有個分頁要讓我連過去,有個子分頁。」
42. 學習方法手冊應放在 server 上,成為網站的一個子頁面;在任何裝置都能打開閱讀。
43. 主畫面應有一個固定的入口(左側面板/手機的展開面板裡,以及方法說明卡內)連到這個子頁面;手冊頁內也要有「回到練習」的連結。
B 驗收對照表
結論:43 條裡,最後 38 條「一樣」、5 條「有差異」(第 13、16、20、37 條是你已追認的 D 差異,第 30 條是一個少見操作的小差異)、0 條「沒做到」。
怎麼讀這張表
- 第一遍:第一位監工(
05-review.md)的判定。當時 36 條一樣、7 條不一樣、0 條沒做到。 - 最後狀態:照最後三次複查(05i、05j、05k)和 04 的修正紀錄判斷。
- 「有差異」不等於壞掉:是做法跟合約字面不同,原因寫在 D 段。
| 條號 | 一句白話 | 第一遍 | 最後狀態 | 證據指向 |
|---|---|---|---|---|
| 1 | 第一次打開,最上方出現「聽力的底層邏輯」說明 | 一樣 | 一樣 | 05-review;05j(1~12 條一樣) |
| 2 | 按「我懂了」收起,之後不再自動展開 | 有差異 | 一樣 | 05-review(按過「重看方法」後會自己再展開)→ 04 改用暫時狀態 → 05e、05j |
| 3 | 收起後一直有「重看方法」可以點 | 一樣 | 一樣 | 05-review;05j |
| 4 | 打開只看到這一次的三區:複習→新學→連續聽 | 有差異 | 一樣 | 05-review(上次停在全部題目,下次打開還是全部)→ 04 打開一律回三區 → 05e、05j |
| 5 | 「看全部題目」和「回到這次的內容」可以來回切 | 一樣 | 一樣 | 05-review;05j |
| 6 | 這一次的第一個動作,記下「第 N 次學習開始」 | 一樣 | 一樣 | 05-review;05j |
| 7 | 沒按完成就關掉,下次仍是同一次、停在原處 | 一樣 | 一樣 | 05-review;05j(n4:電腦做 3 題關掉,手機接著從 6-4 做) |
| 8 | 按「這次完成」才結束;下次是新的一次 | 一樣 | 一樣 | 05-review;05j |
| 9 | 日曆日期不影響安排;沒打開的日子不算一次 | 一樣 | 一樣 | 05-review;05j |
| 10 | 新學從 6-1 往後;第 10 組後接第 1~5 組 | 一樣 | 一樣 | 05-review;P2 於 10/5 裁決「接著學」;05j |
| 11 | 一次最多新學 10 題(一組),做完標已完成 | 一樣 | 一樣 | 05-review;05i(兩台合併時可能超過,邊角)→ 04 合併時也守上限 → 05j |
| 12 | 全部學完顯示「第 1 冊的新題都學完了」 | 一樣 | 一樣 | 05-review;05j |
| 13 | 複習最多 10 句,先到期的排前面,多的留下次 | 一樣 | 有差異 → 見 D6 | 05b D6;05j(只差順序)→ 04 → 05k「改完後一樣了」。差異只剩:超過 10 句時先挑最難的 |
| 14 | 沒有到期句時顯示「這次沒有要複習的」 | 一樣 | 一樣 | 05-review;05j |
| 15 | 作答後點過字的句子,下一次排進複習 | 有差異 | 一樣 | 05-review(在全部題目點字不排複習)→ 04 多輪修正 → 05i(邊角)→ 05j → 05k「正常點法都對」 |
| 16 | 「這次都聽出來了」間隔 1→3→7 次,最後一輪也過就學會 | 一樣 | 有差異 → 見 D6 | 05b D6(改成 1→4 次,連續 2 次就學會);05j(e2e 第 16 項);05d-gate3-r5 實際驗證 |
| 17 | 「還是有沒聽出來的」可重新點字,下一次再到期 | 一樣 | 一樣 | 05-review;05j;05k |
| 18 | 複習時上次點過的字淡色標出 | 一樣 | 一樣 | 05-review;05j |
| 19 | 連續聽:連播這次新學的句子、不顯示句子,播完算完成 | 一樣 | 一樣 | 05-review;05j |
| 20 | 這次沒新學句時改播複習句;都沒有就算完成 | 一樣 | 有差異 → 見 D4 | 05b D4;05j |
| 21 | 三區都完成出現明顯「這次完成 ✓」;沒完成也能按 | 一樣 | 一樣 | 05-review;05i;05j(e2e r4-M3) |
| 22 | 左側面板顯示這次進度與已練幾分鐘 | 一樣 | 一樣 | 05-review;05j(e2e r4-M4) |
| 23 | 「已練幾分鐘」只在網頁被看的時候累計 | 有差異 | 一樣 | 05-review(切到別的程式還在算)→ 04 加「視窗有焦點」判斷(程式檢查;無頭瀏覽器模擬不了焦點)→ 05e、05j |
| 24 | 每區完成時有清楚的「已完成」標示 | 一樣 | 一樣 | 05-review;05j |
| 25 | 題目與選項照原樣顯示,不蓋住 | 一樣 | 一樣 | 05-review;05j |
| 26 | 播放鍵旁一行「什麼時候可以看」提示 | 一樣 | 一樣 | 05-review(與預告頁逐字相同);05j |
| 27 | 方法說明裡有完整的「什麼時候可以看」表 | 有差異 | 一樣 | 05-review(7 處文字被改短)→ 04 逐字改回預告頁 → 05e、05j |
| 28 | 每個字可點,點了變色=沒聽出來,再點取消 | 一樣 | 一樣 | 05-review;05j |
| 29 | 每個聽力步驟旁有一句「在練什麼、為什麼」 | 一樣 | 一樣 | 05-review;05j |
| 30 | 耳朵缺口清單:點過的字和次數,點了播那句 | 一樣 | 有差異(只在少見操作)→ 見小差異 小5 | 05j(不一樣)→ 04 修 → 05k:正常點法都對,只有「複習中到全部題目、在舊字上連點兩下」次數少 1 |
| 31 | 所有進度自動保存;有 server 時以 server 為準 | 一樣 | 一樣 | 05-review;05j(n4、n5、n6b 用真的 Chrome+server) |
| 32 | 舊的作答紀錄保留 | 一樣 | 一樣 | 05-review;05j |
| 33 | 匯出進度檔;匯入前先確認,換成檔案內容 | 一樣 | 一樣 | 05-review;05i(匯入後整頁重畫);05j |
| 34 | 任何裝置打開都從 server 讀,接著上次 | 一樣 | 一樣 | 05-review;05i;05j(n4) |
| 35 | 連不上 server 要明顯提示;先暫存,連上自動補存 | 有差異 | 一樣 | 05-review(開頁就連不上會悄悄變本機模式)→ 04「離線開始」→ 05e、05j |
| 37 | 兩台同時開,舊的那頁存檔前先提示並重新載入,不能蓋掉新的 | 有差異 | 有差異 → 見 D1 | 05b D1(改成事件流水帳,全部合併);05i(兩個破口,後果是多複習一次)→ 04 修 → 05j |
| 38 | 沒設定 server 時存在這台瀏覽器;可匯出再匯入搬上 server | 一樣 | 一樣 | 05-review;05i;05j |
| 39 | 手機寬度全部可用、不跑版;面板收成底部一條 | 一樣 | 一樣 | 05-review(390px 截圖);05j;05k(手機觸控模式 a3) |
| 36 | 「看全部題目」裡原本的功能都照常可用 | 一樣 | 一樣 | 05-review(逐項對照舊頁);05j |
| 40 | 不改任何題目內容 | 一樣 | 一樣 | 05-review;05f(重跑 extract_book.py,book.js 逐位元組相同);05g、05i(book.js 修改時間早於後續修改) |
| 41 | 之後新增題目照文法課綱的出題規則 | 一樣 | 一樣 | 05-review(規則寫進 DEPLOY.md 第 9 節;本案沒新增題目);05j |
| 42 | 學習方法手冊放在 server 上當子頁面 | 一樣 | 一樣 | 05-review;05j;05k |
| 43 | 主畫面有固定入口連到手冊;手冊內有「回到練習」 | 一樣 | 一樣 | 05-review;05k 低 3(只有開頭看得到回練習)→ 04 每節底部都加 |
第 43 條(以及小差異 小6、小7)最後一次修改是在 05k 之後。這幾個修正有 e2e 或讀程式驗證(04 記錄),但沒有再請監工複查。
另外:本表沒有任何一條標「無紀錄」,43 條在審查檔裡都查得到判定。
C1 實際怎麼做
結論:網站把你的每個動作記成一行流水帳;進度就是「把帳本從頭算一次」。所以兩台裝置、斷線時做的事,合起來永遠不會互相蓋掉。
1. 事件流水帳+server 同步
你每做一個動作(播放、作答、點字、按複習鈕、按完成),網站就記一行,像記帳本。這叫事件流水帳。
- 進度=重算帳本。從第一行算到最後一行,就得到「你現在學到哪」。
- 兩台裝置合帳本就好。同一行只算一次(每行有一個獨一無二的編號)。不管先收到哪一行,算出來都一樣。
- server 只會往後加,不會改舊的。所以 server 上的資料庫本身就是完整歷史,要回到哪個時間點都可以。
- 做完動作 0.4 秒後送到 server;每 30 秒去 server 拿別台的新動作。連不上時先存在這台,每 15 秒重試。
另外 server 有一張epoch(資料庫的身分證)。從備份還原時會換一張新的。裝置看到身分證換了,就知道「server 可能少了東西」,把自己有、server 沒有的全部補送回去。
所以對你的影響是:電腦做到一半、手機接著做、斷線時做的,都不會掉。
程式片段 1:重算帳本(app\js\plan.js 第 284–288、363–371 行)
function sortEvents(events) {
const byId = new Map();
for (const e of events) if (e && e.id && !byId.has(e.id)) byId.set(e.id, e);
return [...byId.values()].sort((a, b) => a.t - b.t || (a.dev < b.dev ? -1 : a.dev > b.dev ? 1 : 0) || a.n - b.n);
}
…
function replay(events, book) {
const s = emptyState();
s.skipped = 0;
for (const e of sortEvents(events)) {
try { apply(s, e, book); }
catch (err) { s.skipped++; if (typeof console !== "undefined") console.warn("skipped event", e && e.type, err && err.message); }
}
return s;
}
白話:
sortEvents:先把重複的行丟掉(同一個編號只留一筆),再照「時間 → 哪台裝置 → 第幾筆」排好。replay:從空白的進度開始,一行一行套用。- 某一行壞掉,只跳過那一行並記下跳過幾筆,不會讓整份進度打不開。
2. IndexedDB+「還沒寫完」便條
每台裝置也在瀏覽器裡存一份帳本副本,放在 IndexedDB(瀏覽器內建的大倉庫,空間很大)。
- 原本放在 localStorage(瀏覽器的小抽屜,上限約 5 MB)。監工實測約 10 個月就會塞滿,而且每點一下要把整本重寫(100~220 毫秒)。所以改放 IndexedDB。
- IndexedDB 的問題:寫入要排隊,點完立刻關頁會掉。實測連點 20 下後立刻重新整理,掉 8 筆。
- 解法:寫之前先在 localStorage 貼一張「還沒寫完」的便條(localStorage 是當場寫完的);寫完撕掉。下次開頁看到便條就補寫。改後實測三次一筆不少。
所以對你的影響是:點完立刻關手機瀏覽器,也不會少一筆;3 萬筆時每點一下約 0.1 毫秒,開頁約 0.2 秒(04 實測)。
程式片段 2:便條(app\js\store.js 第 104–110、132–137 行)
const pendingNote = {
add(list) { ls.set(K.pending, JSON.stringify(union(parse(ls.get(K.pending)) || [], list))); },
done(list) {
const ids = new Set(list.map(e => e.id)), left = (parse(ls.get(K.pending)) || []).filter(e => !ids.has(e.id));
if (left.length) ls.set(K.pending, JSON.stringify(left)); else ls.del(K.pending);
},
};
…
async function saveLocal() {
const changed = dirty; dirty = [];
if (!changed.length && cache !== lsCache) return true;
const idb = cache !== lsCache;
if (idb) pendingNote.add(changed); // synchronous: done before the page can close
if (await cache.put(changed)) { if (idb) pendingNote.done(changed); cache.announce(changed); return true; }
白話:
pendingNote.add:把這次要寫的幾行,先抄一份到便條上。cache.put:真的寫進 IndexedDB。成功了才pendingNote.done(撕掉便條),並通知同一個瀏覽器的其他分頁。- 如果中途頁面被關掉,便條還在,下次開頁會補寫。
3. 排程規則(D6)
| 規則 | 白話 |
|---|---|
| 算「次」不算「天」 | 開始做算一次,按「這次完成」才結束。沒打開的日子不算。 |
| 什麼句子會進複習 | 作答後有點過「沒聽出來」的字,下一次就會出現。 |
| 間隔 1 → 4 次 | 第一次「這次都聽出來了」→ 隔 4 次再確認一次。 |
| 連續 2 次就學會 | 連續 2 次「這次都聽出來了」→ 學會,不再複習。 |
| 按「還是有沒聽出來的」 | 回到起點,下一次再出現。 |
| 到期超過 10 句 | 先挑最難的 10 句(點過的字最多的);挑出來的仍照到期先後排。其餘留到下一次。 |
程式片段 3:間隔與挑句子(app\js\plan.js 第 9、48–52、230–236 行)
const INTERVALS = [1, 4];
…
let due = byDue.filter(q => s.review[q].due <= cur);
if (due.length > REVIEW_CAP) { // D6: too many due -> take the hardest (most missed words), still shown in due order
const pick = new Set([...due].sort((a, b) => hard(b) - hard(a)).slice(0, REVIEW_CAP));
due = due.filter(q => pick.has(q));
}
…
function reviewAt(s, q, result, ses, snap) {
delete s.mastered[q]; delete s.reviewPrev[q];
if (result === "miss") { s.review[q] = { stage: 0, due: ses + 1 }; return; }
const stage = (snap.stage || 0) + 1;
if (stage >= INTERVALS.length) { delete s.review[q]; s.mastered[q] = ses; return; }
s.review[q] = { stage, due: ses + INTERVALS[stage] };
}
白話:
INTERVALS = [1, 4]:只有兩格。第一格是「點過字後隔 1 次」,第二格是「第一次聽出來後隔 4 次」。- 挑句子:先找出這次到期的句子;超過 10 句(
REVIEW_CAP)時,照「點過幾個字」由多到少挑 10 句,再照原本的到期順序排。 reviewAt:按「還是有沒聽出來的」→ 回到第 0 格、下一次到期。按「都聽出來了」→ 往下一格;走完兩格就移到「已學會」。
4. 畫面三區
| 區 | 做什麼 | 什麼時候算完成 |
|---|---|---|
| ① 複習 | 這次到期的句子,最多 10 句。上次點過的字淡粉色;這次又沒聽到就直接點它。 | 每句都按了兩顆鈕其中一顆;沒有到期句時直接算完成 |
| ② 新學 | 一組的 5 個新字+還沒學的題目(最多 10 題)。每題:先聽 → 作答 → 點沒聽出來的字。 | 這組都作答 |
| ③ 連續聽 | 一鍵連播這次學過的句子,不顯示文字。這次沒學新題時,改播這次複習過的句子。 | 播完 |
畫面上一直有「下一題 ↓」「↓ 接著做」帶你往下走。只想複習的晚上,複習做完會停在「今天只複習,這次完成」的框。手機上左側面板收成底部一條。
C2 遇到什麼問題、怎麼解的
結論:最大的一次轉彎是:「整份進度互相比較、合併」修了兩輪還在掉資料,所以照規則三(修兩次不行就換方法)整個換成事件流水帳。之後的問題都是小修。
名詞先講清楚
- 第 1 關:e2e 測試(自動開瀏覽器,照合約一條一條點)。
- 第 2 關:監工逐條對照合約(05、05e~05k,共 7 次,每次換一個沒參與過的人)。
- 第 3 關:試用者扮演你本人實際操作、打分(05d r1~r5)。
- 第 4 關:掃描壞味道(程式寫法上「之後容易出錯或難改」的地方,05c、05h)。
依時間排
| 哪一輪 | 問題 | 怎麼修 |
|---|---|---|
| 票 A/票 I(動工) | 抽題目的程式兩個小錯;server 在 Windows 上一直鎖住資料庫檔 | 抽題目照規則改;資料庫用完確實關閉(contextlib.closing) |
| 第 1 關(e2e 第一次 38/43) | ① 關頁時送出的存檔被誤判成衝突;② 斷線時做的進度,在另一台存檔後會被整份丟掉 | ① 內容相同就當已存好;② 改成「三方合併」(兩邊做過的都留下)→ 後來成為差異 D1。修完 44/44 |
| 第 2 關第 1 次(05)+第 4 關第 1 次(05c) | 合約 7 條不一樣(2、4、15、23、27、35、37);救援用的舊版本 1~1.5 小時就被洗光(高) | 7 條逐一修;救援版本改成最近 200 次+每天最後一份留一年 |
| 第 2 關第 2 次(05e) | 「整份進度三方合併」在 server 還原、開頁補送、同瀏覽器兩分頁時仍會掉資料。已修兩輪,每修一條路又冒一條 | 規則三:換方法。改成事件流水帳:每個動作一行,server 只追加、不覆蓋,合併=取聯集(見 C1) |
| 第 3 關第 1 輪(r1) | H1 複習時再點字反而取消紀錄;H2 沒聽就答也拿綠勾;M1~M6:找不到下一題、完成鈕在最底、手機字太小、拆解直接露中文、不知道聽幾遍、合併後跳回頂端 | H1 新增「這次又沒聽到」的點法;H2 沒先聽改灰字「已作答(這題沒先聽)」(差異 D2);M1~M6 各自修(拆解中文先收起=差異 D3) |
| 第 2 關第 3 次(05f) | 高:事件編號只有 4 個亂數字,會撞號、撞到就被丟;中:點字是「切換」,兩台會互相抵銷;晚到的事件會改掉這一次的清單 | 編號改 128 位元亂數;點字改成「設成有/沒有」;每一次第一個動作先記一筆「plan」事件,把這次的清單固定住 |
| 第 3 關第 2 輪(r2) | M1~M5:完成後還能再按完成、複習點了字還能按「都聽出來」、「已聽 N 遍」是累計、斷線提示看不到、別台進度進來整頁重畫 | 逐一修(空的一次不能完成、點字自動算沒聽出來、改算這次的遍數、紅條固定在上方、就地更新不重畫) |
| 第 2 關第 4 次(05g)+第 4 關重掃(05h) | 高:本機模式做的事之後永遠不上傳,卻顯示已同步;中:server 還原後兩邊互缺;高(05h):匯入舊格式進度檔會讓所有裝置打不開 | 新增 epoch:每筆事件記住「哪一張資料庫身分證確認過它」,沒被目前那張確認的一律送出;還原時換身分證、裝置整份補送。匯入時補齊欄位、壞的事件只跳過 |
| 第 3 關第 3 輪(r3) | H1 複習越堆越多(第 9 次積到 48 句);M1 完成後面板像歸零;M2 只想複習的晚上沒出口;M3 斷線關頁沒提醒;M4 偷懶的題不回來 | M1~M3 修(「今天只複習」出口、關頁前提醒)。H1、M4 動到你定的規則 → 停車場 P3、P4,10/5 裁決:P3 成為差異 D6、P4 維持不回來 |
| 第 2 關第 5 次(05i)+D6+第 3 關第 4 輪(r4) | 中:--restore 選錯檔會毀掉資料庫;中:帳本約 10 個月塞滿 localStorage、每點一下 100~220 毫秒;r4 M1~M4:手機完成鈕白字白底、「下一題」沒作答就出現、照「下一題」走會跳過「今天只複習」框、面板字眼看不懂 | 還原前先檢查、先備份;改存 IndexedDB+便條(實作中發現點完立刻關頁會掉 8 筆,便條就是為此加的);r4 四項逐一修;D6 間隔改 1→4 |
| 第 2 關第 6 次(05j) | 0 高 0 中 5 低:複習中到全部題目點字又取消會卡住;10 句以內也照難易排;複習卡誤點又取消仍算沒聽出來;複習會先堆積;文件舊數字 | 低 1、2、4 修好;低 5 文件更正;低 3 不改(D6 的必然結果 → 第 1 節第 3 題) |
| 第 3 關第 5 輪(r5) | M1 學會那一刻畫面沒表示;M2「接著學新的」跳過 5 個新字 | M1 加「學會了 ✓」與完成畫面那句;M2 改捲到「② 新學」標題;L1、L2、L5、L6、L7 一起修;L3、L4 不改 |
| 第 2 關第 7 次(05k) | 0 高 0 中 3 低:在舊字上連點兩下會悄悄變「沒聽出來」;「今天只複習」框的連續聽看不出在播;手冊只有開頭有「回到練習」 | 低 2、3 修好;低 1 不修(要連點兩下舊字才會發生,後果是多複習一次) |
測試數量的變化
| 時間點 | plan | sync | server | e2e |
|---|---|---|---|---|
| 第 1 關修完 | 23 | — | 5 | 44 |
| 流水帳上線後 | 28 | — | 7 | 56 |
| 第 2 關第 4 次修完 | 43 | 7 | 8 | 62 |
| 第 2 關第 5 次修完 | 49 | 8 | 11 | 71 |
| 最後 | 52 | 8 | 11 | 77 |
數字都來自 04-implementation.md 各節的「現況」。「流水帳上線後」那列 server 寫的是「5 個 API 測試+2 個靜態檔測試」,這裡合計成 7。
e2e「恢復連線後補存」曾經失敗一次,之後連跑 4 次都過,無法重現。依規矩不憑推測修。實際使用時每 15 秒會自動重試,進度不會掉。04 寫明:如果在實驗室電腦上再出現,再追。
C3 改了哪些檔案
結論:本案新做了整個 app\ 資料夾,另外在 docs\ 加了紀錄與報告。舊頁 toeic-drill-01.html 和 make-toeic-audio.py 都沒有改。
清單是 2026-10-05 用指令實際列出來的,不是憑印象寫。
app\(全部是本案新做的)
| 檔案 | 用途 |
|---|---|
index.html | 網站主頁的骨架(只放結構) |
app.css | 樣式,含手機版面 |
guide.html | 學習方法手冊子頁(合約 42、43)。這是正本 |
js\book.js | 題目資料(由 extract_book.py 從舊頁抽出,內容不改) |
js\plan.js | 排程規則:一次學習、新學順序、複習間隔、重算帳本。不碰畫面 |
js\store.js | 進度存取:IndexedDB、便條、和 server 同步、匯出匯入 |
js\ui.js | 畫面:三區、題目卡、面板、手機底部條、方法說明、耳朵缺口清單 |
server.py | 小 server(只用 Python 內建功能):送網頁、存事件、密碼、還原 |
start-server.bat | 給工作排程器開機自動啟動 server 用 |
config.example.json | 設定範例(資料庫是 data/progress.db、port 8765) |
config.json | 開發用設定(資料庫指到 data/dev.db)。部署時不要複製(DEPLOY 第 1 節) |
data\dev.db | 開發用資料庫。部署時不要複製 |
DEPLOY.md | 實驗室電腦的部署說明 |
tools\extract_book.py | 從舊頁抽出題目資料,產生 book.js |
tests\plan.test.js | 排程規則的自動測試(52 個) |
tests\sync.test.js、tests\sim.js | 多台裝置、離線、還原的同步測試(8 個);sim.js 是模擬器 |
tests\server_test.py | server 的自動測試(11 個) |
tests\e2e.js | 開真的 Chrome 照合約一條一條點(77 個) |
tests\package.json | e2e 需要的套件清單(puppeteer-core) |
audio\book1\ | 錄音 654 個 mp3(舊的 toeic-drill-01-audio 的複本) |
__pycache__\、tools\__pycache__\ | Python 自動產生的暫存檔,不用管 |
docs\
| 檔案 | 用途 |
|---|---|
docs\changelog.md | 追加一筆「新網站『聽力練習模式』完成(app/)」 |
docs\reports\2026-10-04-listening-method.html | 學習方法手冊(10/4 先交的存檔;正本在 app\guide.html) |
docs\reports\2026-10-04-listening-mode.html | 本報告 |
docs\work\2026-10-04-listening-mode\ | 案子資料夾:26 個 md 檔+evidence\ 截圖(根目錄 11 檔、gate3-r1~r5 各 39/38/30/36/47 檔) |
沒有改的
| 檔案 | 怎麼確認沒改 |
|---|---|
toeic-drill-01.html(舊頁) | 修改時間 2026-10-03 02:16,早於本案開始(10-04)。05-review 用同一套讀法重讀,跟 book.js 完全相同 |
make-toeic-audio.py | 修改時間 2026-10-02 21:56,早於本案。本案只拿它來比對 book.js 的題目(04 票 A);之後出第 2 冊錄音會用到(DEPLOY 第 9 節) |
C4 怎麼退回
結論:本案不在 git,退回很簡單:停掉 server,回去用舊頁 toeic-drill-01.html。舊頁一個字都沒被改過。
步驟
| 步驟 | 做法 |
|---|---|
| 1. 停掉 server | 在實驗室電腦打開「工作排程器」,把「toeic-drill server」這個工作停用(DEPLOY 第 4 節建的)。正在跑的話再結束它。 |
| 2. 回去用舊頁 | 直接用 Chrome 打開 toeic-drill-01.html。它沒被改過,紀錄也還在原本那台電腦的 Chrome 裡。 |
| 3. 資料留著 | 新網站的進度在實驗室電腦的 app\data\progress.db(DEPLOY 第 7 節)。不用刪,哪天想回來,開 server 就接得上。 |
- 新網站的練習紀錄不會回到舊頁。點字、複習排程、學會了幾句,這些舊頁本來就沒有。
- 舊頁的紀錄一直在舊頁的瀏覽器裡(Chrome 的
tq1v2)。新網站只在第一次使用時讀一次、複製過來,從來沒有改它(05-review 第 32 條)。 - 反過來也一樣:退回後在舊頁新做的題,之後再回新網站不會自動帶過來,要用「匯入進度」。
補充:本機開發用的資料庫是 app\data\dev.db(config.json 指到它),跟實驗室電腦的 progress.db 是兩個檔。
D 差異段
結論:跟合約字面不同的地方有 6 個大差異(D1~D6,都已在 10/5 追認)、8 個小差異(6 個已修、2 個刻意不修),另外有一份「刻意不做」清單。
大差異 D1~D6(出處 05b-diff.md)
| 編號 | 合約說 | 實際是 | 為什麼 | 追認狀態 |
|---|---|---|---|---|
| D1 | 第 37 條:比較舊的那一頁存檔前,先提示「另一台裝置有比較新的進度」並重新載入,不能蓋掉新的 | 改成「每個動作一筆」的流水帳。兩台、兩分頁、斷線時做的事全部合在一起,誰都不會被蓋掉。收到別台的新進度時顯示「已載入另一台裝置的新進度」,畫面更新、保持捲動位置 | 整份進度的做法實測與兩輪審查都會掉資料,補了兩輪仍有漏洞。流水帳從根本上不會掉,server 上的流水帳本身就是完整歷史 | 2026-10-05 已追認(主理人授權代決) |
| D2 | (合約沒寫)答題前有沒有先聽 | 有先按播放才標「✓ 用新方法練過」;沒聽就答標灰字「已作答(這題沒先聽)」,一樣算學過 | 試用發現偷懶和認真拿到一樣的綠勾。用誠實的標示提醒,不加鎖,符合「抓分寸」 | 2026-10-05 已追認(主理人授權代決) |
| D3 | (合約沒寫)句子拆解的中文意思 | 先收起,按「看中文意思」才出現 | 試用發現跟「翻譯最後才看」矛盾 | 2026-10-05 已追認(主理人授權代決) |
| D4 | 第 20 條:這一次沒有新學的句子時,連續聽改播複習的句子 | 「沒有新學」改成「這一次還沒學任何新題」,所以只複習的晚上也能連續聽複習過的句子 | 第 3 輪試用:只想複習的晚上沒辦法連續聽 | 2026-10-05 已追認(主理人授權代決) |
| D5 | (合約沒寫)全部學完、又沒有到期的複習時 | 把最近一批複習提前到這一次 | 不然「次數」無法前進,之後的複習永遠不會到期(第 4 次監工發現) | 2026-10-05 已追認(主理人授權代決) |
| D6 | 第 16 條:間隔 1 → 3 → 7 次,隔 7 次那輪也過才算學會 | 間隔 1 → 4 次:連續 2 次「這次都聽出來了」就學會;到期超過 10 句時先排最難的(點過的字越多越先) | 你 10/5 說:學會的字會在新題目裡自然重複,舊題目只要把真正難的磨到聽得出來。原規則下複習需求約是上限的 3 倍,會越堆越多 | 2026-10-05 主理人授權代決 |
停車場 P1 是你親自決定(不做「每遍試說中文」);P2~P4、D1~D6 是你授權代決(01-decisions.md「停車場裁決」節、00-parking.md 裁決結果)。05b 原本把 D2~D5 標為「小差異」、D1 標為「大差異」;這裡照你的要求把 D1~D6 都放在大差異。
小差異(出處 05j、05k)
| 編號 | 出處 | 內容(白話) | 現況 |
|---|---|---|---|
| 小1 | 05j 第 13 條/低 2 | 到期 10 句以內,也照難易排,不是照到期先後 | 已修(04 第 2 關第 6 次;05k 確認) |
| 小2 | 05j 第 30 條/低 1 | 複習中到「看全部題目」點字又取消:複習卡卡住、缺口清單少算 | 已修(改成一個函式處理;05k 確認) |
| 小3 | 05j 低 4 | 複習卡誤點一個字又取消,仍算「還是有沒聽出來的」 | 已修(全部取消時退回原本的答案;05k 確認) |
| 小4 | 05j 低 3 | 學新題期間複習先堆積,模擬最多 44 句到期 | 不改:D6 的必然結果 → 第 1 節第 3 題 |
| 小5 | 05k 低 1 | 複習中到「看全部題目」,在上次點過的字上連點兩下:這句悄悄變「還是有沒聽出來的」;回複習卡改回來,缺口次數少 1 | 不修(04:要連點兩下舊字才會發生,後果是多複習一次) |
| 小6 | 05k 低 2 | 「今天只複習」框的連續聽,播放時框裡看不出在播、停不了 | 已修(04;e2e r7-low2×2,停掉的部分讀程式驗證) |
| 小7 | 05k 低 3 | 手冊只有開頭看得到「回到練習」;目錄沒寫第 7 節已過期 | 已修(04) |
| 小8 | 05j 低 5 | 04 的「已知限制」還寫舊數字(一年 2~4 MB) | 已更正(04) |
05k 另外記錄、不算問題:手機上面板「收起」49×28、頂端「看全部題目」91×33 仍偏小。小6、小7 修完後沒有再請監工複查。
刻意不做的項目(出處 04「刻意不做」與各輪處理表、HANDOFF 第 6 節)
| 項目 | 為什麼不做 |
|---|---|
| 05i 攻擊 9:匯入舊進度時另一台正在學,那台的複習會晚幾次才出現 | 匯入很少用,後果只是晚幾次複習(原本另寫的「時鐘問題」理由已被 05j 證明不成立,已刪除) |
| 05i 建議 11:前端收到 400 時把批次砍半 | 一批最多 4000 筆,實測最大 0.53 MB,離 2 MB 上限很遠 |
| 05i 建議 6:合併清單整段拿掉 | 改成「合併時守 10+10 上限」,效果相同、改動較小 |
| r4 情況 C:已學會的句子點新字被拉回、再取消,有舊標記時不恢復「已學會」 | 行為是多複習一次,比漏掉安全 |
| 05k 低 1(小5) | 見上表 |
| 第 3 關 r5 L3:複習卡收起上次的選項和對錯 | 要動的版面較大 → 第 1 節第 2 題 |
| 第 3 關 r5 L4:沒先聽的題只有灰字、不會回來 | P4 已在 10/5 裁決「不回來」 |
| 流水帳只會變長(「快照」:把很舊的事件壓成一份) | 改 IndexedDB 後實測 3 萬筆每點一下 0.1 毫秒、開頁 0.2 秒,夠用好幾年;哪天變慢再另開案 |
| server 沒有密碼錯誤次數限制 | 靠 Tailscale(只有自己的裝置連得到)擋;不要把 port 直接開到網路上 |
| 多冊(第 2 冊) | 目前只認一冊。加第 2 冊要先開新案設計 |
| 合約第 3 節的「不做」:麥克風錄音、發音打分、新題目、聽寫;另做「只練聽力」頁面 | 你認為多餘;只練聽力頁面留到下一案 |
E 壞味道摘要
結論:會影響正確性的壞味道都修了;剩下的是「程式寫法可以更整齊」的部分,依你的規矩(重構是獨立任務)留著沒動。
壞味道=程式寫法上「之後容易出錯或難改」的地方,不一定是 bug。重構=不改功能,只整理寫法。
處置分三種
- 已修:04 有修正紀錄,或監工已確認。
- 重構候選:04「重構候選」節有列(只記錄、不動手)。
- 不處理:附原因。04 沒有逐項寫原因的,我寫「04 無逐項紀錄」,並標出目前程式的樣子是我讀程式確認的。
第 4 關第 1 次(05c)
監工範圍聲明(照抄):「審查範圍:index.html、app.css、js/plan.js、js/store.js、js/ui.js、server.py、tools/extract_book.py、tests/*。book.js(產生的資料)與 guide.html(靜態文件)未審。判斷基準是 03-tech-spec.md 與 04-implementation.md 的既定設計(例如:不用框架、ui.js 單檔、三方合併是已記錄的決策 D1),不以個人偏好扣分。」
05c 的 28 項,第 4 關重掃(05h)已經整理過現況,照抄成下表:
| 05h 判定 | 項目 | 處置 |
|---|---|---|
| 已解決(架構改掉) | 救援版本只留 200 版被洗掉(高);三方合併把「沒有欄位」當成刪除;開頁誤報衝突;pending 寫入重複三次;合併的多餘三元運算;history_count 放在正式程式 | 已修(換成流水帳後消失) |
| 已修 | 開頁狀態被「已同步」蓋掉;http 下 API 失敗悄悄變本機模式;切字規則兩份;進度欄位要改三處;音訊不支援 Range;server 重複 close | 已修 |
| 部分修 | 同步文案不一致;setStatus 只是原封轉呼叫 | 併入下面 05h 表 |
| 還在 | 連續聽播放鏈競態、log_message、Content-Length、缺口清單未跳脫、ui.js 過大、寫死 10 組、位置陣列等 15 項 | 併入下面 05h 表 |
第 4 關重掃(05h)
監工範圍聲明(照抄):「審查範圍:index.html、app.css、js/plan.js、js/store.js、js/ui.js、server.py、tools/extract_book.py、tests/plan.test.js、tests/server_test.py、tests/e2e.js。book.js(產生的資料)與 guide.html(靜態文件)未審。判斷基準是 03-tech-spec.md(vanilla JS+Python 標準函式庫、不建置、單一資料夾)與 04-implementation.md 已記錄的決策(例如面板門檻改 1240、ui.js 單檔),不以個人偏好扣分。」
| 條號 | 位置 | 白話 | 處置 |
|---|---|---|---|
| 疑似錯誤(高) | store.js、plan.js | 匯入舊格式進度檔,會讓所有裝置永久打不開 | 已修(04:reset 補齊欄位、壞事件只跳過) |
| 1 重複/7 霰彈式修改(中) | plan.js、store.js | 「哪些事件屬於這一次」寫了兩份 | 已修(只留 Plan.SESSION_TYPES) |
| 疑似錯誤(中) | store.js | 同瀏覽器兩分頁共用「未送出清單」的競態 | 已修(移除共用清單,改由每筆事件記 epoch) |
| 1 重複(中) | ui.js | 「該顯示哪顆按鈕」的規則寫了三份 | 已修(nextStep() 一處決定)。進度摘要文字三份:04 無逐項紀錄 |
| 2 過長函式(中) | ui.js 點擊處理 | 點擊處理 50 行、兩種分派方式混用 | 已修(拆成 onWord/onDataButton/ACTIONS 表) |
| 疑似錯誤(低) | store.js | server 恢復後每 15 秒下載全部歷史 | 已修(同時只一個拉取、重試只拿新的) |
| 疑似錯誤(低) | ui.js 面板同步文字 | 沒有「空間滿了」的文字 | 已補(ui.js 第 395 行有 full,讀程式確認) |
| 疑似錯誤(低) | ui.js 連續聽 | 播放中按別的 🔊,畫面一直寫「正在播」;停止後 0.7 秒內再開始,兩條播放互搶 | 前半已修(05k 低 2:其他聲音先停掉連續聽)。後半 04 無逐項紀錄 |
| 疑似錯誤(低) | server.py | Content-Length 不是數字時連線直接斷 | 已修(05i 建議 11;server_test test_11) |
| 疑似錯誤(低) | server.py log_message | 取 args[1],某些情況會出錯 | 不處理:04 無逐項紀錄(讀程式確認仍在第 111 行) |
| 疑似錯誤(低) | store.js/server.py | server 回 400 時前端一直重送同一批 | 不處理:一批最大 0.53 MB,離 2 MB 很遠(04 刻意不做) |
| 疑似錯誤(低,部署) | server.py | 密碼沒有錯誤次數限制 | 不處理:靠 Tailscale 擋(HANDOFF 已知限制) |
| 疑似錯誤(低) | ui.js 缺口清單 | 字和題號直接放進 HTML,沒跳脫 | 不處理:監工自己判定「依設計屬可接受」(只有自己的匯入檔會有風險) |
| 疑似錯誤(低) | ui.js 計時 | 另一台按完成時,這台還沒記的分鐘會算到下一次 | 不處理:04 無逐項紀錄 |
| 2 過長函式(低) | ui.js updateCard、store.js init、tests/e2e.js | 函式太長、三個分支重複 | 不處理:重構是獨立任務;04 無逐項紀錄 |
| 3 過大檔案(低) | ui.js(現在 605 行) | 音訊、畫面、面板、開機都在同一檔 | 不處理:重構是獨立任務;04 無逐項紀錄 |
| 1 重複/9 基本型別偏執(低) | ui.js 的 BLANK、item、groupOf;寫死「10 組」「100 題」「第 1 冊」;題目資料是位置陣列 | 同樣的東西兩個檔各一份;加第 2 冊要逐處找 | 不處理:04 無逐項紀錄(讀程式確認 ui.js 第 10、215 行、index.html 第 20 行仍在)。加第 2 冊時要先開新案(HANDOFF) |
| 11 冗贅/死碼(低) | plan.js version、updatedAt;store.js setStatus | 整份合併拿掉後留下沒人用的東西 | 不處理:04 無逐項紀錄(讀程式確認仍在) |
| 12 註解與程式不符(低) | plan.js 註解、tests/e2e.js | 還在講已經拿掉的「整份合併」、截圖名 desktop-04-conflict | 不處理:04 無逐項紀錄(讀程式確認 e2e 仍有 baseVersion、conflict) |
| 1 重複(低) | ui.js act() 與直接 Store.record | 記錄動作有兩種寫法 | 不處理:04 無逐項紀錄 |
| 7 霰彈式修改(低) | app.css | 補丁直接接在檔尾,同一元件樣式散在兩處 | 不處理:05k 第 7 條也提到,建議「等功能定稿後當成獨立整理」 |
| 規格落差(低) | 03-tech-spec.md、plan.js gapKey | 規格的面板門檻還寫 1080(實際 1240);「tenants'」和「tenants」算成兩個字 | 不處理:04 無逐項紀錄(讀程式確認 03-tech-spec 第 72 行、plan.js 第 169 行仍是原樣) |
第 2 關第 6 次(05j)的壞味道表
監工範圍聲明(照抄):「12 條壞味道掃描(只看這輪改過的部分)」;「其餘幾條(3 過大類別、4 過長參數列、5 資料泥團、6 依戀情結、11 冗贅類別)在這輪改動裡沒有看到。」
| 條號 | 位置 | 白話 | 處置 |
|---|---|---|---|
| 1 重複程式碼 | plan.js mark/remark | 「把字記進這次的複習點字」寫了兩份,一份只處理點上、沒處理取消(就是小2 的成因) | 已修(04:改走同一個函式 clickInReview) |
| 1 重複程式碼 | plan.js | 同一串取快照的寫法出現兩次 | 重構候選(04) |
| 10 過度耦合的訊息鏈 | plan.js | 一行串五層才取到「上次點過的字」 | 重構候選(04) |
| 8 發散式變化 | store.js 兩種 put | 名字一樣、做的事不一樣(localStorage 版偷偷整份合併) | 重構候選(04) |
| 7 霰彈式修改 | store.js | 「現在是哪種儲存」的判斷散在三處 | 重構候選(04) |
| 2 過長函式 | store.js takeServer | 一個函式做五件事 | 重構候選(04) |
| 12 注釋當除臭劑 | store.js | 註解在幫第 8 條的怪介面解釋 | 重構候選(隨第 8 條一起) |
| 9 基本型別偏執 | plan.js | 「學會」藏在一個比較式裡,沒有名字 | 重構候選(04) |
第 2 關第 7 次(05k)的壞味道表
監工範圍聲明(照抄):「壞味道(只看這兩輪改過的部分)」;「建議:照主理人規矩,壞味道的整理是獨立任務,不要跟修低 1~3 混在一起。」
| 條號 | 位置 | 白話 | 處置 |
|---|---|---|---|
| 1 重複程式碼 | ui.js 兩處 | 「這次學會了」的判斷寫了兩次 | 不處理:監工建議獨立整理 |
| 1 重複程式碼 | guide.html 目錄與標題 | 節名寫兩份,只改一份就對不上(小7 的成因) | 症狀已修(04:目錄改「已過期」,翻頁鈕跟著目錄);兩份來源仍在,不處理 |
| 2 過長函式(輕微) | plan.js apply | 本來就長,這輪又多一層條件 | 不處理:監工建議獨立整理 |
| 4 過長參數列/5 資料泥團(輕微) | plan.js | 同一組五個參數一直一起傳 | 不處理:監工建議獨立整理 |
| 6 依戀情結(輕微) | plan.js clickInReview | 一直伸手改 session 的四個欄位 | 不處理:監工自己說「可以接受,先不動」 |
| 7 霰彈式修改 | plan.js reviewAuto;app.css 底部條 | 要看四處才知道何時有效;CSS 照審查輪次分段 | 不處理:監工建議「等功能定稿後當成獨立整理」 |
| 8 發散式變化 | ui.js 連續聽的兩個入口 | 播放狀態只更新一邊(小6 的成因) | 已修(04:抽出 renderRvdone、renderCont) |
| 9 基本型別偏執 | plan.js | 「沒作答」用字串 "none",跟真答案放同一欄 | 不處理:監工建議獨立整理 |
| 10 過度耦合的訊息鏈 | plan.js | 同 05j,取快照那串仍出現兩次 | 重構候選(04) |
| 12 注釋當除臭劑 | plan.js 第 331 行 | 註解在解釋一個四段條件;小5 就藏在這裡 | 不處理:監工建議獨立整理 |
05k 判定「沒看到」的:3 過大類別、11 冗贅類別。
這些都不影響你使用。哪天要加第 2 冊、或常常要改同一塊時,先開一個「整理程式」的獨立案子,從 04 的重構候選開始。
第 3 關分數變化
結論:五個維度都比第 1 輪高;第 2 輪起就沒有低於 3 分的格子。最低的是「學習引導」3.6 和「手機介面」3.7。
第 3 關=每一輪找一個沒參與過的試用者,扮演你本人(研究生、下班很累、聽力 70%、想無腦學習),實際操作、打 1~5 分。低於 3 分就一定要修。
| 輪 | 好用度 | 順暢度 | 方便性 | 手機介面 | 學習引導 | 低於 3 分的格子 |
|---|---|---|---|---|---|---|
| 第 1 輪(r1) | 3.4 | 3.3 | 3.4 | 3.3 | 3.3 | 4 格 |
| 第 2 輪(r2) | 3.9 | 3.6 | 4.0 | 3.5 | 3.4 | 0 |
| 第 3 輪(r3) | 3.8 | 3.8 | 4.0 | 3.5 | 3.4 | 0 |
| 第 4 輪(r4) | 4.0 | 3.6 | 3.6 | 3.3 | 3.6 | 0 |
| 第 5 輪(r5) | 4.3 | 4.1 | 4.1 | 3.7 | 3.6 | 0 |
數字照抄各 05d 檔的分數表平均列,沒有自己重算。
讀這張表要注意
- 每輪的情境不一樣,平均只能看大方向。r3 看的是「連用一週」,r4 看「第一次用+手機」,r5 依你的指示只測正常使用、拿掉了斷線等極端情況。
- r1 評的是改到一半的版本:試用途中程式被改了,r1 檔案寫明「本報告評的是 23:06 以前的版本」。
- r1~r4 的音檔是假的(按 🔊 就算聽過);r5 大部分用真的音檔,每個都有播完。
- r5 給 3 分的格子:手機讀手冊(L5)、學會那一刻沒表示(M1)、「接著學新的」跳過新字(M2)、沒先聽只有灰字(L4)。M1、M2、L5 已在 04 修好;L4 是 P4 的裁決結果。
接下來(給實驗室電腦)
結論:實驗室電腦上的 AI 照 HANDOFF.md 讀、照 DEPLOY.md 架起來;你只要打開網站,照「這一次」做完,按「這次完成」。
三份文件各在哪、做什麼
| 文件 | 位置 | 用途 |
|---|---|---|
| 交接說明 | C:\D槽\英文學習資料\docs\work\2026-10-04-listening-mode\HANDOFF.md | 給實驗室電腦上的 AI:先讀哪些檔、它的工作、規矩(不准改題目、修 bug 先重現、只用正常情境測)、已知限制 |
| 部署說明 | C:\D槽\英文學習資料\app\DEPLOY.md | 一步一步架 server:設密碼、開機自動啟動、Tailscale 讓手機連得到、搬舊紀錄(第 6 節)、備份還原、跑四組測試(第 8 節) |
| 學習方法手冊 | C:\D槽\英文學習資料\docs\reports\2026-10-04-listening-method.html(存檔);網站子頁 app\guide.html(正本) | 給你自己:一次學習的每一步怎麼做、在練什麼、哪些做法是錯的。在網站左側面板、方法說明卡都有入口 |
- 密碼請你自己輸入,不要讓 AI 代設或寫進檔案(HANDOFF 第 3 節)。
app\config.json和app\data\是開發用的,不要複製過去(DEPLOY 第 1 節)。- 四組測試都全過,才算部署成功。
之後怎麼開始學
- 打開網站(手機用 Tailscale 的
http://100.x.x.x:8765/)。 - 照畫面上「這一次」的三區做:複習 → 新學 → 連續聽。不知道下一步就按「下一題 ↓」或「↓ 接著做」。
- 做完按「這次完成」。累了也可以提早按,沒做完的會留到下一次。
本報告的每一項判斷都來自實際查證(讀案子資料夾的檔案與程式碼),不是推測。文中標「04 無逐項紀錄」的處置原因、第 1 節「我推薦」的理由,是我依紀錄做的判斷;第 1 節第 3 題的堆積數字是監工的模擬推估(假設的比例不是實際資料)。