Просмотр исходного кода

chore: auto bump version and changelog [skip ci]

iwt 1 месяц назад
Родитель
Сommit
4ead8ab7ec

+ 92 - 4
cfc-backend/src/main/java/com/etotem/cfc/service/BeijingNutritionService.java

@@ -755,8 +755,96 @@ public class BeijingNutritionService {
         return result.size() > 15 ? new ArrayList<>(result.subList(0, 15)) : result;
     }
     
-    private boolean isWeekend(java.time.LocalDate date) {
-        return date.getDayOfWeek() == java.time.DayOfWeek.SATURDAY || 
-               date.getDayOfWeek() == java.time.DayOfWeek.SUNDAY;
+    // ============================================================
+    // 均衡化评分引擎
+    // ============================================================
+
+    private static class ScoredIngredient {
+        Long foodId;
+        String name;
+        String category;
+        double bacteriaScore;
+        double nutritionScore;
+        double cookingScore;
+        double energyScore;
+        double compositeScore;
+        String balanceReason;
+    }
+
+    private static class CategoryQuota {
+        int min;
+        int max;
+        CategoryQuota(int min, int max) { this.min = min; this.max = max; }
+    }
+
+    private static final Map<String, CategoryQuota> CATEGORY_QUOTA = new LinkedHashMap<>();
+    static {
+        CATEGORY_QUOTA.put("蔬菜",        new CategoryQuota(2, 3));
+        CATEGORY_QUOTA.put("水果",        new CategoryQuota(1, 2));
+        CATEGORY_QUOTA.put("水产品",      new CategoryQuota(1, 2));
+        CATEGORY_QUOTA.put("肉类",        new CategoryQuota(1, 2));
+        CATEGORY_QUOTA.put("蛋类",        new CategoryQuota(1, 1));
+        CATEGORY_QUOTA.put("豆类及豆制品", new CategoryQuota(1, 2));
+        CATEGORY_QUOTA.put("主食",        new CategoryQuota(1, 2));
+        CATEGORY_QUOTA.put("乳制品",      new CategoryQuota(0, 1));
+        CATEGORY_QUOTA.put("干果",        new CategoryQuota(0, 1));
+        CATEGORY_QUOTA.put("汤",          new CategoryQuota(0, 1));
+        CATEGORY_QUOTA.put("快餐",        new CategoryQuota(0, 0));
+    }
+
+    private static final Map<String, Double> NUTRITION_BASE_SCORE = new HashMap<>();
+    static {
+        NUTRITION_BASE_SCORE.put("蔬菜", 85.0);
+        NUTRITION_BASE_SCORE.put("水果", 80.0);
+        NUTRITION_BASE_SCORE.put("水产品", 80.0);
+        NUTRITION_BASE_SCORE.put("豆类及豆制品", 75.0);
+        NUTRITION_BASE_SCORE.put("蛋类", 70.0);
+        NUTRITION_BASE_SCORE.put("肉类", 65.0);
+        NUTRITION_BASE_SCORE.put("乳制品", 60.0);
+        NUTRITION_BASE_SCORE.put("干果", 55.0);
+        NUTRITION_BASE_SCORE.put("主食", 45.0);
+        NUTRITION_BASE_SCORE.put("汤", 35.0);
+        NUTRITION_BASE_SCORE.put("快餐", 20.0);
+    }
+
+    private static final Set<String> QUICK_COOK_CATEGORIES = Set.of("蔬菜", "蛋类", "水果", "汤");
+    private static final Set<String> MEDIUM_COOK_CATEGORIES = Set.of("豆类及豆制品", "乳制品", "干果", "主食");
+
+    private double scoreBacteria(String direction, Integer recommendIndex) {
+        double base;
+        if ("recommend".equals(direction)) {
+            base = 85.0;
+        } else if ("avoid".equals(direction)) {
+            base = 10.0;
+        } else {
+            base = 50.0;
+        }
+        if (recommendIndex != null) {
+            double norm = (recommendIndex + 33.0) / (75.0 + 33.0) * 2.0 - 1.0;
+            base += norm * 10.0;
+        }
+        return Math.max(0, Math.min(100, base));
+    }
+
+    private double scoreNutrition(String category, Food food) {
+        double base = NUTRITION_BASE_SCORE.getOrDefault(category, 50.0);
+        double bonus = 0;
+        if (food.getProtein() != null && food.getProtein().compareTo(BigDecimal.valueOf(5)) >= 0) bonus += 5;
+        if (food.getFiber() != null && food.getFiber().compareTo(BigDecimal.valueOf(2)) >= 0) bonus += 4;
+        if (food.getFat() != null && food.getFat().compareTo(BigDecimal.valueOf(20)) > 0) bonus -= 5;
+        if (food.getCholesterol() != null && food.getCholesterol().compareTo(BigDecimal.valueOf(100)) > 0) bonus -= 3;
+        return Math.max(0, Math.min(100, base + bonus));
+    }
+
+    private double scoreCooking(String category) {
+        if (QUICK_COOK_CATEGORIES.contains(category)) return 90.0;
+        if (MEDIUM_COOK_CATEGORIES.contains(category)) return 60.0;
+        return 35.0;
+    }
+
+    private double scoreEnergyEfficiency(double nutritionScore, Food food) {
+        BigDecimal energyKj = food.getEnergyKj();
+        if (energyKj == null || energyKj.compareTo(BigDecimal.ZERO) <= 0) return nutritionScore;
+        double ratio = energyKj.doubleValue() / 500.0;
+        return Math.max(0, Math.min(100, nutritionScore / Math.max(ratio, 0.3)));
     }
-}

+ 1 - 1
cfc-web/.last_build_commit

@@ -1 +1 @@
-73f27da9119f68bcf8b487ddfdff7af8bb76a5a8
+d9deaa3b9c73959863ee94d32f345d911aa2eea1

+ 2 - 2
cfc-web/package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "cfc-web",
-  "version": "1.0.1390",
+  "version": "1.0.1391",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "cfc-web",
-      "version": "1.0.1390",
+      "version": "1.0.1391",
       "dependencies": {
         "@wangeditor/editor": "^5.1.23",
         "@wangeditor/editor-for-vue": "^1.0.2",

+ 1 - 1
cfc-web/package.json

@@ -1,6 +1,6 @@
 {
   "name": "cfc-web",
-  "version": "1.0.1391",
+  "version": "1.0.1392",
   "private": true,
   "scripts": {
     "dev": "vue-cli-service serve",

+ 6 - 0
cfc-web/public/CHANGELOG-v1.0.md

@@ -4,6 +4,12 @@
 
 ---
 
+## v1.0.1392 (2026-09-13)
+
+### 新功能
+- 排行榜改用 Redis Sorted Set,游戏积分榜+推荐榜双写降级
+
+
 ## v1.0.1391 (2026-09-13)
 
 ### 新功能

+ 7 - 1
cfc-web/public/CHANGELOG.md

@@ -1,6 +1,6 @@
 # 更新日志
 
-> 当前版本: v1.0.1391
+> 当前版本: v1.0.1392
 
 ## 历史版本
 
@@ -8,6 +8,12 @@
 
 ---
 
+## v1.0.1392 (2026-09-13)
+
+### 新功能
+- 排行榜改用 Redis Sorted Set,游戏积分榜+推荐榜双写降级
+
+
 ## v1.0.1391 (2026-09-13)
 
 ### 新功能