|
@@ -183,7 +183,16 @@ public class EnergyService {
|
|
|
dto.setMindScore(calcParentMind(parent));
|
|
dto.setMindScore(calcParentMind(parent));
|
|
|
dto.setWisdomScore(calcParentWisdom(parent));
|
|
dto.setWisdomScore(calcParentWisdom(parent));
|
|
|
dto.setActionScore(calcParentAction(parent));
|
|
dto.setActionScore(calcParentAction(parent));
|
|
|
- dto.setWealthScore(calcParentWealth(parent));
|
|
|
|
|
|
|
+ dto.setWealthScore(calcParentWealth(parent, dto));
|
|
|
|
|
+
|
|
|
|
|
+ // 心的子维度(家长暂无数据源,三方面均回0)
|
|
|
|
|
+ dto.setHeartEmotionStable(calcHeartEmotionStableForParent());
|
|
|
|
|
+ dto.setHeartUnderstanding(calcHeartUnderstandingForParent());
|
|
|
|
|
+ dto.setHeartLegacy(calcHeartLegacy());
|
|
|
|
|
+
|
|
|
|
|
+ // v2.0 三轮算法:克环 → 生环(链式调用,避免迭代收敛)
|
|
|
|
|
+ applyAllRestraints(dto);
|
|
|
|
|
+ applyAllBoosts(dto);
|
|
|
|
|
|
|
|
int overall = (safeScore(dto.getBodyScore()) + safeScore(dto.getMindScore())
|
|
int overall = (safeScore(dto.getBodyScore()) + safeScore(dto.getMindScore())
|
|
|
+ safeScore(dto.getWisdomScore()) + safeScore(dto.getActionScore())
|
|
+ safeScore(dto.getWisdomScore()) + safeScore(dto.getActionScore())
|
|
@@ -249,17 +258,36 @@ public class EnergyService {
|
|
|
Arrays.asList("习惯", "好习惯", "自律", "家务", "自理", "作息"), 365);
|
|
Arrays.asList("习惯", "好习惯", "自律", "家务", "自理", "作息"), 365);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /** 家长 富 — 积分积累效率 */
|
|
|
|
|
- private int calcParentWealth(User parent) {
|
|
|
|
|
|
|
+ /** 家长 富 — 三子维度加权 */
|
|
|
|
|
+ private int calcParentWealth(User parent, MemberEnergyDTO dto) {
|
|
|
|
|
+ int income = calcParentWealthIncome(parent);
|
|
|
|
|
+ int achievement = calcParentWealthAchievement(parent);
|
|
|
|
|
+ int network = calcParentWealthNetwork(parent);
|
|
|
|
|
+ dto.setWealthIncome(income);
|
|
|
|
|
+ dto.setWealthAchievement(achievement);
|
|
|
|
|
+ dto.setWealthNetwork(network);
|
|
|
|
|
+ return (int) Math.round(income * 0.5 + achievement * 0.3 + network * 0.2);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 家长富-金钱收入:积分总量/500 */
|
|
|
|
|
+ private int calcParentWealthIncome(User parent) {
|
|
|
Integer totalPoints = parent.getTotalPoints();
|
|
Integer totalPoints = parent.getTotalPoints();
|
|
|
if (totalPoints == null) totalPoints = 0;
|
|
if (totalPoints == null) totalPoints = 0;
|
|
|
-
|
|
|
|
|
- // 参考上限:假设 500 积分为满分
|
|
|
|
|
int refMax = 500;
|
|
int refMax = 500;
|
|
|
int score = Math.min(totalPoints * 100 / Math.max(refMax, 1), 100);
|
|
int score = Math.min(totalPoints * 100 / Math.max(refMax, 1), 100);
|
|
|
return Math.max(score, 0);
|
|
return Math.max(score, 0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /** 家长富-社会成就:第一阶段返回0占位 */
|
|
|
|
|
+ private int calcParentWealthAchievement(User parent) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 家长富-资源网络:第一阶段返回0占位 */
|
|
|
|
|
+ private int calcParentWealthNetwork(User parent) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// ==================== 孩子能量计算 ====================
|
|
// ==================== 孩子能量计算 ====================
|
|
|
|
|
|
|
|
private MemberEnergyDTO calcChildEnergy(FamilyMember child) {
|
|
private MemberEnergyDTO calcChildEnergy(FamilyMember child) {
|
|
@@ -269,11 +297,22 @@ public class EnergyService {
|
|
|
dto.setName(child.getNickname());
|
|
dto.setName(child.getNickname());
|
|
|
dto.setAvatar(null); // 孩子没有独立头像,用默认
|
|
dto.setAvatar(null); // 孩子没有独立头像,用默认
|
|
|
|
|
|
|
|
- dto.setBodyScore(calcChildBody(child));
|
|
|
|
|
|
|
+ int bodyScore = calcChildBody(child);
|
|
|
|
|
+ dto.setBodyScore(bodyScore);
|
|
|
dto.setMindScore(calcChildMind(child));
|
|
dto.setMindScore(calcChildMind(child));
|
|
|
dto.setWisdomScore(calcChildWisdom(child));
|
|
dto.setWisdomScore(calcChildWisdom(child));
|
|
|
dto.setActionScore(calcChildAction(child));
|
|
dto.setActionScore(calcChildAction(child));
|
|
|
- dto.setWealthScore(calcChildWealth(child));
|
|
|
|
|
|
|
+ dto.setWealthScore(calcChildWealth(child, dto));
|
|
|
|
|
+
|
|
|
|
|
+ // 心的子维度(v2.0):用最近一次 DAN 结果填入情绪稳定/理解包容/传承传递
|
|
|
|
|
+ DanAssessmentResult danForHeart = findLatestDanResult(child.getId());
|
|
|
|
|
+ dto.setHeartEmotionStable(calcHeartEmotionStableForChild(child.getId(), danForHeart));
|
|
|
|
|
+ dto.setHeartUnderstanding(calcHeartUnderstandingForChild(child.getId(), danForHeart));
|
|
|
|
|
+ dto.setHeartLegacy(calcHeartLegacy());
|
|
|
|
|
+
|
|
|
|
|
+ // v2.0 三轮算法:克环 → 生环(链式调用,避免迭代收敛)
|
|
|
|
|
+ applyAllRestraints(dto);
|
|
|
|
|
+ applyAllBoosts(dto);
|
|
|
|
|
|
|
|
int overall = (safeScore(dto.getBodyScore()) + safeScore(dto.getMindScore())
|
|
int overall = (safeScore(dto.getBodyScore()) + safeScore(dto.getMindScore())
|
|
|
+ safeScore(dto.getWisdomScore()) + safeScore(dto.getActionScore())
|
|
+ safeScore(dto.getWisdomScore()) + safeScore(dto.getActionScore())
|
|
@@ -513,11 +552,56 @@ public class EnergyService {
|
|
|
return Math.min((int) Math.round(streakScore * 0.4 + habitScore * 0.6), 100);
|
|
return Math.min((int) Math.round(streakScore * 0.4 + habitScore * 0.6), 100);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /** 孩子 富 — 积分获取效率 */
|
|
|
|
|
- private int calcChildWealth(FamilyMember child) {
|
|
|
|
|
|
|
+ /** 孩子 富 — 三子维度加权 */
|
|
|
|
|
+ private int calcChildWealth(FamilyMember child, MemberEnergyDTO dto) {
|
|
|
|
|
+ int edu = calcChildWealthEducation(child);
|
|
|
|
|
+ int social = calcChildWealthSocial(child);
|
|
|
|
|
+ int points = calcChildWealthPoints(child);
|
|
|
|
|
+ dto.setWealthEducation(edu);
|
|
|
|
|
+ dto.setWealthSocial(social);
|
|
|
|
|
+ dto.setWealthPoints(points);
|
|
|
|
|
+ return (int) Math.round(edu * 0.3 + social * 0.2 + points * 0.5);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 孩子富-学业成绩:DAN测评最近3次综合分+进步趋势 */
|
|
|
|
|
+ private int calcChildWealthEducation(FamilyMember child) {
|
|
|
Long childId = child.getId();
|
|
Long childId = child.getId();
|
|
|
|
|
+ LambdaQueryWrapper<DanAssessmentResult> qw = new LambdaQueryWrapper<DanAssessmentResult>()
|
|
|
|
|
+ .eq(DanAssessmentResult::getChildId, childId)
|
|
|
|
|
+ .eq(DanAssessmentResult::getStatus, "completed")
|
|
|
|
|
+ .orderByDesc(DanAssessmentResult::getAssessmentDate)
|
|
|
|
|
+ .last("LIMIT 3");
|
|
|
|
|
+ List<DanAssessmentResult> results = danAssessmentResultMapper.selectList(qw);
|
|
|
|
|
+ if (results.isEmpty()) return 0;
|
|
|
|
|
+
|
|
|
|
|
+ double avg = results.stream()
|
|
|
|
|
+ .filter(r -> r.getOverallScore() != null)
|
|
|
|
|
+ .mapToInt(DanAssessmentResult::getOverallScore)
|
|
|
|
|
+ .average()
|
|
|
|
|
+ .orElse(0);
|
|
|
|
|
+
|
|
|
|
|
+ // 进步趋势:最近一次 vs 前面平均
|
|
|
|
|
+ if (results.size() >= 2 && results.get(0).getOverallScore() != null && results.get(1).getOverallScore() != null) {
|
|
|
|
|
+ int latest = results.get(0).getOverallScore();
|
|
|
|
|
+ double prevAvg = results.subList(1, results.size()).stream()
|
|
|
|
|
+ .filter(r -> r.getOverallScore() != null)
|
|
|
|
|
+ .mapToInt(DanAssessmentResult::getOverallScore)
|
|
|
|
|
+ .average()
|
|
|
|
|
+ .orElse(latest);
|
|
|
|
|
+ double trend = (latest - prevAvg) / Math.max(prevAvg, 1) * 10;
|
|
|
|
|
+ avg += trend;
|
|
|
|
|
+ }
|
|
|
|
|
+ return clamp((int) Math.round(avg), 0, 100);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 孩子富-社交筹码:活动参与次数(第一阶段返回0) */
|
|
|
|
|
+ private int calcChildWealthSocial(FamilyMember child) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 已获得积分: points_log 中正向入账
|
|
|
|
|
|
|
+ /** 孩子富-规则博弈:积分获取效率 */
|
|
|
|
|
+ private int calcChildWealthPoints(FamilyMember child) {
|
|
|
|
|
+ Long childId = child.getId();
|
|
|
Calendar cal = Calendar.getInstance();
|
|
Calendar cal = Calendar.getInstance();
|
|
|
cal.add(Calendar.YEAR, -1);
|
|
cal.add(Calendar.YEAR, -1);
|
|
|
Date oneYearAgo = cal.getTime();
|
|
Date oneYearAgo = cal.getTime();
|
|
@@ -531,7 +615,6 @@ public class EnergyService {
|
|
|
.mapToInt(pl -> pl.getAmount() != null ? pl.getAmount() : 0)
|
|
.mapToInt(pl -> pl.getAmount() != null ? pl.getAmount() : 0)
|
|
|
.sum();
|
|
.sum();
|
|
|
|
|
|
|
|
- // 参考上限: 同期可获得的积分上限
|
|
|
|
|
LambdaQueryWrapper<Task> taskWrapper = new LambdaQueryWrapper<Task>()
|
|
LambdaQueryWrapper<Task> taskWrapper = new LambdaQueryWrapper<Task>()
|
|
|
.eq(Task::getChildId, childId)
|
|
.eq(Task::getChildId, childId)
|
|
|
.ne(Task::getIsTemplate, 1)
|
|
.ne(Task::getIsTemplate, 1)
|
|
@@ -546,7 +629,318 @@ public class EnergyService {
|
|
|
return Math.max(score, 0);
|
|
return Math.max(score, 0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // ==================== 通用方法 ====================
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 身克富杠杆:身体底盘制约财富能量(ke-full-design §克② 重写版)
|
|
|
|
|
+ * - body=0 && wealth=0 → normal(无数据边界保护)
|
|
|
|
|
+ * - 身<50 且 富>身+20 → overdraw(透支预警,不下调)
|
|
|
|
|
+ * - 身<40 → penalty(wealth *= 0.5 + 0.5×身/100,文案"健康正在稀释财富能量")
|
|
|
|
|
+ * - 否则 → normal(身≥70 且 富≥60:双优;身≥70 且 富<40:创富时机;其他:空)
|
|
|
|
|
+ */
|
|
|
|
|
+ private int applyBodyWealthRestraint(Integer bodyScore, Integer wealthScore, MemberEnergyDTO dto) {
|
|
|
|
|
+ int body = safeScore(bodyScore);
|
|
|
|
|
+ int wealth = safeScore(wealthScore);
|
|
|
|
|
+
|
|
|
|
|
+ if (body == 0 && wealth == 0) {
|
|
|
|
|
+ dto.setBodyWealthStatus("normal");
|
|
|
|
|
+ dto.setBodyWealthMessage("");
|
|
|
|
|
+ return wealth;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (body < 50 && wealth > body + 20) {
|
|
|
|
|
+ dto.setBodyWealthStatus("overdraw");
|
|
|
|
|
+ dto.setBodyWealthMessage("财富能量超出身体承受范围,注意劳逸结合");
|
|
|
|
|
+ return wealth;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (body < 40) {
|
|
|
|
|
+ double factor = 0.5 + 0.5 * body / 100.0;
|
|
|
|
|
+ int adjusted = (int) Math.round(wealth * factor);
|
|
|
|
|
+ dto.setBodyWealthStatus("penalty");
|
|
|
|
|
+ dto.setBodyWealthMessage("健康正在稀释财富能量,建议优先关注身体健康");
|
|
|
|
|
+ return Math.max(adjusted, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ dto.setBodyWealthStatus("normal");
|
|
|
|
|
+ if (body >= 70 && wealth >= 60) {
|
|
|
|
|
+ dto.setBodyWealthMessage("身体是财富的底盘,您处于双优状态");
|
|
|
|
|
+ } else if (body >= 70 && wealth < 40) {
|
|
|
|
|
+ dto.setBodyWealthMessage("您的健康基础很好,是启动创富的好时机");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dto.setBodyWealthMessage("");
|
|
|
|
|
+ }
|
|
|
|
|
+ return wealth;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 五行相克(v2.0 克环其余4个 + 统一入口) ====================
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 行克身(木克土)—— 行动社交对身体健康的制约
|
|
|
|
|
+ * - 行>75 且 身<40 → overdraw(身 *= 0.5 + 0.5×身/100,透支)
|
|
|
|
|
+ * - 行>60 且 身>60 → balanced(不下调,身心兼修)
|
|
|
|
|
+ * - 身>70 且 行<30 → cautious(不下调,缺少行动提示)
|
|
|
|
|
+ * - 否则 → normal
|
|
|
|
|
+ */
|
|
|
|
|
+ private int applyActionBodyRestraint(Integer actionScore, Integer bodyScore, MemberEnergyDTO dto) {
|
|
|
|
|
+ int action = safeScore(actionScore);
|
|
|
|
|
+ int body = safeScore(bodyScore);
|
|
|
|
|
+
|
|
|
|
|
+ if (action > 75 && body < 40) {
|
|
|
|
|
+ double penalty = 0.5 + 0.5 * (body / 100.0);
|
|
|
|
|
+ int adjusted = (int) Math.round(body * penalty);
|
|
|
|
|
+ dto.setActionBodyStatus("overdraw");
|
|
|
|
|
+ dto.setActionBodyMessage("行动力很强,但身体在报警。适度暂停,是另一种前进");
|
|
|
|
|
+ return Math.min(adjusted, body);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (action > 60 && body > 60) {
|
|
|
|
|
+ dto.setActionBodyStatus("balanced");
|
|
|
|
|
+ dto.setActionBodyMessage("身心兼修,动态平衡");
|
|
|
|
|
+ return body;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (body > 70 && action < 30) {
|
|
|
|
|
+ dto.setActionBodyStatus("cautious");
|
|
|
|
|
+ dto.setActionBodyMessage("身体底子好,但缺少行动。出门走走,也是养生的一部分");
|
|
|
|
|
+ return body;
|
|
|
|
|
+ }
|
|
|
|
|
+ dto.setActionBodyStatus("normal");
|
|
|
|
|
+ dto.setActionBodyMessage("");
|
|
|
|
|
+ return body;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 富克心(水克火)—— 财富对心(情绪/包容/传承)三层面的侵蚀
|
|
|
|
|
+ * 检测优先级:情绪<40→eruption / 包容<40→judgmental / 传承<20→materialized / 富>70心>65→nourished / normal
|
|
|
|
|
+ */
|
|
|
|
|
+ private int applyWealthHeartRestraint(Integer wealthScore, Integer heartScore, MemberEnergyDTO dto) {
|
|
|
|
|
+ int wealth = safeScore(wealthScore);
|
|
|
|
|
+ int heart = safeScore(heartScore);
|
|
|
|
|
+
|
|
|
|
|
+ int emotionStable = dto.getHeartEmotionStable() != null ? dto.getHeartEmotionStable() : 50;
|
|
|
|
|
+ int understanding = dto.getHeartUnderstanding() != null ? dto.getHeartUnderstanding() : 50;
|
|
|
|
|
+ int legacy = dto.getHeartLegacy() != null ? dto.getHeartLegacy() : 50;
|
|
|
|
|
+
|
|
|
|
|
+ if (wealth > 70 && emotionStable < 40) {
|
|
|
|
|
+ double penalty = 0.4 + 0.6 * (emotionStable / 100.0);
|
|
|
|
|
+ int adjusted = (int) Math.round(heart * penalty);
|
|
|
|
|
+ dto.setWealthHeartStatus("eruption");
|
|
|
|
|
+ dto.setWealthHeartMessage("财富给了底气,也偷走了对家人的耐心。先稳住情绪,再谈其他");
|
|
|
|
|
+ return Math.min(adjusted, heart);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (wealth > 60 && understanding < 40) {
|
|
|
|
|
+ dto.setWealthHeartStatus("judgmental");
|
|
|
|
|
+ dto.setWealthHeartMessage("站在高处久了,可能忘了普通人走路的难处");
|
|
|
|
|
+ return heart;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (wealth > 60 && legacy < 20) {
|
|
|
|
|
+ dto.setWealthHeartStatus("materialized");
|
|
|
|
|
+ dto.setWealthHeartMessage("留给孩子的只有存款,价值观也需要传下去");
|
|
|
|
|
+ return heart;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (wealth > 70 && heart > 65) {
|
|
|
|
|
+ dto.setWealthHeartStatus("nourished");
|
|
|
|
|
+ dto.setWealthHeartMessage("您的财富正在滋养家庭情感,这是最好的传承");
|
|
|
|
|
+ return heart;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ dto.setWealthHeartStatus("normal");
|
|
|
|
|
+ dto.setWealthHeartMessage("");
|
|
|
|
|
+ return heart;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 心克智(火克金)—— 情感关爱对理性培养的制约
|
|
|
|
|
+ * - 心>70 且 智<40 → overprotect(智 *= 0.5+0.5×智/100,过度保护)
|
|
|
|
|
+ * - 智>70 且 心<40 → cold_wise(不下调,理性冷淡提示)
|
|
|
|
|
+ * - 心>60 且 智>60 → balanced(不下调)
|
|
|
|
|
+ * - 否则 → normal
|
|
|
|
|
+ */
|
|
|
|
|
+ private int applyMindWisdomRestraint(Integer mindScore, Integer wisdomScore, MemberEnergyDTO dto) {
|
|
|
|
|
+ int mind = safeScore(mindScore);
|
|
|
|
|
+ int wisdom = safeScore(wisdomScore);
|
|
|
|
|
+
|
|
|
|
|
+ if (mind > 70 && wisdom < 40) {
|
|
|
|
|
+ double penalty = 0.5 + 0.5 * (wisdom / 100.0);
|
|
|
|
|
+ int adjusted = (int) Math.round(wisdom * penalty);
|
|
|
|
|
+ dto.setMindWisdomStatus("overprotect");
|
|
|
|
|
+ dto.setMindWisdomMessage("放手让孩子试错,是培养智慧的第一步");
|
|
|
|
|
+ return Math.min(adjusted, wisdom);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (wisdom > 70 && mind < 40) {
|
|
|
|
|
+ dto.setMindWisdomStatus("cold_wise");
|
|
|
|
|
+ dto.setMindWisdomMessage("智慧需要温度,不然长大了只会做事不会做人");
|
|
|
|
|
+ return wisdom;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (mind > 60 && wisdom > 60) {
|
|
|
|
|
+ dto.setMindWisdomStatus("balanced");
|
|
|
|
|
+ dto.setMindWisdomMessage("爱与理性并行,是最好的教育");
|
|
|
|
|
+ return wisdom;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ dto.setMindWisdomStatus("normal");
|
|
|
|
|
+ dto.setMindWisdomMessage("");
|
|
|
|
|
+ return wisdom;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 智克行(金克木)—— 认知分析对人际关系的制约
|
|
|
|
|
+ * - 智<30 且 行>50 → blind(行 *= 0.6+0.4×智/100,盲目社交下调)
|
|
|
|
|
+ * - 智>80 且 行<40 → paralysis(不下调,认知孤独预警)
|
|
|
|
|
+ * - 智>60 且 行>60 → balanced(不下调)
|
|
|
|
|
+ * - 否则 → normal
|
|
|
|
|
+ */
|
|
|
|
|
+ private int applyWisdomActionRestraint(Integer wisdomScore, Integer actionScore, MemberEnergyDTO dto) {
|
|
|
|
|
+ int wisdom = safeScore(wisdomScore);
|
|
|
|
|
+ int action = safeScore(actionScore);
|
|
|
|
|
+
|
|
|
|
|
+ if (wisdom < 30 && action > 50) {
|
|
|
|
|
+ double penalty = 0.6 + 0.4 * (wisdom / 100.0);
|
|
|
|
|
+ int adjusted = (int) Math.round(action * penalty);
|
|
|
|
|
+ dto.setWisdomActionStatus("blind");
|
|
|
|
|
+ dto.setWisdomActionMessage("行动力很强,但有方向会让努力更有效。建议先做一次测评");
|
|
|
|
|
+ return Math.min(adjusted, action);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (wisdom > 80 && action < 40) {
|
|
|
|
|
+ dto.setWisdomActionStatus("paralysis");
|
|
|
|
|
+ dto.setWisdomActionMessage("聪明不等于会相处。朋友不是用逻辑交来的");
|
|
|
|
|
+ return action;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (wisdom >= 60 && action >= 60) {
|
|
|
|
|
+ dto.setWisdomActionStatus("balanced");
|
|
|
|
|
+ dto.setWisdomActionMessage("知行合一状态,继续保持");
|
|
|
|
|
+ return action;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ dto.setWisdomActionStatus("normal");
|
|
|
|
|
+ if (action >= 60 && wisdom < 50) {
|
|
|
|
|
+ dto.setWisdomActionMessage("行动力很好,建议增加测评了解方向");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dto.setWisdomActionMessage("");
|
|
|
|
|
+ }
|
|
|
|
|
+ return action;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 五行相克统一入口 — 按克环顺序:行克身→身克富→富克心→心克智→智克行。
|
|
|
|
|
+ * 关键:每个克方法使用前一个克方法调整后的分值(链式调用,避免迭代收敛问题)。
|
|
|
|
|
+ */
|
|
|
|
|
+ private void applyAllRestraints(MemberEnergyDTO dto) {
|
|
|
|
|
+ int bodyAdj = applyActionBodyRestraint(dto.getActionScore(), dto.getBodyScore(), dto);
|
|
|
|
|
+ dto.setBodyScore(bodyAdj);
|
|
|
|
|
+
|
|
|
|
|
+ int wealthAdj = applyBodyWealthRestraint(dto.getBodyScore(), dto.getWealthScore(), dto);
|
|
|
|
|
+ dto.setWealthScore(wealthAdj);
|
|
|
|
|
+
|
|
|
|
|
+ int mindAdj = applyWealthHeartRestraint(dto.getWealthScore(), dto.getMindScore(), dto);
|
|
|
|
|
+ dto.setMindScore(mindAdj);
|
|
|
|
|
+
|
|
|
|
|
+ int wisdomAdj = applyMindWisdomRestraint(dto.getMindScore(), dto.getWisdomScore(), dto);
|
|
|
|
|
+ dto.setWisdomScore(wisdomAdj);
|
|
|
|
|
+
|
|
|
|
|
+ int actionAdj = applyWisdomActionRestraint(dto.getWisdomScore(), dto.getActionScore(), dto);
|
|
|
|
|
+ dto.setActionScore(actionAdj);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 五行相生(v2.0 生环5个 + 统一入口) ====================
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 生增益统一公式:boost = (upstream-50)/100×10,仅当 upstream>60 且 downstream<80 触发,
|
|
|
|
|
+ * 上限 80-downstream(留成长空间)。
|
|
|
|
|
+ */
|
|
|
|
|
+ private int applyBoost(Integer upstreamScore, Integer downstreamScore) {
|
|
|
|
|
+ int up = safeScore(upstreamScore);
|
|
|
|
|
+ int down = safeScore(downstreamScore);
|
|
|
|
|
+ if (up > 60 && down < 80) {
|
|
|
|
|
+ double boost = (up - 50) / 100.0 * 10;
|
|
|
|
|
+ int room = 80 - down;
|
|
|
|
|
+ int gain = (int) Math.round(boost);
|
|
|
|
|
+ if (gain > room) gain = room;
|
|
|
|
|
+ if (gain < 0) gain = 0;
|
|
|
|
|
+ return down + gain;
|
|
|
|
|
+ }
|
|
|
|
|
+ return down;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 心生身(火生土) */
|
|
|
|
|
+ private int applyMindBodyBoost(Integer mindScore, Integer bodyScore, MemberEnergyDTO dto) {
|
|
|
|
|
+ return applyBoost(mindScore, bodyScore);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 身生智(土生金) */
|
|
|
|
|
+ private int applyBodyWisdomBoost(Integer bodyScore, Integer wisdomScore, MemberEnergyDTO dto) {
|
|
|
|
|
+ return applyBoost(bodyScore, wisdomScore);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 智生富(金生水) */
|
|
|
|
|
+ private int applyWisdomWealthBoost(Integer wisdomScore, Integer wealthScore, MemberEnergyDTO dto) {
|
|
|
|
|
+ return applyBoost(wisdomScore, wealthScore);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 富生行(水生木) */
|
|
|
|
|
+ private int applyWealthActionBoost(Integer wealthScore, Integer actionScore, MemberEnergyDTO dto) {
|
|
|
|
|
+ return applyBoost(wealthScore, actionScore);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 行生心(木生火) */
|
|
|
|
|
+ private int applyActionMindBoost(Integer actionScore, Integer mindScore, MemberEnergyDTO dto) {
|
|
|
|
|
+ return applyBoost(actionScore, mindScore);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 五行相生统一入口 — 按生环顺序:心生身→身生智→智生富→富生行→行生心。
|
|
|
|
|
+ * 链式调用,每个生方法使用前一个的输出作为下游输入。
|
|
|
|
|
+ */
|
|
|
|
|
+ private void applyAllBoosts(MemberEnergyDTO dto) {
|
|
|
|
|
+ dto.setBodyScore(applyMindBodyBoost(dto.getMindScore(), dto.getBodyScore(), dto));
|
|
|
|
|
+ dto.setWisdomScore(applyBodyWisdomBoost(dto.getBodyScore(), dto.getWisdomScore(), dto));
|
|
|
|
|
+ dto.setWealthScore(applyWisdomWealthBoost(dto.getWisdomScore(), dto.getWealthScore(), dto));
|
|
|
|
|
+ dto.setActionScore(applyWealthActionBoost(dto.getWealthScore(), dto.getActionScore(), dto));
|
|
|
|
|
+ dto.setMindScore(applyActionMindBoost(dto.getActionScore(), dto.getMindScore(), dto));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 心的子维度(v2.0 心三层拆分) ====================
|
|
|
|
|
+
|
|
|
|
|
+ /** 心·情绪稳定 — 孩子:DAN EMI 三子分(emotionManagement+resilience+stressCoping)均值。
|
|
|
|
|
+ * 文档原 emotionCheckinService 在本项目不存在,用此现有 DAN 字段做代理实现。 */
|
|
|
|
|
+ private int calcHeartEmotionStableForChild(Long childId, DanAssessmentResult dan) {
|
|
|
|
|
+ if (dan == null) return 50;
|
|
|
|
|
+ Integer ems = dan.getEmotionManagementScore();
|
|
|
|
|
+ Integer resilience = dan.getResilienceScore();
|
|
|
|
|
+ Integer stress = dan.getStressCopingScore();
|
|
|
|
|
+ if (ems == null || resilience == null || stress == null) return 50;
|
|
|
|
|
+ return clamp((ems + resilience + stress) / 3, 0, 100);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 心·情绪稳定 — 家长:暂无数据,回0(ke-full-design 维度表显式标注) */
|
|
|
|
|
+ private int calcHeartEmotionStableForParent() {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 心·理解包容 — 孩子:DAN (empathy+socialAdaptability)/2。
|
|
|
|
|
+ * 文档原家庭天盘 helper 不存在,按 doc §克③ line 295-296 用 100% DAN fallback。 */
|
|
|
|
|
+ private int calcHeartUnderstandingForChild(Long childId, DanAssessmentResult dan) {
|
|
|
|
|
+ if (dan == null) return 50;
|
|
|
|
|
+ Integer empathy = dan.getEmpathyScore();
|
|
|
|
|
+ Integer social = dan.getSocialAdaptabilityScore();
|
|
|
|
|
+ if (empathy == null || social == null) return 50;
|
|
|
|
|
+ return clamp((empathy + social) / 2, 0, 100);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 心·理解包容 — 家长:暂无数据,回0 */
|
|
|
|
|
+ private int calcHeartUnderstandingForParent() {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 心·传承传递 — 第一阶段回0占位(孩子+家长通用) */
|
|
|
|
|
+ private int calcHeartLegacy() {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 计算指定成员的任务完成率得分 (0-100)
|
|
* 计算指定成员的任务完成率得分 (0-100)
|