commit 926acb0fe899779b9b9cca2b28712864b163e64f Author: zfusx Date: Wed Jun 3 18:17:37 2026 +0800 Add BaZi translation skill diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6900290 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +__pycache__/ +*.py[cod] +.DS_Store +*.pdf diff --git a/README.md b/README.md new file mode 100644 index 0000000..d10b1b8 --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +# bazi_translation + +Codex skill for BaZi translation and naming review. It keeps BaZi/Four Pillars terms consistent across Chinese source terms, English display labels, and code identifiers. + +The skill is simplified-Chinese-first: + +- `简体` is the concept key. +- `标准英文` is for UI/docs when an English label is needed. +- `代码名` is for identifiers, API fields, classes, schemas, and tests. + +The source PDF is not included in this repository. + +## Install + +Clone the repository and copy it into Codex skills: + +```bash +git clone git@git.aplexlogic.com:fireparty/bazi_translation.git +mkdir -p ~/.codex/skills +rsync -a --delete bazi_translation/ ~/.codex/skills/bazi-translation/ +``` + +Validate the skill: + +```bash +python ~/.codex/skills/.system/skill-creator/scripts/quick_validate.py ~/.codex/skills/bazi-translation +``` + +## Use In Codex + +Invoke the skill by name: + +```text +Use $bazi-translation to review BaZi naming in src/bazi. +``` + +Typical requests: + +```text +Use $bazi-translation to translate these terms into approved English and code names: 日主, 天干, 地支, 大运, 用神. +``` + +```text +Use $bazi-translation to review API field names in packages/bazi. +``` + +## Use The Checker + +Run the local checker against files or directories: + +```bash +python ~/.codex/skills/bazi-translation/scripts/check_bazi_names.py +``` + +Exploratory review without failing the command: + +```bash +python ~/.codex/skills/bazi-translation/scripts/check_bazi_names.py --no-fail +``` + +List approved code names: + +```bash +python ~/.codex/skills/bazi-translation/scripts/check_bazi_names.py --list-approved +``` + +Example output: + +```text +src/chart.ts:42: dayOwner -> dayMaster + zh: 日主; standard_en: Day Master + line: const dayOwner = chart.dayOwner; +``` + +## Core Naming Rules + +- Use `dayMaster`, not `dayOwner` or `dayLord`. +- Use `heavenlyStem`, not `skyStem`. +- Use `earthlyBranch`, not `groundBranch`. +- Use `luckPillar`, not `fortuneColumn`. +- Use `usefulGod`, not `useGod`. +- Use `favorableElement` in code by default; keep `Favourable Element` for book-style display text. +- Keep `Useful God` separate from `Favourable Element`. + +## Files + +- `SKILL.md`: Codex skill trigger and workflow. +- `references/terms.md`: simplified-Chinese-first dictionary. +- `references/naming-rules.md`: review rules and anti-patterns. +- `references/pending-terms.md`: staging area for terms needing domain review. +- `scripts/check_bazi_names.py`: source-code naming checker. diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..26ad20c --- /dev/null +++ b/SKILL.md @@ -0,0 +1,44 @@ +--- +name: bazi-translation +description: Simplified-Chinese-first BaZi/Four Pillars terminology dictionary and code naming review workflow. Use when translating Chinese BaZi, Four Pillars, Chinese metaphysics, destiny analysis, Heavenly Stem/Earthly Branch, Ten Gods, Five Factors, luck cycle, or favorable-element terms into English; naming code identifiers, classes, files, API fields, database columns, UI labels, or documentation; or reviewing code for inconsistent or literal translations such as dayOwner, skyStem, groundBranch, fortuneColumn, useGod, or mixed BaZi vocabulary. +--- + +# BaZi Translation + +## Overview + +Use this skill to keep BaZi terminology readable and consistent across code, UI labels, comments, docs, schemas, and tests. + +The source of truth is simplified Chinese first. Use the approved English display term for user-facing text, and use the approved ASCII code name for identifiers unless an existing project convention is stronger. + +## Workflow + +1. Read `references/terms.md` when translating or naming a BaZi concept. +2. Read `references/naming-rules.md` before reviewing code, schemas, APIs, or file names. +3. Run the checker when a local path is available: + +```bash +python ~/.codex/skills/bazi-translation/scripts/check_bazi_names.py +``` + +Use `--no-fail` for exploratory review and `--list-approved` to print approved code names. + +4. Report naming findings as concrete replacements: current name, approved name, reason, and file/line when available. +5. When a concept is not in `terms.md`, do not invent a final translation. Add or propose a row in `references/pending-terms.md` with context and a provisional English/code name. + +## Standards + +- Treat simplified Chinese as the primary key. Keep traditional Chinese and pinyin as aliases. +- Preserve book-style English for display labels when known, for example `Favourable Element`. +- Use project-local spelling for code when already established. If there is no project convention, default to American spelling in identifiers, for example `favorableElement`. +- Prefer established BaZi terms over literal translation: `Day Master`, `Heavenly Stem`, `Earthly Branch`, `Luck Pillar`. +- Keep Chinese, English display text, and code names separate. Do not force one field to serve all audiences. +- Do not conflate `用神` (`Useful God`, advanced concept) with `喜用元素` or `有利元素` (`Favourable Element`, beginner balancing element). +- Do not translate classical terms word by word when the approved table has a domain term. + +## Resources + +- `references/terms.md`: approved simplified-Chinese-first dictionary. +- `references/naming-rules.md`: code naming rules, anti-patterns, and review checklist. +- `references/pending-terms.md`: staging area for terms needing domain review. +- `scripts/check_bazi_names.py`: scans source files for forbidden or suspicious BaZi translations and suggests approved names. diff --git a/agents/openai.yaml b/agents/openai.yaml new file mode 100644 index 0000000..cbbf92a --- /dev/null +++ b/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "BaZi Translation" + short_description: "Simplified Chinese BaZi naming dictionary" + default_prompt: "Use $bazi-translation to review BaZi terminology and code naming consistency." diff --git a/references/naming-rules.md b/references/naming-rules.md new file mode 100644 index 0000000..52e8b0c --- /dev/null +++ b/references/naming-rules.md @@ -0,0 +1,63 @@ +# 八字代码命名规则 + +## 总原则 + +- 简体中文是概念主键;英文显示名和代码名是派生字段。 +- 用户可见文本优先用 `terms.md` 的 `标准英文`,例如 `Favourable Element`。 +- 代码 identifier 优先用 `terms.md` 的 `代码名`,例如 `favorableElement`。 +- 项目内已有统一拼写时先保持一致;没有统一拼写时,代码默认美式 spelling,显示文本可保留书中英式 spelling。 +- 类型名用 PascalCase:`HeavenlyStem`、`EarthlyBranch`、`FiveElement`。 +- 变量、字段、函数用 camelCase:`dayMaster`、`luckPillar`、`getDayMaster()`。 +- 枚举值建议用稳定拼音或大写常量:`jia`/`JIA`、`zi`/`ZI`,避免把 enum value 写成解释句。 + +## 高风险混淆 + +| 中文 | 正确用法 | 避免 | 原因 | +|---|---|---|---| +| 日主 | `dayMaster` | `dayOwner`, `dayLord`, `sunOwner` | 八字固定术语是 Day Master | +| 天干 | `heavenlyStem` | `skyStem`, `celestialTrunk` | Heavenly Stem 是标准术语 | +| 地支 | `earthlyBranch` | `groundBranch`, `terrestrialBranch` | Earthly Branch 是标准术语 | +| 大运 | `luckPillar` | `fortuneColumn`, `bigLuck` | 书中使用 Luck Pillar | +| 用神 | `usefulGod` | `useGod` | Useful God 是术语,不是动词短语 | +| 有利元素 | `favorableElement` | `luckyElement`, `goodElement` | 表示平衡元素,不只是好运元素 | +| 冲 | `clash` | `crash`, `rush` | `crash` 在程序里会误读为崩溃 | +| 金 | `metal` | `gold` | 五行金通常是 Metal,不是黄金 | +| 阴阳 | `yin`/`yang` 或 `polarity` | `negative`/`positive` | 阴阳不是正负数 | + +## Review 流程 + +1. 先找项目中已有的 BaZi 词汇:`bazi`、`stem`、`branch`、`pillar`、`luck`、`god`、`wealth`、`resource`、`officer`。 +2. 对照 `terms.md` 的 `代码名`,列出不一致项。 +3. 优先修正公共 API、数据库字段、模型属性、文件名和 UI label。 +4. 如果发现一个中文概念有多个英文名,选择一个保留,其余写迁移说明。 +5. 如果发现英文名可能对应多个中文概念,不要直接重命名;先补 `pending-terms.md`。 + +## 输出格式 + +命名 review 应该直接给替换建议: + +```text +path/to/file.ts:42 dayOwner -> dayMaster +原因:日主的标准术语是 Day Master,代码名为 dayMaster。 +``` + +需要批量改名时,先列影响面: + +```text +dayOwner appears in API response fields and tests; rename requires migration. +skyStem appears only in local variables; safe to replace with heavenlyStem. +``` + +## 可接受的项目差异 + +- 如果项目已经全部使用 `favourableElement`,可以保持英式拼写,但不要和 `favorableElement` 混用。 +- 如果 enum 已经使用中文字符值,例如 `stem: "甲"`,可以保留;代码侧仍应把类型命名为 `HeavenlyStem`。 +- 如果 UI 面向中文用户,label 可以用中文,但代码仍应使用 approved code name。 +- 如果系统同时支持紫微斗数,不要复用 BaZi 的 `chart`、`pillar`、`star` 类型名,避免跨体系污染。 + +## 什么时候不要自动改 + +- `用神`、`喜神`、`忌神` 在不同流派和层级中含义可能不同。 +- `透干`、`通根`、`合化` 牵涉具体算法定义。 +- `空亡`、`神煞`、`格局` 类术语需要先确认项目采用的体系。 +- 已发布 API、数据库列、序列化字段需要兼容策略,不应只改源代码 identifier。 diff --git a/references/pending-terms.md b/references/pending-terms.md new file mode 100644 index 0000000..1f58e12 --- /dev/null +++ b/references/pending-terms.md @@ -0,0 +1,11 @@ +# 待校对术语 + +把没有进入 `terms.md` 的词先放在这里。确认后再移入正式术语表。 + +| 简体 | 繁体 | 拼音 | 暂定英文 | 暂定代码名 | 来源/上下文 | 待确认问题 | +|---|---|---|---|---|---|---| +| 格局 | 格局 | ge ju | Structure | structure | 八字格局判断 | 需要确认项目是否使用传统格局体系 | +| 神煞 | 神煞 | shen sha | Auxiliary Stars | auxiliaryStars | 神煞系统 | 是否纳入第一版命名范围 | +| 调候 | 調候 | tiao hou | Climate Adjustment | climateAdjustment | 寒暖燥湿调候 | 是否与有利元素分开建模 | +| 扶抑 | 扶抑 | fu yi | Support and Suppress | supportSuppress | 强弱平衡法 | 是否作为算法名 | +| 从格 | 從格 | cong ge | Follower Structure | followerStructure | 特殊格局 | 具体英文需按项目体系确认 | diff --git a/references/terms.md b/references/terms.md new file mode 100644 index 0000000..797e9c7 --- /dev/null +++ b/references/terms.md @@ -0,0 +1,178 @@ +# 八字术语表(简体中文为主) + +本表用于代码、文档、UI 和数据结构命名。`标准英文`偏向用户可见文本;`代码名`偏向 ASCII identifier。若项目已有更强约定,先保持项目一致,再更新本表。 + +来源说明:第一版参考用户提供的 Joey Yap《BaZi - The Destiny Code》PDF 可抽取文本和通行八字术语。页码为 PDF 页码,非纸书页码。表格只记录术语,不复刻书中长段内容。 + +## 基础概念 + +| 简体 | 繁体 | 拼音 | 标准英文 | 代码名 | 可接受别名 | 避免 | 说明 | +|---|---|---|---|---|---|---|---| +| 八字 | 八字 | ba zi | BaZi | bazi | Eight Characters | eightWords,eightLetters | 四柱八个字的命理系统 | +| 四柱 | 四柱 | si zhu | Four Pillars | fourPillars | Four Pillars of Destiny | fourColumns,fourPosts | 年月日时四组干支 | +| 命 | 命 | ming | Destiny | destiny | life path | fateCode | 固定的生命容量或格局 | +| 运 | 運 | yun | Luck | luck | Fortunes | fortuneOnly | 随时间变化的运势,不等同随机好运 | +| 命运 | 命運 | ming yun | Destiny and Luck | destinyAndLuck | destiny fortunes | fateAndFortune | 命与运的组合概念 | +| 风水 | 風水 | feng shui | Feng Shui | fengShui | geomancy | windWater | 作为专名保留拼音 | +| 命学 | 命學 | ming xue | Destiny Studies | destinyStudies | life studies | fateStudy | 五术中的命类 | +| 五术 | 五術 | wu shu | Chinese Five Arts | chineseFiveArts | Five Techniques | fiveSkills | 命、卜、相、医、山 | +| 卜筮 | 卜筮 | bu shi | Divination | divination | science of divination | fortuneTelling | 五术中的卜类 | +| 相学 | 相學 | xiang xue | Physiognomy | physiognomy | appearance studies | faceReadingOnly | 五术中的相类 | +| 医学 | 醫學 | yi xue | Chinese Medicine | chineseMedicine | medicine studies | medicalScience | 五术中的医类 | +| 山术 | 山術 | shan shu | Mountain Arts | mountainArts | alchemy arts | hillSkill | 五术中的山类 | +| 紫微斗数 | 紫微斗數 | zi wei dou shu | Purple Star Astrology | purpleStarAstrology | Zi Wei Dou Shu | purpleMicroCount | 另一个命理系统,不等同八字 | +| 河图洛书 | 河圖洛書 | he tu luo shu | River Map and Lo Shu | riverMapLoShu | He Tu Luo Shu | riverBook | 传统术数基础文本名 | + +## 命盘结构 + +| 简体 | 繁体 | 拼音 | 标准英文 | 代码名 | 可接受别名 | 避免 | 说明 | +|---|---|---|---|---|---|---|---| +| 命盘 | 命盤 | ming pan | BaZi Chart | baziChart | chart | destinyPlate | 八字排盘结果 | +| 年柱 | 年柱 | nian zhu | Year Pillar | yearPillar | year pillar | yearColumn | 年份干支柱 | +| 月柱 | 月柱 | yue zhu | Month Pillar | monthPillar | month pillar | monthColumn | 月令所在干支柱 | +| 日柱 | 日柱 | ri zhu | Day Pillar | dayPillar | day pillar | dayColumn | 日主所在干支柱 | +| 时柱 | 時柱 | shi zhu | Hour Pillar | hourPillar | hour pillar | timePillar,hourColumn | 时辰干支柱 | +| 日主 | 日主 | ri zhu | Day Master | dayMaster | Self Element | dayOwner,dayLord,sunOwner,selfLord | 日柱天干,八字分析参照点 | +| 自我元素 | 自我元素 | zi wo yuan su | Self Element | selfElement | Day Master element | selfStar | 日主的元素表达 | +| 月令 | 月令 | yue ling | Season Master | seasonMaster | month command,season | monthOrder,monthMaster | 月支代表的季节力量 | +| 天干 | 天干 | tian gan | Heavenly Stem | heavenlyStem | stem | skyStem,celestialTrunk,heavenStemOnly | 每柱上方的字 | +| 地支 | 地支 | di zhi | Earthly Branch | earthlyBranch | branch | groundBranch,earthBranchOnly,terrestrialBranch | 每柱下方的字 | +| 藏干 | 藏干 | cang gan | Hidden Stem | hiddenStem | hidden heavenly stem | hiddenTrunk,storedStem | 地支中藏的天干 | +| 干支 | 干支 | gan zhi | Stem-Branch | stemBranch | Jia Zi pair | stemAndBranchPair | 一个天干加一个地支 | +| 甲子 | 甲子 | jia zi | Jia Zi | jiaZi | sexagenary pair | sixtyPair | 六十甲子中的第一组,也可泛指干支组合 | +| 空亡 | 空亡 | kong wang | Void | voidBranch | emptiness | emptyDeath | 需要项目确认具体体系后再细化 | + +## 十天干 + +| 简体 | 繁体 | 拼音 | 标准英文 | 代码名 | 可接受别名 | 避免 | 说明 | +|---|---|---|---|---|---|---|---| +| 甲 | 甲 | jia | Jia Yang Wood | jia | yangWoodStem | firstStem | 阳木天干 | +| 乙 | 乙 | yi | Yi Yin Wood | yi | yinWoodStem | secondStem | 阴木天干 | +| 丙 | 丙 | bing | Bing Yang Fire | bing | yangFireStem | thirdStem | 阳火天干 | +| 丁 | 丁 | ding | Ding Yin Fire | ding | yinFireStem | fourthStem | 阴火天干 | +| 戊 | 戊 | wu | Wu Yang Earth | wu | yangEarthStem | fifthStem | 阳土天干 | +| 己 | 己 | ji | Ji Yin Earth | ji | yinEarthStem | sixthStem | 阴土天干 | +| 庚 | 庚 | geng | Geng Yang Metal | geng | yangMetalStem | seventhStem | 阳金天干 | +| 辛 | 辛 | xin | Xin Yin Metal | xin | yinMetalStem | eighthStem | 阴金天干 | +| 壬 | 壬 | ren | Ren Yang Water | ren | yangWaterStem | ninthStem | 阳水天干 | +| 癸 | 癸 | gui | Gui Yin Water | gui | yinWaterStem | tenthStem | 阴水天干 | + +## 十二地支 + +| 简体 | 繁体 | 拼音 | 标准英文 | 代码名 | 可接受别名 | 避免 | 说明 | +|---|---|---|---|---|---|---|---| +| 子 | 子 | zi | Zi Rat | zi | rat branch | mouseBranch | 鼠,水 | +| 丑 | 丑 | chou | Chou Ox | chou | ox branch | cowBranch | 牛,土 | +| 寅 | 寅 | yin | Yin Tiger | yin | tiger branch | tigerStem | 虎,木 | +| 卯 | 卯 | mao | Mao Rabbit | mao | rabbit branch | hareBranch | 兔,木 | +| 辰 | 辰 | chen | Chen Dragon | chen | dragon branch | dragonStem | 龙,土 | +| 巳 | 巳 | si | Si Snake | si | snake branch | serpentBranch | 蛇,火 | +| 午 | 午 | wu | Wu Horse | wuBranch | horse branch | noonBranchOnly | 马,火。为避免与戊同名,代码可用 wuBranch | +| 未 | 未 | wei | Wei Goat | wei | goat branch | sheepBranchOnly | 羊,土 | +| 申 | 申 | shen | Shen Monkey | shen | monkey branch | monkeyStem | 猴,金 | +| 酉 | 酉 | you | You Rooster | you | rooster branch | chickenBranch | 鸡,金 | +| 戌 | 戌 | xu | Xu Dog | xu | dog branch | dogStem | 狗,土 | +| 亥 | 亥 | hai | Hai Pig | hai | pig branch | boarBranchOnly | 猪,水 | + +## 五行与阴阳 + +| 简体 | 繁体 | 拼音 | 标准英文 | 代码名 | 可接受别名 | 避免 | 说明 | +|---|---|---|---|---|---|---|---| +| 五行 | 五行 | wu xing | Five Elements | fiveElements | elements | fiveMovementsOnly | 木火土金水 | +| 木 | 木 | mu | Wood | wood | wood element | tree | 五行之一 | +| 火 | 火 | huo | Fire | fire | fire element | flameOnly | 五行之一 | +| 土 | 土 | tu | Earth | earth | earth element | soilOnly | 五行之一 | +| 金 | 金 | jin | Metal | metal | metal element | goldOnly | 五行之一,通常不是黄金 | +| 水 | 水 | shui | Water | water | water element | liquidOnly | 五行之一 | +| 阴 | 陰 | yin | Yin | yin | yin polarity | negative | 阴性,不直接等于弱 | +| 阳 | 陽 | yang | Yang | yang | yang polarity | positive | 阳性,不直接等于强 | +| 相生 | 相生 | xiang sheng | Production Cycle | productionCycle | produces,generating cycle | birthCycle | 五行生助关系 | +| 相克 | 相剋 | xiang ke | Controlling Cycle | controllingCycle | controls,countering cycle | destroyCycle,killingCycle | 五行制约关系,避免简单写 destroy | +| 泄 | 洩 | xie | Weakening | weakening | drains | leakOnly | 日主生出导致自身减力 | +| 平衡 | 平衡 | ping heng | Balance | balance | equilibrium | evennessOnly | 八字分析核心目标 | +| 气 | 氣 | qi | Qi | qi | energy | airOnly | 专名保留拼音 | + +## 五因素与十神 + +| 简体 | 繁体 | 拼音 | 标准英文 | 代码名 | 可接受别名 | 避免 | 说明 | +|---|---|---|---|---|---|---|---| +| 五因素 | 五因素 | wu yin su | Five Factors | fiveFactors | five factor layer | fiveReasons | Joey Yap 初级体系中常用的五类关系 | +| 比劫 | 比劫 | bi jie | Companion Element | companionElement | companions | peerElementOnly | 比肩与劫财的总类 | +| 食伤 | 食傷 | shi shang | Output Element | outputElement | output | foodInjury | 食神与伤官的总类 | +| 财星 | 財星 | cai xing | Wealth Element | wealthElement | wealth | moneyStarOnly | 正财与偏财的总类 | +| 官杀 | 官殺 | guan sha | Influence Element | influenceElement | officer killing group | authorityStarOnly | 正官与七杀的总类 | +| 印星 | 印星 | yin xing | Resource Element | resourceElement | resource | sealStarOnly | 正印与偏印的总类 | +| 比肩 | 比肩 | bi jian | Friend | friend | peer,companion | shoulderCompare | 同阴阳同五行 | +| 劫财 | 劫財 | jie cai | Rob Wealth | robWealth | wealth robber | robMoney | 同五行异阴阳 | +| 食神 | 食神 | shi shen | Eating God | eatingGod | food god | foodSpirit | 日主所生且同阴阳 | +| 伤官 | 傷官 | shang guan | Hurting Officer | hurtingOfficer | harm officer | injuredOfficial | 日主所生且异阴阳 | +| 正财 | 正財 | zheng cai | Direct Wealth | directWealth | proper wealth | mainMoney | 日主所克且异阴阳 | +| 偏财 | 偏財 | pian cai | Indirect Wealth | indirectWealth | unconventional wealth | sideMoney | 日主所克且同阴阳 | +| 正官 | 正官 | zheng guan | Direct Officer | directOfficer | officer | officialOnly | 克日主且异阴阳 | +| 七杀 | 七殺 | qi sha | Seven Killings | sevenKillings | 7 Killings,indirect officer | sevenMurders | 克日主且同阴阳 | +| 偏官 | 偏官 | pian guan | Indirect Officer | indirectOfficer | Seven Killings | partialOfficerOnly | 常与七杀关联 | +| 正印 | 正印 | zheng yin | Direct Resource | directResource | proper resource | mainSeal | 生日主且异阴阳 | +| 偏印 | 偏印 | pian yin | Indirect Resource | indirectResource | unconventional resource | sideSeal | 生日主且同阴阳 | + +## 喜忌与强弱 + +| 简体 | 繁体 | 拼音 | 标准英文 | 代码名 | 可接受别名 | 避免 | 说明 | +|---|---|---|---|---|---|---|---| +| 有利元素 | 有利元素 | you li yuan su | Favourable Element | favorableElement | favourableElement | luckyElementOnly,goodElementOnly | 代码默认美式 favorable;显示可保留 Favourable | +| 不利元素 | 不利元素 | bu li yuan su | Unfavourable Element | unfavorableElement | unfavourableElement | badElementOnly | 代码默认美式 unfavorable | +| 喜神 | 喜神 | xi shen | Favorable God | favorableGod | favourable god | happyGod | 传统细分术语,使用前确认体系 | +| 忌神 | 忌神 | ji shen | Negative God | negativeGod | Unfavorable God,unfavourable god | hateGod | 传统细分术语,使用前确认体系 | +| 用神 | 用神 | yong shen | Useful God | usefulGod | Yong Shen | useGod,usableGod | 高阶概念,不要等同有利元素 | +| 强日主 | 強日主 | qiang ri zhu | Strong Day Master | strongDayMaster | strong self element | powerfulDayOwner | 日主偏强 | +| 弱日主 | 弱日主 | ruo ri zhu | Weak Day Master | weakDayMaster | weak self element | powerlessDayOwner | 日主偏弱 | +| 旺 | 旺 | wang | Prosperous | prosperous | thriving | peakOnly | 五行季节强度之一 | +| 强 | 強 | qiang | Strong | strong | strong stage | robustOnly | 五行季节强度之一 | +| 弱 | 弱 | ruo | Weak | weak | weak stage | fragileOnly | 五行季节强度之一 | +| 囚 | 囚 | qiu | Trap | trap | trapped stage | prisonerOnly | 书中用 Trap 表示阶段 | +| 死 | 死 | si | Dead | dead | dead stage | deathOnly | 五行季节强度之一 | +| 得令 | 得令 | de ling | In Season | inSeason | seasonal support | gotOrder | 得月令支持 | +| 失令 | 失令 | shi ling | Out of Season | outOfSeason | lacks seasonal support | lostOrder | 不得月令支持 | +| 透干 | 透干 | tou gan | Penetrates to Heavenly Stem | penetratesToHeavenlyStem | penetrate to stem | exposeStemOnly | 同元素从支到干显现 | +| 通根 | 通根 | tong gen | Rooted | rooted | has root | passRoot | 天干在地支有根 | + +## 合冲刑害破 + +| 简体 | 繁体 | 拼音 | 标准英文 | 代码名 | 可接受别名 | 避免 | 说明 | +|---|---|---|---|---|---|---|---| +| 合 | 合 | he | Combination | combination | combine | unionOnly | 合化或合绊需按上下文细分 | +| 六合 | 六合 | liu he | Six Combinations | sixCombinations | six harmony | sixUnions | 地支六合 | +| 三合 | 三合 | san he | Three Harmonies | threeHarmonies | trine combination | threeCombinationsOnly | 地支三合局 | +| 三会 | 三會 | san hui | Three Meetings | threeMeetings | seasonal meeting | threeMeetups | 地支三会局 | +| 冲 | 沖 | chong | Clash | clash | conflict | crash,rush | 地支冲,代码避免 crash | +| 刑 | 刑 | xing | Punishment | punishment | penalty | sentenceOnly | 地支刑 | +| 害 | 害 | hai | Harm | harm | harming | damageOnly | 地支害 | +| 破 | 破 | po | Destruction | destruction | break | brokenOnly | 地支破 | +| 合化 | 合化 | he hua | Combination Transformation | combinationTransformation | transforms | chemicalCombine | 合而化成另一五行 | + +## 运势与时间 + +| 简体 | 繁体 | 拼音 | 标准英文 | 代码名 | 可接受别名 | 避免 | 说明 | +|---|---|---|---|---|---|---|---| +| 大运 | 大運 | da yun | Luck Pillar | luckPillar | 10-year luck pillar | fortuneColumn,luckColumn,bigLuck | 十年一柱的运程 | +| 运程 | 運程 | yun cheng | Luck Cycle | luckCycle | fortune cycle | luckProgram | 运势流转过程 | +| 顺行 | 順行 | shun xing | Forward Cycle | forwardCycle | forward luck cycle | normalDirection | 顺排运 | +| 逆行 | 逆行 | ni xing | Reverse Cycle | reverseCycle | reverse luck cycle | backwardCycle | 逆排运 | +| 流年 | 流年 | liu nian | Annual Luck | annualLuck | annual pillar,year luck | flowingYearOnly | 当年干支对命盘的影响,避免和本命年柱混淆 | +| 流月 | 流月 | liu yue | Monthly Luck | monthlyLuck | monthly pillar | flowingMonthOnly | 当月干支对命盘的影响 | +| 流日 | 流日 | liu ri | Daily Luck | dailyLuck | daily pillar | flowingDayOnly | 当日干支对命盘的影响 | +| 流时 | 流時 | liu shi | Hourly Luck | hourlyLuck | hourly pillar | flowingHourOnly | 当时干支对命盘的影响 | +| 早子时 | 早子時 | zao zi shi | Early Rat Hour | earlyRatHour | early zi hour | morningRat | 00:00-00:59 的子时处理 | +| 晚子时 | 晚子時 | wan zi shi | Late Rat Hour | lateRatHour | late zi hour | nightRat | 23:00-23:59 的子时处理 | +| 万年历 | 萬年曆 | wan nian li | Ten Thousand Year Calendar | tenThousandYearCalendar | perpetual calendar | millionYearCalendar | 排盘用历法资料 | + +## 编程约定 + +| 简体 | 繁体 | 拼音 | 标准英文 | 代码名 | 可接受别名 | 避免 | 说明 | +|---|---|---|---|---|---|---|---| +| 枚举天干 | 枚舉天干 | mei ju tian gan | Heavenly Stem enum | HeavenlyStem | Stem | SkyStem | 类型名用 PascalCase | +| 枚举地支 | 枚舉地支 | mei ju di zhi | Earthly Branch enum | EarthlyBranch | Branch | GroundBranch | 类型名用 PascalCase | +| 枚举五行 | 枚舉五行 | mei ju wu xing | Five Element enum | FiveElement | Element | WuXingOnly | 类型名用单数 | +| 枚举阴阳 | 枚舉陰陽 | mei ju yin yang | Polarity enum | Polarity | YinYang | PositiveNegative | 代码中避免 positive/negative | +| 干支值 | 干支值 | gan zhi zhi | Stem-Branch value | stemBranch | ganzhi | stemBranchPair | 数据值 | +| 排盘 | 排盤 | pai pan | Plot Chart | plotChart | calculate chart | arrangePlate | 动词命名 | +| 取日主 | 取日主 | qu ri zhu | Get Day Master | getDayMaster | find day master | getDayOwner | 函数命名 | diff --git a/scripts/check_bazi_names.py b/scripts/check_bazi_names.py new file mode 100755 index 0000000..4a2e39d --- /dev/null +++ b/scripts/check_bazi_names.py @@ -0,0 +1,276 @@ +#!/usr/bin/env python3 +"""Scan source files for suspicious BaZi terminology translations.""" + +from __future__ import annotations + +import argparse +import os +import re +import sys +from dataclasses import dataclass +from pathlib import Path + + +SKILL_DIR = Path(__file__).resolve().parents[1] +DEFAULT_TERMS = SKILL_DIR / "references" / "terms.md" + +EXCLUDE_DIRS = { + ".git", + ".hg", + ".svn", + ".idea", + ".vscode", + "__pycache__", + "node_modules", + "vendor", + "dist", + "build", + "coverage", + ".next", + ".nuxt", + ".venv", + "venv", +} + +TEXT_EXTENSIONS = { + ".c", + ".cc", + ".cpp", + ".cs", + ".css", + ".csv", + ".go", + ".h", + ".hpp", + ".html", + ".java", + ".js", + ".json", + ".jsx", + ".kt", + ".lua", + ".md", + ".mjs", + ".php", + ".py", + ".rb", + ".rs", + ".scss", + ".sh", + ".sql", + ".svelte", + ".swift", + ".toml", + ".ts", + ".tsx", + ".txt", + ".vue", + ".xml", + ".yaml", + ".yml", +} + + +@dataclass(frozen=True) +class BadTerm: + bad: str + preferred: str + zh: str + standard_en: str + reason: str + + @property + def normalized(self) -> str: + return normalize_identifier(self.bad) + + +def split_md_row(line: str) -> list[str]: + stripped = line.strip() + if not stripped.startswith("|") or not stripped.endswith("|"): + return [] + return [cell.strip().strip("`").strip() for cell in stripped.strip("|").split("|")] + + +def normalize_cell(value: str) -> str: + value = re.sub(r"", ",", value, flags=re.IGNORECASE) + value = value.replace(",", ",").replace("、", ",").replace(";", ",").replace(";", ",") + return value.strip() + + +def normalize_identifier(value: str) -> str: + return re.sub(r"[^a-z0-9]+", "", value.lower()) + + +def parse_bad_terms(terms_path: Path) -> list[BadTerm]: + rows: list[BadTerm] = [] + header: list[str] | None = None + + for raw_line in terms_path.read_text(encoding="utf-8").splitlines(): + cells = split_md_row(raw_line) + if not cells: + continue + if "简体" in cells and "代码名" in cells and "避免" in cells: + header = cells + continue + if cells and all(set(cell) <= {"-"} for cell in cells): + continue + if not header or len(cells) < len(header): + continue + + row = dict(zip(header, cells)) + preferred = row.get("代码名", "").strip("` ") + avoid = normalize_cell(row.get("避免", "")) + if not preferred or not avoid or avoid == "-": + continue + + for item in [part.strip("` ") for part in avoid.split(",")]: + if not item or item == "-": + continue + rows.append( + BadTerm( + bad=item, + preferred=preferred, + zh=row.get("简体", ""), + standard_en=row.get("标准英文", ""), + reason=f"{row.get('简体', '')} should use {preferred}", + ) + ) + + return rows + + +def parse_approved_names(terms_path: Path) -> list[str]: + names: set[str] = set() + header: list[str] | None = None + for raw_line in terms_path.read_text(encoding="utf-8").splitlines(): + cells = split_md_row(raw_line) + if not cells: + continue + if "简体" in cells and "代码名" in cells: + header = cells + continue + if cells and all(set(cell) <= {"-"} for cell in cells): + continue + if not header or len(cells) < len(header): + continue + row = dict(zip(header, cells)) + code_name = row.get("代码名", "").strip("` ") + if code_name and code_name != "-": + names.add(code_name) + return sorted(names, key=str.lower) + + +def iter_files(paths: list[Path]) -> list[Path]: + found: list[Path] = [] + for path in paths: + if not path.exists(): + print(f"warning: path does not exist: {path}", file=sys.stderr) + continue + if path.is_file(): + if is_text_candidate(path): + found.append(path) + continue + for root, dirs, files in os.walk(path): + dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS] + for name in files: + candidate = Path(root) / name + if is_text_candidate(candidate): + found.append(candidate) + return found + + +def is_text_candidate(path: Path) -> bool: + if path.name.startswith(".") and path.suffix == "": + return False + return path.suffix.lower() in TEXT_EXTENSIONS + + +def line_has_bad_term(line: str, bad_term: BadTerm) -> bool: + bad = bad_term.bad + lower = line.lower() + identifier_like_bad_term = re.match(r"^[A-Za-z_][A-Za-z0-9_]*$", bad) is not None + pascal_case_bad_term = bad[:1].isupper() and identifier_like_bad_term + + if " " in bad: + words = [re.escape(part) for part in bad.lower().split()] + if re.search(r"\b" + r"\s+".join(words) + r"\b", lower): + return True + + if identifier_like_bad_term: + bad_norm = bad_term.normalized + for identifier in re.findall(r"[A-Za-z_][A-Za-z0-9_]*", line): + if pascal_case_bad_term: + if identifier == bad: + return True + continue + if identifier[:1].isupper() and bad[:1].islower(): + continue + if normalize_identifier(identifier) == bad_norm: + return True + return False + + if pascal_case_bad_term: + if re.search(r"\b" + re.escape(bad) + r"\b", line): + return True + elif re.search(r"\b" + re.escape(bad.lower()) + r"\b", lower): + return True + + return False + + +def scan(paths: list[Path], bad_terms: list[BadTerm]) -> list[tuple[Path, int, str, BadTerm]]: + issues: list[tuple[Path, int, str, BadTerm]] = [] + for path in iter_files(paths): + try: + text = path.read_text(encoding="utf-8") + except UnicodeDecodeError: + try: + text = path.read_text(encoding="utf-8-sig") + except UnicodeDecodeError: + continue + + for line_no, line in enumerate(text.splitlines(), start=1): + for bad_term in bad_terms: + if line_has_bad_term(line, bad_term): + issues.append((path, line_no, line.strip(), bad_term)) + return issues + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("paths", nargs="*", type=Path, help="files or directories to scan") + parser.add_argument("--terms", type=Path, default=DEFAULT_TERMS, help="path to terms.md") + parser.add_argument("--no-fail", action="store_true", help="always exit 0") + parser.add_argument("--list-approved", action="store_true", help="print approved code names and exit") + args = parser.parse_args() + + if not args.terms.exists(): + print(f"terms file not found: {args.terms}", file=sys.stderr) + return 2 + + if args.list_approved: + for name in parse_approved_names(args.terms): + print(name) + return 0 + + if not args.paths: + parser.error("provide at least one file or directory") + + bad_terms = parse_bad_terms(args.terms) + issues = scan(args.paths, bad_terms) + + if not issues: + print("No suspicious BaZi terminology names found.") + return 0 + + for path, line_no, line, bad_term in issues: + print(f"{path}:{line_no}: {bad_term.bad} -> {bad_term.preferred}") + print(f" zh: {bad_term.zh}; standard_en: {bad_term.standard_en}") + print(f" line: {line}") + + print(f"\n{len(issues)} issue(s) found.") + return 0 if args.no_fail else 1 + + +if __name__ == "__main__": + raise SystemExit(main())