feat: build mini app frontend pages
This commit is contained in:
1 parent
ca36409e41
commit
869376979c
84 files changed
+16922
-86
No files matched your search
@@ -0,0 +1,90 @@
|
||||
import { Solar } from 'lunar-typescript'
|
||||
import { ElementScore } from '../services/request'
|
||||
|
||||
type ElementName = '木' | '火' | '土' | '金' | '水'
|
||||
|
||||
export type FiveElementReport = {
|
||||
scores: ElementScore[]
|
||||
favorable: string
|
||||
unfavorable: string
|
||||
dayMaster: string
|
||||
}
|
||||
|
||||
const stemElements: Record<string, ElementName> = {
|
||||
甲: '木', 乙: '木', 丙: '火', 丁: '火', 戊: '土', 己: '土', 庚: '金', 辛: '金', 壬: '水', 癸: '水'
|
||||
}
|
||||
|
||||
const branchElements: Record<string, ElementName> = {
|
||||
子: '水', 丑: '土', 寅: '木', 卯: '木', 辰: '土', 巳: '火', 午: '火', 未: '土', 申: '金', 酉: '金', 戌: '土', 亥: '水'
|
||||
}
|
||||
|
||||
const elementMeta: Record<ElementName, { color: string }> = {
|
||||
木: { color: '#36b85b' },
|
||||
火: { color: '#ef5a58' },
|
||||
土: { color: '#b46a18' },
|
||||
金: { color: '#d59a05' },
|
||||
水: { color: '#35bfe8' }
|
||||
}
|
||||
|
||||
const scoreOrder: ElementName[] = ['土', '金', '水', '木', '火']
|
||||
const generationOrder: ElementName[] = ['木', '火', '土', '金', '水']
|
||||
|
||||
const hourFromBirthHour = (birthHour: string) => {
|
||||
const numericHour = Number.parseInt(birthHour, 10)
|
||||
if (Number.isFinite(numericHour)) return Math.max(0, Math.min(23, numericHour))
|
||||
|
||||
const branchHours: Record<string, number> = {
|
||||
子: 23, 丑: 1, 寅: 3, 卯: 5, 辰: 7, 巳: 9,
|
||||
午: 11, 未: 13, 申: 15, 酉: 17, 戌: 19, 亥: 21
|
||||
}
|
||||
return branchHours[birthHour.slice(0, 1)] ?? 12
|
||||
}
|
||||
|
||||
export function calculateFiveElements(birthday: string, birthHour: string): FiveElementReport {
|
||||
const date = new Date(`${birthday}T00:00:00`)
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return {
|
||||
scores: scoreOrder.map((name) => ({ name, color: elementMeta[name].color, value: 20 })),
|
||||
favorable: '金水',
|
||||
unfavorable: '木火土',
|
||||
dayMaster: '壬'
|
||||
}
|
||||
}
|
||||
|
||||
const solar = Solar.fromYmdHms(
|
||||
date.getFullYear(),
|
||||
date.getMonth() + 1,
|
||||
date.getDate(),
|
||||
hourFromBirthHour(birthHour),
|
||||
0,
|
||||
0
|
||||
)
|
||||
const eightChar = solar.getLunar().getEightChar()
|
||||
const pillars = [eightChar.getYear(), eightChar.getMonth(), eightChar.getDay(), eightChar.getTime()]
|
||||
const weights: Record<ElementName, number> = { 木: 0, 火: 0, 土: 0, 金: 0, 水: 0 }
|
||||
|
||||
pillars.forEach((pillar) => {
|
||||
const [stem, branch] = pillar
|
||||
if (stemElements[stem]) weights[stemElements[stem]] += 2
|
||||
if (branchElements[branch]) weights[branchElements[branch]] += 1
|
||||
})
|
||||
|
||||
const total = Object.values(weights).reduce((sum, value) => sum + value, 0)
|
||||
const scores = scoreOrder.map((name) => ({
|
||||
name,
|
||||
color: elementMeta[name].color,
|
||||
value: Math.round((weights[name] / total) * 100)
|
||||
}))
|
||||
const dayMaster = eightChar.getDay().slice(0, 1)
|
||||
const masterElement = stemElements[dayMaster] || '水'
|
||||
const masterIndex = generationOrder.indexOf(masterElement)
|
||||
const resourceElement = generationOrder[(masterIndex + generationOrder.length - 1) % generationOrder.length]
|
||||
const unfavorable = generationOrder.filter((element) => element !== resourceElement && element !== masterElement).join('')
|
||||
|
||||
return {
|
||||
scores,
|
||||
favorable: `${resourceElement}${masterElement}`,
|
||||
unfavorable,
|
||||
dayMaster
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user