ziwei-mcp
Version:
紫微斗数 MCP (Ziwei Doushu Model Context Protocol) - 基于 MCP 协议的紫微斗数命理分析工具
618 lines (556 loc) • 14.8 kB
JavaScript
/**
* 增强版图表可视化工具
* 集成模板化SVG生成器,支持多种图表类型和自定义主题
*/
const { z } = require("zod");
const { EnhancedSVGGenerator } = require("../core/enhanced-svg-generator.js");
/**
* 输入参数验证模式
*/
const VisualizeChartSchema = z.object({
chartId: z.string().min(1, "命盘ID不能为空"),
type: z
.enum([
"traditional_chart",
"modern_wheel",
"grid_layout",
"star_relationship",
"fortune_timeline",
"compatibility_radar",
])
.default("traditional_chart")
.describe("图表类型"),
theme: z
.enum(["classic", "dark", "chinese", "minimal"])
.optional()
.describe("主题样式"),
width: z.number().min(200).max(2000).optional().describe("图表宽度"),
height: z.number().min(200).max(2000).optional().describe("图表高度"),
animations: z.boolean().default(false).describe("是否启用动画"),
interactive: z.boolean().default(false).describe("是否启用交互"),
exportFormat: z
.enum(["svg", "png", "pdf"])
.default("svg")
.describe("导出格式"),
quality: z
.enum(["draft", "standard", "high"])
.default("standard")
.describe("图表质量"),
customOptions: z
.object({
showStarNames: z.boolean().default(true),
showPalaceNames: z.boolean().default(true),
showBrightness: z.boolean().default(true),
showSihua: z.boolean().default(true),
showPatterns: z.boolean().default(false),
fontSize: z.number().min(8).max(24).default(12),
colorScheme: z.string().optional(),
})
.optional(),
});
class EnhancedChartVisualizerTool {
constructor() {
this.name = "visualize_enhanced_chart";
this.description = "生成增强版紫微斗数图表可视化,支持多种类型和主题";
this.inputSchema = VisualizeChartSchema;
this.svgGenerator = new EnhancedSVGGenerator();
this.charts = new Map(); // 存储命盘数据
// 性能统计
this.stats = {
totalGenerated: 0,
byType: {},
byTheme: {},
averageTime: 0,
errors: 0,
};
}
/**
* 执行图表可视化
*/
async execute(input) {
const startTime = Date.now();
try {
// 验证输入参数
const validatedInput = this.inputSchema.parse(input);
console.log(
`开始生成图表: ${validatedInput.chartId} (${validatedInput.type})`,
);
// 获取命盘数据
const chartData = await this.getChartData(validatedInput.chartId);
if (!chartData) {
throw new Error(`找不到命盘数据: ${validatedInput.chartId}`);
}
// 准备生成选项
const options = this.prepareGenerationOptions(validatedInput);
// 生成SVG图表
const result = await this.svgGenerator.generateChart(chartData, options);
if (!result.success) {
throw new Error(`图表生成失败: ${result.error}`);
}
// 后处理
const processedResult = await this.postProcessChart(
result,
validatedInput,
);
// 更新统计信息
const executionTime = Date.now() - startTime;
this.updateStats(
validatedInput.type,
validatedInput.theme,
executionTime,
);
console.log(`图表生成完成,耗时: ${executionTime}ms`);
return {
success: true,
data: {
chartId: validatedInput.chartId,
visualization: processedResult,
metadata: {
...result.metadata,
executionTime: executionTime,
quality: validatedInput.quality,
exportFormat: validatedInput.exportFormat,
},
},
};
} catch (error) {
this.stats.errors++;
console.error("图表可视化失败:", error);
return {
success: false,
error: error.message,
errorType: error.name,
timestamp: new Date().toISOString(),
};
}
}
/**
* 准备生成选项
*/
prepareGenerationOptions(input) {
const options = {
type: input.type,
theme: input.theme,
width: input.width,
height: input.height,
animations: input.animations,
interactive: input.interactive,
quality: input.quality,
};
// 添加自定义选项
if (input.customOptions) {
options.customOptions = input.customOptions;
}
// 根据质量调整参数
switch (input.quality) {
case "draft":
options.simplify = true;
options.reducedDetails = true;
break;
case "high":
options.enhancedDetails = true;
options.antiAliasing = true;
break;
default:
// standard quality
break;
}
return options;
}
/**
* 获取命盘数据
*/
async getChartData(chartId) {
// 首先从内存缓存中查找
if (this.charts.has(chartId)) {
return this.charts.get(chartId);
}
// 模拟从数据库或其他存储中获取
// 实际应用中这里应该连接到真实的数据源
const mockChartData = this.generateMockChartData(chartId);
// 缓存数据
this.charts.set(chartId, mockChartData);
return mockChartData;
}
/**
* 生成模拟命盘数据
*/
generateMockChartData(chartId) {
return {
id: chartId,
info: {
name: "示例用户",
gender: "male",
birthDate: "1990-05-15",
birthTime: "14:30",
age: 33,
destinyPalace: "destiny",
bodyPalace: "wealth",
},
palaces: [
{
id: "destiny",
name: "命宫",
position: { angle: 0, radius: 200 },
stars: [
{
name: "紫微",
type: "main",
brightness: "庙",
sihua: null,
element: "earth",
},
{
name: "天府",
type: "main",
brightness: "旺",
sihua: null,
element: "earth",
},
{
name: "左辅",
type: "auxiliary",
brightness: "平",
sihua: null,
element: "earth",
},
],
earthlyBranch: "子",
heavenlyStem: "甲",
},
{
id: "siblings",
name: "兄弟",
position: { angle: 30, radius: 200 },
stars: [
{
name: "太阳",
type: "main",
brightness: "旺",
sihua: "化禄",
element: "fire",
},
{
name: "太阴",
type: "main",
brightness: "陷",
sihua: null,
element: "water",
},
],
earthlyBranch: "丑",
heavenlyStem: "乙",
},
// 其他宫位...
],
sihua: {
化禄: { star: "太阳", palace: "siblings" },
化权: { star: "武曲", palace: "wealth" },
化科: { star: "天机", palace: "career" },
化忌: { star: "廉贞", palace: "health" },
},
patterns: [
{
name: "紫府同宫",
type: "excellent",
strength: "excellent",
influence: "positive",
description: "紫微天府同宫,主贵显,有领导才能",
},
],
metadata: {
generatedAt: new Date().toISOString(),
algorithm: "enhanced",
accuracy: "high",
},
};
}
/**
* 后处理图表
*/
async postProcessChart(result, input) {
let processedSvg = result.svg;
// 根据质量设置进行优化
if (input.quality === "high") {
processedSvg = this.enhanceQuality(processedSvg);
} else if (input.quality === "draft") {
processedSvg = this.simplifyForDraft(processedSvg);
}
// 添加水印或版权信息
processedSvg = this.addWatermark(processedSvg);
// 格式转换
const finalResult = {
svg: processedSvg,
metadata: result.metadata,
};
// 如果需要其他格式
if (input.exportFormat !== "svg") {
finalResult.converted = await this.convertFormat(
processedSvg,
input.exportFormat,
);
}
return finalResult;
}
/**
* 增强图表质量
*/
enhanceQuality(svg) {
// 添加抗锯齿
svg = svg.replace("<svg", '<svg shape-rendering="geometricPrecision"');
// 增强文字渲染
svg = svg.replace(/<text/g, '<text text-rendering="optimizeLegibility"');
// 添加更多细节
return svg;
}
/**
* 简化草稿模式
*/
simplifyForDraft(svg) {
// 移除复杂的渐变和滤镜
svg = svg.replace(/filter="[^"]*"/g, "");
svg = svg.replace(/url\(#[^)]*\)/g, "none");
return svg;
}
/**
* 添加水印
*/
addWatermark(svg) {
const watermark = `
<text x="10" y="20" font-size="10" fill="rgba(0,0,0,0.3)" font-family="Arial">
Generated by Enhanced Ziwei Chart Visualizer
</text>
`;
return svg.replace("</svg>", watermark + "</svg>");
}
/**
* 格式转换
*/
async convertFormat(svg, format) {
switch (format) {
case "png":
return await this.convertToPNG(svg);
case "pdf":
return await this.convertToPDF(svg);
default:
return null;
}
}
/**
* 转换为PNG(模拟实现)
*/
async convertToPNG(svg) {
// 实际应用中需要使用如 puppeteer 或 sharp 等库
return {
format: "png",
data: "base64_encoded_png_data",
size: { width: 800, height: 600 },
};
}
/**
* 转换为PDF(模拟实现)
*/
async convertToPDF(svg) {
// 实际应用中需要使用如 puppeteer 或 jsPDF 等库
return {
format: "pdf",
data: "base64_encoded_pdf_data",
pages: 1,
};
}
/**
* 批量生成图表
*/
async generateBatch(requests) {
const results = [];
const errors = [];
for (const request of requests) {
try {
const result = await this.execute(request);
results.push({
chartId: request.chartId,
success: result.success,
data: result.data,
});
} catch (error) {
errors.push({
chartId: request.chartId,
error: error.message,
});
}
}
return {
success: errors.length === 0,
results: results,
errors: errors,
summary: {
total: requests.length,
successful: results.length,
failed: errors.length,
},
};
}
/**
* 获取可用的图表类型
*/
getAvailableChartTypes() {
return [
{
id: "traditional_chart",
name: "传统命盘",
description: "经典的圆形命盘布局,适合传统解读",
features: ["宫位分布", "星曜显示", "四化标记"],
recommendedThemes: ["chinese", "classic"],
},
{
id: "modern_wheel",
name: "现代轮盘",
description: "现代化的轮盘设计,视觉效果更佳",
features: ["扇形宫位", "渐变效果", "动态布局"],
recommendedThemes: ["classic", "dark"],
},
{
id: "grid_layout",
name: "网格布局",
description: "网格式布局,便于详细信息展示",
features: ["清晰布局", "详细信息", "易于阅读"],
recommendedThemes: ["minimal", "classic"],
},
{
id: "star_relationship",
name: "星曜关系图",
description: "展示星曜之间的相互关系",
features: ["关系连线", "影响强度", "互动效果"],
recommendedThemes: ["dark", "minimal"],
},
{
id: "fortune_timeline",
name: "运势时间线",
description: "时间轴形式展示运势变化",
features: ["时间轴", "趋势显示", "关键节点"],
recommendedThemes: ["classic", "minimal"],
},
{
id: "compatibility_radar",
name: "合婚雷达图",
description: "雷达图形式展示合婚匹配度",
features: ["多维度", "直观对比", "匹配度"],
recommendedThemes: ["minimal", "classic"],
},
];
}
/**
* 获取可用主题
*/
getAvailableThemes() {
return [
{
id: "classic",
name: "经典",
description: "经典蓝白配色,适合正式场合",
preview: "#3498db",
},
{
id: "dark",
name: "暗色",
description: "深色主题,护眼且现代",
preview: "#1a1a1a",
},
{
id: "chinese",
name: "中国风",
description: "传统中式配色,古典雅致",
preview: "#dc143c",
},
{
id: "minimal",
name: "简约",
description: "简洁明了,突出内容",
preview: "#ffffff",
},
];
}
/**
* 预览图表
*/
async previewChart(chartId, type, theme) {
const previewOptions = {
chartId: chartId,
type: type,
theme: theme,
width: 400,
height: 300,
quality: "draft",
};
return await this.execute(previewOptions);
}
/**
* 更新统计信息
*/
updateStats(type, theme, executionTime) {
this.stats.totalGenerated++;
// 按类型统计
if (!this.stats.byType[type]) {
this.stats.byType[type] = 0;
}
this.stats.byType[type]++;
// 按主题统计
if (theme) {
if (!this.stats.byTheme[theme]) {
this.stats.byTheme[theme] = 0;
}
this.stats.byTheme[theme]++;
}
// 平均时间
this.stats.averageTime =
(this.stats.averageTime * (this.stats.totalGenerated - 1) +
executionTime) /
this.stats.totalGenerated;
}
/**
* 获取统计信息
*/
getStats() {
return {
...this.stats,
popularType: this.getMostPopular(this.stats.byType),
popularTheme: this.getMostPopular(this.stats.byTheme),
};
}
/**
* 获取最受欢迎的选项
*/
getMostPopular(stats) {
let maxCount = 0;
let mostPopular = null;
for (const [key, count] of Object.entries(stats)) {
if (count > maxCount) {
maxCount = count;
mostPopular = key;
}
}
return mostPopular;
}
/**
* 清理缓存
*/
clearCache() {
this.charts.clear();
console.log("图表缓存已清理");
}
/**
* 设置命盘数据
*/
setChartData(chartId, chartData) {
this.charts.set(chartId, chartData);
}
/**
* 删除命盘数据
*/
removeChartData(chartId) {
return this.charts.delete(chartId);
}
}
module.exports = {
EnhancedChartVisualizerTool,
};