import 'models.dart'; /// Stable A0 core identities taught by each seed lesson. Wording can vary in /// future exercises without creating a different mastery item. const a0TargetItemIdsByLesson = >{ 'a0-01': ['A0-W36', 'A0-W37', 'A0-W40', 'A0-P01', 'A0-P02', 'A0-P03'], 'a0-02': ['A0-P04'], 'a0-03': ['A0-W33', 'A0-W34', 'A0-W35', 'A0-P05', 'A0-P06'], 'a0-04': [ 'A0-W01', 'A0-W02', 'A0-W03', 'A0-W04', 'A0-W05', 'A0-W06', 'A0-W07', 'A0-W08', 'A0-W09', 'A0-W10', 'A0-W11', 'A0-W20', 'A0-P07', 'A0-P08', ], 'a0-05': ['A0-W19', 'A0-W21', 'A0-W22', 'A0-W23', 'A0-P09', 'A0-P10'], 'a0-06': ['A0-P11', 'A0-P12'], 'a0-07': ['A0-W25', 'A0-W26', 'A0-W27', 'A0-W28', 'A0-P13'], 'a0-08': [ 'A0-W12', 'A0-W13', 'A0-W14', 'A0-W15', 'A0-W16', 'A0-W17', 'A0-W18', 'A0-P14', 'A0-P15', 'A0-P16', 'A0-P17', ], 'a0-09': [ 'A0-W29', 'A0-W30', 'A0-W31', 'A0-W32', 'A0-W38', 'A0-W39', 'A0-P18', 'A0-P19', ], 'a0-10': ['A0-W24', 'A0-P20'], }; /// A topic may contain multiple independently resumable teaching segments. /// Segment IDs are stable even if later wording or exercises change. class LessonSegment { const LessonSegment({ required this.id, required this.targetItemIds, required this.previewItemIds, this.dialogueRequiredTerms = const [], this.independentRequiredTerms = const [], this.estimatedMinutes = 12, }); final String id; final List targetItemIds; final List previewItemIds; /// One accepted term group per controlled dialogue turn. A learner only /// needs to use one term from the current group; the surrounding wording /// may vary naturally. final List> dialogueRequiredTerms; /// Terms that show the independent attempt contains the taught content. final List independentRequiredTerms; final int estimatedMinutes; } const a0LessonSegments = >{ 'a0-04': [ LessonSegment( id: 'a0-04-a', targetItemIds: [ 'A0-W01', 'A0-W02', 'A0-W03', 'A0-W04', 'A0-W05', 'A0-W06', ], previewItemIds: [ 'A0-W01', 'A0-W02', 'A0-W03', 'A0-W04', 'A0-W05', 'A0-W06', ], dialogueRequiredTerms: [ ['zero', 'one', 'two'], ['three', 'four', 'five'], ], independentRequiredTerms: ['zero', 'one', 'two', 'three', 'four', 'five'], ), LessonSegment( id: 'a0-04-b', targetItemIds: [ 'A0-W07', 'A0-W08', 'A0-W09', 'A0-W10', 'A0-W11', 'A0-W20', ], previewItemIds: [ 'A0-W07', 'A0-W08', 'A0-W09', 'A0-W10', 'A0-W11', 'A0-W20', ], dialogueRequiredTerms: [ ['six', 'seven', 'eight'], ['it is a phone', "it's a phone"], ], independentRequiredTerms: ['six', 'seven', 'eight', 'nine', 'ten'], ), LessonSegment( id: 'a0-04-c', targetItemIds: ['A0-P07', 'A0-P08'], previewItemIds: ['A0-P07', 'A0-P08'], dialogueRequiredTerms: [ [ 'my number is', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'zero', ], [ 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'zero', ], ], independentRequiredTerms: [ 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'zero', ], ), ], 'a0-08': [ LessonSegment( id: 'a0-08-a', targetItemIds: ['A0-W12', 'A0-W13', 'A0-W14', 'A0-P14', 'A0-P15'], previewItemIds: ['A0-W12', 'A0-W13', 'A0-W14', 'A0-P14', 'A0-P15'], dialogueRequiredTerms: [ ['what day'], ['monday', 'tuesday', 'wednesday'], ], independentRequiredTerms: ['monday', 'tuesday', 'wednesday'], ), LessonSegment( id: 'a0-08-b', targetItemIds: ['A0-W15', 'A0-W16', 'A0-W17', 'A0-W18'], previewItemIds: ['A0-W15', 'A0-W16', 'A0-W17', 'A0-W18'], dialogueRequiredTerms: [ ['what day'], ['thursday', 'friday', 'saturday', 'sunday'], ], independentRequiredTerms: ['thursday', 'friday', 'saturday', 'sunday'], ), LessonSegment( id: 'a0-08-c', targetItemIds: ['A0-P16', 'A0-P17'], previewItemIds: ['A0-P16', 'A0-P17'], dialogueRequiredTerms: [ ['what time'], ["o'clock", 'oclock'], ], independentRequiredTerms: ["o'clock", 'oclock'], ), ], }; class SeedLesson { const SeedLesson({ required this.id, required this.number, required this.title, required this.outcome, required this.vocabulary, this.schemaVersion = '1.0', this.revision = 1, this.stageVersion = 'A0-1.0', this.source = ContentSource.builtInOriginal, this.status = ContentStatus.approved, this.estimatedMinutes = 12, }); final String id; final int number; final String title; final String outcome; final List vocabulary; final String schemaVersion; final int revision; final String stageVersion; final ContentSource source; final ContentStatus status; final int estimatedMinutes; List get targetItemIds => a0TargetItemIdsByLesson[id] ?? const []; List get abilityIds => ['A0-C${number.toString().padLeft(2, '0')}']; List get prerequisiteIds => number == 1 ? const [] : ['a0-${(number - 1).toString().padLeft(2, '0')}']; List get segments => a0LessonSegments[id] ?? [ LessonSegment( id: '$id-a', targetItemIds: targetItemIds, previewItemIds: targetItemIds, estimatedMinutes: estimatedMinutes, ), ]; } const a0SeedLessons = [ SeedLesson( id: 'a0-01', number: 1, title: '你好,我是……', outcome: '介绍姓名并回应问候', vocabulary: [ VocabularyItem( id: 'a0-01-hello', word: 'Hello', meaning: '你好', example: 'Hello. I’m Mia.', exampleMeaning: '你好。我是 Mia。', ipa: '/həˈləʊ/', ), VocabularyItem( id: 'a0-01-name', word: 'name', meaning: '名字', example: 'My name is Shen.', exampleMeaning: '我的名字是 Shen。', ipa: '/neɪm/', ), VocabularyItem( id: 'a0-01-nice', word: 'Nice to meet you', meaning: '很高兴认识你', example: 'Nice to meet you, too.', exampleMeaning: '我也很高兴认识你。', ), ], ), SeedLesson( id: 'a0-02', number: 2, title: '拼读我的名字', outcome: '听懂拼写,并说出名字字母', vocabulary: [ VocabularyItem( id: 'a0-02-spell', word: 'spell', meaning: '拼写', example: 'How do you spell that?', exampleMeaning: '那个怎么拼?', ipa: '/spel/', ), VocabularyItem( id: 'a0-02-name', word: 'name', meaning: '名字', example: 'My name is Shen.', exampleMeaning: '我的名字是 Shen。', ipa: '/neɪm/', ), VocabularyItem( id: 'a0-02-question', word: 'How do you spell that?', meaning: '那个怎么拼?', example: 'How do you spell your name?', exampleMeaning: '你的名字怎么拼?', ), ], ), SeedLesson( id: 'a0-03', number: 3, title: '你好吗?', outcome: '问候并表达简单状态', vocabulary: [ VocabularyItem( id: 'a0-03-good', word: 'good', meaning: '好的', example: 'I’m good, thanks.', exampleMeaning: '我很好,谢谢。', ipa: '/ɡʊd/', ), VocabularyItem( id: 'a0-03-tired', word: 'tired', meaning: '累的', example: 'I’m tired today.', exampleMeaning: '我今天有点累。', ipa: '/ˈtaɪəd/', ), VocabularyItem( id: 'a0-03-how', word: 'How are you?', meaning: '你好吗?', example: 'How are you today?', exampleMeaning: '你今天怎么样?', ), ], ), SeedLesson( id: 'a0-04', number: 4, title: '数字与电话号码', outcome: '说 0–10 与虚拟号码', vocabulary: [ VocabularyItem( id: 'a0-04-three', word: 'three', meaning: '三', example: 'One, three, eight.', exampleMeaning: '一、三、八。', ipa: '/θriː/', ), VocabularyItem( id: 'a0-04-number', word: 'number', meaning: '号码', example: 'My number is 1-3-8.', exampleMeaning: '我的号码是 138。', ipa: '/ˈnʌmbə(r)/', ), VocabularyItem( id: 'a0-04-phone', word: 'phone', meaning: '电话', example: 'What’s your phone number?', exampleMeaning: '你的电话号码是多少?', ), ], ), SeedLesson( id: 'a0-05', number: 5, title: '这是什么?', outcome: '询问并说出常见物品', vocabulary: [ VocabularyItem( id: 'a0-05-book', word: 'book', meaning: '书', example: 'It’s a book.', exampleMeaning: '这是一本书。', ipa: '/bʊk/', ), VocabularyItem( id: 'a0-05-pen', word: 'pen', meaning: '笔', example: 'It’s a pen.', exampleMeaning: '这是一支笔。', ipa: '/pen/', ), VocabularyItem( id: 'a0-05-this', word: 'What’s this?', meaning: '这是什么?', example: 'What’s this? It’s a key.', exampleMeaning: '这是什么?这是钥匙。', ), ], ), SeedLesson( id: 'a0-06', number: 6, title: '我来自哪里?', outcome: '说明来自哪里并反问', vocabulary: [ VocabularyItem( id: 'a0-06-from', word: 'from', meaning: '来自', example: 'I’m from Hong Kong.', exampleMeaning: '我来自香港。', ipa: '/frəm/', ), VocabularyItem( id: 'a0-06-place', word: 'place', meaning: '地点', example: 'Where are you from?', exampleMeaning: '你来自哪里?', ), ], ), SeedLesson( id: 'a0-07', number: 7, title: '我的家人', outcome: '介绍一位家人', vocabulary: [ VocabularyItem( id: 'a0-07-family', word: 'family', meaning: '家人', example: 'This is my family.', exampleMeaning: '这是我的家人。', ipa: '/ˈfæməli/', ), VocabularyItem( id: 'a0-07-mother', word: 'mother', meaning: '母亲', example: 'This is my mother.', exampleMeaning: '这是我的妈妈。', ), ], ), SeedLesson( id: 'a0-08', number: 8, title: '星期与时间', outcome: '说今天和整点', vocabulary: [ VocabularyItem( id: 'a0-08-monday', word: 'Monday', meaning: '星期一', example: 'It is Monday.', exampleMeaning: '今天是星期一。', ), VocabularyItem( id: 'a0-08-oclock', word: 'o’clock', meaning: '整点', example: 'It’s three o’clock.', exampleMeaning: '现在三点整。', ), ], ), SeedLesson( id: 'a0-09', number: 9, title: '我喜欢……', outcome: '表达喜好并回答', vocabulary: [ VocabularyItem( id: 'a0-09-like', word: 'like', meaning: '喜欢', example: 'I like tea.', exampleMeaning: '我喜欢茶。', ipa: '/laɪk/', ), VocabularyItem( id: 'a0-09-tea', word: 'tea', meaning: '茶', example: 'Do you like tea?', exampleMeaning: '你喜欢茶吗?', ), ], ), SeedLesson( id: 'a0-10', number: 10, title: 'A0 综合任务', outcome: '完成自我介绍、喜好和反问', vocabulary: [ VocabularyItem( id: 'a0-10-again', word: 'Please say that again.', meaning: '请再说一遍。', example: 'Please say that again.', exampleMeaning: '请再说一遍。', ), VocabularyItem( id: 'a0-10-slowly', word: 'Please speak slowly.', meaning: '请说慢一点。', example: 'Please speak slowly.', exampleMeaning: '请说慢一点。', ), ], ), ]; SeedLesson lessonById(String id) => a0SeedLessons.firstWhere((lesson) => lesson.id == id); class LessonActivity { const LessonActivity({ required this.listening, required this.listeningQuestion, required this.answers, required this.speaking, required this.reading, required this.readingQuestion, required this.readingAnswer, required this.writingPrompt, required this.writingExample, required this.independentPrompt, required this.independentHelp, }); final String listening; final String listeningQuestion; final List answers; final String speaking; final String reading; final String readingQuestion; final String readingAnswer; final String writingPrompt; final String writingExample; final String independentPrompt; final String independentHelp; } const a0Activities = { 'a0-01': LessonActivity( listening: 'Hello. I’m Mia. Nice to meet you.', listeningQuestion: 'Mia 在做什么?', answers: ['自我介绍', '买东西', '问时间'], speaking: 'Hello. I’m Shen. Nice to meet you.', reading: 'Mia: Hello. I’m Mia.\nShen: Hi. I’m Shen.\nMia: Nice to meet you.\nShen: Nice to meet you, too.', readingQuestion: '谁叫 Mia?', readingAnswer: '第一位说话的人', writingPrompt: '写一句问候和姓名介绍。', writingExample: 'Hello. I’m Shen.', independentPrompt: '不看句框,介绍你的名字并回应“Nice to meet you”。', independentHelp: 'Hi. I’m … / Nice to meet you, too.', ), 'a0-02': LessonActivity( listening: 'How do you spell your name?', listeningQuestion: '这句话是什么意思?', answers: ['你的名字怎么拼?', '你的名字是什么?', '你来自哪里?'], speaking: 'S H E N', reading: 'Mia: What’s your name?\nShen: Shen.\nMia: How do you spell that?\nShen: S-H-E-N.', readingQuestion: 'Shen 的名字怎么拼?', readingAnswer: 'S-H-E-N', writingPrompt: '把名字和拼写写完整。', writingExample: 'My name is Shen.\nS-H-E-N.', independentPrompt: '不看句框,用英文介绍名字并拼读它。', independentHelp: 'My name is … / A-B-C.', ), 'a0-03': LessonActivity( listening: 'How are you today?', listeningQuestion: '对方在问什么?', answers: ['你的状态', '你的号码', '你的地点'], speaking: 'How are you? I’m good, thanks.', reading: 'Mia: Hi, Shen. How are you?\nShen: I’m good, thanks. How are you?\nMia: I’m okay.', readingQuestion: 'Mia 状态如何?', readingAnswer: 'okay', writingPrompt: '写一句今天的状态。', writingExample: 'I’m okay today.', independentPrompt: '不看句框,问候并说出你的状态。', independentHelp: 'How are you? / I’m …', ), 'a0-04': LessonActivity( listening: 'One, three, eight.', listeningQuestion: '你听到的是哪个号码?', answers: ['138', '183', '318'], speaking: 'My number is one-three-eight.', reading: 'Mia: What’s your phone number?\nShen: One-three-eight.\nMia: Thank you.', readingQuestion: 'Shen 的号码是?', readingAnswer: '138', writingPrompt: '把虚拟号码 139 写成英文。', writingExample: 'one-three-nine', independentPrompt: '不看句框,说出一个三位虚拟号码。', independentHelp: 'My number is one-two-three.', ), 'a0-05': LessonActivity( listening: 'What’s this? It’s a key.', listeningQuestion: '这是什么?', answers: ['钥匙', '书', '水'], speaking: 'What’s this? It’s a pen.', reading: 'Mia: What’s this?\nShen: It’s a book.', readingQuestion: '这是什么?', readingAnswer: 'a book', writingPrompt: '写一句“这是一支笔”。', writingExample: 'It’s a pen.', independentPrompt: '不看句框,说出一个身边物品。', independentHelp: 'It’s a …', ), 'a0-06': LessonActivity( listening: 'Where are you from?', listeningQuestion: '对方在问什么?', answers: ['来自哪里', '叫什么', '喜欢什么'], speaking: 'I’m from Hong Kong.', reading: 'Mia: Where are you from?\nShen: I’m from Hong Kong.', readingQuestion: 'Shen 来自哪里?', readingAnswer: 'Hong Kong', writingPrompt: '写一句你来自哪里。', writingExample: 'I’m from Hong Kong.', independentPrompt: '不看句框,说来自哪里并反问对方。', independentHelp: 'I’m from … / Where are you from?', ), 'a0-07': LessonActivity( listening: 'Who is this? This is my mother.', listeningQuestion: '这个人是谁?', answers: ['妈妈', '朋友', '老师'], speaking: 'This is my family.', reading: 'Mia: Who is this?\nShen: This is my mother.', readingQuestion: 'Shen 在介绍谁?', readingAnswer: 'my mother', writingPrompt: '介绍一位家人或朋友。', writingExample: 'This is my mother.', independentPrompt: '不看句框,介绍一位家人或朋友。', independentHelp: 'This is my …', ), 'a0-08': LessonActivity( listening: 'It’s three o’clock on Monday.', listeningQuestion: '是什么时间?', answers: ['星期一三点', '星期三一点', '星期一一点'], speaking: 'It’s three o’clock.', reading: 'Mia: What day is it?\nShen: It’s Monday.', readingQuestion: '今天星期几?', readingAnswer: 'Monday', writingPrompt: '写一句今天和整点。', writingExample: 'It’s Monday. It’s three o’clock.', independentPrompt: '不看句框,说今天星期几或现在几点。', independentHelp: 'It’s … / It’s … o’clock.', ), 'a0-09': LessonActivity( listening: 'Do you like tea? Yes, I do.', listeningQuestion: '对方喜欢茶吗?', answers: ['喜欢', '不喜欢', '不知道'], speaking: 'I like tea. Do you like tea?', reading: 'Mia: I like tea. Do you like tea?\nShen: Yes, I do.', readingQuestion: 'Shen 的回答是什么?', readingAnswer: 'Yes, I do.', writingPrompt: '写一句你的喜好。', writingExample: 'I like tea.', independentPrompt: '不看句框,说一个喜好并反问。', independentHelp: 'I like … / Do you like …?', ), 'a0-10': LessonActivity( listening: 'Please say that again.', listeningQuestion: '对方希望什么?', answers: ['再说一遍', '说慢一点', '写下来'], speaking: 'Please speak slowly.', reading: 'Mia: Please say that again.\nShen: Please speak slowly.', readingQuestion: 'Shen 希望什么?', readingAnswer: 'speak slowly', writingPrompt: '写姓名、地点和喜好三句。', writingExample: 'I’m Shen.\nI’m from Hong Kong.\nI like tea.', independentPrompt: '不看帮助,完成姓名、地点、喜好和反问。', independentHelp: 'I’m … / I’m from … / I like …', ), }; LessonActivity activityByLessonId(String id) => a0Activities[id]!; /// Reviewed activities for split topics. They intentionally avoid values from /// later segments so a segment can be completed independently. const a0SegmentActivities = { 'a0-04-a': LessonActivity( listening: 'One, two, three.', listeningQuestion: '听到哪一组数字?', answers: ['123', '132', '213'], speaking: 'Zero, one, two, three.', reading: 'Mia: One, two, three.\nShen: Four, five.', readingQuestion: 'Shen 说了哪两个数字?', readingAnswer: 'four, five', writingPrompt: '把 0、1、2、3 写成英文。', writingExample: 'zero, one, two, three', independentPrompt: '不看帮助,说出三个 0 到 5 的数字。', independentHelp: 'zero / one / two / three / four / five', ), 'a0-04-b': LessonActivity( listening: 'Six, seven, eight.', listeningQuestion: '听到哪一组数字?', answers: ['678', '687', '768'], speaking: 'My phone is here.', reading: 'Mia: What is this?\nShen: It is a phone.', readingQuestion: '这是什么?', readingAnswer: 'a phone', writingPrompt: '把 6、7、8 写成英文。', writingExample: 'six, seven, eight', independentPrompt: '不看帮助,说出三个 6 到 10 的数字。', independentHelp: 'six / seven / eight / nine / ten', ), 'a0-04-c': LessonActivity( listening: 'My number is one-three-eight.', listeningQuestion: '号码是多少?', answers: ['138', '183', '318'], speaking: 'My number is one-three-eight.', reading: 'Mia: What’s your phone number?\nShen: One-three-eight.', readingQuestion: 'Shen 的号码是?', readingAnswer: '138', writingPrompt: '把虚拟号码 139 写成英文。', writingExample: 'one-three-nine', independentPrompt: '不看句框,说出一个三位虚拟号码。', independentHelp: 'My number is one-two-three.', ), 'a0-08-a': LessonActivity( listening: 'It is Monday.', listeningQuestion: '今天星期几?', answers: ['星期一', '星期二', '星期三'], speaking: 'It is Monday.', reading: 'Mia: What day is it?\nShen: It is Tuesday.', readingQuestion: '今天星期几?', readingAnswer: 'Tuesday', writingPrompt: '写一句今天是星期一、二或三。', writingExample: 'It is Monday.', independentPrompt: '不看帮助,说出星期一、二或三。', independentHelp: 'It is Monday / Tuesday / Wednesday.', ), 'a0-08-b': LessonActivity( listening: 'It is Friday.', listeningQuestion: '今天星期几?', answers: ['星期五', '星期四', '星期日'], speaking: 'It is Friday.', reading: 'Mia: What day is it?\nShen: It is Sunday.', readingQuestion: '今天星期几?', readingAnswer: 'Sunday', writingPrompt: '写一句今天是星期四到日。', writingExample: 'It is Friday.', independentPrompt: '不看帮助,说出星期四到日。', independentHelp: 'It is Thursday / Friday / Saturday / Sunday.', ), 'a0-08-c': LessonActivity( listening: 'It is three o’clock.', listeningQuestion: '是什么时间?', answers: ['三点', '一点', '星期三'], speaking: 'It is three o’clock.', reading: 'Mia: What time is it?\nShen: It is three o’clock.', readingQuestion: '几点?', readingAnswer: 'three o’clock', writingPrompt: '写一句整点时间。', writingExample: 'It is three o’clock.', independentPrompt: '不看帮助,说一个整点时间。', independentHelp: 'It is … o’clock.', ), }; LessonActivity activityBySegmentId(String segmentId, String lessonId) => a0SegmentActivities[segmentId] ?? activityByLessonId(lessonId); /// Short, reviewed entries used before each split segment. These are kept /// separate from review prompts: a review hint is not a learner-facing /// dictionary definition. const a0SegmentVocabulary = >{ 'a0-04-a': [ VocabularyItem( id: 'A0-W01', word: 'zero', meaning: '零', example: 'Zero, one, two.', exampleMeaning: '零、一、二。', ipa: '/ˈzɪrəʊ/', ), VocabularyItem( id: 'A0-W02', word: 'one', meaning: '一', example: 'One, two, three.', exampleMeaning: '一、二、三。', ipa: '/wʌn/', ), VocabularyItem( id: 'A0-W03', word: 'two', meaning: '二', example: 'Two and three.', exampleMeaning: '二和三。', ipa: '/tuː/', ), VocabularyItem( id: 'A0-W04', word: 'three', meaning: '三', example: 'Three, four, five.', exampleMeaning: '三、四、五。', ipa: '/θriː/', ), VocabularyItem( id: 'A0-W05', word: 'four', meaning: '四', example: 'Four and five.', exampleMeaning: '四和五。', ipa: '/fɔː/', ), VocabularyItem( id: 'A0-W06', word: 'five', meaning: '五', example: 'Five, please.', exampleMeaning: '五,请。', ipa: '/faɪv/', ), ], 'a0-04-b': [ VocabularyItem( id: 'A0-W07', word: 'six', meaning: '六', example: 'Six, seven, eight.', exampleMeaning: '六、七、八。', ipa: '/sɪks/', ), VocabularyItem( id: 'A0-W08', word: 'seven', meaning: '七', example: 'Seven, eight, nine.', exampleMeaning: '七、八、九。', ipa: '/ˈsevən/', ), VocabularyItem( id: 'A0-W09', word: 'eight', meaning: '八', example: 'Eight, nine, ten.', exampleMeaning: '八、九、十。', ipa: '/eɪt/', ), VocabularyItem( id: 'A0-W10', word: 'nine', meaning: '九', example: 'Nine and ten.', exampleMeaning: '九和十。', ipa: '/naɪn/', ), VocabularyItem( id: 'A0-W11', word: 'ten', meaning: '十', example: 'Ten, please.', exampleMeaning: '十,请。', ipa: '/ten/', ), VocabularyItem( id: 'A0-W20', word: 'phone', meaning: '电话;手机', example: 'It is a phone.', exampleMeaning: '它是一部手机。', ipa: '/fəʊn/', ), ], 'a0-04-c': [ VocabularyItem( id: 'A0-P07', word: "What's your phone number?", meaning: '你的电话号码是多少?', example: "What's your phone number?", exampleMeaning: '你的电话号码是多少?', ), VocabularyItem( id: 'A0-P08', word: 'My number is one-three-eight.', meaning: '我的号码是 138。', example: 'My number is one-three-eight.', exampleMeaning: '我的号码是 138。', ), ], 'a0-08-a': [ VocabularyItem( id: 'A0-W12', word: 'Monday', meaning: '星期一', example: 'It is Monday.', exampleMeaning: '今天是星期一。', ipa: '/ˈmʌndeɪ/', ), VocabularyItem( id: 'A0-W13', word: 'Tuesday', meaning: '星期二', example: 'It is Tuesday.', exampleMeaning: '今天是星期二。', ipa: '/ˈtjuːzdeɪ/', ), VocabularyItem( id: 'A0-W14', word: 'Wednesday', meaning: '星期三', example: 'It is Wednesday.', exampleMeaning: '今天是星期三。', ipa: '/ˈwenzdeɪ/', ), VocabularyItem( id: 'A0-P14', word: 'What day is it today?', meaning: '今天星期几?', example: 'What day is it today?', exampleMeaning: '今天星期几?', ), VocabularyItem( id: 'A0-P15', word: "It's Monday.", meaning: '今天是星期一。', example: "It's Monday.", exampleMeaning: '今天是星期一。', ), ], 'a0-08-b': [ VocabularyItem( id: 'A0-W15', word: 'Thursday', meaning: '星期四', example: 'It is Thursday.', exampleMeaning: '今天是星期四。', ipa: '/ˈθɜːzdeɪ/', ), VocabularyItem( id: 'A0-W16', word: 'Friday', meaning: '星期五', example: 'It is Friday.', exampleMeaning: '今天是星期五。', ipa: '/ˈfraɪdeɪ/', ), VocabularyItem( id: 'A0-W17', word: 'Saturday', meaning: '星期六', example: 'It is Saturday.', exampleMeaning: '今天是星期六。', ipa: '/ˈsætədeɪ/', ), VocabularyItem( id: 'A0-W18', word: 'Sunday', meaning: '星期日', example: 'It is Sunday.', exampleMeaning: '今天是星期日。', ipa: '/ˈsʌndeɪ/', ), ], 'a0-08-c': [ VocabularyItem( id: 'A0-P16', word: 'What time is it?', meaning: '现在几点?', example: 'What time is it?', exampleMeaning: '现在几点?', ), VocabularyItem( id: 'A0-P17', word: "It's three o'clock.", meaning: '现在三点。', example: "It's three o'clock.", exampleMeaning: '现在三点。', ), ], }; List vocabularyBySegmentId(String segmentId, String lessonId) { if (!a0SegmentActivities.containsKey(segmentId)) { return lessonById(lessonId).vocabulary; } return a0SegmentVocabulary[segmentId] ?? const []; } /// One practical rule per seed lesson. These are reminders for using a sentence /// in context, not abstract grammar lectures. const a0GrammarNotes = { 'a0-01': '介绍自己时,把名字放在 I’m 后面:I’m Mia. 不需要先学复杂时态。', 'a0-02': 'My name is 后面接名字;拼读时每个字母之间稍微停顿。', 'a0-03': '说状态用 I’m + 状态:I’m good / okay / tired。', 'a0-04': '报号码时数字一个一个说:one-three-eight,不要当成一百三十八。', 'a0-05': '问物品用 What’s this?;回答用 It’s a + 物品。', 'a0-06': '说地点用 I’m from + 地点:I’m from Hong Kong。', 'a0-07': '介绍人用 This is my + 人:This is my mother。', 'a0-08': '星期和整点都可用 It’s:It’s Monday. / It’s three o’clock。', 'a0-09': '说喜好用 I like + 东西;一般问句用 Do you like + 东西?', 'a0-10': '礼貌请求以 Please 开头:Please say that again.', }; String grammarNoteForLesson(String id) => a0GrammarNotes[id] ?? ''; const a0SegmentGrammarNotes = { 'a0-04-a': '数字单独说就可以:zero, one, two。每个词之间稍微停顿。', 'a0-04-b': '认物品可以说 It is a phone. 口语里也常说 It’s a phone.', 'a0-04-c': '报号码时一个数字一个数字说:one-three-eight,不把它读成一百三十八。', 'a0-08-a': '问星期用 What day is it?;回答用 It is / It’s + 星期。', 'a0-08-b': '星期四到星期日也沿用 It is / It’s + 星期这个句型。', 'a0-08-c': '说整点用 It is / It’s + 数字 + o’clock,例如 It’s three o’clock。', }; String grammarNoteForSegment(String segmentId, String lessonId) => a0SegmentGrammarNotes[segmentId] ?? grammarNoteForLesson(lessonId); bool matchesSegmentDialogue(String segmentId, int stage, String response) { final text = response.toLowerCase().replaceAll('’', "'"); final segment = a0LessonSegments.values .expand((segments) => segments) .where((item) => item.id == segmentId) .firstOrNull; if (segment == null || stage >= segment.dialogueRequiredTerms.length) { return false; } bool hasAny(Iterable terms) => terms.any((term) => text.contains(term)); // A phone-number report needs both the reporting frame and at least one // spoken digit. Other segment turns need one reviewed, task-specific term. if (segmentId == 'a0-04-c' && stage == 0) { return text.contains('my number is') && hasAny(segment.dialogueRequiredTerms[stage].skip(1)); } return hasAny(segment.dialogueRequiredTerms[stage]); } bool matchesSegmentIndependent(String segmentId, String response) { final text = response.toLowerCase().replaceAll('’', "'"); final segment = a0LessonSegments.values .expand((segments) => segments) .where((item) => item.id == segmentId) .firstOrNull; if (segment == null) return true; if (segmentId == 'a0-04-a' || segmentId == 'a0-04-b') { final count = segment.independentRequiredTerms .where((term) => text.contains(term)) .length; return count >= 3; } if (segmentId == 'a0-04-c') { return segment.independentRequiredTerms .where((term) => text.contains(term)) .length >= 3; } return segment.independentRequiredTerms.any((term) => text.contains(term)); } class LessonDialogue { const LessonDialogue({ required this.goal, required this.prompts, required this.hints, }); final String goal; final List prompts; final List hints; } const a0Dialogues = { 'a0-01': LessonDialogue( goal: '问候、介绍姓名并回应见面问候', prompts: [ 'Hi! I’m Mia. What’s your name?', 'Nice to meet you. Say: Nice to meet you, too.', 'Great! Say hello one more time.', 'Now ask me my name!', ], hints: [ 'I’m Alex.', 'Nice to meet you, too.', 'Hello!', 'What’s your name?', ], ), 'a0-02': LessonDialogue( goal: '介绍姓名并完整拼读名字', prompts: [ 'Hi! What’s your name?', 'How do you spell that?', 'Thank you. Spell it one more time.', 'Now ask me my name!', ], hints: ['My name is Alex.', 'A-L-E-X.', 'A-L-E-X.', 'What’s your name?'], ), 'a0-03': LessonDialogue( goal: '询问状态、回答并反问', prompts: [ 'Hi! How are you today?', 'Good! Ask me: How are you?', 'I’m okay. Say your state one more time.', 'Now say goodbye!', ], hints: ['I’m good, thanks.', 'How are you?', 'I’m okay.', 'Bye!'], ), 'a0-04': LessonDialogue( goal: '报告一个虚拟三位号码并确认', prompts: [ 'What’s your phone number? Use a fake three-digit number.', 'I heard one-three-eight. Is that right?', 'Please say the three numbers again.', 'Now ask me for my number!', ], hints: [ 'My number is one-three-eight.', 'Yes.', 'One-three-eight.', 'What’s your phone number?', ], ), 'a0-05': LessonDialogue( goal: '询问并说出一个物品', prompts: [ 'What’s this? It is a pen.', 'Now say: It’s a pen.', 'Ask me: What’s this?', 'Great! Say one more object.', ], hints: ['It’s a pen.', 'It’s a pen.', 'What’s this?', 'It’s a book.'], ), 'a0-06': LessonDialogue( goal: '说来自哪里并反问', prompts: [ 'Where are you from?', 'Nice! Ask me: Where are you from?', 'Say where you are from one more time.', 'Say goodbye!', ], hints: [ 'I’m from Hong Kong.', 'Where are you from?', 'I’m from Hong Kong.', 'Bye!', ], ), 'a0-07': LessonDialogue( goal: '介绍一位家人或朋友', prompts: [ 'Who is this?', 'Good. Say: This is my mother.', 'Ask me: Who is this?', 'Introduce one person again.', ], hints: [ 'This is my mother.', 'This is my mother.', 'Who is this?', 'This is my friend.', ], ), 'a0-08': LessonDialogue( goal: '说明星期或整点', prompts: [ 'What day is it today?', 'What time is it?', 'Say one full time sentence.', 'Now ask me the day!', ], hints: [ 'It’s Monday.', 'It’s three o’clock.', 'It’s three o’clock.', 'What day is it?', ], ), 'a0-09': LessonDialogue( goal: '表达喜好、回答和反问', prompts: [ 'What do you like?', 'Do you like tea?', 'Now ask me what I like.', 'Say your like one more time.', ], hints: ['I like tea.', 'Yes, I do.', 'Do you like tea?', 'I like tea.'], ), 'a0-10': LessonDialogue( goal: '请求重复或放慢语速,并完成基础沟通', prompts: [ 'Say: Please say that again.', 'Say: Please speak slowly.', 'Now ask me your name or where I am from.', 'Say one thing you like.', ], hints: [ 'Please say that again.', 'Please speak slowly.', 'What’s your name?', 'I like tea.', ], ), }; const a0SegmentDialogues = { 'a0-04-a': LessonDialogue( goal: '听辨并说出 0 到 5', prompts: ['Say zero, one, two.', 'Now say three, four, five.'], hints: ['zero, one, two', 'three, four, five'], ), 'a0-04-b': LessonDialogue( goal: '听辨 6 到 10 并认识 phone', prompts: ['Say six, seven, eight.', 'What is this? Say: It is a phone.'], hints: ['six, seven, eight', 'It is a phone.'], ), 'a0-04-c': LessonDialogue( goal: '询问并报告三位号码', prompts: ['What is your phone number?', 'Say a three-digit number again.'], hints: ['My number is one-three-eight.', 'one-three-eight'], ), 'a0-08-a': LessonDialogue( goal: '询问并说出星期一到三', prompts: ['What day is it?', 'Say Monday, Tuesday, or Wednesday.'], hints: ['What day is it?', 'It is Monday.'], ), 'a0-08-b': LessonDialogue( goal: '说出星期四到日', prompts: ['What day is it?', 'Say Thursday, Friday, Saturday, or Sunday.'], hints: ['What day is it?', 'It is Friday.'], ), 'a0-08-c': LessonDialogue( goal: '询问并说出整点', prompts: ['What time is it?', 'Say one full time sentence.'], hints: ['What time is it?', 'It is three o’clock.'], ), }; LessonDialogue dialogueByLessonId(String id) => a0Dialogues[id]!; LessonDialogue dialogueBySegmentId(String segmentId, String lessonId) => a0SegmentDialogues[segmentId] ?? dialogueByLessonId(lessonId);