feat: A1 短材料复现本单元理解词,并加入黑夜模式

课程内容
- 重写全部 21 个 A1 单元的听读材料,把本单元理解词织进听/读文本,
  单元内理解词复现率从约 20% 提升到约 77%(各单元 56–96%)。
- 修正 U01 房间号与机场大巴同为 thirty 的撞车(改为 17/30/40)。
- 校验器容差按级别读取(A1 为 8%),materials 覆盖率、字数、
  选项子串等校验全部通过;course_content_test 通过。

黑夜模式
- app_theme 拆分明/暗两套调色板,AppColors 随亮度切换;
  main 用 theme/darkTheme/themeMode + builder 镜像已解析亮度;
  主题偏好持久化到快照;进度页新增“外观主题”切换。

文档
- COURSE-PACK-JSON.md 更新 A1 词池覆盖(840/933)与材料复现约定。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-18 11:16:09 +09:00
co-authored by Claude Opus 4.8
parent 9ab08c25ef
commit febfd30f49
93 changed files with 72676 additions and 274 deletions
+910
View File
@@ -0,0 +1,910 @@
{
"schemaVersion": 1,
"id": "A1-U05",
"revision": 1,
"level": "A1",
"title": "在餐厅点餐",
"categories": [
"日常",
"旅行"
],
"canDo": "点餐、问推荐、要账单",
"status": "draft",
"meta": {
"draftedBy": "claude-opus-5",
"draftedAt": "2026-09-17",
"sources": [
"CEFR-J Vocabulary Profile 1.5",
"CEFR-J Grammar Profile 20180315"
],
"reviews": [],
"frozenAt": null
},
"names": [],
"grammar": [
{
"id": "141",
"use": "active",
"reason": "只把 I'll have… 当作点菜的固定句块,不展开 will 的将来用法"
},
{
"id": "123",
"use": "active"
},
{
"id": "239",
"use": "receptive"
},
{
"id": "142",
"use": "receptive"
},
{
"id": "15",
"use": "active"
}
],
"coreItems": [
{
"id": "A1-U05-P01",
"type": "phrase",
"en": "A table for two, please.",
"zh": "请给我们一张两人桌。",
"sceneWord": false,
"match": [
[
"table for"
]
],
"example": {
"en": "A table for four, please.",
"zh": "请给我们一张四人桌。"
},
"review": {
"prompt": "你们两个人走进餐厅,告诉服务员要几人桌。"
}
},
{
"id": "A1-U05-P02",
"type": "phrase",
"en": "What do you recommend?",
"zh": "你推荐什么?",
"sceneWord": true,
"sceneReason": "recommend 在 CEFR-J 为 B1,但在餐厅请人推荐是外出吃饭最常用的一句",
"match": [
[
"recommend"
]
],
"example": {
"en": "What do you recommend today?",
"zh": "你今天推荐什么?"
},
"review": {
"prompt": "你不知道点什么,请服务员推荐。"
}
},
{
"id": "A1-U05-P03",
"type": "phrase",
"en": "I'll have the fish.",
"zh": "我要鱼。",
"sceneWord": false,
"match": [
[
"i will have"
]
],
"example": {
"en": "I'll have the soup, please.",
"zh": "我要汤,谢谢。"
},
"review": {
"prompt": "告诉服务员你要牛肉。"
}
},
{
"id": "A1-U05-W01",
"type": "word",
"en": "soup",
"zh": "汤",
"sceneWord": false,
"match": [
[
"soup"
]
],
"example": {
"en": "The soup is very hot.",
"zh": "汤很烫。"
},
"review": {
"prompt": "说“汤”。"
}
},
{
"id": "A1-U05-W02",
"type": "word",
"en": "rice",
"zh": "米饭",
"sceneWord": false,
"match": [
[
"rice"
]
],
"example": {
"en": "Can I have some rice, please?",
"zh": "可以给我一些米饭吗?"
},
"review": {
"prompt": "向服务员要一些米饭。"
}
},
{
"id": "A1-U05-W03",
"type": "word",
"en": "fish",
"zh": "鱼",
"sceneWord": false,
"match": [
[
"fish"
]
],
"example": {
"en": "The fish is very good here.",
"zh": "这里的鱼很好吃。"
},
"review": {
"prompt": "说“鱼”。"
}
},
{
"id": "A1-U05-W04",
"type": "word",
"en": "vegetables",
"zh": "蔬菜",
"sceneWord": false,
"match": [
[
"vegetable",
"vegetables"
]
],
"example": {
"en": "I'd like some vegetables, please.",
"zh": "我想要一些蔬菜。"
},
"review": {
"prompt": "说你想要蔬菜。"
}
},
{
"id": "A1-U05-P04",
"type": "phrase",
"en": "Is it spicy?",
"zh": "辣吗?",
"sceneWord": true,
"sceneReason": "spicy 在 CEFR-J 为 B1,但对习惯问辣度的中国游客点菜很关键",
"match": [
[
"spicy"
]
],
"example": {
"en": "Is the chicken spicy?",
"zh": "鸡肉辣吗?"
},
"review": {
"prompt": "点菜前问这道菜辣不辣。"
}
},
{
"id": "A1-U05-P05",
"type": "phrase",
"en": "Some water, please.",
"zh": "请给我一些水。",
"sceneWord": false,
"match": [
[
"water"
]
],
"example": {
"en": "Can I have some water, please?",
"zh": "可以给我一些水吗?"
},
"review": {
"prompt": "向服务员要水。"
}
},
{
"id": "A1-U05-W05",
"type": "word",
"en": "hungry",
"zh": "饿的",
"sceneWord": false,
"match": [
[
"hungry"
]
],
"example": {
"en": "I'm very hungry.",
"zh": "我很饿。"
},
"review": {
"prompt": "说你很饿。"
}
},
{
"id": "A1-U05-P06",
"type": "phrase",
"en": "I'm full.",
"zh": "我饱了。",
"sceneWord": false,
"match": [
[
"i am full",
"we are full"
]
],
"example": {
"en": "No dessert, thanks. I'm full.",
"zh": "不要甜点了,谢谢。我饱了。"
},
"review": {
"prompt": "服务员问你要不要甜点,说你已经饱了。"
}
},
{
"id": "A1-U05-P07",
"type": "phrase",
"en": "Can I have the bill, please?",
"zh": "请给我账单。",
"sceneWord": true,
"sceneReason": "bill 在 CEFR-J 为 A2,但吃完结账必须会说",
"match": [
[
"the bill",
"the check"
]
],
"example": {
"en": "Excuse me. Can we have the bill, please?",
"zh": "打扰一下,可以给我们账单吗?"
},
"review": {
"prompt": "吃完了,向服务员要账单。"
}
}
],
"receptiveWords": [
{
"id": "A1-U05-R01",
"en": "meal",
"zh": "一顿饭"
},
{
"id": "A1-U05-R02",
"en": "dinner",
"zh": "晚饭"
},
{
"id": "A1-U05-R03",
"en": "lunch",
"zh": "午饭"
},
{
"id": "A1-U05-R04",
"en": "waiter",
"zh": "服务员"
},
{
"id": "A1-U05-R05",
"en": "egg",
"zh": "鸡蛋"
},
{
"id": "A1-U05-R06",
"en": "meat",
"zh": "肉"
},
{
"id": "A1-U05-R07",
"en": "beef",
"zh": "牛肉"
},
{
"id": "A1-U05-R08",
"en": "potato",
"zh": "土豆"
},
{
"id": "A1-U05-R09",
"en": "tomato",
"zh": "西红柿"
},
{
"id": "A1-U05-R10",
"en": "pizza",
"zh": "比萨饼"
},
{
"id": "A1-U05-R11",
"en": "salad",
"zh": "沙拉"
},
{
"id": "A1-U05-R12",
"en": "fruit",
"zh": "水果"
},
{
"id": "A1-U05-R13",
"en": "banana",
"zh": "香蕉"
},
{
"id": "A1-U05-R14",
"en": "ice cream",
"zh": "冰淇淋"
},
{
"id": "A1-U05-R15",
"en": "glass",
"zh": "玻璃杯"
},
{
"id": "A1-U05-R16",
"en": "knife",
"zh": "刀"
},
{
"id": "A1-U05-R17",
"en": "fork",
"zh": "叉子"
},
{
"id": "A1-U05-R18",
"en": "spoon",
"zh": "勺子"
},
{
"id": "A1-U05-R19",
"en": "dessert",
"zh": "甜点"
},
{
"id": "A1-U05-R20",
"en": "special",
"zh": "特别的;特色菜"
},
{
"id": "A1-U05-R21",
"en": "try",
"zh": "尝试"
},
{
"id": "A1-U05-R22",
"en": "people",
"zh": "人们"
},
{
"id": "A1-U05-R23",
"en": "seat",
"zh": "座位"
},
{
"id": "A1-U05-R24",
"en": "dish",
"zh": "一道菜"
},
{
"id": "A1-U05-R25",
"en": "too",
"zh": "太"
},
{
"id": "A1-U05-R26",
"en": "smell",
"zh": "闻起来"
},
{
"id": "A1-U05-R27",
"en": "tip",
"zh": "小费"
},
{
"id": "A1-U05-R28",
"en": "hamburger",
"zh": "汉堡包"
},
{
"id": "A1-U05-R29",
"en": "butter",
"zh": "黄油"
},
{
"id": "A1-U05-R30",
"en": "ask",
"zh": "问;请求"
},
{
"id": "A1-U05-R31",
"en": "sit",
"zh": "坐"
}
],
"segments": [
{
"id": "A1-U05-S1",
"title": "入座与请人推荐",
"minutes": 12,
"itemIds": [
"A1-U05-P01",
"A1-U05-W05",
"A1-U05-P02",
"A1-U05-P03"
],
"listening": {
"text": "Hello. How many people? A table for two, please. Sure. Sit here, please. Here is the menu, and some bread and butter.",
"question": "他们要几人桌?",
"options": [
"两人桌",
"三人桌",
"四人桌"
]
},
"speaking": [
{
"text": "A table for two, please."
},
{
"text": "I'm very hungry."
},
{
"text": "What do you recommend?",
"tip": "recommend 重音在最后的 mend"
},
{
"text": "I'll have the fish, please.",
"tip": "I'll 读作 /aɪl/,很短"
}
],
"reading": {
"text": "TODAY'S SPECIAL\nFish with rice $15\nBeef with potatoes $18\nTomato soup $6\nEgg salad $7\nPizza $12\nDessert: banana ice cream $5",
"question": "哪一道菜最便宜?",
"options": [
"tomato soup",
"egg salad",
"pizza"
]
},
"writing": {
"prompt": "写两句话:要一张两人桌,再说你要鱼。",
"example": "A table for two, please. I'll have the fish.",
"itemIds": [
"A1-U05-P01",
"A1-U05-P03"
]
},
"independent": {
"prompt": "想想你常去的一家餐厅,用英语请服务员推荐,然后点一道菜。",
"itemIds": [
"A1-U05-P02",
"A1-U05-P03"
]
}
},
{
"id": "A1-U05-S2",
"title": "点菜:汤、米饭、辣不辣",
"minutes": 13,
"itemIds": [
"A1-U05-W01",
"A1-U05-W02",
"A1-U05-W03",
"A1-U05-W04",
"A1-U05-P04",
"A1-U05-P05"
],
"listening": {
"text": "What would you like? I'll have the chicken soup and rice. Is the soup spicy? No, it isn't. It has meat and vegetables. And some water, please.",
"question": "顾客点了什么?",
"options": [
"鸡汤和米饭",
"鱼和米饭",
"鸡汤和蔬菜"
]
},
"speaking": [
{
"text": "soup, rice, fish"
},
{
"text": "I'd like some vegetables, please.",
"tip": "vegetables 读作三个音节 /ˈvedʒtəblz/"
},
{
"text": "Is it spicy?"
},
{
"text": "Some water, please."
}
],
"reading": {
"text": "Waiter: Would you like to try the beef? It's very good.\nMia: Is it spicy?\nWaiter: Yes, very spicy.\nMia: Oh, no. I'll have the fish and some vegetables.\nWaiter: And to drink?\nMia: A glass of water, please.",
"question": "Mia 点了什么主菜?",
"options": [
"the fish",
"the beef",
"a glass of water"
]
},
"writing": {
"prompt": "写两句话:问鱼辣不辣,再要一些水。",
"example": "Is the fish spicy? Some water, please.",
"itemIds": [
"A1-U05-P04",
"A1-U05-P05",
"A1-U05-W03"
]
},
"independent": {
"prompt": "用英语点一份汤、米饭和蔬菜。",
"itemIds": [
"A1-U05-W01",
"A1-U05-W02",
"A1-U05-W04"
]
}
},
{
"id": "A1-U05-S3",
"title": "吃饱了,结账",
"minutes": 10,
"itemIds": [
"A1-U05-P06",
"A1-U05-P07"
],
"listening": {
"text": "Would you like some dessert? We have ice cream and fruit. No, thanks. I'm full. Can I have the bill, please?",
"question": "顾客为什么不要甜点?",
"options": [
"已经吃饱了",
"不喜欢冰淇淋",
"甜点太贵"
]
},
"speaking": [
{
"text": "I'm full."
},
{
"text": "No dessert, thanks."
},
{
"text": "Can I have the bill, please?",
"tip": "bill 的 i 是短音,不要读成 beer"
}
],
"reading": {
"text": "Please wait here. The waiter will take you to a seat.\nLunch: 11 to 2. Dinner: 5 to 10.\nYou can pay by cash or card at your table. Please ask the waiter for the bill.\nNo tips, please.",
"question": "怎么结账?",
"options": [
"在餐桌上向服务员要账单",
"去门口付钱",
"只能付现金"
]
},
"writing": {
"prompt": "写两句话:说你吃饱了,再要账单。",
"example": "I'm full. Can I have the bill, please?",
"itemIds": [
"A1-U05-P06",
"A1-U05-P07"
]
},
"independent": {
"prompt": "回想上次在外面吃饭,用英语说你吃饱了并要账单。",
"itemIds": [
"A1-U05-P06",
"A1-U05-P07"
]
}
}
],
"scenes": [
{
"id": "A1-U05-C1",
"kind": "main",
"title": "晚饭点菜",
"learnerRole": "顾客",
"aiRole": "服务员",
"setting": "你和朋友晚上走进一家餐厅吃饭。",
"turns": [
{
"ai": "Hello! How many people?",
"goal": "说要两人桌",
"model": "A table for two, please.",
"zh": "两人桌,谢谢。",
"itemIds": [
"A1-U05-P01"
]
},
{
"ai": "Sure. Sit here, please. Here is the menu. Our special dish today is beef with potatoes.",
"goal": "说你们很饿,请服务员推荐",
"model": "Thank you. We're very hungry. What do you recommend?",
"zh": "谢谢。我们很饿。你推荐什么?",
"itemIds": [
"A1-U05-W05",
"A1-U05-P02"
]
},
{
"ai": "The fish is very good. It comes with rice and vegetables.",
"goal": "问辣不辣",
"model": "Is it spicy?",
"zh": "辣吗?",
"itemIds": [
"A1-U05-P04"
]
},
{
"ai": "No, it isn't.",
"goal": "点鱼和一份汤",
"model": "Great. I'll have the fish and a soup, please.",
"zh": "好的,我要鱼和一份汤。",
"itemIds": [
"A1-U05-P03",
"A1-U05-W03",
"A1-U05-W01"
]
},
{
"ai": "And to drink? Here is a spoon for the soup.",
"goal": "要水",
"model": "Some water, please.",
"zh": "请给我一些水。",
"itemIds": [
"A1-U05-P05"
]
}
]
},
{
"id": "A1-U05-C2",
"kind": "variant",
"title": "吃完结账",
"learnerRole": "顾客",
"aiRole": "服务员",
"setting": "你吃完午饭,想结账离开。",
"turns": [
{
"ai": "How is your meal?",
"goal": "说很好,你已经饱了",
"model": "Very good, thank you. I'm full.",
"zh": "很好,谢谢。我饱了。",
"itemIds": [
"A1-U05-P06"
]
},
{
"ai": "Would you like some dessert? We have ice cream, fruit and cake.",
"goal": "拒绝并要账单",
"model": "No, thanks. Can I have the bill, please?",
"zh": "不用了,谢谢。可以给我账单吗?",
"itemIds": [
"A1-U05-P07"
]
},
{
"ai": "Sure. Here you are. Lunch for one, twelve dollars.",
"goal": "问能不能刷卡",
"model": "Can I pay by card?",
"zh": "可以刷卡吗?",
"itemIds": []
},
{
"ai": "Yes, sure.",
"goal": "道谢,说这里的汤和米饭很好",
"model": "Thank you. The soup and rice are very good here.",
"zh": "谢谢。这里的汤和米饭很好。",
"itemIds": [
"A1-U05-W01",
"A1-U05-W02"
]
}
]
},
{
"id": "A1-U05-C3",
"kind": "variant",
"title": "快餐店点汉堡",
"learnerRole": "顾客",
"aiRole": "店员",
"setting": "你在一家快餐店,很饿,但不太能吃辣。",
"turns": [
{
"ai": "Hi! What would you like?",
"goal": "说你很饿,要一个汉堡",
"model": "I'm hungry. I'll have a hamburger, please.",
"zh": "我饿了。我要一个汉堡。",
"itemIds": [
"A1-U05-W05",
"A1-U05-P03"
]
},
{
"ai": "Beef or chicken? The chicken is spicy.",
"goal": "说要牛肉的,鸡肉太辣",
"model": "Beef, please. The chicken is too spicy for me.",
"zh": "牛肉的。鸡肉对我来说太辣了。",
"itemIds": [
"A1-U05-P04"
]
},
{
"ai": "Would you like vegetables or potatoes with it?",
"goal": "选蔬菜",
"model": "Vegetables, please.",
"zh": "蔬菜,谢谢。",
"itemIds": [
"A1-U05-W04"
]
},
{
"ai": "And to drink?",
"goal": "要水",
"model": "Just some water, please.",
"zh": "只要一些水,谢谢。",
"itemIds": [
"A1-U05-P05"
]
},
{
"ai": "OK. Here is your food, and a knife and fork.",
"goal": "道谢",
"model": "Thank you! It smells good.",
"zh": "谢谢!闻起来很香。",
"itemIds": []
}
]
}
],
"tasks": [
{
"id": "A1-U05-T1",
"sceneId": "A1-U05-C1",
"goal": "要座位、请人推荐、问辣度并点主菜、汤和饮料",
"itemIds": [
"A1-U05-P01",
"A1-U05-W05",
"A1-U05-P02",
"A1-U05-P04",
"A1-U05-P03",
"A1-U05-W03",
"A1-U05-W01",
"A1-U05-P05"
],
"slots": [
"人数",
"主菜",
"饮料"
]
},
{
"id": "A1-U05-T2",
"sceneId": "A1-U05-C2",
"goal": "吃完说饱了,拒绝甜点并结账",
"itemIds": [
"A1-U05-P06",
"A1-U05-P07",
"A1-U05-W01",
"A1-U05-W02"
],
"slots": [
"甜点",
"账单"
]
},
{
"id": "A1-U05-T3",
"sceneId": "A1-U05-C3",
"goal": "在快餐店按口味点餐",
"itemIds": [
"A1-U05-W05",
"A1-U05-P03",
"A1-U05-P04",
"A1-U05-W04",
"A1-U05-P05"
],
"slots": [
"主食",
"辣度",
"配菜"
]
}
],
"materials": [
{
"id": "A1-U05-M1",
"mode": "listening",
"title": "餐厅介绍今晚的菜",
"text": "Good evening, and welcome to our restaurant. Please sit down; here is a seat for you. Tonight we have a special meal. First, a hot soup or a fresh salad with tomato. Then you can try beef with potato, chicken with rice, or a pizza. The fish is our best dish — it smells wonderful and is not spicy. For dessert, we have ice cream, fruit and banana cake. Here are your knife, fork and spoon, and a glass of water. Tell the waiter when you are ready. Enjoy your dinner!",
"glosses": {
"evening": "傍晚,晚上",
"tell": "告诉",
"tonight": "今晚",
"best": "最好的",
"wonderful": "很棒的",
"fresh": "新鲜的"
},
"questions": [
{
"type": "gist",
"question": "这段话主要说什么?",
"options": [
"餐厅今晚有什么菜",
"怎么去餐厅",
"餐厅几点关门"
]
},
{
"type": "detail",
"question": "关于鱼,下面哪个对?",
"options": [
"很好吃,不辣",
"很辣",
"已经卖完了"
]
}
]
},
{
"id": "A1-U05-M2",
"mode": "reading",
"title": "读一段对话:在餐厅点餐",
"text": "Waiter: Good evening. A table for two? Here are your seats.\nBen: Thank you. We're very hungry. What do you recommend?\nWaiter: The beef is our special dish today. The fish and the salad are good too.\nBen: I'll have the fish with rice and some vegetables. Is it spicy?\nWaiter: No, it isn't. And to drink?\nBen: A glass of water, please. Can I have a fork and a spoon?\nWaiter: Of course. Would you like a dessert? The ice cream is sweet and the fruit is fresh.\nBen: Ice cream, please. That was delicious. I'm full now. Can I have the bill?\nWaiter: Sure. Many people ask for the ice cream — it's the best!\nBen: Great. Here is a tip. Thank you!",
"glosses": {
"evening": "傍晚,晚上",
"best": "最好的",
"course": "of course 当然",
"fresh": "新鲜的"
},
"questions": [
{
"type": "detail",
"question": "服务员今天推荐什么菜?",
"options": [
"牛肉",
"汤",
"香蕉"
]
},
{
"type": "inference",
"question": "Ben 为什么最后要账单?",
"options": [
"他吃完了,吃饱了",
"菜太辣了",
"他要换一张桌子"
]
}
]
}
],
"excluded": [
{
"en": "reservation / book a table",
"reason": "B1;预订放到 A2 的预订单元"
},
{
"en": "noodle",
"reason": "CEFR-J 未收录,作为菜单专名由应用临时提示"
}
]
}