输入关键词开始搜索

推荐引擎算法

501. 每日菜单推荐引擎算法

日期: 2026-05-20 关联开发任务: 阶段 5 任务 5.1~5.2 菜单生成+推荐算法 关联设计文档: 003.详细设计文档 §3、005.接口设计文档 TDEE 公式


一、算法目标

根据用户 TDEE、饮食模式、用餐人数,为每餐智能推荐菜品组合,使全天营养摄入接近目标且菜品多样化。


二、核心公式

2.1 每餐热量目标

全天目标 = 用户 TDEE × 饮食模式系数 × 用餐人数
每餐目标 = 全天目标 × 餐段比例

饮食模式系数: 减脂 0.80 / 增肌 1.15 / 维持 1.00 / 聚餐 1.30 / 放纵 1.20
餐段比例:   减脂/增肌 → 早 0.22  午 0.42  晚 0.36
            维持/聚餐 → 早 0.20  午 0.45  晚 0.35

2.2 营养比例目标

理想宏量比: 蛋白质 30% / 碳水 50% / 脂肪 20%

蛋白质目标(g) = 热量目标 × 0.30 ÷ 4
碳水目标(g)   = 热量目标 × 0.50 ÷ 4
脂肪目标(g)   = 热量目标 × 0.20 ÷ 9

2.3 份数换算

选定份数 sv (0.5 ~ maxSv, 步进 0.5)
maxSv = 用餐人数 × 2.5 (上限 10)

菜品贡献 = 整份营养 × (sv ÷ 默认份数)

三、贪心选菜评分

对每个候选菜谱 × 每个可选份数 {
    calScore = 100 - |(已选热量+新热量-目标)/目标| × 100

    严格度判断(来自饮食模式):
      减脂/增肌 → tolerance = ±10%, 超限得分×0.3
      维持/聚餐 → tolerance = ±30%, 超限得分×0.3

    营养比例惩罚:
      计算(已选+新选)后的蛋白/碳水/脂肪比
      macroPenalty = |蛋白比-0.30| + |碳水比-0.50| + |脂肪比-0.20| (×100)
      calScore -= macroPenalty × 0.5

    份数惩罚:
      if sv > maxSv × 0.5: calScore -= (sv - maxSv×0.5) × 15

    取 calScore 最高的 (菜谱, 份数) 组合
}

四、约束规则

约束规则
全天不重复三餐不能出现相同菜谱(早/晚之间允许)
锁定菜品已锁定菜不被清除,份数可手动调节
份数范围0.5 ~ 人数×2.5(≤10),步进 0.5

五、数据流

HomePage(QML)
  ↓ gen(mt, cnt, dietMode, dinerCount)
MenuService::generateMenu()
  ├── 读取用户 TDEE (AuthService::getUserTdee)
  ├── 计算每餐营养目标
  ├── 收集今日所有餐已选菜品(全天去重)
  ├── 贪心循环(need 次):
  │   └── 遍历候选×份数 → 评分 → 选最优
  └── 写入 menu_items (含 servings_override)
  ↓ loadMenu()
HomePage 刷新卡片 + Canvas 双柱图

六、验证

场景期望
减脂模式每餐热量严格 ±10%,全天菜品不重复
2人用餐份数上限 5.0
一键全天生成三餐各有不同菜品,无重复
手动调份数±0.5 份,营养摘要实时更新
锁定 2 道再生成锁定菜保留,新菜补足到目标道数