Procházet zdrojové kódy

feat: calcInnateScore 可配置权重+数字能量参与

Xiaogang Liao před 3 týdny
rodič
revize
d128bd4e10

+ 54 - 3
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyMemberAttributeService.java

@@ -34,6 +34,12 @@ public class FamilyMemberAttributeService extends ServiceImpl<FamilyMemberAttrib
     @Resource
     private NumSoulConfigMapper numSoulConfigMapper;
 
+    @Resource
+    private InnatePortraitConfigMapper innatePortraitConfigMapper;
+
+    @Resource
+    private NumSoulDetailConfigMapper numSoulDetailConfigMapper;
+
     // ========== Chinese Zodiac constants ==========
     private static final String[] ZODIAC_CODES = {"rat", "ox", "tiger", "rabbit", "dragon", "snake",
             "horse", "sheep", "monkey", "rooster", "dog", "pig"};
@@ -292,9 +298,54 @@ public class FamilyMemberAttributeService extends ServiceImpl<FamilyMemberAttrib
             }
         }
 
-        // --- Weighted sum: zodiac×50% + bazi×30% + blood×20% ---
-        // Weights in bps: 50% = 5000, 30% = 3000, 20% = 2000
-        Integer result = (zodiacScore * 5000 + baziScore * 3000 + bloodScore * 2000) / 10000;
+        // --- Weighted sum with configurable weights from innate_portrait_config ---
+        // 1) Read enabled sources + weights
+        List<InnatePortraitConfig> configs = innatePortraitConfigMapper.selectList(
+                new LambdaQueryWrapper<InnatePortraitConfig>().eq(InnatePortraitConfig::getEnabled, 1)
+                        .orderByAsc(InnatePortraitConfig::getSortOrder));
+        if (configs.isEmpty()) {
+            // Fallback to legacy fixed weights: zodiac 50%, bazi 30%, blood 20%
+            Integer result = (zodiacScore * 5000 + baziScore * 3000 + bloodScore * 2000) / 10000;
+            if ("mind".equals(dimensionCode)) {
+                attrs.setMindBaseScore(result);
+            } else {
+                attrs.setWisdomBaseScore(result);
+            }
+            this.updateById(attrs);
+            return result;
+        }
+
+        // 2) Build source score map (sourceType -> score)
+        Map<String, Integer> sourceScores = new LinkedHashMap<>();
+        sourceScores.put("zodiac", zodiacScore);
+        sourceScores.put("bazi", baziScore);
+        sourceScores.put("blood", bloodScore);
+        // numsoul contribution
+        Integer numsoulScore = 0;
+        if ("mind".equals(dimensionCode)) {
+            if (attrs.getBirthDatetime() != null) {
+                Calendar cal2 = Calendar.getInstance();
+                cal2.setTime(attrs.getBirthDatetime());
+                int lifePath = NumSoulCalculator.calcLifePath(cal2.get(Calendar.YEAR), cal2.get(Calendar.MONTH) + 1, cal2.get(Calendar.DAY_OF_MONTH));
+                NumSoulDetailConfig nsCfg = numSoulDetailConfigMapper.selectOne(
+                        new LambdaQueryWrapper<NumSoulDetailConfig>()
+                                .eq(NumSoulDetailConfig::getNumberType, "life_path")
+                                .eq(NumSoulDetailConfig::getNumberValue, lifePath));
+                numsoulScore = nsCfg != null && nsCfg.getMindBase() != null ? nsCfg.getMindBase() : 0;
+            }
+        }
+        sourceScores.put("numsoul", numsoulScore);
+
+        // 3) Weighted sum
+        long numerator = 0;
+        long denominator = 0;
+        for (InnatePortraitConfig cfg : configs) {
+            int weight = cfg.getWeight() != null ? cfg.getWeight() : 2500;
+            int score = sourceScores.getOrDefault(cfg.getSourceType(), 0);
+            numerator += (long) score * weight;
+            denominator += weight;
+        }
+        int result = denominator > 0 ? (int) Math.round((double) numerator / denominator) : 0;
 
         // Cache the result
         if ("mind".equals(dimensionCode)) {