UNPKG

ziwei-mcp

Version:

紫微斗数 MCP (Ziwei Doushu Model Context Protocol) - 基于 MCP 协议的紫微斗数命理分析工具

648 lines (575 loc) 18.3 kB
/** * 专业紫微斗数数据源服务 * 集成多个专业数据源和API接口 */ const axios = require("axios"); const fs = require("fs").promises; const path = require("path"); /** * 专业数据源配置 */ const DATA_SOURCES = { // 中华万年历API(示例) ZHWNL_API: { baseUrl: "https://api.zhwnl.com", endpoints: { lunarCalendar: "/lunar/calendar", solarTerms: "/solar/terms", ganzhiCalendar: "/ganzhi/calendar", }, apiKey: process.env.ZHWNL_API_KEY || "your_api_key_here", }, // 紫微斗数专业数据库API(示例) ZIWEI_PRO_API: { baseUrl: "https://api.ziwei-pro.com", endpoints: { starPositions: "/stars/positions", patterns: "/patterns/analysis", interpretations: "/interpretations", }, apiKey: process.env.ZIWEI_PRO_API_KEY || "your_api_key_here", }, // 本地专业数据库 LOCAL_DATABASE: { starsData: path.join(__dirname, "../data/professional-stars.json"), patternsData: path.join(__dirname, "../data/professional-patterns.json"), interpretationsData: path.join( __dirname, "../data/professional-interpretations.json", ), }, }; class ProfessionalDataService { constructor() { this.cache = new Map(); this.cacheTimeout = 24 * 60 * 60 * 1000; // 24小时缓存 } /** * 获取精确的农历信息 */ async getPreciseLunarInfo(solarDate) { const cacheKey = `lunar_${solarDate.year}_${solarDate.month}_${solarDate.day}`; // 检查缓存 if (this.cache.has(cacheKey)) { const cached = this.cache.get(cacheKey); if (Date.now() - cached.timestamp < this.cacheTimeout) { return cached.data; } } try { // 尝试从专业API获取 const apiResult = await this.fetchFromZhwnlApi(solarDate); if (apiResult) { this.cache.set(cacheKey, { data: apiResult, timestamp: Date.now(), }); return apiResult; } } catch (error) { console.warn("专业API调用失败,使用本地算法:", error.message); } // 降级到本地算法 return this.calculateLunarLocal(solarDate); } /** * 从中华万年历API获取农历信息 */ async fetchFromZhwnlApi(solarDate) { const url = `${DATA_SOURCES.ZHWNL_API.baseUrl}${DATA_SOURCES.ZHWNL_API.endpoints.lunarCalendar}`; const response = await axios.get(url, { params: { year: solarDate.year, month: solarDate.month, day: solarDate.day, apikey: DATA_SOURCES.ZHWNL_API.apiKey, }, timeout: 5000, }); if (response.data && response.data.code === 200) { return { year: response.data.data.lunar_year, month: response.data.data.lunar_month, day: response.data.data.lunar_day, isLeapMonth: response.data.data.is_leap_month, yearInGanZhi: response.data.data.year_ganzhi, monthInGanZhi: response.data.data.month_ganzhi, dayInGanZhi: response.data.data.day_ganzhi, hourInGanZhi: this.calculateHourGanZhi( solarDate.hour, response.data.data.day_ganzhi, ), solarTerms: response.data.data.solar_terms, zodiac: response.data.data.zodiac, constellation: response.data.data.constellation, }; } throw new Error("API返回数据格式错误"); } /** * 获取专业星曜定位数据 */ async getProfessionalStarPositions(lunarInfo, gender) { try { // 尝试从专业紫微斗数API获取 const apiResult = await this.fetchStarPositionsFromApi(lunarInfo, gender); if (apiResult) { return apiResult; } } catch (error) { console.warn("专业星曜API调用失败,使用本地数据:", error.message); } // 降级到本地专业数据 return this.calculateStarPositionsLocal(lunarInfo, gender); } /** * 从专业API获取星曜定位 */ async fetchStarPositionsFromApi(lunarInfo, gender) { const url = `${DATA_SOURCES.ZIWEI_PRO_API.baseUrl}${DATA_SOURCES.ZIWEI_PRO_API.endpoints.starPositions}`; const response = await axios.post( url, { lunar_year: lunarInfo.year, lunar_month: lunarInfo.month, lunar_day: lunarInfo.day, lunar_hour: lunarInfo.hour, gender: gender, year_ganzhi: lunarInfo.yearInGanZhi, month_ganzhi: lunarInfo.monthInGanZhi, day_ganzhi: lunarInfo.dayInGanZhi, hour_ganzhi: lunarInfo.hourInGanZhi, }, { headers: { Authorization: `Bearer ${DATA_SOURCES.ZIWEI_PRO_API.apiKey}`, "Content-Type": "application/json", }, timeout: 10000, }, ); if (response.data && response.data.success) { return { mainStars: response.data.data.main_stars, auxiliaryStars: response.data.data.auxiliary_stars, maleficStars: response.data.data.malefic_stars, brightness: response.data.data.brightness, sihua: response.data.data.sihua, accuracy: "professional_api", }; } throw new Error("专业API返回数据格式错误"); } /** * 获取专业格局分析 */ async getProfessionalPatternAnalysis(chart) { try { // 尝试从专业API获取格局分析 const apiResult = await this.fetchPatternAnalysisFromApi(chart); if (apiResult) { return apiResult; } } catch (error) { console.warn("专业格局API调用失败,使用本地分析:", error.message); } // 降级到本地专业分析 return this.analyzePatternLocal(chart); } /** * 从专业API获取格局分析 */ async fetchPatternAnalysisFromApi(chart) { const url = `${DATA_SOURCES.ZIWEI_PRO_API.baseUrl}${DATA_SOURCES.ZIWEI_PRO_API.endpoints.patterns}`; const response = await axios.post( url, { palaces: chart.palaces, destiny_palace: chart.info.destinyPalace, body_palace: chart.info.bodyPalace, sihua: chart.sihua, lunar_info: chart.lunarInfo, }, { headers: { Authorization: `Bearer ${DATA_SOURCES.ZIWEI_PRO_API.apiKey}`, "Content-Type": "application/json", }, timeout: 15000, }, ); if (response.data && response.data.success) { return { patterns: response.data.data.patterns, strength_analysis: response.data.data.strength_analysis, life_phases: response.data.data.life_phases, recommendations: response.data.data.recommendations, accuracy: "professional_api", }; } throw new Error("专业格局API返回数据格式错误"); } /** * 获取专业解释文本 */ async getProfessionalInterpretations(chart, analysisType = "comprehensive") { try { // 尝试从专业API获取解释 const apiResult = await this.fetchInterpretationsFromApi( chart, analysisType, ); if (apiResult) { return apiResult; } } catch (error) { console.warn("专业解释API调用失败,使用本地数据:", error.message); } // 降级到本地专业解释 return this.generateInterpretationsLocal(chart, analysisType); } /** * 从专业API获取解释文本 */ async fetchInterpretationsFromApi(chart, analysisType) { const url = `${DATA_SOURCES.ZIWEI_PRO_API.baseUrl}${DATA_SOURCES.ZIWEI_PRO_API.endpoints.interpretations}`; const response = await axios.post( url, { chart: chart, analysis_type: analysisType, detail_level: "professional", language: "zh-CN", }, { headers: { Authorization: `Bearer ${DATA_SOURCES.ZIWEI_PRO_API.apiKey}`, "Content-Type": "application/json", }, timeout: 20000, }, ); if (response.data && response.data.success) { return { personality: response.data.data.personality, career: response.data.data.career, wealth: response.data.data.wealth, relationships: response.data.data.relationships, health: response.data.data.health, fortune: response.data.data.fortune, recommendations: response.data.data.recommendations, accuracy: "professional_api", }; } throw new Error("专业解释API返回数据格式错误"); } /** * 加载本地专业数据 */ async loadLocalProfessionalData(dataType) { const filePath = DATA_SOURCES.LOCAL_DATABASE[dataType]; if (!filePath) { throw new Error(`未知的数据类型: ${dataType}`); } try { const data = await fs.readFile(filePath, "utf8"); return JSON.parse(data); } catch (error) { console.warn(`加载本地专业数据失败: ${filePath}`, error.message); return null; } } /** * 本地农历计算(降级方案) */ calculateLunarLocal(solarDate) { // 这里使用现有的lunar-javascript库作为降级方案 const { CalendarConverter } = require("../core/calendar.js"); return CalendarConverter.solarToLunar(solarDate); } /** * 本地星曜定位计算(降级方案) */ async calculateStarPositionsLocal(lunarInfo, gender) { // 使用增强版算法 const { EnhancedChartGenerator, } = require("../core/enhanced-chart-generator.js"); const generator = new EnhancedChartGenerator(); // 这里可以调用增强版的星曜定位算法 const palaces = generator.calculatePalacesEnhanced(lunarInfo, gender); generator.placeStarsEnhanced(palaces, lunarInfo); return { palaces: palaces, accuracy: "enhanced_local", }; } /** * 本地格局分析(降级方案) */ async analyzePatternLocal(chart) { const professionalPatterns = await this.loadLocalProfessionalData("patternsData"); if (professionalPatterns) { // 使用专业格局数据进行分析 return this.analyzeWithProfessionalPatterns(chart, professionalPatterns); } // 使用基础格局分析 const { EnhancedChartGenerator, } = require("../core/enhanced-chart-generator.js"); const generator = new EnhancedChartGenerator(); const destinyPalace = chart.palaces.find( (p) => p.id === chart.info.destinyPalace, ); const bodyPalace = chart.palaces.find( (p) => p.id === chart.info.bodyPalace, ); return { patterns: generator.recognizePatterns( chart.palaces, destinyPalace, bodyPalace, ), accuracy: "enhanced_local", }; } /** * 本地专业解释生成(降级方案) */ async generateInterpretationsLocal(chart, analysisType) { const interpretationsData = await this.loadLocalProfessionalData( "interpretationsData", ); if (interpretationsData) { return this.generateWithProfessionalData( chart, interpretationsData, analysisType, ); } // 使用基础解释生成 return this.generateBasicInterpretations(chart, analysisType); } /** * 使用专业格局数据进行分析 */ analyzeWithProfessionalPatterns(chart, professionalPatterns) { const patterns = []; const destinyPalace = chart.palaces.find( (p) => p.id === chart.info.destinyPalace, ); const destinyStars = destinyPalace.stars.map((s) => s.name); // 遍历专业格局数据 for (const [patternName, patternData] of Object.entries( professionalPatterns, )) { if ( this.checkProfessionalPattern(patternData, chart.palaces, destinyStars) ) { patterns.push({ name: patternName, type: patternData.type, strength: patternData.strength, description: patternData.description, influence: patternData.influence, professional_notes: patternData.professional_notes, accuracy: "professional_local", }); } } return { patterns: patterns, strength_analysis: this.analyzeOverallStrength(patterns), accuracy: "professional_local", }; } /** * 检查专业格局是否成立 */ checkProfessionalPattern(patternData, palaces, destinyStars) { // 实现更复杂的格局检查逻辑 const conditions = patternData.conditions || []; return conditions.every((condition) => { switch (condition.type) { case "stars_in_palace": return this.checkStarsInPalace(condition, palaces); case "stars_brightness": return this.checkStarsBrightness(condition, palaces); case "sihua_combination": return this.checkSihuaCombination(condition, palaces); case "palace_relationship": return this.checkPalaceRelationship(condition, palaces); default: return false; } }); } /** * 计算时辰干支 */ calculateHourGanZhi(hour, dayGanZhi) { const hourIndex = Math.floor(hour / 2); const dayGanIndex = "甲乙丙丁戊己庚辛壬癸".indexOf(dayGanZhi[0]); // 时干计算公式:日干 * 2 + 时支序号 const hourGanIndex = (dayGanIndex * 2 + hourIndex) % 10; const hourGan = "甲乙丙丁戊己庚辛壬癸"[hourGanIndex]; const hourZhi = "子丑寅卯辰巳午未申酉戌亥"[hourIndex]; return hourGan + hourZhi; } /** * 数据源健康检查 */ async healthCheck() { const results = { zhwnl_api: false, ziwei_pro_api: false, local_database: false, timestamp: new Date().toISOString(), }; // 检查中华万年历API try { const response = await axios.get( `${DATA_SOURCES.ZHWNL_API.baseUrl}/health`, { timeout: 3000, }, ); results.zhwnl_api = response.status === 200; } catch (error) { console.warn("中华万年历API健康检查失败:", error.message); } // 检查紫微斗数专业API try { const response = await axios.get( `${DATA_SOURCES.ZIWEI_PRO_API.baseUrl}/health`, { headers: { Authorization: `Bearer ${DATA_SOURCES.ZIWEI_PRO_API.apiKey}`, }, timeout: 3000, }, ); results.ziwei_pro_api = response.status === 200; } catch (error) { console.warn("紫微斗数专业API健康检查失败:", error.message); } // 检查本地数据库 try { const starsDataExists = await fs .access(DATA_SOURCES.LOCAL_DATABASE.starsData) .then(() => true) .catch(() => false); const patternsDataExists = await fs .access(DATA_SOURCES.LOCAL_DATABASE.patternsData) .then(() => true) .catch(() => false); results.local_database = starsDataExists && patternsDataExists; } catch (error) { console.warn("本地数据库健康检查失败:", error.message); } return results; } /** * 获取数据源统计信息 */ getDataSourceStats() { return { cache_size: this.cache.size, cache_timeout: this.cacheTimeout, available_sources: Object.keys(DATA_SOURCES), last_health_check: this.lastHealthCheck || null, }; } /** * 清理缓存 */ clearCache() { this.cache.clear(); console.log("数据源缓存已清理"); } // 辅助方法 checkStarsInPalace(condition, palaces) { // 实现星曜在宫位的检查逻辑 return true; // 简化实现 } checkStarsBrightness(condition, palaces) { // 实现星曜亮度的检查逻辑 return true; // 简化实现 } checkSihuaCombination(condition, palaces) { // 实现四化组合的检查逻辑 return true; // 简化实现 } checkPalaceRelationship(condition, palaces) { // 实现宫位关系的检查逻辑 return true; // 简化实现 } analyzeOverallStrength(patterns) { // 分析整体格局强度 const excellentCount = patterns.filter( (p) => p.strength === "excellent", ).length; const goodCount = patterns.filter((p) => p.strength === "good").length; const averageCount = patterns.filter( (p) => p.strength === "average", ).length; const poorCount = patterns.filter((p) => p.strength === "poor").length; let overallStrength = "average"; let score = 60; if (excellentCount >= 2) { overallStrength = "excellent"; score = 90 + excellentCount * 5; } else if (excellentCount >= 1 || goodCount >= 3) { overallStrength = "good"; score = 75 + excellentCount * 10 + goodCount * 5; } else if (poorCount >= 2) { overallStrength = "poor"; score = 40 - poorCount * 5; } return { overall_strength: overallStrength, score: Math.max(0, Math.min(100, score)), pattern_counts: { excellent: excellentCount, good: goodCount, average: averageCount, poor: poorCount, }, }; } generateBasicInterpretations(chart, analysisType) { // 基础解释生成逻辑 return { personality: "基于命盘星曜的基础性格分析", career: "基于官禄宫的基础事业分析", wealth: "基于财帛宫的基础财运分析", relationships: "基于夫妻宫的基础感情分析", health: "基于疾厄宫的基础健康分析", accuracy: "basic_local", }; } generateWithProfessionalData(chart, interpretationsData, analysisType) { // 使用专业数据生成解释 const destinyPalace = chart.palaces.find( (p) => p.id === chart.info.destinyPalace, ); const mainStar = destinyPalace.stars.find((s) => s.type === "main"); if (mainStar && interpretationsData[mainStar.name]) { const starData = interpretationsData[mainStar.name]; return { personality: starData.personality || "专业性格分析", career: starData.career || "专业事业分析", wealth: starData.wealth || "专业财运分析", relationships: starData.relationships || "专业感情分析", health: starData.health || "专业健康分析", accuracy: "professional_local", }; } return this.generateBasicInterpretations(chart, analysisType); } } module.exports = { ProfessionalDataService, DATA_SOURCES, };