146 lines
5.1 KiB
TypeScript
146 lines
5.1 KiB
TypeScript
import { calculateHua, HuaInput } from './analysis.js';
|
||
|
||
// CLI 入口
|
||
const args = process.argv.slice(2);
|
||
function getArg(name: string): string | undefined {
|
||
const found = args.find(a => a.startsWith(`--${name}=`));
|
||
return found ? found.split('=')[1] : undefined;
|
||
}
|
||
|
||
const method = (getArg('method') || 'time') as 'number' | 'time' | 'observation';
|
||
const question = getArg('question') || undefined;
|
||
const numbersStr = getArg('numbers');
|
||
const observation = getArg('observation') || undefined;
|
||
const trigramsStr = getArg('trigrams');
|
||
const outputFormat = getArg('output') || 'json'; // json | text
|
||
|
||
const input: HuaInput = { method, question };
|
||
|
||
if (method === 'number' && numbersStr) {
|
||
input.numbers = numbersStr.split(',').map(Number);
|
||
} else if (method === 'observation') {
|
||
input.observation = observation;
|
||
if (trigramsStr) {
|
||
input.observedTrigrams = trigramsStr.split(',').map(Number);
|
||
}
|
||
}
|
||
|
||
try {
|
||
const result = calculateHua(input);
|
||
|
||
if (outputFormat === 'text') {
|
||
// 文本输出(供 LLM 阅读)
|
||
console.log(formatAsText(result));
|
||
} else {
|
||
console.log(JSON.stringify(result, null, 2));
|
||
}
|
||
} catch (e: any) {
|
||
console.error('排盘错误:', e.message);
|
||
process.exit(1);
|
||
}
|
||
|
||
function formatAsText(r: ReturnType<typeof calculateHua>): string {
|
||
const main = r.mainHexagram;
|
||
const changed = r.changedHexagram;
|
||
const mutual = r.mutualHexagram;
|
||
const ti = r.tiGua;
|
||
const yong = r.yongGua;
|
||
|
||
let text = `═══════════════════════════════════
|
||
梅花易数 排盘结果
|
||
═══════════════════════════════════
|
||
|
||
【起卦方式】${r.meta.method === 'number' ? '数字起卦' : r.meta.method === 'time' ? '时间起卦' : '梅花心易(外应)'}
|
||
${r.meta.question ? `【问事】${r.meta.question}` : ''}
|
||
【起卦时间】${r.meta.timestamp}
|
||
|
||
───────────────────────────────────
|
||
主 卦
|
||
───────────────────────────────────
|
||
${main.hexagram.fullName} (${main.hexagram.symbol})
|
||
上卦:${main.upper.name}(${main.upper.element}) 下卦:${main.lower.name}(${main.lower.element})
|
||
卦辞:${main.hexagram.judgment}
|
||
象辞:${main.hexagram.image}
|
||
吉凶:${main.hexagram.nature}
|
||
|
||
───────────────────────────────────
|
||
体 用 分 析
|
||
───────────────────────────────────
|
||
动爻:第${r.dongYao}爻
|
||
体卦:${ti.trigram.name}(${ti.trigram.element}) — ${ti.position === 'upper' ? '上卦' : '下卦'}(不动之卦)
|
||
用卦:${yong.trigram.name}(${yong.trigram.element}) — ${yong.position === 'upper' ? '上卦' : '下卦'}(动爻所在)
|
||
五行关系:${r.wuxingAnalysis.relation}
|
||
判定:${r.wuxingAnalysis.verdict}
|
||
|
||
───────────────────────────────────
|
||
旺 衰
|
||
───────────────────────────────────
|
||
${r.wangShuai.analysis}
|
||
|
||
───────────────────────────────────
|
||
变 卦(趋势走向)
|
||
───────────────────────────────────
|
||
${changed.fullName} (${changed.symbol})
|
||
卦辞:${changed.judgment}
|
||
象辞:${changed.image}
|
||
|
||
───────────────────────────────────
|
||
互 卦(内在因素)
|
||
───────────────────────────────────
|
||
${mutual.fullName} (${mutual.symbol})
|
||
卦辞:${mutual.judgment}
|
||
`;
|
||
|
||
// 证据链摘要
|
||
if (r.evidence) {
|
||
const ev = r.evidence;
|
||
text += `
|
||
───────────────────────────────────
|
||
证 据 链
|
||
───────────────────────────────────
|
||
`;
|
||
// 阶段体用
|
||
for (const s of ev.stages) {
|
||
text += `【${s.label}】${s.hexagramName}:体${s.ti.name}${s.ti.element}(${s.ti.seasonState})vs 用${s.yong.name}${s.yong.element}(${s.yong.seasonState})→ ${s.relation}
|
||
`;
|
||
}
|
||
// 推进
|
||
if (ev.transitionFacts.length > 0) {
|
||
text += `
|
||
【阶段推进】
|
||
`;
|
||
for (const t of ev.transitionFacts) {
|
||
text += ` ${t.promptText}
|
||
`;
|
||
}
|
||
}
|
||
// 反证
|
||
text += `
|
||
【反证】${ev.counterSummary.detail}
|
||
`;
|
||
// 应期
|
||
if (ev.timingFacts.length > 0) {
|
||
text += `
|
||
【应期参考】
|
||
`;
|
||
for (const t of ev.timingFacts) {
|
||
text += ` ${t.promptText}
|
||
`;
|
||
}
|
||
}
|
||
// 传统文本(仅动爻爻辞)
|
||
const movingYaoFacts = ev.traditionalFacts.filter(f => f.applicability === '当前动爻辅助');
|
||
if (movingYaoFacts.length > 0) {
|
||
text += `
|
||
【动爻爻辞】
|
||
`;
|
||
for (const f of movingYaoFacts) {
|
||
text += ` ${f.originalText}
|
||
`;
|
||
}
|
||
}
|
||
}
|
||
|
||
return text;
|
||
}
|