推荐引擎算法
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 道再生成 | 锁定菜保留,新菜补足到目标道数 |