// SKEight chart demo engine + visual components // Educational/cultural framing only. Calculations are simplified for demo purposes. const STEMS = [ { ch: "甲", py: "Jiǎ", el: "wood", yy: "yang" }, { ch: "乙", py: "Yǐ", el: "wood", yy: "yin" }, { ch: "丙", py: "Bǐng", el: "fire", yy: "yang" }, { ch: "丁", py: "Dīng", el: "fire", yy: "yin" }, { ch: "戊", py: "Wù", el: "earth", yy: "yang" }, { ch: "己", py: "Jǐ", el: "earth", yy: "yin" }, { ch: "庚", py: "Gēng", el: "metal", yy: "yang" }, { ch: "辛", py: "Xīn", el: "metal", yy: "yin" }, { ch: "壬", py: "Rén", el: "water", yy: "yang" }, { ch: "癸", py: "Guǐ", el: "water", yy: "yin" }, ]; const BRANCHES = [ { ch: "子", py: "Zǐ", el: "water", animal: "Rat" }, { ch: "丑", py: "Chǒu", el: "earth", animal: "Ox" }, { ch: "寅", py: "Yín", el: "wood", animal: "Tiger" }, { ch: "卯", py: "Mǎo", el: "wood", animal: "Rabbit" }, { ch: "辰", py: "Chén", el: "earth", animal: "Dragon" }, { ch: "巳", py: "Sì", el: "fire", animal: "Snake" }, { ch: "午", py: "Wǔ", el: "fire", animal: "Horse" }, { ch: "未", py: "Wèi", el: "earth", animal: "Goat" }, { ch: "申", py: "Shēn", el: "metal", animal: "Monkey" }, { ch: "酉", py: "Yǒu", el: "metal", animal: "Rooster" }, { ch: "戌", py: "Xū", el: "earth", animal: "Dog" }, { ch: "亥", py: "Hài", el: "water", animal: "Pig" }, ]; const ELEMENT_INFO = { wood: { ch: "木", py: "Mù", en: "Wood", color: "#6b8e5a", soft: "rgba(107,142,90,0.15)" }, fire: { ch: "火", py: "Huǒ", en: "Fire", color: "#c45c3d", soft: "rgba(196,92,61,0.15)" }, earth: { ch: "土", py: "Tǔ", en: "Earth", color: "#b8893a", soft: "rgba(184,137,58,0.18)" }, metal: { ch: "金", py: "Jīn", en: "Metal", color: "#cfc8b3", soft: "rgba(207,200,179,0.12)" }, water: { ch: "水", py: "Shuǐ", en: "Water", color: "#5d7fa0", soft: "rgba(93,127,160,0.15)" }, }; // Simplified, deterministic pillar generator for demo. NOT astronomically accurate. function computeBaZi({ year, month, day, hour }) { const yStem = STEMS[((year - 4) % 10 + 10) % 10]; const yBranch = BRANCHES[((year - 4) % 12 + 12) % 12]; // month pillar: stem uses (year stem index, month) table; simplified const monthStemIdx = (((year - 4) % 5) * 2 + (month + 1)) % 10; const mStem = STEMS[(monthStemIdx + 10) % 10]; const mBranch = BRANCHES[((month + 1) % 12 + 12) % 12]; // day pillar: pseudo-deterministic from date const t = Date.UTC(year, month, day) / 86400000; const dStem = STEMS[((Math.floor(t) + 9) % 10 + 10) % 10]; const dBranch = BRANCHES[((Math.floor(t) + 11) % 12 + 12) % 12]; // hour pillar const hBranchIdx = Math.floor(((hour + 1) % 24) / 2); const hStemIdx = ((((((Math.floor(t) + 9) % 10) + 10) % 10) * 2) + hBranchIdx) % 10; const hStem = STEMS[hStemIdx]; const hBranch = BRANCHES[hBranchIdx]; const pillars = [ { label: "Hour", stem: hStem, branch: hBranch }, { label: "Day", stem: dStem, branch: dBranch, isMaster: true }, { label: "Month", stem: mStem, branch: mBranch }, { label: "Year", stem: yStem, branch: yBranch }, ]; // five-element distribution const counts = { wood: 0, fire: 0, earth: 0, metal: 0, water: 0 }; pillars.forEach(p => { counts[p.stem.el] += 1; counts[p.branch.el] += 1; }); return { pillars, dayMaster: dStem, counts }; } // ───────────────────────────────────────────────────────────── // Visual: A polished four-pillar chart card // ───────────────────────────────────────────────────────────── function BaZiChart({ chart, compact = false }) { const { pillars, counts } = chart; const px = compact ? 10 : 16; return (