|
@@ -0,0 +1,536 @@
|
|
|
|
|
+package com.etotem.cfc.service;
|
|
|
|
|
+
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.etotem.cfc.entity.ZodiacConfig;
|
|
|
|
|
+import com.etotem.cfc.mapper.ZodiacConfigMapper;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+
|
|
|
|
|
+import javax.annotation.Resource;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 星座运势年度五维能量计算服务
|
|
|
|
|
+ *
|
|
|
|
|
+ * 融合东西方星座体系的年度能量计算:
|
|
|
|
|
+ * - 西方星座(60%权重):太阳星座元素倾向 + 模态倾向 + 木星/土星年度周期修正
|
|
|
|
|
+ * - 中国生肖(40%权重):太岁关系(本命年/六合/三合/冲/害/平)+ 干支五行修正
|
|
|
|
|
+ *
|
|
|
|
|
+ * 五维能量值范围 0-100:身、心、智、行、富
|
|
|
|
|
+ */
|
|
|
|
|
+@Service
|
|
|
|
|
+public class ZodiacAnnualEnergyService {
|
|
|
|
|
+
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private ZodiacConfigMapper zodiacConfigMapper;
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 西方星座体系 ====================
|
|
|
|
|
+
|
|
|
|
|
+ /** 黄道十二星座代码 */
|
|
|
|
|
+ private static final String[] WESTERN_SIGNS = {
|
|
|
|
|
+ "capricorn", "aquarius", "pisces", "aries", "taurus", "gemini",
|
|
|
|
|
+ "cancer", "leo", "virgo", "libra", "scorpio", "sagittarius"
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ /** 星座中文名 */
|
|
|
|
|
+ private static final String[] WESTERN_NAMES_CN = {
|
|
|
|
|
+ "摩羯座", "水瓶座", "双鱼座", "白羊座", "金牛座", "双子座",
|
|
|
|
|
+ "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座"
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ /** 星座元素:fire/earth/air/water */
|
|
|
|
|
+ private static final String[] WESTERN_ELEMENTS = {
|
|
|
|
|
+ "earth", "air", "water",
|
|
|
|
|
+ "fire", "earth", "air",
|
|
|
|
|
+ "water", "fire", "earth",
|
|
|
|
|
+ "air", "water", "fire"
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ /** 星座模态:cardinal/fixed/mutable */
|
|
|
|
|
+ private static final String[] WESTERN_MODALITIES = {
|
|
|
|
|
+ "fixed", "cardinal", "mutable",
|
|
|
|
|
+ "cardinal", "fixed", "mutable",
|
|
|
|
|
+ "fixed", "cardinal", "mutable",
|
|
|
|
|
+ "cardinal", "fixed", "mutable"
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ /** 星座日期范围 [startMonth, startDay, endMonth, endDay],跨年星座(摩羯)end 设为 12/31 */
|
|
|
|
|
+ private static final int[][] WESTERN_RANGES = {
|
|
|
|
|
+ {1, 20, 2, 18}, // capricorn (cross-year: Jan-Feb)
|
|
|
|
|
+ {1, 20, 2, 18}, // aquarius (Feb)
|
|
|
|
|
+ {2, 19, 3, 20}, // pisces (Mar)
|
|
|
|
|
+ {3, 21, 4, 19}, // aries (Apr)
|
|
|
|
|
+ {4, 20, 5, 20}, // taurus (May)
|
|
|
|
|
+ {5, 21, 6, 20}, // gemini (Jun)
|
|
|
|
|
+ {6, 21, 7, 22}, // cancer (Jul)
|
|
|
|
|
+ {7, 23, 8, 22}, // leo (Aug)
|
|
|
|
|
+ {8, 23, 9, 22}, // virgo (Sep)
|
|
|
|
|
+ {9, 23, 10, 22}, // libra (Oct)
|
|
|
|
|
+ {10, 23, 11, 21}, // scorpio (Nov)
|
|
|
|
|
+ {11, 22, 12, 21}, // sagittarius (Dec)
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ /** 元素 → 五维映射(先天倾向)*/
|
|
|
|
|
+ private static final Map<String, DimensionBias> ELEMENT_BIASES = new LinkedHashMap<String, DimensionBias>() {{
|
|
|
|
|
+ put("fire", new DimensionBias(55, 72, 50, 78, 48)); // 火:行强心高
|
|
|
|
|
+ put("earth", new DimensionBias(78, 50, 55, 50, 72)); // 土:身富强智中
|
|
|
|
|
+ put("air", new DimensionBias(50, 55, 78, 50, 55)); // 风:智强心身中
|
|
|
|
|
+ put("water", new DimensionBias(50, 78, 55, 55, 50)); // 水:心强身智中
|
|
|
|
|
+ }};
|
|
|
|
|
+
|
|
|
|
|
+ /** 模态 → 五维修正 */
|
|
|
|
|
+ private static final Map<String, DimensionBias> MODALITY_BIASES = new LinkedHashMap<String, DimensionBias>() {{
|
|
|
|
|
+ put("cardinal", new DimensionBias(60, 55, 55, 75, 55)); // 开创:行动强
|
|
|
|
|
+ put("fixed", new DimensionBias(70, 65, 60, 55, 70)); // 固定:身富稳
|
|
|
|
|
+ put("mutable", new DimensionBias(55, 75, 70, 60, 55)); // 变动:心智活
|
|
|
|
|
+ }};
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 中国生肖体系 ====================
|
|
|
|
|
+
|
|
|
|
|
+ /** 十二生肖代码(与 FamilyMemberAttributeService 一致)*/
|
|
|
|
|
+ static final String[] ZODIAC_CODES = {"rat", "ox", "tiger", "rabbit", "dragon", "snake",
|
|
|
|
|
+ "horse", "sheep", "monkey", "rooster", "dog", "pig"};
|
|
|
|
|
+
|
|
|
|
|
+ /** 生肖中文名 */
|
|
|
|
|
+ private static final String[] ZODIAC_CN = {"鼠", "牛", "虎", "兔", "龙", "蛇",
|
|
|
|
|
+ "马", "羊", "猴", "鸡", "狗", "猪"};
|
|
|
|
|
+
|
|
|
|
|
+ /** 生肖五行 */
|
|
|
|
|
+ private static final String[] ZODIAC_ELEMENTS = {"水", "土", "木", "木", "土", "火",
|
|
|
|
|
+ "火", "土", "金", "金", "土", "水"};
|
|
|
|
|
+
|
|
|
|
|
+ /** 地支六冲偏移 */
|
|
|
|
|
+ private static final int[] CHONG_OFFSET = {6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5};
|
|
|
|
|
+
|
|
|
|
|
+ /** 地支六合 */
|
|
|
|
|
+ private static final Map<String, String> LIU_HE = new LinkedHashMap<String, String>() {{
|
|
|
|
|
+ put("rat", "ox"); put("ox", "rat");
|
|
|
|
|
+ put("tiger", "pig"); put("pig", "tiger");
|
|
|
|
|
+ put("rabbit", "dog"); put("dog", "rabbit");
|
|
|
|
|
+ put("dragon", "monkey"); put("monkey", "dragon");
|
|
|
|
|
+ put("snake", "rooster"); put("rooster", "snake");
|
|
|
|
|
+ put("horse", "sheep"); put("sheep", "horse");
|
|
|
|
|
+ }};
|
|
|
|
|
+
|
|
|
|
|
+ /** 地支三合 */
|
|
|
|
|
+ private static final Map<String, List<String>> SAN_HE = new LinkedHashMap<String, List<String>>() {{
|
|
|
|
|
+ put("rat", Arrays.asList("dragon", "monkey"));
|
|
|
|
|
+ put("dragon", Arrays.asList("monkey", "rat"));
|
|
|
|
|
+ put("monkey", Arrays.asList("rat", "dragon"));
|
|
|
|
|
+ put("ox", Arrays.asList("snake", "rooster"));
|
|
|
|
|
+ put("snake", Arrays.asList("rooster", "ox"));
|
|
|
|
|
+ put("rooster", Arrays.asList("ox", "snake"));
|
|
|
|
|
+ put("tiger", Arrays.asList("horse", "dog"));
|
|
|
|
|
+ put("horse", Arrays.asList("dog", "tiger"));
|
|
|
|
|
+ put("dog", Arrays.asList("tiger", "horse"));
|
|
|
|
|
+ put("rabbit", Arrays.asList("sheep", "pig"));
|
|
|
|
|
+ put("sheep", Arrays.asList("rabbit", "pig"));
|
|
|
|
|
+ put("pig", Arrays.asList("rabbit", "sheep"));
|
|
|
|
|
+ }};
|
|
|
|
|
+
|
|
|
|
|
+ /** 五行 → 五维基础映射 */
|
|
|
|
|
+ private static final Map<String, DimensionBias> WUXING_BIASES = new LinkedHashMap<String, DimensionBias>() {{
|
|
|
|
|
+ put("金", new DimensionBias(50, 60, 78, 50, 60)); // 金:智心偏强
|
|
|
|
|
+ put("木", new DimensionBias(55, 55, 55, 78, 50)); // 木:行偏强
|
|
|
|
|
+ put("水", new DimensionBias(50, 78, 60, 50, 55)); // 水:心偏强
|
|
|
|
|
+ put("火", new DimensionBias(60, 72, 50, 65, 50)); // 火:身心偏强
|
|
|
|
|
+ put("土", new DimensionBias(78, 50, 55, 50, 72)); // 土:身富偏强
|
|
|
|
|
+ }};
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 五维能量结果
|
|
|
|
|
+ */
|
|
|
|
|
+ public static class AnnualEnergyResult {
|
|
|
|
|
+ private String westernSign;
|
|
|
|
|
+ private String westernSignCn;
|
|
|
|
|
+ private String westernElement;
|
|
|
|
|
+ private String westernModality;
|
|
|
|
|
+ private String zodiacCode;
|
|
|
|
|
+ private String zodiacName;
|
|
|
|
|
+ private String yearBranch;
|
|
|
|
|
+ private String yearRelation;
|
|
|
|
|
+ private String jupiterPhase;
|
|
|
|
|
+ private String saturnPhase;
|
|
|
|
|
+ private int body;
|
|
|
|
|
+ private int mind;
|
|
|
|
|
+ private int wisdom;
|
|
|
|
|
+ private int action;
|
|
|
|
|
+ private int wealth;
|
|
|
|
|
+
|
|
|
|
|
+ public String getWesternSign() { return westernSign; }
|
|
|
|
|
+ public void setWesternSign(String westernSign) { this.westernSign = westernSign; }
|
|
|
|
|
+ public String getWesternSignCn() { return westernSignCn; }
|
|
|
|
|
+ public void setWesternSignCn(String westernSignCn) { this.westernSignCn = westernSignCn; }
|
|
|
|
|
+ public String getWesternElement() { return westernElement; }
|
|
|
|
|
+ public void setWesternElement(String westernElement) { this.westernElement = westernElement; }
|
|
|
|
|
+ public String getWesternModality() { return westernModality; }
|
|
|
|
|
+ public void setWesternModality(String westernModality) { this.westernModality = westernModality; }
|
|
|
|
|
+ public String getZodiacCode() { return zodiacCode; }
|
|
|
|
|
+ public void setZodiacCode(String zodiacCode) { this.zodiacCode = zodiacCode; }
|
|
|
|
|
+ public String getZodiacName() { return zodiacName; }
|
|
|
|
|
+ public void setZodiacName(String zodiacName) { this.zodiacName = zodiacName; }
|
|
|
|
|
+ public String getYearBranch() { return yearBranch; }
|
|
|
|
|
+ public void setYearBranch(String yearBranch) { this.yearBranch = yearBranch; }
|
|
|
|
|
+ public String getYearRelation() { return yearRelation; }
|
|
|
|
|
+ public void setYearRelation(String yearRelation) { this.yearRelation = yearRelation; }
|
|
|
|
|
+ public String getJupiterPhase() { return jupiterPhase; }
|
|
|
|
|
+ public void setJupiterPhase(String jupiterPhase) { this.jupiterPhase = jupiterPhase; }
|
|
|
|
|
+ public String getSaturnPhase() { return saturnPhase; }
|
|
|
|
|
+ public void setSaturnPhase(String saturnPhase) { this.saturnPhase = saturnPhase; }
|
|
|
|
|
+ public int getBody() { return body; }
|
|
|
|
|
+ public void setBody(int body) { this.body = body; }
|
|
|
|
|
+ public int getMind() { return mind; }
|
|
|
|
|
+ public void setMind(int mind) { this.mind = mind; }
|
|
|
|
|
+ public int getWisdom() { return wisdom; }
|
|
|
|
|
+ public void setWisdom(int wisdom) { this.wisdom = wisdom; }
|
|
|
|
|
+ public int getAction() { return action; }
|
|
|
|
|
+ public void setAction(int action) { this.action = action; }
|
|
|
|
|
+ public int getWealth() { return wealth; }
|
|
|
|
|
+ public void setWealth(int wealth) { this.wealth = wealth; }
|
|
|
|
|
+
|
|
|
|
|
+ /** 五维能量 Map */
|
|
|
|
|
+ public Map<String, Integer> toMap() {
|
|
|
|
|
+ Map<String, Integer> m = new LinkedHashMap<>();
|
|
|
|
|
+ m.put("body", body);
|
|
|
|
|
+ m.put("mind", mind);
|
|
|
|
|
+ m.put("wisdom", wisdom);
|
|
|
|
|
+ m.put("action", action);
|
|
|
|
|
+ m.put("wealth", wealth);
|
|
|
|
|
+ return m;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 五维偏差载体 */
|
|
|
|
|
+ static class DimensionBias {
|
|
|
|
|
+ final int body, mind, wisdom, action, wealth;
|
|
|
|
|
+ DimensionBias(int body, int mind, int wisdom, int action, int wealth) {
|
|
|
|
|
+ this.body = body; this.mind = mind; this.wisdom = wisdom;
|
|
|
|
|
+ this.action = action; this.wealth = wealth;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 主入口 ====================
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 计算某成员当年的五维能量值(融合东西方体系)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param birthYear 出生年份
|
|
|
|
|
+ * @param birthMonth 出生月份(西方星座用)
|
|
|
|
|
+ * @param birthDay 出生日期(西方星座用)
|
|
|
|
|
+ * @param zodiacCode 生肖代码(选填,null 则自动推算)
|
|
|
|
|
+ * @param targetYear 目标年份(默认今年)
|
|
|
|
|
+ * @return 五维能量结果
|
|
|
|
|
+ */
|
|
|
|
|
+ public AnnualEnergyResult calculate(int birthYear, int birthMonth, int birthDay,
|
|
|
|
|
+ String zodiacCode, Integer targetYear) {
|
|
|
|
|
+ if (birthYear < 1900 || birthYear > targetYearOrDefault(targetYear) - 1) {
|
|
|
|
|
+ return emptyResult();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ int year = targetYear != null ? targetYear : Calendar.getInstance().get(Calendar.YEAR);
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 西方星座
|
|
|
|
|
+ String westernSign = findWesternSign(birthMonth, birthDay);
|
|
|
|
|
+ int westernIdx = indexOfWestern(westernSign);
|
|
|
|
|
+ String element = westernIdx >= 0 ? WESTERN_ELEMENTS[westernIdx] : "earth";
|
|
|
|
|
+ String modality = westernIdx >= 0 ? WESTERN_MODALITIES[westernIdx] : "fixed";
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 中国生肖
|
|
|
|
|
+ if (zodiacCode == null) {
|
|
|
|
|
+ zodiacCode = ZODIAC_CODES[(birthYear - 4) % 12];
|
|
|
|
|
+ int idx = (birthYear - 4) % 12;
|
|
|
|
|
+ if (idx < 0) idx += 12;
|
|
|
|
|
+ zodiacCode = ZODIAC_CODES[idx];
|
|
|
|
|
+ }
|
|
|
|
|
+ int zodiacIdx = indexOf(zodiacCode);
|
|
|
|
|
+ if (zodiacIdx < 0) zodiacIdx = 0;
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 当年地支
|
|
|
|
|
+ int yearIdx = (year - 4) % 12;
|
|
|
|
|
+ if (yearIdx < 0) yearIdx += 12;
|
|
|
|
|
+ String yearBranch = ZODIAC_CODES[yearIdx];
|
|
|
|
|
+ String yearBranchCn = ZODIAC_CN[yearIdx];
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 太岁关系
|
|
|
|
|
+ String relation = calcRelation(zodiacIdx, yearIdx);
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 行星周期(木星12年回归 / 土星29.5年回归)
|
|
|
|
|
+ String jupiterPhase = calcJupiterPhase(birthYear, year);
|
|
|
|
|
+ String saturnPhase = calcSaturnPhase(birthYear, year);
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 融合计算
|
|
|
|
|
+ AnnualEnergyResult result = new AnnualEnergyResult();
|
|
|
|
|
+ result.setWesternSign(westernSign);
|
|
|
|
|
+ result.setWesternSignCn(westernIdx >= 0 ? WESTERN_NAMES_CN[westernIdx] : "");
|
|
|
|
|
+ result.setWesternElement(element);
|
|
|
|
|
+ result.setWesternModality(modality);
|
|
|
|
|
+ result.setZodiacCode(zodiacCode);
|
|
|
|
|
+ result.setZodiacName(findZodiacName(zodiacCode));
|
|
|
|
|
+ result.setYearBranch(yearBranchCn + "年");
|
|
|
|
|
+ result.setYearRelation(relation);
|
|
|
|
|
+ result.setJupiterPhase(jupiterPhase);
|
|
|
|
|
+ result.setSaturnPhase(saturnPhase);
|
|
|
|
|
+
|
|
|
|
|
+ // 西方部分(60%)
|
|
|
|
|
+ DimensionBias eastBias = ELEMENT_BIASES.getOrDefault(element, new DimensionBias(55, 55, 55, 55, 55));
|
|
|
|
|
+ DimensionBias modBias = MODALITY_BIASES.getOrDefault(modality, new DimensionBias(55, 55, 55, 55, 55));
|
|
|
|
|
+ DimensionBias wuxingBias = WUXING_BIASES.getOrDefault(ZODIAC_ELEMENTS[zodiacIdx], new DimensionBias(55, 55, 55, 55, 55));
|
|
|
|
|
+
|
|
|
|
|
+ int wBody = round60(eastBias.body, modBias.body, wuxingBias.body, relation, zodiacIdx, yearIdx);
|
|
|
|
|
+ int wMind = round60(eastBias.mind, modBias.mind, wuxingBias.mind, relation, zodiacIdx, yearIdx);
|
|
|
|
|
+ int wWisdom = round60(eastBias.wisdom, modBias.wisdom, wuxingBias.wisdom, relation, zodiacIdx, yearIdx);
|
|
|
|
|
+ int wAction = round60(eastBias.action, modBias.action, wuxingBias.action, relation, zodiacIdx, yearIdx);
|
|
|
|
|
+ int wWealth = round60(eastBias.wealth, modBias.wealth, wuxingBias.wealth, relation, zodiacIdx, yearIdx);
|
|
|
|
|
+
|
|
|
|
|
+ // 查 zodiac_config 覆盖(如果有配置)
|
|
|
|
|
+ ZodiacConfig config = findByCode(zodiacCode);
|
|
|
|
|
+ if (config != null) {
|
|
|
|
|
+ // 用配置的 mindBase/wisdomBase 覆盖心和智
|
|
|
|
|
+ if (config.getMindBase() != null && config.getMindBase() > 0) {
|
|
|
|
|
+ wMind = clamp((int) Math.round(wMind * 0.6 + config.getMindBase() * 0.4), relation);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (config.getWisdomBase() != null && config.getWisdomBase() > 0) {
|
|
|
|
|
+ wWisdom = clamp((int) Math.round(wWisdom * 0.6 + config.getWisdomBase() * 0.4), relation);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 用配置的修正系数覆盖身/行/富
|
|
|
|
|
+ wBody = applyModifier(wBody, config.getBodyModifier(), relation);
|
|
|
|
|
+ wAction = applyModifier(wAction, config.getActionModifier(), relation);
|
|
|
|
|
+ wWealth = applyModifier(wWealth, config.getWealthModifier(), relation);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ result.setBody(wBody);
|
|
|
|
|
+ result.setMind(wMind);
|
|
|
|
|
+ result.setWisdom(wWisdom);
|
|
|
|
|
+ result.setAction(wAction);
|
|
|
|
|
+ result.setWealth(wWealth);
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 简化的快捷方法(仅传出生年份 + 生肖)
|
|
|
|
|
+ */
|
|
|
|
|
+ public AnnualEnergyResult calculate(Integer birthYear, String zodiacCode, Integer targetYear) {
|
|
|
|
|
+ // 无法计算西方星座,退化为纯中国生肖模式
|
|
|
|
|
+ if (birthYear == null || birthYear < 1900) {
|
|
|
|
|
+ return emptyResult();
|
|
|
|
|
+ }
|
|
|
|
|
+ int year = targetYear != null ? targetYear : Calendar.getInstance().get(Calendar.YEAR);
|
|
|
|
|
+ if (zodiacCode == null) {
|
|
|
|
|
+ int idx = (birthYear - 4) % 12;
|
|
|
|
|
+ if (idx < 0) idx += 12;
|
|
|
|
|
+ zodiacCode = ZODIAC_CODES[idx];
|
|
|
|
|
+ }
|
|
|
|
|
+ int zodiacIdx = indexOf(zodiacCode);
|
|
|
|
|
+ if (zodiacIdx < 0) return emptyResult();
|
|
|
|
|
+
|
|
|
|
|
+ int yearIdx = (year - 4) % 12;
|
|
|
|
|
+ if (yearIdx < 0) yearIdx += 12;
|
|
|
|
|
+ String yearBranchCn = ZODIAC_CN[yearIdx];
|
|
|
|
|
+ String relation = calcRelation(zodiacIdx, yearIdx);
|
|
|
|
|
+
|
|
|
|
|
+ AnnualEnergyResult result = new AnnualEnergyResult();
|
|
|
|
|
+ result.setWesternSign("");
|
|
|
|
|
+ result.setWesternSignCn("");
|
|
|
|
|
+ result.setWesternElement("");
|
|
|
|
|
+ result.setWesternModality("");
|
|
|
|
|
+ result.setZodiacCode(zodiacCode);
|
|
|
|
|
+ result.setZodiacName(findZodiacName(zodiacCode));
|
|
|
|
|
+ result.setYearBranch(yearBranchCn + "年");
|
|
|
|
|
+ result.setYearRelation(relation);
|
|
|
|
|
+ result.setJupiterPhase("");
|
|
|
|
|
+ result.setSaturnPhase("");
|
|
|
|
|
+
|
|
|
|
|
+ ZodiacConfig config = findByCode(zodiacCode);
|
|
|
|
|
+ if (config != null) {
|
|
|
|
|
+ result.setBody(clamp(60 + (config.getBodyModifier() != null ? config.getBodyModifier() / 10 : 0), relation));
|
|
|
|
|
+ result.setMind(clamp(config.getMindBase() != null ? config.getMindBase() : 50, relation));
|
|
|
|
|
+ result.setWisdom(clamp(config.getWisdomBase() != null ? config.getWisdomBase() : 50, relation));
|
|
|
|
|
+ result.setAction(clamp(55 + (config.getActionModifier() != null ? config.getActionModifier() / 10 : 0), relation));
|
|
|
|
|
+ result.setWealth(clamp(50 + (config.getWealthModifier() != null ? config.getWealthModifier() / 10 : 0), relation));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ result.setBody(50); result.setMind(50); result.setWisdom(50);
|
|
|
|
|
+ result.setAction(50); result.setWealth(50);
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据生肖代码计算当年五维能量(快捷方法)
|
|
|
|
|
+ */
|
|
|
|
|
+ public AnnualEnergyResult calculateByZodiac(String zodiacCode, Integer targetYear) {
|
|
|
|
|
+ return calculate(null, zodiacCode, targetYear);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据出生年份自动推算生肖并计算
|
|
|
|
|
+ */
|
|
|
|
|
+ public AnnualEnergyResult calculateByBirthYear(int birthYear, Integer targetYear) {
|
|
|
|
|
+ return calculate(birthYear, 0, 0, null, targetYear);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 内部计算逻辑 ====================
|
|
|
|
|
+
|
|
|
|
|
+ /** 60/40 加权融合 + 关系钳制 */
|
|
|
|
|
+ private int round60(int eastern, int chinese, int wuxing, String relation, int zIdx, int yIdx) {
|
|
|
|
|
+ // 西方星座 60%
|
|
|
|
|
+ int west = (eastern + chinese) / 2;
|
|
|
|
|
+ // 中国生肖 40%
|
|
|
|
|
+ int cn = wuxing;
|
|
|
|
|
+ // 太岁关系修正
|
|
|
|
|
+ int combined = (int) Math.round(west * 0.6 + cn * 0.4);
|
|
|
|
|
+ return clamp(combined, relation);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 应用 zodiac_config 修正系数(千分比)*/
|
|
|
|
|
+ private int applyModifier(int base, Integer modifier, String relation) {
|
|
|
|
|
+ if (modifier == null) return clamp(base, relation);
|
|
|
|
|
+ double mult = getRelationMultiplier(relation);
|
|
|
|
|
+ int adj = (int) Math.round(modifier * mult / 1000.0);
|
|
|
|
|
+ return clamp(base + adj, relation);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 判定太岁关系 */
|
|
|
|
|
+ private String calcRelation(int zodiacIdx, int yearIdx) {
|
|
|
|
|
+ if (zodiacIdx == yearIdx) return "benming";
|
|
|
|
|
+ if (CHONG_OFFSET[zodiacIdx] == yearIdx) return "chong";
|
|
|
|
|
+ String code = ZODIAC_CODES[zodiacIdx];
|
|
|
|
|
+ if (LIU_HE.get(code).equals(ZODIAC_CODES[yearIdx])) return "liuhe";
|
|
|
|
|
+ List<String> sanHe = SAN_HE.get(code);
|
|
|
|
|
+ if (sanHe != null && sanHe.contains(ZODIAC_CODES[yearIdx])) return "sanhe";
|
|
|
|
|
+ if ((zodiacIdx + 7) % 12 == yearIdx) return "hai";
|
|
|
|
|
+ return "ping";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 钳制分数 + 关系微调 */
|
|
|
|
|
+ private int clamp(int score, String relation) {
|
|
|
|
|
+ switch (relation) {
|
|
|
|
|
+ case "sanhe": score = (int) Math.round(score * 1.08); break;
|
|
|
|
|
+ case "liuhe": score = (int) Math.round(score * 1.12); break;
|
|
|
|
|
+ case "benming": score = (int) Math.round(score * 0.92); break;
|
|
|
|
|
+ case "chong": score = (int) Math.round(score * 0.85); break;
|
|
|
|
|
+ case "hai": score = (int) Math.round(score * 0.90); break;
|
|
|
|
|
+ default: break;
|
|
|
|
|
+ }
|
|
|
|
|
+ return Math.max(0, Math.min(100, score));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 关系乘数 */
|
|
|
|
|
+ private double getRelationMultiplier(String relation) {
|
|
|
|
|
+ switch (relation) {
|
|
|
|
|
+ case "sanhe": return 1.15;
|
|
|
|
|
+ case "liuhe": return 1.25;
|
|
|
|
|
+ case "benming": return 0.80;
|
|
|
|
|
+ case "chong": return 0.65;
|
|
|
|
|
+ case "hai": return 0.75;
|
|
|
|
|
+ default: return 1.0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 西方星座 ====================
|
|
|
|
|
+
|
|
|
|
|
+ /** 根据月日查找太阳星座 */
|
|
|
|
|
+ private String findWesternSign(int month, int day) {
|
|
|
|
|
+ if (month < 1 || month > 12 || day < 1 || day > 31) {
|
|
|
|
|
+ return "capricorn"; // fallback
|
|
|
|
|
+ }
|
|
|
|
|
+ // 按月份排序遍历(避免跨年摩羯的边界问题)
|
|
|
|
|
+ int[][] monthOrder = {
|
|
|
|
|
+ {1, 20, 2, 18}, {2, 19, 3, 20}, {3, 21, 4, 19},
|
|
|
|
|
+ {4, 20, 5, 20}, {5, 21, 6, 20}, {6, 21, 7, 22},
|
|
|
|
|
+ {7, 23, 8, 22}, {8, 23, 9, 22}, {9, 23, 10, 22},
|
|
|
|
|
+ {10, 23, 11, 21}, {11, 22, 12, 21}, {12, 22, 1, 19}
|
|
|
|
|
+ };
|
|
|
|
|
+ String[] signs = {
|
|
|
|
|
+ "aquarius", "pisces", "aries", "taurus", "gemini", "cancer",
|
|
|
|
|
+ "leo", "virgo", "libra", "scorpio", "sagittarius", "capricorn"
|
|
|
|
|
+ };
|
|
|
|
|
+ for (int i = 0; i < monthOrder.length; i++) {
|
|
|
|
|
+ int sm = monthOrder[i][0], sd = monthOrder[i][1];
|
|
|
|
|
+ int em = monthOrder[i][2], ed = monthOrder[i][3];
|
|
|
|
|
+ if (dateInRange(month, day, sm, sd, em, ed)) {
|
|
|
|
|
+ return signs[i];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return "capricorn";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 日期是否在范围内(支持跨年)*/
|
|
|
|
|
+ private boolean dateInRange(int m, int d, int sm, int sd, int em, int ed) {
|
|
|
|
|
+ int input = m * 100 + d;
|
|
|
|
|
+ if (sm <= em) {
|
|
|
|
|
+ // 同年内
|
|
|
|
|
+ return input >= sm * 100 + sd && input <= em * 100 + ed;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 跨年(如摩羯 1/20 - 2/18 实际是上一年的1/20到2/18,这里简化处理)
|
|
|
|
|
+ return input >= sm * 100 + sd || input <= em * 100 + ed;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private int indexOfWestern(String code) {
|
|
|
|
|
+ for (int i = 0; i < WESTERN_SIGNS.length; i++) {
|
|
|
|
|
+ if (WESTERN_SIGNS[i].equals(code)) return i;
|
|
|
|
|
+ }
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 行星周期 ====================
|
|
|
|
|
+
|
|
|
|
|
+ /** 木星周期(约12年),基于出生年判断当前相位 */
|
|
|
|
|
+ private String calcJupiterPhase(int birthYear, int targetYear) {
|
|
|
|
|
+ int diff = targetYear - birthYear;
|
|
|
|
|
+ int phase = diff % 12;
|
|
|
|
|
+ if (phase == 0) return "conjunction"; // 木星合相(本命回归)
|
|
|
|
|
+ if (phase == 6) return "opposition"; // 木星对冲
|
|
|
|
|
+ if (phase <= 3) return "waxing"; // 渐盈
|
|
|
|
|
+ if (phase <= 9) return "waning"; // 渐亏
|
|
|
|
|
+ return "neutral";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 土星周期(约29.5年),基于出生年判断当前相位 */
|
|
|
|
|
+ private String calcSaturnPhase(int birthYear, int targetYear) {
|
|
|
|
|
+ int diff = targetYear - birthYear;
|
|
|
|
|
+ // 取整到最近整数周期
|
|
|
|
|
+ int cycles = Math.round(diff / 29.5f);
|
|
|
|
|
+ int phase = diff - cycles * 29;
|
|
|
|
|
+ if (phase <= 2) return "saturn-return"; // 土星回归
|
|
|
|
|
+ if (phase >= 27) return "saturn-return";
|
|
|
|
|
+ if (phase == 14 || phase == 15) return "opposition";
|
|
|
|
|
+ return "transit";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private int targetYearOrDefault(Integer targetYear) {
|
|
|
|
|
+ return targetYear != null ? targetYear : Calendar.getInstance().get(Calendar.YEAR);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 辅助方法 ====================
|
|
|
|
|
+
|
|
|
|
|
+ private ZodiacConfig findByCode(String zodiacCode) {
|
|
|
|
|
+ return zodiacConfigMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<ZodiacConfig>()
|
|
|
|
|
+ .eq(ZodiacConfig::getZodiacCode, zodiacCode));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private int indexOf(String code) {
|
|
|
|
|
+ for (int i = 0; i < ZODIAC_CODES.length; i++) {
|
|
|
|
|
+ if (ZODIAC_CODES[i].equals(code)) return i;
|
|
|
|
|
+ }
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String findZodiacName(String code) {
|
|
|
|
|
+ int idx = indexOf(code);
|
|
|
|
|
+ return idx >= 0 ? ZODIAC_CN[idx] : code;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private AnnualEnergyResult emptyResult() {
|
|
|
|
|
+ AnnualEnergyResult r = new AnnualEnergyResult();
|
|
|
|
|
+ r.setWesternSign(""); r.setWesternSignCn("");
|
|
|
|
|
+ r.setWesternElement(""); r.setWesternModality("");
|
|
|
|
|
+ r.setZodiacCode(""); r.setZodiacName("");
|
|
|
|
|
+ r.setYearBranch(""); r.setYearRelation("unknown");
|
|
|
|
|
+ r.setJupiterPhase(""); r.setSaturnPhase("");
|
|
|
|
|
+ r.setBody(0); r.setMind(0); r.setWisdom(0);
|
|
|
|
|
+ r.setAction(0); r.setWealth(0);
|
|
|
|
|
+ return r;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|