package star import ( "fmt" "time" "github.com/yuxingu/digital-psychology/apps/api/internal/star/natal" ) func signIndexOf(key string) int { for i, s := range []string{ "aries", "taurus", "gemini", "cancer", "leo", "virgo", "libra", "scorpio", "sagittarius", "capricorn", "aquarius", "pisces", } { if s == key { return i } } return 0 } func planetBullets(chart natal.Chart) []string { out := make([]string, 0, 6) for _, key := range []string{"mercury", "venus", "mars", "jupiter", "saturn"} { for _, p := range chart.Planets { if p.Key == key { out = append(out, fmt.Sprintf("%s在%s第%d宫", p.Title, p.Sign, p.House)) break } } } return out } func signCard(key, title string, b natal.Body, teaser string, keywords []string) map[string]any { ks := keywords if len(ks) > 3 { ks = ks[:3] } return map[string]any{ "key": key, "title": title, "label": b.Sign, "element": b.Element, "modality": b.Modality, "teaser": teaser, "keywords": ks, } } func section(title, body string, bullets []string) map[string]any { return map[string]any{"title": title, "body": body, "bullets": bullets} } func min(a, b int) int { if a < b { return a } return b } // SignLabels returns sun/moon/rise labels (uses natal engine). func SignLabels(birth time.Time, birthTime *string) (sun, moon, rise string) { return SignLabelsPlace(birth, birthTime, nil) } // SignLabelsPlace includes birth place for rising accuracy. func SignLabelsPlace(birth time.Time, birthTime, place *string) (sun, moon, rise string) { c, err := natal.Compute(birth, birthTime, place) if err != nil { return "", "", "" } return c.Sun.Sign, c.Moon.Sign, c.Rise.Sign } // NatalChart exposes chart for relation/synastry. func NatalChart(birth time.Time, birthTime, place *string) (natal.Chart, error) { return natal.Compute(birth, birthTime, place) }