Skip to content

Latest commit

 

History

History
223 lines (168 loc) · 19.1 KB

File metadata and controls

223 lines (168 loc) · 19.1 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

專案概述

台灣學習者日文學習系統——假名記憶、單字管理、測驗工具維護。學習者母語台語、華語,略懂粵語,熟悉注音符號和漢字。平假名、片假名五十音(含濁音、半濁音)皆已完成,目前進入單字擴充與會話學習階段。

記憶鉤優先順序

每個假名必須附漢字來源記憶鉤(依以下優先順序選擇):

  1. 台語文言音——子音母音都對才用
  2. 台語白話音——補充或替代
  3. 華語——台語子音不對時(例:奴 nú → ぬ、祢 nǐ → ね)
  4. 粵語——漢音層接近(例:知 zi → ち chi)
  5. 注音字形——形近但音不近時(例:へ 像 ㄟ)
  6. 英文聯想——以上都不近時
  7. 純字形規則——濁點、合讀等

台語子音不對就不用台語,改用其他工具。漢字來源是最優先的字形聯想。

發音規則(九條,片假名完全適用)

  1. 濁點(゛)——清音加兩點,子音變有聲(た→だ、か→が)
  2. 半濁點(゜)——は行專用,回到古代 p 音(は→ぱ);は行古代念 p,演變成 h(清)/b(濁)/p(半濁)
  3. 小字合讀(拗音)——ょゅゃ 縮小跟前面合讀,母音被取代
  4. 長音——a/i/u 用同母音延長;e 行用い;o 行用う
  5. ん 特殊性——打字要打 nn
  6. っ 促音——停頓一拍再爆發,台語入聲音感接近
  7. 助詞雙重發音——は念 wa、を念 o
  8. 母音無聲化——i 和 u 在特定位置消音(です→des)
  9. 清音弱化——單字中間的清音自然有聲化

工具檔案

檔案 用途
hiragana-quiz.html 平假名互動測驗(五十音+單字,SRS)
katakana-quiz.html 片假名互動測驗(五十音+單字,SRS)
hiragana.md 平假名字表、發音規則、語法筆記
katakana.md 片假名字表、單字分類
vocabulary.md 所有單字,依主題分類(疑問詞、飲食、時間、顏色等)
conversation.md 會話筆記(基本用語、購物、點餐等情境)
language-notes.md 台語/粵語/注音記憶鉤對照表
already-known.md 已知單字片語,在測驗中減少出現頻率
kanji.md 漢字筆記(字表、發音規則、單字分類)
grammar.md N5 語法筆記(句型、活用、例句)——文法內容的唯一正本,章節頁由它生成
grammar/ 文法章節 HTML(NN.htmlindex.html,由 tools/build_grammar_pages.py 從 grammar.md 產生,不要手改chapters.json 是「進度項編號→grammar.md 標題」登錄表、chapter.css 是手寫樣式)
grammar-quiz.html 文法 SRS 測驗(填空輸入+語感選擇;題庫 grammarCards 內嵌,SRS 走 quiz-common.js)
tools/build_grammar_pages.py 章節頁產生器(--check 供驗證器比對是否過期);會把配對的單字批次嵌進章節頁
grammar/pairings.json 文法項 → 單字批次的配對表,一課=一個文法項+一批單字
vocab-lessons.md 每日單字教學的唯一正本(一批一節),課程頁由它生成
vocab/ 單字課程 HTML(NN.htmlindex.html,由 tools/build_vocab_pages.py 產生,不要手改batches.json 是登錄表;樣式沿用 grammar/chapter.css
tools/build_vocab_pages.py 單字課程頁產生器(渲染器 import build_grammar_pages,同一份實作)
vocab-quiz.html 課程單字 SRS 測驗(只收每日課程教過的字,依批次篩選;卡片內嵌 vocabCards,SRS 走 quiz-common.js)
PRODUCT.md 設計策略文件(受眾、品牌個性、設計原則,impeccable skill 使用)

參考文件(.claude/skills/japanese-learning/references/ 目錄):

  • quiz-structure.md — 測驗 HTML 結構與更新方法
  • language-correspondences.md — 台語/粵語音對應詳表
  • vocab-categories.md — 單字分類與 topic 標籤說明

工作流程

General workflow

  1. Explore first, plan, then code — read relevant files and understand the current state before making changes.
  2. Smoke test before commit — for scripts, a dry-run counts; for notes/edits, verify the output looks correct before staging.
  3. Check git status before starting work — confirm the correct branch and no unexpected prior changes.
  4. Read an existing note before creating a new one — match frontmatter format and conventions rather than guessing.
  5. One concern per commit — keep commits focused; don't bundle unrelated changes.

學新假名

每次只介紹 5–10 個,確認記熟後再進下一批。不要一次把整行或整個五十音全部教完。

漢字來源 → 記憶鉤(依優先順序)→ 清濁音一起介紹 → 形近字提示 → 更新筆記和測驗

拆解格式:

假名 發音 新/舊
X Y ✅/🆕

有新字就單獨介紹,全部學過才說「全學過!」。

學新單字

  1. 拆解每個假名(標明新/舊)
  2. 說明漢字來源和台語連結(如有)
  3. 同音異義詞提示
  4. 更新測驗 vocabCards,格式:{ meaning, display, reading, kanji?, topic, round }
    • meaning純中文意思,不能夾雜日文假名(填 '哪裡',不是 'どこ(哪裡)'
    • kanji:有常見漢字寫法就必須加(一杯、何処、服、耳等);純口語/擬聲語/純假名詞可省略(ゆっくり、じゃあね);片假名外來語不加
  5. 將單字加入 recentBatch(見下方說明);若這批字屬於某個課程批次,同時登錄進 lessonBatch'單字': 批次號),否則單字測驗的批次篩選會漏掉它們
  6. 將單字加入對應筆記檔,並更新 frontmatter 的 date > updated
    • 一般單字 → vocabulary.md 對應主題區塊
    • 會話句型/口語表達 → conversation.md 對應情境區塊
    • 片假名外來語 → katakana.md 對應單字區塊

單字表格式:漢字 | 假名 | 羅馬拼音 | 意思

topic 標籤greeting / food / family / time / color / number / nature / daily / question

recentBatch 機制(新單字優先出現)

hiragana-quiz.htmlkatakana-quiz.html 各有一個 recentBatch 物件,控制未被 SRS 記錄的單字出現優先度:

const recentBatch = {
  '單字': 批次號,  // 數字越大 = 越近加入 = 越優先
};
  • 批次規則:同一天加入的算同一批——當天若已有批次號就沿用,否則用目前最大批次號 + 1
  • 目前最大批次號以該測驗 HTML 內 recentBatch 的實際最大值為準(新增前先查,不在此記死數字)
  • 批次號轉換為 nextReview = -(批次號 × 5),確保新字在 pickFromQueue 排序中優先
  • 已被 SRS 記錄過的字不受影響

「我本來就會」的單字

使用者說某個單字「本來就會」時,需同時更新兩處:

  1. already-known.md:加入表格(漢字 | 假名 | 羅馬拼音 | 意思)
  2. 對應測驗的 alreadyKnown Set:加入假名(hiragana 用 display、katakana 用 word

alreadyKnown 中的字初始 SRS 等級為 2(間隔 8 題),降低出現頻率。

更新學習日誌

每次修改任何 .md 筆記檔後,在 log.md 新增條目:

  • 標題格式:## YYYY-MM-DD HH:MM:SS(GMT+8,精確到秒)
  • 內容:更新了什麼(學了哪些假名/單字,或修正了什麼)

更新測驗 HTML

詳見 .claude/skills/japanese-learning/references/quiz-structure.md。更新時用 Python 處理中文字串避免編碼問題,覆寫前先確認。

每次更新 vocabCards/alreadyKnown/recentBatch 後,必須跑 python3 tools/validate_quiz_data.py——它會重算所有 round、查重複條目、比對 already-known.md 與 alreadyKnown Set,全部通過才能 commit。

單字輪次(round)計算規則(嚴格字符規則):

  • word_round = max(所有字符的輪次)
  • 平假名輪次:R1(あ・ら行・ん)、R2(か・が・な行)、R3(さ・ざ・や・わ行)、R4(た・だ・ま行)、R5(は・ば・ぱ行)
  • 小假名 ゃゅょ 及 っ 依所屬行計算(ゃゅょ → R3,っ → R5)
  • 片假名輪次規則相同

設計維護(index.html)

index.html 採現代日式風格,設計原則詳見 PRODUCT.md。UI 設計任務使用 /impeccable skill。

  • 配色:OKLCH,禁用純 #000/#fff;底色微暖白、墨色深靛、強調磚紅
  • 字型:Klee One(標題,與 index.html 一致)+ Noto Sans TC(內文)
  • 無障礙:最小字體 18px,WCAG AA,互動目標 ≥ 44×44px,尊重 prefers-reduced-motion
  • 禁止:gradient text、glassmorphism、等高卡片格、side-stripe border

課程頁(文法章節/單字批次)與測驗

  • 一課=文法+單字(2026-09-08 起)grammar/pairings.json 把每個文法項配一個單字批次, build_grammar_pages.py 會把該批單字用 render_section(demote=1) 嵌成章節頁底部的 「這一課的單字」一節,CTA 多一顆 vocab-quiz.html?batch=N。動機是量出來的——未教的 22 批 共 135 字裡,有 45 字已經出現在已上架的文法章節(動詞批次 11–16 的 48 字中就佔 34 字), 文法為了示範活用會提前把動詞拉進來,單字軌兩個月後再教一次,等於重背。 vocab/NN.html 仍照常產生,當依主題查詢的存檔(同 grammar.mdgrammar/ 的關係)。一課配到兩批以上時,每批的逐字講解會收進 <details>,只留完整表展開(切點是該批第一個含「完整」的 ### 小標;沒有 ### 就退而找 ####——用「第一個」而非「最後一個」,否則批次6 巢狀在完整表底下的 #### 半 はん 的完整用法 會把那一節從中間切開)。summary 標出藏了幾節,否則收起時直接看到「四、完整表」會摸不著頭緒。單批的課不收合。配對值可以是陣列——一個文法項配多批單字(第 5 項 あります/います 同時帶場所設施 A 與 B,因為那才是「東西在哪個地方」的文法;原本 B 掛在第 6 項 ます形上,與動詞活用無關又讓那頁變成 20KB,2026-09-08 移走)。 兩軌同一天跑、文法先跑,那時該批還沒上架,所以 vocab_section_html() 找不到就回 None 出純文法頁;build_vocab_pages.py 收尾時會重建文法頁補上——少了這一步,驗證器會在單字軌 收尾時判文法頁過期,讓整輪還原。批次編號因重排而跳號是正常的。

  • grammar.md 是文法內容的唯一正本grammar/NN.htmlgrammar/index.htmltools/build_grammar_pages.py 的建置產物,絕對不要手改(改了下次重建就沒了,驗證器也會報「過期」)。_sidebar.mdnotes/(docsify)照舊渲染 grammar.md 當完整筆記檢視,兩者並存是刻意的,不要「修掉」。

  • grammar.md 只能用這個 markdown 子集###/#### 小標、段落、行尾兩空格換行、**粗體**`行內程式碼`、GFM 表格、> 引言、``` 圍欄、單層 -/`1.` 清單、`---`。產生器認不得的語法會直接建置失敗。

  • 改了 grammar.md(已上架章節的部分)→ 必跑 python3 tools/build_grammar_pages.py 重建,再跑 python3 tools/validate_quiz_data.py;precommit hook 會擋住過期頁面的 commit。

  • 單字同一套vocab-lessons.md 是單字教學正本、vocab/NN.html 是產物(勿手改)、vocab/batches.json 是登錄表,產生器 tools/build_vocab_pages.py 直接 import build_grammar_pages 的渲染器——markdown 子集與版型兩邊完全相同,改一支兩邊同時生效。vocabulary.md(主題總表)與 vocab-lessons.md(課程順序)刻意並存,同 grammar.mdgrammar/ 的關係。課程單字的練習在獨立的 vocab-quiz.html(2026-09-06 拆出):它只收每日課程教過的字,篩選軸是課程批次;卡片上的 batch 欄位一物二用——既是篩選軸,也是新字的出現優先度(未做過的字 nextReview = -(batch×5)),所以不需要 lessonBatchrecentBatch 那兩張對照表。lessonTitles 只供按鈕 tooltip,驗證器會比對 vocab/batches.jsonhiragana-quiz.html 則回到原本的樣子:五十音與舊單字都依假名輪次 R1–R5 篩選,recentBatch 凍結在批次 21 不再成長。兩頁的單字池互斥(驗證器有這條不變量)——同一個字若兩邊都在,會被各自排程、等於每天複習兩次。互斥是比對「假名+漢字」成對,不是只比假名:同音異字是不同的字(批次28 的 橋/虫/鳥/一回 對上舊頁的 箸/蒸し/鶏/一階),只比假名會把它們誤判成重複,讓當天的 pipeline 整天失敗。batch: 0預習——還沒教到但已經在字池裡的字(目前三張:もらう→批次12、こわれる→批次14、ちかい→批次18),篩選列顯示為「預習」按鈕,教到那批時把 batch 從 0 改成該批編號即可。篩選「全部」的哨兵值因此是 -1 而不是 0。另外 getVocabDistractors() 的干擾項按語意分層取(同批 → 同主題 → 其餘),避免選項一眼就能刪掉。

  • grammar-quiz.html 的題庫 grammarCards 一行一題:idcNN-qM,NN=進度項編號)是 SRS key——修錯字保留 id、改題意換新 id 並刪舊行batch 同天同批、越大越新(未做過的題 nextReview = -(batch×5) 優先出現);cloze 題目必含 ___acceptedanswer;mc choices ≥3 且含 answer;每題必有 explain。作答後頁面會自動把答案句轉羅馬字顯示(wapuro 慣例、句中 は→wa 啟發式);句子含漢字或非助詞的 は 開頭單字(はなし系以外)時,加選填的 romaji 欄位手動指定,覆寫自動轉換。頁內 chapters 陣列必須與 grammar/chapters.json 一致(驗證器會比對)。

每日教學排程(17:30,文法+單字兩軌)

每天 17:30,vault 的 com.didiowen.nihongo-grammar-daily 排程(~/LFCxBVB/X/scripts/nihongo-grammar-notify.sh)為文法與單字各起一個獨立的 headless session:

  • 文法軌(2026-09-05 起改版):依 grammar-daily-progress.md 的規則推進一章——(新增類先寫進 grammar.md)→ 登錄 grammar/chapters.jsongrammar-quiz.htmlchapters、追加 3–5 題進 grammarCards → 跑產生器+驗證器 → Telegram 只發短通知+連結(章節頁+測驗頁),教學內容在網頁、複習交給測驗頁的 SRS。grammar-daily-latest.md 只是 10 行紀錄(日期/編號/連結/新題 id)。
  • 單字軌(2026-09-06 起同樣改版):教學內容寫進 vocab-lessons.md 正本 → 登錄 vocab/batches.json → 跑 build_vocab_pages.py 產出課程頁 → 完成收錄(vocabulary.mdkanji.mdvocab-quiz.htmlvocabCards(每張卡帶 batch)+ lessonTitles)並跑 validate_quiz_data.py。新字一律加進 vocab-quiz.html不要再加進 hiragana-quiz.html
  • Telegram 合併成一則:兩軌各自把內容做完、各自 commit,最後由腳本組出單一通知(今日文法第 N 章+單字批次 M、各自連結、測驗提醒)。單軌失敗時另一軌照常出現在訊息裡。

批改規則(2026-09-06 起)Telegram 不再批改任何題目——文法題在 grammar-quiz.html、單字題在 hiragana-quiz.html,答對答錯都由測驗頁自己記 SRS。兩張進度表的備註欄改記概念性觀察(哪類文法點/哪類字反覆卡住),不再逐題記分。狀態 ✅ 與完成日期排程已填好,不要重複標。

commit/push 節奏

每完成一次更動就 commit + push,不要累積在工作區。 未 commit 的改動是最脆弱的狀態——並行的 session、排程、或下一輪操作都可能把它掃掉。

  • push 一律推 claude-playground,不要推 main main 有分支保護(Changes must be made through a pull request),直推只是靠管理者權限 bypass 掉自己設的規則;本機的 branch guard 也會擋下在 main 上的 commit。工作樹平常就停在 claude-playground
  • 一次更動=一個 concern:新增一批假名/單字、修一個筆記錯誤、更新一次測驗資料,各自成一個 commit,不要把不相關的改動綁在一起
  • 照原有流程做完再提交:檔案修改(vocabulary.mdkanji.mdhiragana-quiz.htmlkatakana-quiz.htmllog.md)、validate_quiz_data.py 驗證、frontmatter 的 updated 更新,全部通過才 commit
  • commit + push 不必先問使用者,那是預設動作;要問的是下面的 PR

PR/merge 節奏

不要每次 push 都開 PR。 讓 commit 在分支上累積,等到一段工作告一段落、或使用者開口時,再一次開 PR 並合併。GitHub Actions 額度是共用且有限的,一個小改動開一個 PR 純粹浪費。

  • PR 一律 claude-playgroundmain
  • 每日 23:30 會自動開 PR 並合併(vault 排程 com.didiowen.nihongo-daily-merge~/LFCxBVB/X/scripts/nihongo-daily-merge.sh):claude-playground 有領先 main 的 commit 就開 PR、合併、把分支快轉回 main;沒有就靜默結束。所以平常不需要手動開 PR,push 完就交給它
  • GitHub Pages 從 main 根目錄發佈,所以測驗網站(hiragana-quiz.html 等)的更新要等合併後才上線——正常情況就是當晚 23:30。使用者若急著看到某個改動,才需要立刻手動開 PR
  • 手動 merge 之後記得把 claude-playground 快轉回 maingit fetch origin && git push origin origin/main:claude-playground),否則它會越拖越舊,下次 PR 開始出現無謂的衝突;23:30 那支排程自己會做這一步
  • 使用者明確說「開 PR」「merge」「cpprm」時直接照做,不需再問
  • 一段工作結束時可以主動問一句「要開 PR 嗎」,但不要停在那裡等——commit + push 該做的照做
  • 同一批的多個 commit 合併在同一個 PR;建立後把 PR 網址回報給使用者
  • smoke test 通過即視為可合併;PR 建立後不需要主動檢查 CI 狀態或 review 意見,等使用者通知再處理

PR 描述格式:

## 使用者指令
(根據上下文完整理解語意而不是單純逐字)

## 修改摘要
(每個 commit 對應做了什麼改動)

互動風格

  • 繁體中文回答
  • 解釋新假名:漢字來源 + 記憶鉤 + 清濁音一起介紹
  • 形近字主動提示
  • 語法說明穿插在真實單字裡,不抽象解釋
  • 台語連結是核心優勢,積極找對應

重要語言學背景

  • 日語音読み和台語文言音同樣保留中古漢語,高度對應
  • 台語日語借詞超過 1000 個(歐巴桑、便當、名刺、運將等)
  • 平假名是漢字草書演變,片假名是漢字楷書演變
  • 台語有文言音和白話音兩套,文言音更接近日語音読み