UNPKG

yijing-bazi-mcp

Version:

易经八字分析 MCP 服务器 - 提供传统命理分析和易经卦象解读的AI工具

525 lines (445 loc) 15.3 kB
/** * 易经计算工具 * 用于易经卦象的生成和计算 */ const Logger = require('./logger.js'); class YijingCalculator { constructor() { this.logger = new Logger(); } /** * 使用铜钱法生成卦象 * @param {string} question - 问题 * @param {string} seed - 随机种子 * @returns {Object} 卦象数据 */ generateByCoin(question, seed = null) { this.logger.info('使用铜钱法生成卦象', { question }); const lines = []; const random = this.createSeededRandom(seed || question + Date.now()); for (let i = 0; i < 6; i++) { // 模拟投掷三枚铜钱 const coin1 = random() > 0.5 ? 3 : 2; // 正面3,反面2 const coin2 = random() > 0.5 ? 3 : 2; const coin3 = random() > 0.5 ? 3 : 2; const sum = coin1 + coin2 + coin3; // 根据总和确定爻的性质 let lineType, isChanging; switch (sum) { case 6: // 三个反面 - 老阴 lineType = 'yin'; isChanging = true; break; case 7: // 两反一正 - 少阳 lineType = 'yang'; isChanging = false; break; case 8: // 两正一反 - 少阴 lineType = 'yin'; isChanging = false; break; case 9: // 三个正面 - 老阳 lineType = 'yang'; isChanging = true; break; } lines.push({ position: i + 1, type: lineType, changing: isChanging, value: sum }); } return this.buildHexagram(lines, 'coin', question); } /** * 使用蓍草法生成卦象 * @param {string} question - 问题 * @param {string} seed - 随机种子 * @returns {Object} 卦象数据 */ generateByYarrow(question, seed = null) { this.logger.info('使用蓍草法生成卦象', { question }); const lines = []; const random = this.createSeededRandom(seed || question + Date.now()); for (let i = 0; i < 6; i++) { // 模拟蓍草分组过程(简化版) let stalks = 49; // 蓍草总数 let operations = []; for (let op = 0; op < 3; op++) { // 第一次分组 const leftGroup = Math.floor(random() * (stalks - 1)) + 1; const rightGroup = stalks - leftGroup; // 计算余数 const leftRemainder = leftGroup % 4 || 4; const rightRemainder = rightGroup % 4 || 4; const totalRemainder = leftRemainder + rightRemainder; operations.push(totalRemainder); stalks -= totalRemainder; } // 根据操作结果确定爻的性质 const finalValue = stalks / 4; let lineType, isChanging; if (finalValue === 6) { lineType = 'yin'; isChanging = false; } else if (finalValue === 7) { lineType = 'yang'; isChanging = false; } else if (finalValue === 8) { lineType = 'yin'; isChanging = true; } else if (finalValue === 9) { lineType = 'yang'; isChanging = true; } lines.push({ position: i + 1, type: lineType, changing: isChanging, value: finalValue, operations: operations }); } return this.buildHexagram(lines, 'yarrow', question); } /** * 使用梅花易数法生成卦象 * @param {string} question - 问题 * @param {string} seed - 随机种子 * @returns {Object} 卦象数据 */ generateByPlumBlossom(question, seed = null) { this.logger.info('使用梅花易数法生成卦象', { question }); const now = new Date(); const year = now.getFullYear(); const month = now.getMonth() + 1; const day = now.getDate(); const hour = now.getHours(); const minute = now.getMinutes(); // 计算上卦 const upperSum = (year + month + day) % 8; const upperTrigram = this.getTrigramByNumber(upperSum || 8); // 计算下卦 const lowerSum = (year + month + day + hour) % 8; const lowerTrigram = this.getTrigramByNumber(lowerSum || 8); // 计算动爻 const changingLine = (year + month + day + hour + minute) % 6 || 6; // 构建卦象 const lines = []; const upperLines = upperTrigram.lines; const lowerLines = lowerTrigram.lines; // 下卦在下(1-3爻),上卦在上(4-6爻) for (let i = 0; i < 3; i++) { lines.push({ position: i + 1, type: lowerLines[i], changing: (i + 1) === changingLine, value: (i + 1) === changingLine ? 9 : 7 }); } for (let i = 0; i < 3; i++) { lines.push({ position: i + 4, type: upperLines[i], changing: (i + 4) === changingLine, value: (i + 4) === changingLine ? 9 : 7 }); } const hexagram = this.buildHexagram(lines, 'plum_blossom', question); hexagram.calculation_details = { year, month, day, hour, minute, upper_sum: upperSum, lower_sum: lowerSum, changing_line: changingLine, upper_trigram: upperTrigram.name, lower_trigram: lowerTrigram.name }; return hexagram; } /** * 使用时间起卦法生成卦象 * @param {string} question - 问题 * @param {string} seed - 随机种子 * @returns {Object} 卦象数据 */ generateByTime(question, seed = null) { this.logger.info('使用时间起卦法生成卦象', { question }); const now = new Date(); const year = now.getFullYear() % 12; // 地支 const month = now.getMonth() + 1; const day = now.getDate(); const hour = Math.floor(now.getHours() / 2); // 时辰 // 计算上卦(年月日之和除以8) const upperSum = (year + month + day) % 8; const upperTrigram = this.getTrigramByNumber(upperSum || 8); // 计算下卦(年月日时之和除以8) const lowerSum = (year + month + day + hour) % 8; const lowerTrigram = this.getTrigramByNumber(lowerSum || 8); // 计算动爻(年月日时之和除以6) const changingLine = (year + month + day + hour) % 6 || 6; // 构建卦象 const lines = []; const upperLines = upperTrigram.lines; const lowerLines = lowerTrigram.lines; // 下卦在下(1-3爻),上卦在上(4-6爻) for (let i = 0; i < 3; i++) { lines.push({ position: i + 1, type: lowerLines[i], changing: (i + 1) === changingLine, value: (i + 1) === changingLine ? 9 : 7 }); } for (let i = 0; i < 3; i++) { lines.push({ position: i + 4, type: upperLines[i], changing: (i + 4) === changingLine, value: (i + 4) === changingLine ? 9 : 7 }); } const hexagram = this.buildHexagram(lines, 'time', question); hexagram.calculation_details = { year, month, day, hour, upper_sum: upperSum, lower_sum: lowerSum, changing_line: changingLine, upper_trigram: upperTrigram.name, lower_trigram: lowerTrigram.name }; return hexagram; } /** * 构建卦象对象 * @param {Array} lines - 爻线数组 * @param {string} method - 生成方法 * @param {string} question - 问题 * @returns {Object} 卦象对象 */ buildHexagram(lines, method, question) { // 获取上下卦 const lowerTrigram = this.getTrigramFromLines(lines.slice(0, 3)); const upperTrigram = this.getTrigramFromLines(lines.slice(3, 6)); // 计算卦象编号 const hexagramNumber = this.calculateHexagramNumber(upperTrigram.number, lowerTrigram.number); // 生成变卦(如果有变爻) const changingLines = lines.filter(line => line.changing); let changingHexagram = null; if (changingLines.length > 0) { const changedLines = lines.map(line => ({ ...line, type: line.changing ? (line.type === 'yang' ? 'yin' : 'yang') : line.type, changing: false })); const changedLowerTrigram = this.getTrigramFromLines(changedLines.slice(0, 3)); const changedUpperTrigram = this.getTrigramFromLines(changedLines.slice(3, 6)); const changedHexagramNumber = this.calculateHexagramNumber(changedUpperTrigram.number, changedLowerTrigram.number); changingHexagram = { number: changedHexagramNumber, upper_trigram: changedUpperTrigram, lower_trigram: changedLowerTrigram, lines: changedLines }; } return { number: hexagramNumber, upper_trigram: upperTrigram, lower_trigram: lowerTrigram, lines: lines, changing_lines: changingLines, changing_hexagram: changingHexagram, method: method, question: question, timestamp: new Date().toISOString() }; } /** * 根据数字获取八卦 * @param {number} number - 数字(1-8) * @returns {Object} 八卦信息 */ getTrigramByNumber(number) { const trigrams = { 1: { name: '乾', symbol: '☰', lines: ['yang', 'yang', 'yang'], number: 1, element: '金', direction: '西北' }, 2: { name: '兑', symbol: '☱', lines: ['yin', 'yang', 'yang'], number: 2, element: '金', direction: '西' }, 3: { name: '离', symbol: '☲', lines: ['yang', 'yin', 'yang'], number: 3, element: '火', direction: '南' }, 4: { name: '震', symbol: '☳', lines: ['yin', 'yin', 'yang'], number: 4, element: '木', direction: '东' }, 5: { name: '巽', symbol: '☴', lines: ['yang', 'yin', 'yin'], number: 5, element: '木', direction: '东南' }, 6: { name: '坎', symbol: '☵', lines: ['yin', 'yang', 'yin'], number: 6, element: '水', direction: '北' }, 7: { name: '艮', symbol: '☶', lines: ['yang', 'yin', 'yin'], number: 7, element: '土', direction: '东北' }, 8: { name: '坤', symbol: '☷', lines: ['yin', 'yin', 'yin'], number: 8, element: '土', direction: '西南' } }; return trigrams[number] || trigrams[1]; } /** * 从爻线获取八卦 * @param {Array} lines - 三个爻线 * @returns {Object} 八卦信息 */ getTrigramFromLines(lines) { const pattern = lines.map(line => line.type).join(''); const patterns = { 'yangyangyang': 1, // 乾 'yinyangyang': 2, // 兑 'yangyinyang': 3, // 离 'yinyinyang': 4, // 震 'yangyinyin': 5, // 巽 'yinyangyin': 6, // 坎 'yangyinyin': 7, // 艮 'yinyinyin': 8 // 坤 }; const number = patterns[pattern] || 1; return this.getTrigramByNumber(number); } /** * 计算卦象编号 * @param {number} upperNumber - 上卦编号 * @param {number} lowerNumber - 下卦编号 * @returns {number} 卦象编号(1-64) */ calculateHexagramNumber(upperNumber, lowerNumber) { // 简化的卦象编号计算 // 实际应用中应该使用标准的64卦编号表 return ((upperNumber - 1) * 8 + lowerNumber); } /** * 创建带种子的随机数生成器 * @param {string} seed - 种子 * @returns {Function} 随机数生成函数 */ createSeededRandom(seed) { let hash = 0; if (seed.length === 0) return Math.random; for (let i = 0; i < seed.length; i++) { const char = seed.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; // 转换为32位整数 } return function () { hash = (hash * 9301 + 49297) % 233280; return hash / 233280; }; } /** * 随机生成卦象 * @param {string} question - 问题 * @param {string} seed - 随机种子 * @returns {Object} 卦象数据 */ generateRandom(question = '随机起卦', seed = null) { this.logger.info('使用随机方法生成卦象', { question }); const random = this.createSeededRandom(seed || question + Date.now()); const lines = []; for (let i = 0; i < 6; i++) { // 随机生成阴阳 const isYang = random() > 0.5; // 10%的概率为变爻 const isChanging = random() < 0.1; lines.push({ position: i + 1, type: isYang ? 'yang' : 'yin', changing: isChanging, value: isChanging ? (isYang ? 9 : 6) : (isYang ? 7 : 8) }); } return this.buildHexagram(lines, 'random', question); } /** * 使用数字生成卦象 * @param {string} seed - 数字种子 * @returns {Object} 卦象数据 */ generateFromNumber(seed) { this.logger.info('使用数字方法生成卦象', { seed }); const random = this.createSeededRandom(seed.toString()); const lines = []; for (let i = 0; i < 6; i++) { const isYang = random() > 0.5; const isChanging = random() < 0.1; lines.push({ position: i + 1, type: isYang ? 'yang' : 'yin', changing: isChanging, value: isChanging ? (isYang ? 9 : 6) : (isYang ? 7 : 8) }); } return this.buildHexagram(lines, 'number', seed); } /** * 使用时间生成卦象 * @param {Date} date - 时间对象 * @returns {Object} 卦象数据 */ generateFromTime(date) { this.logger.info('使用时间方法生成卦象', { date }); const seed = date.getTime().toString(); const random = this.createSeededRandom(seed); const lines = []; for (let i = 0; i < 6; i++) { const isYang = random() > 0.5; const isChanging = random() < 0.1; lines.push({ position: i + 1, type: isYang ? 'yang' : 'yin', changing: isChanging, value: isChanging ? (isYang ? 9 : 6) : (isYang ? 7 : 8) }); } return this.buildHexagram(lines, 'time', date.toISOString()); } /** * 使用梅花易数生成卦象 * @param {string} seed - 种子 * @returns {Object} 卦象数据 */ generateFromPlumBlossom(seed) { this.logger.info('使用梅花易数方法生成卦象', { seed }); const now = new Date(); const timeSeed = now.getFullYear() + now.getMonth() + now.getDate() + now.getHours(); const combinedSeed = seed + timeSeed.toString(); const random = this.createSeededRandom(combinedSeed); const lines = []; for (let i = 0; i < 6; i++) { const isYang = random() > 0.5; const isChanging = random() < 0.1; lines.push({ position: i + 1, type: isYang ? 'yang' : 'yin', changing: isChanging, value: isChanging ? (isYang ? 9 : 6) : (isYang ? 7 : 8) }); } return this.buildHexagram(lines, 'plum_blossom', seed); } /** * 验证卦象数据 * @param {Object} hexagram - 卦象数据 * @returns {boolean} 是否有效 */ validateHexagram(hexagram) { if (!hexagram || typeof hexagram !== 'object') { return false; } // 检查必要字段 const requiredFields = ['number', 'upper_trigram', 'lower_trigram', 'lines']; for (const field of requiredFields) { if (!hexagram[field]) { return false; } } // 检查爻线数量 if (!Array.isArray(hexagram.lines) || hexagram.lines.length !== 6) { return false; } // 检查每个爻线 for (let i = 0; i < 6; i++) { const line = hexagram.lines[i]; if (!line || line.position !== i + 1 || !['yang', 'yin'].includes(line.type)) { return false; } } return true; } } module.exports = YijingCalculator;