by paraboy-s
麦当劳配餐决策 Skill|1881 种搭配里算出三档最优解,并告诉你为什么不是另外那些。控卡、忌口、拼单 max-min 公平分配;LLM 不参与算钱,每个数字可追溯。
# Add to your Claude Code skills
git clone https://github.com/paraboy-s/mcd-meal-pairingGuides for using ai agents skills like mcd-meal-pairing.
See how mcd-meal-pairing compares with popular alternatives.
mcd-meal-pairing is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by paraboy-s. 麦当劳配餐决策 Skill|1881 种搭配里算出三档最优解,并告诉你为什么不是另外那些。控卡、忌口、拼单 max-min 公平分配;LLM 不参与算钱,每个数字可追溯。. It has 50 GitHub stars.
mcd-meal-pairing's catalog security scan is still queued. You can run an instant dependency and prompt-injection check now with the "Scan for vulnerabilities" button above.
Clone the repository with "git clone https://github.com/paraboy-s/mcd-meal-pairing" and add it to your Claude Code skills directory (see the Installation section above). mcd-meal-pairing ships a SKILL.md manifest, so compatible agents can discover and load it automatically.
mcd-meal-pairing is primarily written in Python. It is open-source under paraboy-s on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh mcd-meal-pairing against similar tools.
No comments yet. Be the first to share your thoughts!
Available after the catalog security scan passes.
⚠️ Third-Party Software Notice
This skill is third-party open-source software developed and hosted independently on GitHub. SkillsLLM is an informational directory and does not control or maintain the underlying repository.
Any security checks, ratings, or warnings displayed by SkillsLLM are automated and limited in scope. They do not constitute a security certification or guarantee that the software is safe, error-free, or free from malicious code, vulnerabilities, compromised dependencies, or prompt-injection risks.
Review the source code, permissions, dependencies, and configuration before installing or running any third-party skill. Use is at your own risk. To the maximum extent permitted by applicable law, SkillsLLM is not liable for losses arising from third-party software.
The deep catalog scan for this skill is still queued. Run an instant dependency check now instead.
不推荐套餐,只做最优配对。 你说一句「随便」,它算完上千种搭配,给你三档方案,并告诉你为什么不是另外那些。
scripts/pair.py 的计算结果。接口没给的,就说「这个我查不到」,不要估。query-meals 返回过的商品。名字必须逐字照抄,不能写成你以为的简称。dataStatus.issues 里每一条都要在回复里说清楚(用了离线数据、券没取到、套餐构成是推断的),不能当作没看见。pair.py 返回 ok: false,把 error 原样告诉用户。绝对不要因为脚本挂了就自己心算一个方案——那正是本项目要消灭的行为。| 用户说的话 | 模式 |
|---|---|
| 「我想吃」「帮我配一份」「今天中午」 | solo |
| 「我们」「同事」「一起点」「AA」「三个人」「带娃」 | squad |
只有一个人吃,就 solo。提到两个人以上共同吃一单,才切 squad。
「我和朋友各点各的」仍是 solo,不要自作主张合并。
先 now-time-info 拿准当前时间(券的可用性完全依赖它),再并行取以下数据。
| 工具 | 参数 | 用途 | 缺失后果 |
|---|---|---|---|
query-meals |
storeCode、orderType、beType |
门店在售商品与真实价格 | 无法计算,必须拿到 |
list-nutrition-foods |
无 | 营养表(热量/蛋白/脂肪/钠/钙) | 热量与控卡失效 |
query-my-coupons |
无 | 用户持有的券 | 算不出券抵扣 |
order-list |
无 | 历史订单 → 口味画像 | 画像为空,只能按中性口味配 |
门店未知时先 query-nearby-stores(beType=1 到店自取 / 5 得来速;searchType=1 收藏门店,2 按城市+关键词搜索)。
orderType=1, beType=1,不传 beCodeorderType=2, beType=2,必传 beCodeorderType=1, beType=5,必传 beCodeorder-list 拿不到不要报错,画像为空是正常状态,等于「第一次来」。此时不要编造口味,直接按中性口味配。
query-meals 的返回是三层结构,注意 meals 是 map 不是数组:
data.categories[] → 分类名(饮品 / 鸡肉汉堡 / 小食甜品 …)
data.categories[].meals[] → { code, tags } ← tags 里有「套餐」「单品」
data.meals.{code} → { name, currentPrice, originalPrice } ← 价格是字符串
data.frequent → 我的常点
把 query-meals 的原始 data 整块塞进 payload 的 menu 字段即可,解析交给脚本。不要自己拍平、不要自己改字段名、不要四舍五入价格——脚本已经处理了 map 结构、字符串价格、套餐标签和周边过滤。
| 工具 | 返回格式 | 怎么放进 payload |
|---|---|---|
query-meals |
JSON(data.categories + data.meals) |
"menu": <整个 data 对象> |
list-nutrition-foods |
JSON 数组 | "nutrition": <数组> |
query-my-coupons |
Markdown 文本(给人读的,不是 JSON) | "coupons": "<整段文本>" |
order-list |
JSON(data.list[],明细叫 orderProductList) |
"orders": <整个 data 对象> |
query-my-coupons 返回长这样,原样当字符串传,脚本用正则解析:
## 11.9元麦辣鸡腿堡
- **优惠**: ¥11.9 (用券价格)
- **有效期**: 2026-10-19 10:30-2026-10-23 23:59 周一、二、三、四、五 10:30-23:59
- **标签**: 到店专用、外送专用
不要自己从这段文本里抄价格——抄错一位,整单就错了。交给脚本解析,解析不出来它会记进 issues。
构造一个 JSON 对象。除 menus/constraints 外都可以省略。
{
"mode": "solo",
"now": "2026-10-19 12:30",
"channel": "到店",
"constraints": {
"budget": 40,
"kcalCap": 600,
"proteinMin": 0,
"avoid": ["spicy", "beef"],
"needDrink": false
},
"store": {"storeCode": "1950064", "storeName": "麦当劳北京和平街北口餐厅"},
"menu": { "categories": [...], "meals": {...} },
"nutrition": [ ... list-nutrition-foods 的返回 ... ],
"coupons": "## 11.9元麦辣鸡腿堡\n- **优惠**: ¥11.9 (用券价格)\n- **有效期**: ...",
"orders": { "list": [ ... order-list 的 data.list ... ] }
}
squad 模式把 constraints 换成 budget + members:
{
"mode": "squad",
"budget": 100,
"now": "2026-10-19 12:30",
"members": [
{"name": "小明", "kcalCap": 600, "avoid": ["spicy"], "budget": 34,
"taste": "chicken", "spiceTolerance": 0.15},
{"name": "小美", "taste": "beef", "budget": 40},
{"name": "老王", "taste": "chicken", "spiceTolerance": 0.9, "budget": 40}
],
"store": {...}, "menu": {...}, "nutrition": [...], "coupons": [...]
}
成员字段全部来自用户亲口说的内容,没说就留空:
| 用户说 | 字段 |
|---|---|
| 「我控制在 600 大卡」 | kcalCap: 600 |
| 「我不吃辣」 | avoid: ["spicy"] |
| 「我最多花 34」 | budget: 34 |
| 「我想吃牛肉的」 | taste: "beef" |
| 「我能吃辣」 | spiceTolerance: 0.9 |
没有提到的不要编。 编了就等于替用户决定,而他并没有说过。
avoid 可选值:beef chicken fish pork spicy fried dessert。
用户说「不吃牛肉」写 beef,说「不吃辣」写 spicy——不要说「不吃辣」就顺手把 beef 也加上。
cd <本 Skill 根目录>
echo '<payload JSON>' | python scripts/pair.py
只想验证安装是否成功、或没有 Token 时:
python scripts/pair.py --demo
脚本输出一个 JSON 对象,ok 为 true 才算成功。所有数字以它为准。
如果 dataStatus.issues 非空,说明部分数据缺失或为推断值,渲染时必须转述。
按下面的结构输出,不要一次性倒出全部字段。
从 {stats.enumerated} 种搭配里筛出 {stats.passed} 组可行。(可选,一句话)
{profile.labels 用「 / 」连接}(置信度 {profile.confidence})
{profile.surprise —— 有就放在这里,这是最容易被记住的一句话}
**方案一 · {tiers[0].label}** ¥{tiers[0].netPrice}
{items 名称,用「 + 」连接}
{tiers[0].kcal} kcal · 蛋白 {tiers[0].protein} g
{rationale 第一条,或券的信息}
**方案二 · {tiers[1].label}** …(同上)
**方案三 · {tiers[2].label}** …(同上)
{如果有 couponNotes,用两三行转述最要紧的那条}
三条硬要求:
tierSpread 小于 5 时,把 spreadNote 说出来:「三档只差 ¥x,不是没算开,是约束把空间压窄了」{party} 人拼单 · 预算池 ¥{budget}
最公平的一单 ¥{options[0].netPrice}
{购物车:名称 ×份数,用「、」连接}
{member.name} ¥{member.pay} 满意度 {member.score}({member.kcal} kcal)
{member.notes 逐条列出,没有就省略这一行}
最不满意的是 {min score 的成员}({score})——这是 max-min 解:它不追求总分最高,
只保证最不满意的人不被牺牲。
拼单绝对不要说「已为你们优化到最优」。 目标是 max-min,不是总和最优。正确说法是「最不满意的是小美(0.77),这套方案保证这个数被抬到最高」。
成员问「凭什么我少吃了」时,直接引用该成员的 notes,不要重新组织语言——那是引擎算出来的让步,不是话术。
| 用户说 | 动作 |
|---|---|
| 「还有更便宜的吗」 | budget 乘以 0.8 重跑,或直接讲省钱档 |
| 「热量再低点」 | kcalCap 设为当前值的 0.85 重跑 |
| 「这个券怎么用」 | 只讲 couponNotes,说清生效日、时段、渠道 |
| 「就它了」 | 输出商品清单与到手价,提示到官方渠道下单 |
| 「为什么不是 X」 | 引用 eliminated 里 X 的 reasons |
| 「加钱能吃到什么」 | 引用 counterfactuals |
追问时沿用上一轮的约束,只改用户指定的那一项。
这些都是真实踩过的,别重复踩:
| 现象 | 原因 | 怎么处理 |
|---|---|---|
| 推荐了帽子、徽章、毛绒玩具 | 菜单接口混入周边商品 | 脚本已过滤,若仍出现就报告 |
| 三件套热量只有 300 多 | 套餐名被模糊匹配到单品营养 | 已修复:套餐禁止借用单品热量,算不出就标 missing 并排除 |
| 薯条被当成饮料 | 分类名把薯条挂在「饮品」下 | 判定顺序已改为「标签 > 商品名 > 分类」 |
| 「脆汁鸡」被当成饮品 | 名字含「汁」 | 已修复 |
| 券永远匹配不上 | 券面写「麦辣鸡腿堡」,菜单叫「麦辣鸡腿汉堡」 | 有别名归一 + 内置对照表 |
meals 遍历出的是编码不是商品 |
它是 map 不是数组 | 整块传进 payload,别自己遍历 |
dataStatus.issues 会说明。nutrientSource 会是 composed,需要说明。now 为准。默认用真实当前时间,不要自己假设「现在是中午」。¥kcal;蛋白取整,单位 g"堡" 你欢乐套餐、【美汁源】"多汁柠柠")不推荐套餐,只做最优配对。
你说一句「40 块以内,随便」,它在门店实时菜单上枚举 1881 种搭配,剪枝出 1326 组可行解,给你三档方案——并告诉你为什么不是另外那些。
这个项目里,LLM 不参与算钱。价格、热量、用券全部由确定性代码算出,每个数字都能追溯到某一次 MCP 工具返回。
→ 打开输出预览页 三个真实场景的完整输出——预算 40、减脂 600 大卡、三人拼单 100 元。打开即看,不需要 Token、不需要安装。
三档方案之外,它会说三句别的推荐说不出的话:
关于预算 —— 「预算从 ¥40 加到 ¥48,均衡档的主餐不会变。再往上加钱,只会让你多一份小食或甜品,换不到更好的主餐。」
关于券 —— 「当前时刻你的 6 张券一张都用不了。最近可用:巧克力味厚松饼猪柳蛋套餐,10-18 05:00,约 10.1 小时后。」
关于你 —— 「2 张券指向你几乎不点的品类——券不是没用,是没发对人。」
还有被淘汰的那些,为什么不选:
精选超值随心配 ¥13.9 · 461 kcal —— 各项指标被同价位方案全面压制
麦麦脆汁鸡1块 ¥24.9 · 495 kcal —— 口味契合比均衡档低 27%
「为什么不是那些」比「为什么是这个」更难回答,也更有用。
让模型直接推荐套餐,几乎必然出现三个问题:
这个 Skill 的做法是:把「说话」和「算账」拆开。
模型理解「帮我配个 40 以内的、不要辣」之后,就不再参与计算。所有金额与热量来自门店接口与求解器的真实运算,可复现、可对账。
| 你会问 | 它怎么答 | 对应引擎 |
|---|---|---|
| 「40 以内吃点什么好」 | 三档方案,每档强制不同主餐,价格与热量单调递增 | solver_engine |
| 「我有 6 张券,该用哪张」 | 按生效日 / 时段 / 渠道逐张判定,算最优抵扣,并告诉你凑单是真优惠还是多花钱 | coupon_engine |
| 「这券什么时候能用」 | 「最近可用在 10.1 小时后」——不糊弄,直接给时刻 | coupon_engine |
| 「我在控卡,600 以内」 | 热量上限与蛋白下限是硬约束,算不出就直说,不拿估算值凑 | solver_engine + guard_engine |
| 「不吃辣、也不要牛肉」 | 按蛋白类型与辣度做硬否决,不靠模型理解「不要辣」是什么意思 | guard_engine |
| 「再加点钱能换到什么」 | 反事实:预算 +8 元后主餐变不变、变哪一款 | explain_engine |
| 「我们四个人,100 块」 | max-min 公平分配 + 分账,并把每个人的让步摆到台面上 | squad_engine |
还有个开场白是别人给不了的:
「你 7 单里 0 单牛肉——你可能以为自己是巨无霸党,但数据不是这么说的。」
这句不是话术,是从 order-list 的真实订单里算出来的,还带置信度(0.52,样本少时会直说「有 48% 的可能我判断错了」)。
| 人群 | 他们的原话 | 为什么现有推荐解决不了 |
|---|---|---|
| 写字楼午餐决策者 | 「随便,别超 40」 | 「随便」不是没需求,是需求太多说不出口。他需要的是一个已经算完的答案,不是十个选项 |
| 控卡与健身人群 | 「600 大卡以内,还要有饮料」 | 模型报的热量是估的。差 300 大卡不是误差,是这一顿白控了 |
| 券的持有者 | 「我有 6 张券,到底该用哪张」 | 券有时段、有渠道、有门槛。用错一张,或者为了凑单多花 8 块 |
| 团队拼单的组织者 | 「我们四个人,100 块」 | 四个人诉求互斥时,平均满意度最高的方案往往让某个人吃亏——而那个人不会当场说 |
不适合谁(写清楚边界,比夸大适用范围更可信):
前置条件:麦当劳 MCP Token(从 麦当劳 MCP 控制台 申请)。
git clone https://github.com/paraboy-s/mcd-meal-pairing ~/.workbuddy/skills/mcd-meal-pairing
Windows 对应
%USERPROFILE%\.workbuddy\skills\mcd-meal-pairing。
WorkBuddy → 左侧【专家·技能·连接器】→【连接器】→ 右上角【自定义连接器】→【配置 MCP】:
{
"mcpServers": {
"mcd-mcp": {
"type": "streamablehttp",
"url": "https://mcp.mcd.cn",
"headers": { "Authorization": "Bearer YOUR_MCP_TOKEN" }
}
}
}
把 YOUR_MCP_TOKEN 换成实际 Token,保存并启用。
直接在对话框里说人话:
我中午想吃麦当劳,40 块以内,不要辣
Skill 会自动取门店菜单、营养表、你的券和点餐史,算完给你三档方案。
cd ~/.workbuddy/skills/mcd-meal-pairing
python scripts/pair.py --demo
输出(真实结果,非示意图 —— 完整 JSON 见 预览页):
枚举 1881 种搭配 → 1326 组可行
省钱档 ¥14.9 582 kcal 人气经典随心配
均衡档 ¥34.5 827 kcal 板烧鸡腿堡三件套(原价 ¥48,让利 ¥13.5)
放纵档 ¥39.5 920 kcal 板烧鸡腿堡三件套 + 圆筒冰淇淋
品味指纹 鸡肉党 / 不碰辣 · 置信度 0.52 · 7 单里 0 单牛肉
反事实 预算加到 ¥48,均衡档主餐不变
券诊断 6 张券当前一张都用不了,最近可用在 10.1 小时后
--demo 用的是 fixtures/ 里固化的真实接口截面(2026-10-17 18:57),零依赖、零 Token。
输出里那句「鸡肉党 / 不碰辣」,背后是 9 个可复算的数字。taste_engine 把每件商品按名字归类(板烧→鸡肉、麦辣→辣+炸、圆筒→甜品),再按时间衰减加权(半衰期 180 天,越近的订单权重越高),压成 9 维向量:
| 维度 | 这 7 单算出来 | 计算方式 |
|---|---|---|
| 鸡肉 / 牛肉 / 鱼肉 / 猪柳占比 | 1.00 / 0 / 0 / 0 | 主餐蛋白源加权占比,四维之和恒为 1 |
| 辣度耐受 | 0.06 | 辣味件数 ÷ 主餐件数 |
| 油炸倾向 | 0.39 | 炸物件数 ÷ 主餐件数 |
| 甜品倾向 | 0.15 | 甜品件数 ÷ 主餐件数 |
| 小食习惯 / 套餐习惯 | 0.00 / 0.18 | 小食、套餐件数 ÷ 主餐件数 |
两个让它站得住的设计:
13 件商品 / (13 + 12) = 0.52,输出会直说「有 48% 的可能我判断错了」。低置信度时画像只做软加权,不当硬约束。点餐史来自使用者本人账号的 order-list,只在内存中参与计算,不写盘、不上传。
用户一句话
↓ LLM:只做意图理解
{ budget: 40, avoid: ["spicy"], kcalCap: null }
↓
query-meals ── 门店在售 90+ SKU 与真实价
list-nutrition-foods ── 158 条营养
query-my-coupons ── 6 张券的时段与渠道
order-list ── 历史订单 → 品味指纹
↓
scripts/pair.py(确定性求解,LLM 不介入)
硬约束剪枝 → 帕累托非支配排序 → 三档选优 → 券最优抵扣
↓
结构化 JSON(每个数字可追溯到某次计算)
↓ LLM:只做渲染
三档方案 + 淘汰理由 + 反事实 + 券诊断
| 引擎 | 职责 | 关键设计 |
|---|---|---|
接入 ingest |
把 MCP 原始返回拍平成内部结构 | 字段名容错但不猜内容,对不上就记 issues |
品味 taste_engine |
7 笔订单 → 9 维可计算指纹 | 带置信度:样本少时直说「有 48% 的可能我判断错了」 |
求解 solver_engine |
枚举 → 剪枝 → 非支配排序 → 三档 | 三档强制不同主餐、价格与热量单调 |
券 coupon_engine |
生效日 / 时段 / 渠道 / 凑单 ROI | 判断凑单是真优惠还是多花钱 |
解释 explain_engine |
反事实 + 淘汰理由 | 不只说「为什么是 A」,还说「预算 +4 元能换什么」 |
拼单 squad_engine |
多人偏好聚合 | max-min(罗尔斯差异原则),不是平均满意度 |
我在减脂,600 大卡以内,还要带杯饮料
Skill 会把 kcalCap: 600, needDrink: true 交给引擎。若可行空间被压得很窄,它会直说而不是硬凑差异:
三档只差 ¥3.1——不是没算开,而是你的约束把可行空间压窄了,再往上加钱也换不到明显更好的组合。
不吃辣,也不要牛肉,预算 45
avoid: ["spicy", "beef"]。引擎按蛋白类型和辣度做硬否决,不靠模型理解「不要辣」是什么意思。
我们三个人一起吃,预算 100
三个人诉求互斥时(一个控卡、一个不吃辣、一个只想吃炸鸡),不存在让所有人同时最优的解。Skill 用 max-min 求「最不满意的那个人尽量不惨」的解,并把每个人的让步摆到台面上:
最不满意的是小美(0.77)——这是 max-min 解:它不追求总分最高,只保证最不满意的人不被牺牲。
小美:最想要的「巨无霸」这单没点上,比个人最优让了 0.23
拼单最容易吵架的地方,被提前说出来了。
40 个场景(预算 × 热量上限 × 忌口 × 饮品约束),与三个典型基线对比:
| 方案 | 可行率 | 平均客单价 | 主餐口味契合 | 热量贴合 | 用上券的场景 |
|---|---|---|---|---|---|
| 最便宜套餐 | 100% | ¥13.9 | 0.60 | 0.42 | 0 |
| 让利最大 | 100% | ¥26.5 | 0.26 | 0.47 | 0 |
| 菜单首个 | 100% | ¥20.7 | 0.50 | 0.71 | 0 |
| McPair | 100% | ¥22.2 | 0.55 | 0.78 | 16 |
基线只看单个套餐,无法组合小食与饮品,所以热量贴合天然吃亏。 不是刻意设弱,而是「只做套餐推荐」这个范式的天花板。
| 配置 | 主餐口味契合 | 热量贴合 | 用上券 |
|---|---|---|---|
| 完整 | 0.55 | 0.78 | 16 |
| 关闭品味引擎(画像置中性) | 0.05 | 0.79 | 16 |
| 关闭券引擎(券一律不匹配) | 0.55 | 0.77 | 0 |
| 关闭营养约束 | 0.59 | 0.65 | 17 |
关掉品味引擎,口味契合从 0.55 掉到 0.05——推荐退化成一个不看人的优化器。这就是画像的必要性证据。
21 个多人场景:
| 方案 | 平均 max-min | 平均总满意度 | 平均到手价 |
|---|---|---|---|
| 最大化总分 | 0.66 | 2.12 | ¥86.8 |
| max-min | 0.66 | 2.11 | ¥85.7 |
| 各点各的(理想上界) | 0.79 | 2.51 | ¥65.7 |
19/21 个场景里,公平解与效率解是同一单——公平通常不花钱。 只在 2/21 个「预算紧到必须有人让步」的场景分离,max-min 把短板抬高 +0.06,代价是总分 −0.06。
这不是「我们的方案更好」,而是「目标函数换了,取舍就变了」。
菜单接口不返回商品角色(汉堡 / 小食 / 饮品 / 甜品),这层只能从名称推断。 推断规则有多准,用人工标注的 81 个真实 SKU 回归:
| 指标 | 结果 |
|---|---|
| 角色推断与人工标注一致 | 78/81 = 96.3% |
| 差异项 | 3 个「蘸酱炸鸡」系列(业务上兼作小食,判为 side) |
| 套餐热量口径 | 三件套按「主餐 + 标准配餐」累加,与订单接口的 comboItemList 一致 |
这个数字写在测试里,准确率跌破 95% 会直接挂 CI。误差范围被写下来,而不是靠「看起来还行」。
SKILL.md ← 智能体执行指令(本 Skill 的核心)
scripts/
pair.py ← 唯一计算入口:stdin JSON → stdout JSON
src/
ingest.py 接入层:把 MCP 返回拍平(含周边过滤、角色推断)
classify.py 名称 → 角色 / 蛋白 / 辣度 推断规则
data.py 目录与营养解析(含别名归一、套餐构成推断)
taste_engine.py 品味指纹
solver_engine.py 组合求解
coupon_engine.py 券引擎
explain_engine.py 解释引擎
squad_engine.py 拼单 max-min
guard_engine.py 护栏
view.py 输出结构
fixtures/ 真实接口截面数据(--demo 用)
tests/ 56 个单测
eval/ 基准与消融
assets/ 首屏图(hero / pipeline,纯 SVG)
docs/ 输出预览页(GitHub Pages 托管)
python scripts/pair.py --demo # 无需 Token 跑一份示例
python scripts/pair.py --demo --mode squad # 拼单示例
python -m unittest discover -s tests # 56 个测试
python -m eval.benchmark # 基线对比 + 消融
python -m eval.squad_benchmark # 拼单公平性
composed。| 文件 | 说明 |
|---|---|
SKILL.md |
智能体执行指令 |
MCP_INTEGRATION.md |
实际使用的 MCP Tool、调用链路与业务价值 |
CONTEST_DECLARATION.md |
官方参赛声明,原文未改动 |
workbuddy.md |
WorkBuddy 开发过程记录 |
本项目为「麦当劳程序员创意开发大赛」参赛作品,由参赛者独立开发,非麦当劳官方产品。 餐品信息、价格及供应状态以麦当劳官方渠道的实时结果为准;输出仅供参考,不构成营养或医疗建议。
它不会替你下单——只做决策,下单请走官方渠道。
如果这个项目让你少算过一次账,或者让你觉得「原来推荐还能这么写」, 点一个 Star 就是最好的支持。Star 是这个比赛唯一的排名依据,也是我继续把它做完的理由。