|
@@ -34,6 +34,12 @@ public class FamilyMemberAttributeService extends ServiceImpl<FamilyMemberAttrib
|
|
|
@Resource
|
|
@Resource
|
|
|
private NumSoulConfigMapper numSoulConfigMapper;
|
|
private NumSoulConfigMapper numSoulConfigMapper;
|
|
|
|
|
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private InnatePortraitConfigMapper innatePortraitConfigMapper;
|
|
|
|
|
+
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private NumSoulDetailConfigMapper numSoulDetailConfigMapper;
|
|
|
|
|
+
|
|
|
// ========== Chinese Zodiac constants ==========
|
|
// ========== Chinese Zodiac constants ==========
|
|
|
private static final String[] ZODIAC_CODES = {"rat", "ox", "tiger", "rabbit", "dragon", "snake",
|
|
private static final String[] ZODIAC_CODES = {"rat", "ox", "tiger", "rabbit", "dragon", "snake",
|
|
|
"horse", "sheep", "monkey", "rooster", "dog", "pig"};
|
|
"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
|
|
// Cache the result
|
|
|
if ("mind".equals(dimensionCode)) {
|
|
if ("mind".equals(dimensionCode)) {
|