import { PalaceType, StarNature, EarthlyBranch } from './enums' import { determineLuckLevel } from './ziweiAlgorithm' import { generateDailyFortune, generateMonthlyFortune, generateYearlyFortune, calculateDailyAdjustment, calculateMonthlyAdjustment, calculateYearlyAdjustment, } from './fortuneStrategy' import type { ZiweiChart, Palace, LoveFortuneDetail, StudyFortuneDetail, SocialFortuneDetail, TravelFortuneDetail, DailyFortune, MonthlyFortune, YearlyFortune, } from './types' const PEACH_BLOSSOM_STARS = ['HONGLUAN', 'TIANXI', 'TANLANG'] const STUDY_STARS = ['WENCHANG', 'WENQU'] const NOBLE_STARS = ['ZUOFU', 'YOUBI', 'TIANKUI', 'TIANYUE'] const TRAVEL_STARS = ['TIANMA'] const DATING_TIME_MAP: Record = { '大吉': '下午3点至5点,傍晚6点至8点', '吉': '下午2点至4点,晚上7点至9点', '中吉': '上午10点至12点,下午3点至5点', '平': '下午1点至3点', '中平': '上午9点至11点', '小凶': '暂不宜约会,宜先调整自身状态', '凶': '不宜约会,宜静待时机', } const STUDY_TIME_MAP: Record = { '大吉': '清晨6点至8点,晚上8点至10点', '吉': '上午8点至10点,晚上7点至9点', '中吉': '上午9点至11点,下午3点至5点', '平': '上午10点至12点', '中平': '下午2点至4点', '小凶': '学习效率较低,建议短暂休息后复习', '凶': '不宜高强度学习,宜轻松阅读', } const SOCIAL_TIME_MAP: Record = { '大吉': '中午12点至2点,晚上6点至9点', '吉': '下午1点至3点,晚上7点至10点', '中吉': '上午10点至12点,下午3点至5点', '平': '下午2点至4点', '中平': '上午9点至11点', '小凶': '社交运势偏弱,宜减少应酬', '凶': '不宜社交,宜独处调整', } const TRAVEL_TIME_MAP: Record = { '大吉': '上午8点至10点出发最佳', '吉': '上午9点至11点出发较佳', '中吉': '上午10点至12点可出行', '平': '中午前后出行即可', '中平': '下午出行较为稳妥', '小凶': '出行需谨慎,注意安全', '凶': '不宜远行,近处活动为佳', } const SUITABLE_SUBJECTS_MAP: Record = { '大吉': '文学、哲学、历史等文科类,或管理、领导力相关', '吉': '语言、艺术、社会科学等,或技术类基础学科', '中吉': '数学、逻辑、计算机等理科类', '平': '实用技能、职业培训等应用型学科', '中平': '通识类课程,宜广泛涉猎', '小凶': '宜复习巩固已有知识,不宜开启新领域', '凶': '宜休息调整,轻松阅读即可', } const SUITABLE_OCCASION_MAP: Record = { '大吉': '商务宴请、高端社交、行业峰会', '吉': '朋友聚会、团队活动、文化交流', '中吉': '社区活动、兴趣小组、学习交流', '平': '日常社交、同事聚餐', '中平': '小范围聚会、线上交流', '小凶': '减少社交活动,宜小范围相处', '凶': '不宜参加社交活动,宜独处', } const SUITABLE_TRANSPORT_MAP: Record = { '大吉': '飞机、高铁等快速交通工具', '吉': '高铁、自驾等舒适出行方式', '中吉': '火车、大巴等常规交通', '平': '公共交通、地铁等日常出行', '中平': '短途公交、步行等', '小凶': '出行需注意安全,避免自驾', '凶': '不宜远行,就近活动为佳', } const DIRECTION_LIST = ['东方', '南方', '西方', '北方', '东南', '西南', '东北', '西北'] function findPalace(chart: ZiweiChart, palaceType: PalaceType): Palace | undefined { return chart.palaces.find(p => p.palaceType === palaceType) } function countMinorStars(palace: Palace | undefined, starNames: string[]): number { if (palace == null) return 0 let count = 0 for (const star of starNames) { if (palace.minorStars.includes(star)) count++ } return count } function countMajorStars(palace: Palace | undefined, starNames: string[]): number { if (palace == null) return 0 let count = 0 for (const starInfo of palace.majorStars) { if (starNames.includes(starInfo.star)) count++ } return count } function clampScore(score: number): number { return Math.max(0, Math.min(100, Math.floor(score))) } export function analyzeLoveFortune(chart: ZiweiChart, date: Date): LoveFortuneDetail { const fuqiPalace = findPalace(chart, PalaceType.FUQI) const baseScore = fuqiPalace?.score ?? 50 const peachBlossomCount = countMinorStars(fuqiPalace, PEACH_BLOSSOM_STARS) + countMajorStars(fuqiPalace, PEACH_BLOSSOM_STARS) const peachBonus = peachBlossomCount * 5 const dayAdj = fuqiPalace ? calculateDailyAdjustment(fuqiPalace, date) : 0 const loveScore = clampScore(baseScore + peachBonus + dayAdj) const luckLevel = determineLuckLevel(loveScore) const peachBlossomIndex = getPeachBlossomLevel(peachBlossomCount) return { loveScore, overallLoveLuck: luckLevel, peachBlossomIndex, singleAdvice: getSingleAdvice(luckLevel, peachBlossomCount), datingAdvice: getDatingAdvice(luckLevel), marriageAdvice: getMarriageAdvice(luckLevel), bestDatingTime: DATING_TIME_MAP[luckLevel] ?? '下午2点至4点', } } function getPeachBlossomLevel(count: number): string { if (count >= 3) return '极旺' if (count >= 2) return '旺盛' if (count >= 1) return '一般' return '偏弱' } function getSingleAdvice(luckLevel: string, peachCount: number): string { if (peachCount >= 2) return '桃花旺盛,有望遇到心仪对象,可主动出击' if (luckLevel === '大吉' || luckLevel === '吉') return '感情运势良好,可多参加社交活动,增加遇见良缘的机会' if (luckLevel === '中吉' || luckLevel === '平') return '感情运势平稳,宜耐心等待,不宜急于求成' return '感情运势偏弱,宜先提升自我,静待良缘' } function getDatingAdvice(luckLevel: string): string { if (luckLevel === '大吉' || luckLevel === '吉') return '感情甜蜜,适合深入交流,增进彼此了解' if (luckLevel === '中吉' || luckLevel === '平') return '感情平稳,保持日常沟通,多关心对方需求' if (luckLevel === '中平') return '感情略显平淡,可制造小惊喜,增添情趣' return '感情易生波折,需多包容理解,避免争执' } function getMarriageAdvice(luckLevel: string): string { if (luckLevel === '大吉' || luckLevel === '吉') return '婚姻运势良好,适合商讨婚事或增进夫妻感情' if (luckLevel === '中吉' || luckLevel === '平') return '婚姻运势平稳,宜相互扶持,共同经营家庭' if (luckLevel === '中平') return '婚姻运势一般,需多沟通协调,避免误解' return '婚姻运势欠佳,需多忍让包容,共同面对困难' } export function analyzeStudyFortune(chart: ZiweiChart, date: Date): StudyFortuneDetail { const guanluPalace = findPalace(chart, PalaceType.GUANLU) const baseScore = guanluPalace?.score ?? 50 const studyStarCount = countMinorStars(guanluPalace, STUDY_STARS) const studyBonus = studyStarCount * 6 const dayAdj = guanluPalace ? calculateDailyAdjustment(guanluPalace, date) : 0 const studyScore = clampScore(baseScore + studyBonus + dayAdj) const luckLevel = determineLuckLevel(studyScore) return { studyScore, overallStudyLuck: luckLevel, focusIndex: getFocusLevel(studyScore), memoryIndex: getMemoryLevel(studyScore), studyAdvice: getStudyAdvice(luckLevel, studyStarCount), examLuck: getExamLuck(luckLevel), bestStudyTime: STUDY_TIME_MAP[luckLevel] ?? '上午9点至11点', suitableSubjects: SUITABLE_SUBJECTS_MAP[luckLevel] ?? '通识类课程', studyEnvironmentAdvice: getStudyEnvironmentAdvice(luckLevel), } } function getFocusLevel(score: number): string { if (score >= 80) return '高度集中' if (score >= 60) return '较为集中' if (score >= 40) return '一般' return '容易分心' } function getMemoryLevel(score: number): string { if (score >= 80) return '记忆力佳' if (score >= 60) return '记忆力良好' if (score >= 40) return '记忆力一般' return '记忆力偏弱' } function getStudyAdvice(luckLevel: string, studyStarCount: number): string { if (studyStarCount >= 2) return '文昌文曲双星照耀,学业运势极佳,适合攻克难题和备考' if (luckLevel === '大吉' || luckLevel === '吉') return '学业运势良好,适合深入学习新知识,效率较高' if (luckLevel === '中吉' || luckLevel === '平') return '学业运势平稳,按计划学习即可,注意劳逸结合' return '学业运势偏弱,宜复习巩固已有知识,不宜开启新领域' } function getExamLuck(luckLevel: string): string { if (luckLevel === '大吉' || luckLevel === '吉') return '考试运佳,发挥出色' if (luckLevel === '中吉' || luckLevel === '平') return '考试运平稳,正常发挥' if (luckLevel === '中平') return '考试运一般,需多加准备' return '考试运欠佳,需格外用心准备' } function getStudyEnvironmentAdvice(luckLevel: string): string { if (luckLevel === '大吉' || luckLevel === '吉') return '宜在安静明亮的环境中学习,效率最佳' if (luckLevel === '中吉' || luckLevel === '平') return '宜选择图书馆或自习室等安静场所' return '宜在熟悉的环境中学习,减少外界干扰' } export function analyzeSocialFortune(chart: ZiweiChart, date: Date): SocialFortuneDetail { const xiongPalace = findPalace(chart, PalaceType.XIONG) const baseScore = xiongPalace?.score ?? 50 const nobleStarCount = countMinorStars(xiongPalace, NOBLE_STARS) const nobleBonus = nobleStarCount * 5 const dayAdj = xiongPalace ? calculateDailyAdjustment(xiongPalace, date) : 0 const socialScore = clampScore(baseScore + nobleBonus + dayAdj) const luckLevel = determineLuckLevel(socialScore) return { socialScore, overallSocialLuck: luckLevel, popularityIndex: getPopularityLevel(socialScore), communicationAbility: getCommunicationLevel(socialScore), socialAdvice: getSocialAdvice(luckLevel, nobleStarCount), nobleLuck: getNobleLuck(nobleStarCount), bestSocialTime: SOCIAL_TIME_MAP[luckLevel] ?? '下午2点至4点', suitableOccasion: SUITABLE_OCCASION_MAP[luckLevel] ?? '日常社交', interpersonalAdvice: getInterpersonalAdvice(luckLevel), } } function getPopularityLevel(score: number): string { if (score >= 80) return '人气旺盛' if (score >= 60) return '人缘良好' if (score >= 40) return '人缘一般' return '人缘偏弱' } function getCommunicationLevel(score: number): string { if (score >= 80) return '表达流畅' if (score >= 60) return '沟通顺畅' if (score >= 40) return '沟通一般' return '沟通不畅' } function getSocialAdvice(luckLevel: string, nobleStarCount: number): string { if (nobleStarCount >= 2) return '贵人星照耀,社交运势极佳,易获他人帮助与支持' if (luckLevel === '大吉' || luckLevel === '吉') return '社交运势良好,适合拓展人脉,参加社交活动' if (luckLevel === '中吉' || luckLevel === '平') return '社交运势平稳,保持正常交往即可' return '社交运势偏弱,宜减少不必要的应酬,专注自身' } function getNobleLuck(nobleStarCount: number): string { if (nobleStarCount >= 3) return '贵人运极旺,多有助力' if (nobleStarCount >= 2) return '贵人运旺盛,易遇贵人' if (nobleStarCount >= 1) return '贵人运一般,偶有助力' return '贵人运偏弱,需自力更生' } function getInterpersonalAdvice(luckLevel: string): string { if (luckLevel === '大吉' || luckLevel === '吉') return '人际关系和谐,宜主动关心他人,增进感情' if (luckLevel === '中吉' || luckLevel === '平') return '人际关系平稳,保持真诚待人即可' if (luckLevel === '中平') return '人际关系略显平淡,可主动联络朋友' return '人际关系易生摩擦,需多忍让,避免冲突' } export function analyzeTravelFortune(chart: ZiweiChart, date: Date): TravelFortuneDetail { const qianPalace = findPalace(chart, PalaceType.QIAN) const baseScore = qianPalace?.score ?? 50 const travelStarCount = countMinorStars(qianPalace, TRAVEL_STARS) const travelBonus = travelStarCount * 5 const dayAdj = qianPalace ? calculateDailyAdjustment(qianPalace, date) : 0 const travelScore = clampScore(baseScore + travelBonus + dayAdj) const luckLevel = determineLuckLevel(travelScore) return { travelScore, overallTravelLuck: luckLevel, safetyIndex: getSafetyLevel(travelScore), smoothnessIndex: getSmoothnessLevel(travelScore), travelAdvice: getTravelAdvice(luckLevel, travelStarCount), bestTravelTime: TRAVEL_TIME_MAP[luckLevel] ?? '中午前后', suitableTransport: SUITABLE_TRANSPORT_MAP[luckLevel] ?? '常规交通', precautions: getPrecautions(luckLevel), nobleDirection: getNobleDirection(chart, date), } } function getSafetyLevel(score: number): string { if (score >= 80) return '安全指数高' if (score >= 60) return '安全指数良好' if (score >= 40) return '安全指数一般' return '安全指数偏低' } function getSmoothnessLevel(score: number): string { if (score >= 80) return '顺畅无阻' if (score >= 60) return '较为顺畅' if (score >= 40) return '一般' return '可能受阻' } function getTravelAdvice(luckLevel: string, travelStarCount: number): string { if (travelStarCount >= 1) return '天马星动,出行运势佳,适合出差旅行' if (luckLevel === '大吉' || luckLevel === '吉') return '出行运势良好,旅途顺利,可安排出行计划' if (luckLevel === '中吉' || luckLevel === '平') return '出行运势平稳,按计划出行即可' return '出行运势欠佳,建议减少不必要的外出' } function getPrecautions(luckLevel: string): string { if (luckLevel === '大吉' || luckLevel === '吉') return '出行顺利,注意常规安全即可' if (luckLevel === '中吉' || luckLevel === '平') return '出行注意交通安全,提前查看天气' if (luckLevel === '中平') return '出行需谨慎,注意人身和财物安全' return '出行风险较高,务必注意安全,避免夜间出行' } function getNobleDirection(chart: ZiweiChart, _date: Date): string { const mingGong = findPalace(chart, PalaceType.MING) if (mingGong == null) return '东方' const hasJiStar = mingGong.majorStars.some(s => s.nature === StarNature.JI) const branchIndex = EarthlyBranch.index(chart.mingGongBranch) - 1 const directionIndex = hasJiStar ? (branchIndex + 1) % DIRECTION_LIST.length : (branchIndex + 3) % DIRECTION_LIST.length return DIRECTION_LIST[directionIndex] } export function generateComprehensiveFortune(chart: ZiweiChart, date: Date): DailyFortune { const baseFortune = generateDailyFortune(chart, date) const loveFortune = analyzeLoveFortune(chart, date) const studyFortune = analyzeStudyFortune(chart, date) const socialFortune = analyzeSocialFortune(chart, date) const travelFortune = analyzeTravelFortune(chart, date) return { ...baseFortune, loveScore: loveFortune.loveScore, overallLoveLuck: loveFortune.overallLoveLuck, peachBlossomIndex: loveFortune.peachBlossomIndex, singleAdvice: loveFortune.singleAdvice, datingAdvice: loveFortune.datingAdvice, marriageAdvice: loveFortune.marriageAdvice, bestDatingTime: loveFortune.bestDatingTime, studyScore: studyFortune.studyScore, overallStudyLuck: studyFortune.overallStudyLuck, focusIndex: studyFortune.focusIndex, memoryIndex: studyFortune.memoryIndex, studyAdvice: studyFortune.studyAdvice, examLuck: studyFortune.examLuck, bestStudyTime: studyFortune.bestStudyTime, suitableSubjects: studyFortune.suitableSubjects, studyEnvironmentAdvice: studyFortune.studyEnvironmentAdvice, socialScore: socialFortune.socialScore, overallSocialLuck: socialFortune.overallSocialLuck, popularityIndex: socialFortune.popularityIndex, communicationAbility: socialFortune.communicationAbility, socialAdvice: socialFortune.socialAdvice, nobleLuck: socialFortune.nobleLuck, bestSocialTime: socialFortune.bestSocialTime, suitableOccasion: socialFortune.suitableOccasion, interpersonalAdvice: socialFortune.interpersonalAdvice, travelScore: travelFortune.travelScore, overallTravelLuck: travelFortune.overallTravelLuck, safetyIndex: travelFortune.safetyIndex, smoothnessIndex: travelFortune.smoothnessIndex, travelAdvice: travelFortune.travelAdvice, bestTravelTime: travelFortune.bestTravelTime, suitableTransport: travelFortune.suitableTransport, precautions: travelFortune.precautions, nobleDirection: travelFortune.nobleDirection, } } export function generateComprehensiveMonthlyFortune( chart: ZiweiChart, year: number, month: number, ): MonthlyFortune { const baseFortune = generateMonthlyFortune(chart, year, month) const midMonthDate = new Date(year, month - 1, 15) const loveFortune = analyzeLoveFortune(chart, midMonthDate) const studyFortune = analyzeStudyFortune(chart, midMonthDate) const socialFortune = analyzeSocialFortune(chart, midMonthDate) const travelFortune = analyzeTravelFortune(chart, midMonthDate) return { ...baseFortune, loveScore: loveFortune.loveScore, overallLoveLuck: loveFortune.overallLoveLuck, peachBlossomIndex: loveFortune.peachBlossomIndex, singleAdvice: loveFortune.singleAdvice, datingAdvice: loveFortune.datingAdvice, marriageAdvice: loveFortune.marriageAdvice, bestDatingTime: loveFortune.bestDatingTime, studyScore: studyFortune.studyScore, overallStudyLuck: studyFortune.overallStudyLuck, focusIndex: studyFortune.focusIndex, memoryIndex: studyFortune.memoryIndex, studyAdvice: studyFortune.studyAdvice, examLuck: studyFortune.examLuck, bestStudyTime: studyFortune.bestStudyTime, suitableSubjects: studyFortune.suitableSubjects, studyEnvironmentAdvice: studyFortune.studyEnvironmentAdvice, socialScore: socialFortune.socialScore, overallSocialLuck: socialFortune.overallSocialLuck, popularityIndex: socialFortune.popularityIndex, communicationAbility: socialFortune.communicationAbility, socialAdvice: socialFortune.socialAdvice, nobleLuck: socialFortune.nobleLuck, bestSocialTime: socialFortune.bestSocialTime, suitableOccasion: socialFortune.suitableOccasion, interpersonalAdvice: socialFortune.interpersonalAdvice, travelScore: travelFortune.travelScore, overallTravelLuck: travelFortune.overallTravelLuck, safetyIndex: travelFortune.safetyIndex, smoothnessIndex: travelFortune.smoothnessIndex, travelAdvice: travelFortune.travelAdvice, bestTravelTime: travelFortune.bestTravelTime, suitableTransport: travelFortune.suitableTransport, precautions: travelFortune.precautions, nobleDirection: travelFortune.nobleDirection, } } export function generateComprehensiveYearlyFortune( chart: ZiweiChart, year: number, ): YearlyFortune { const baseFortune = generateYearlyFortune(chart, year) const midYearDate = new Date(year, 6, 1) const loveFortune = analyzeLoveFortune(chart, midYearDate) const studyFortune = analyzeStudyFortune(chart, midYearDate) const socialFortune = analyzeSocialFortune(chart, midYearDate) const travelFortune = analyzeTravelFortune(chart, midYearDate) return { ...baseFortune, loveScore: loveFortune.loveScore, overallLoveLuck: loveFortune.overallLoveLuck, peachBlossomIndex: loveFortune.peachBlossomIndex, singleAdvice: loveFortune.singleAdvice, datingAdvice: loveFortune.datingAdvice, marriageAdvice: loveFortune.marriageAdvice, bestDatingTime: loveFortune.bestDatingTime, studyScore: studyFortune.studyScore, overallStudyLuck: studyFortune.overallStudyLuck, focusIndex: studyFortune.focusIndex, memoryIndex: studyFortune.memoryIndex, studyAdvice: studyFortune.studyAdvice, examLuck: studyFortune.examLuck, bestStudyTime: studyFortune.bestStudyTime, suitableSubjects: studyFortune.suitableSubjects, studyEnvironmentAdvice: studyFortune.studyEnvironmentAdvice, socialScore: socialFortune.socialScore, overallSocialLuck: socialFortune.overallSocialLuck, popularityIndex: socialFortune.popularityIndex, communicationAbility: socialFortune.communicationAbility, socialAdvice: socialFortune.socialAdvice, nobleLuck: socialFortune.nobleLuck, bestSocialTime: socialFortune.bestSocialTime, suitableOccasion: socialFortune.suitableOccasion, interpersonalAdvice: socialFortune.interpersonalAdvice, travelScore: travelFortune.travelScore, overallTravelLuck: travelFortune.overallTravelLuck, safetyIndex: travelFortune.safetyIndex, smoothnessIndex: travelFortune.smoothnessIndex, travelAdvice: travelFortune.travelAdvice, bestTravelTime: travelFortune.bestTravelTime, suitableTransport: travelFortune.suitableTransport, precautions: travelFortune.precautions, nobleDirection: travelFortune.nobleDirection, } }