// Package relation builds 关系理解 content from two birth-based portraits. package relation import ( "fmt" "time" "github.com/yuxingu/digital-psychology/apps/api/internal/portrait" ) // Output is free summary + gated detail. type Output struct { Summary map[string]any Detail map[string]any } // Build compares two profiles' exploration styles (lexicon-safe copy). func Build(aBirth, bBirth time.Time, aName, bName string) Output { if aName == "" { aName = "我" } if bName == "" { bName = "TA" } pa := portrait.Build(aBirth, aName) pb := portrait.Build(bBirth, bName) aLabel := str(pa.Summary["headline"]) bLabel := str(pb.Summary["headline"]) aKeys := strSlice(pa.Summary["keywords"]) bKeys := strSlice(pb.Summary["keywords"]) summary := map[string]any{ "title": "关系理解·基础", "me_style": aLabel, "other_style": bLabel, "me_keywords": aKeys, "other_keywords": bKeys, "diff_one_liner": fmt.Sprintf("%s更偏内在节奏,%s的表达方式不同——差异可以成为互补,而不是对立。", aName, bName), "share_hint": "了解彼此的沟通方式,查看关系理解", } detail := map[string]any{ "title": "相处建议·完整分析", "communication": []string{ fmt.Sprintf("%s:先讲清楚事实与需要,再谈感受。", aName), fmt.Sprintf("%s:先确认被听见,再进入方案讨论。", bName), "冲突时约定「复述对方一句」再回应,降低误解。", }, "interaction": []string{ "用「我观察到…我需要…」代替指责句式。", "每周留一次轻松同步:最近什么在消耗/滋养这段关系。", }, "maintenance": []string{ "差异标签不是评分,而是协作说明书。", "重要决定前,双方各写三点顾虑再合并。", }, "me_behavior": str(pa.Detail["behavior_pattern"]), "other_behavior": str(pb.Detail["behavior_pattern"]), } return Output{Summary: summary, Detail: detail} } func str(v any) string { s, _ := v.(string) return s } func strSlice(v any) []string { arr, ok := v.([]string) if ok { return arr } raw, ok := v.([]any) if !ok { return nil } out := make([]string, 0, len(raw)) for _, x := range raw { if s, ok := x.(string); ok { out = append(out, s) } } return out }