diff --git a/flutter_app/README.md b/flutter_app/README.md index b5dce68..d2b9c12 100644 --- a/flutter_app/README.md +++ b/flutter_app/README.md @@ -15,6 +15,18 @@ Mandarin Pathways has been converted from a Progressive Web App (PWA) to a nativ ## Features +### 📚 Full PWA Parity (2026) + +- **Learning dashboard**: streaks, SRS due count, placement recommendation, achievements +- **SRS flashcards**: spaced repetition with again/good/easy grading +- **Starred phrase review**: bookmark phrases from daily lessons +- **Placement test**: level assessment with recommended start day +- **Day quizzes**: self-assessment for days 1, 8, 16, 31+ +- **Karaoke audio sync**: phrase highlighting during playback +- **Reading & writing**: full topic navigation with bundled content +- **Character canvas**: touch drawing practice for writing exercises +- **Progress portability**: export/import JSON compatible with PWA localStorage keys + ### 📚 40-Day Structured Curriculum - Daily lessons organized into 5 progressive sections @@ -319,14 +331,20 @@ flutter pub cache repair ## Future Enhancements -- [ ] Canvas-based character drawing practice - [ ] Speech recognition for pronunciation practice -- [ ] Spaced repetition flashcards - [ ] Social features (study groups, leaderboards) -- [ ] Offline media caching enhancements - [ ] Multi-user profiles - [ ] Cloud sync across devices +## Asset sync + +After regenerating PWA content, sync assets into the Flutter bundle: + +```bash +python scripts/sync_flutter_assets.py +cd flutter_app && flutter pub get +``` + ## Contributing Contributions are welcome! Please: @@ -351,4 +369,4 @@ For issues, questions, or suggestions: --- -**Note**: This Flutter client mirrors the Mandarin Pathways curriculum and primary flows from the sibling PWA (home, the 40-day course, supplementary material, plus reading/writing practice) while trading the browser runtime for Flutter's native shell, richer bundled-audio controls, and installable/mobile/desktop binaries. +**Note**: This Flutter client mirrors the full PWA feature set: 40-day course, supplementary material, reading/writing practice, SRS flashcards, starred review, placement test, day quizzes, streaks/achievements, and progress portability. diff --git a/flutter_app/assets/audio/day10_en.mp3 b/flutter_app/assets/audio/day10_en.mp3 index 418e434..45cb83e 100644 Binary files a/flutter_app/assets/audio/day10_en.mp3 and b/flutter_app/assets/audio/day10_en.mp3 differ diff --git a/flutter_app/assets/audio/day10_zh.mp3 b/flutter_app/assets/audio/day10_zh.mp3 index 7a510f1..a1d318b 100644 Binary files a/flutter_app/assets/audio/day10_zh.mp3 and b/flutter_app/assets/audio/day10_zh.mp3 differ diff --git a/flutter_app/assets/audio/day11_en.mp3 b/flutter_app/assets/audio/day11_en.mp3 index 291741c..82ac548 100644 Binary files a/flutter_app/assets/audio/day11_en.mp3 and b/flutter_app/assets/audio/day11_en.mp3 differ diff --git a/flutter_app/assets/audio/day11_zh.mp3 b/flutter_app/assets/audio/day11_zh.mp3 index eff84b9..c6d4ad7 100644 Binary files a/flutter_app/assets/audio/day11_zh.mp3 and b/flutter_app/assets/audio/day11_zh.mp3 differ diff --git a/flutter_app/assets/audio/day12_en.mp3 b/flutter_app/assets/audio/day12_en.mp3 index 13b77f9..6a45a1b 100644 Binary files a/flutter_app/assets/audio/day12_en.mp3 and b/flutter_app/assets/audio/day12_en.mp3 differ diff --git a/flutter_app/assets/audio/day12_zh.mp3 b/flutter_app/assets/audio/day12_zh.mp3 index b498bfc..4191a27 100644 Binary files a/flutter_app/assets/audio/day12_zh.mp3 and b/flutter_app/assets/audio/day12_zh.mp3 differ diff --git a/flutter_app/assets/audio/day13_en.mp3 b/flutter_app/assets/audio/day13_en.mp3 index 62cb6f8..a3e8afb 100644 Binary files a/flutter_app/assets/audio/day13_en.mp3 and b/flutter_app/assets/audio/day13_en.mp3 differ diff --git a/flutter_app/assets/audio/day13_zh.mp3 b/flutter_app/assets/audio/day13_zh.mp3 index 9ec74bf..2b5b555 100644 Binary files a/flutter_app/assets/audio/day13_zh.mp3 and b/flutter_app/assets/audio/day13_zh.mp3 differ diff --git a/flutter_app/assets/audio/day14_en.mp3 b/flutter_app/assets/audio/day14_en.mp3 index 1b38cd9..fb397ab 100644 Binary files a/flutter_app/assets/audio/day14_en.mp3 and b/flutter_app/assets/audio/day14_en.mp3 differ diff --git a/flutter_app/assets/audio/day14_zh.mp3 b/flutter_app/assets/audio/day14_zh.mp3 index b3dc877..7341b74 100644 Binary files a/flutter_app/assets/audio/day14_zh.mp3 and b/flutter_app/assets/audio/day14_zh.mp3 differ diff --git a/flutter_app/assets/audio/day15_en.mp3 b/flutter_app/assets/audio/day15_en.mp3 index 037bd77..916fea3 100644 Binary files a/flutter_app/assets/audio/day15_en.mp3 and b/flutter_app/assets/audio/day15_en.mp3 differ diff --git a/flutter_app/assets/audio/day15_zh.mp3 b/flutter_app/assets/audio/day15_zh.mp3 index 29e1f30..42f02aa 100644 Binary files a/flutter_app/assets/audio/day15_zh.mp3 and b/flutter_app/assets/audio/day15_zh.mp3 differ diff --git a/flutter_app/assets/audio/day16_en.mp3 b/flutter_app/assets/audio/day16_en.mp3 index 4f4e28a..a06cb91 100644 Binary files a/flutter_app/assets/audio/day16_en.mp3 and b/flutter_app/assets/audio/day16_en.mp3 differ diff --git a/flutter_app/assets/audio/day16_zh.mp3 b/flutter_app/assets/audio/day16_zh.mp3 index fea5f45..25d7623 100644 Binary files a/flutter_app/assets/audio/day16_zh.mp3 and b/flutter_app/assets/audio/day16_zh.mp3 differ diff --git a/flutter_app/assets/audio/day17_en.mp3 b/flutter_app/assets/audio/day17_en.mp3 index e1985ac..731d1ab 100644 Binary files a/flutter_app/assets/audio/day17_en.mp3 and b/flutter_app/assets/audio/day17_en.mp3 differ diff --git a/flutter_app/assets/audio/day17_zh.mp3 b/flutter_app/assets/audio/day17_zh.mp3 index 64efc08..c6106c7 100644 Binary files a/flutter_app/assets/audio/day17_zh.mp3 and b/flutter_app/assets/audio/day17_zh.mp3 differ diff --git a/flutter_app/assets/audio/day18_en.mp3 b/flutter_app/assets/audio/day18_en.mp3 index ac3b139..b986b58 100644 Binary files a/flutter_app/assets/audio/day18_en.mp3 and b/flutter_app/assets/audio/day18_en.mp3 differ diff --git a/flutter_app/assets/audio/day18_zh.mp3 b/flutter_app/assets/audio/day18_zh.mp3 index a4f2286..704346e 100644 Binary files a/flutter_app/assets/audio/day18_zh.mp3 and b/flutter_app/assets/audio/day18_zh.mp3 differ diff --git a/flutter_app/assets/audio/day19_en.mp3 b/flutter_app/assets/audio/day19_en.mp3 index cafef1d..eae8aa3 100644 Binary files a/flutter_app/assets/audio/day19_en.mp3 and b/flutter_app/assets/audio/day19_en.mp3 differ diff --git a/flutter_app/assets/audio/day19_zh.mp3 b/flutter_app/assets/audio/day19_zh.mp3 index 1c10bcd..5bd72af 100644 Binary files a/flutter_app/assets/audio/day19_zh.mp3 and b/flutter_app/assets/audio/day19_zh.mp3 differ diff --git a/flutter_app/assets/audio/day1_en.mp3 b/flutter_app/assets/audio/day1_en.mp3 index 01ee30d..b768ec2 100644 Binary files a/flutter_app/assets/audio/day1_en.mp3 and b/flutter_app/assets/audio/day1_en.mp3 differ diff --git a/flutter_app/assets/audio/day1_zh.mp3 b/flutter_app/assets/audio/day1_zh.mp3 index f41ed03..6155423 100644 Binary files a/flutter_app/assets/audio/day1_zh.mp3 and b/flutter_app/assets/audio/day1_zh.mp3 differ diff --git a/flutter_app/assets/audio/day20_en.mp3 b/flutter_app/assets/audio/day20_en.mp3 index da04c62..ab93888 100644 Binary files a/flutter_app/assets/audio/day20_en.mp3 and b/flutter_app/assets/audio/day20_en.mp3 differ diff --git a/flutter_app/assets/audio/day20_zh.mp3 b/flutter_app/assets/audio/day20_zh.mp3 index ab82494..107f61f 100644 Binary files a/flutter_app/assets/audio/day20_zh.mp3 and b/flutter_app/assets/audio/day20_zh.mp3 differ diff --git a/flutter_app/assets/audio/day21_en.mp3 b/flutter_app/assets/audio/day21_en.mp3 index dd4c944..681de00 100644 Binary files a/flutter_app/assets/audio/day21_en.mp3 and b/flutter_app/assets/audio/day21_en.mp3 differ diff --git a/flutter_app/assets/audio/day21_zh.mp3 b/flutter_app/assets/audio/day21_zh.mp3 index 6c6da8b..72a634c 100644 Binary files a/flutter_app/assets/audio/day21_zh.mp3 and b/flutter_app/assets/audio/day21_zh.mp3 differ diff --git a/flutter_app/assets/audio/day22_en.mp3 b/flutter_app/assets/audio/day22_en.mp3 index fe55258..0bb5718 100644 Binary files a/flutter_app/assets/audio/day22_en.mp3 and b/flutter_app/assets/audio/day22_en.mp3 differ diff --git a/flutter_app/assets/audio/day22_zh.mp3 b/flutter_app/assets/audio/day22_zh.mp3 index 8ffeee0..26456fb 100644 Binary files a/flutter_app/assets/audio/day22_zh.mp3 and b/flutter_app/assets/audio/day22_zh.mp3 differ diff --git a/flutter_app/assets/audio/day23_en.mp3 b/flutter_app/assets/audio/day23_en.mp3 index 28228cd..4e764cf 100644 Binary files a/flutter_app/assets/audio/day23_en.mp3 and b/flutter_app/assets/audio/day23_en.mp3 differ diff --git a/flutter_app/assets/audio/day23_zh.mp3 b/flutter_app/assets/audio/day23_zh.mp3 index dad8ba8..bb8a983 100644 Binary files a/flutter_app/assets/audio/day23_zh.mp3 and b/flutter_app/assets/audio/day23_zh.mp3 differ diff --git a/flutter_app/assets/audio/day24_en.mp3 b/flutter_app/assets/audio/day24_en.mp3 index d57adbc..cf98970 100644 Binary files a/flutter_app/assets/audio/day24_en.mp3 and b/flutter_app/assets/audio/day24_en.mp3 differ diff --git a/flutter_app/assets/audio/day24_zh.mp3 b/flutter_app/assets/audio/day24_zh.mp3 index df20f6a..fefd429 100644 Binary files a/flutter_app/assets/audio/day24_zh.mp3 and b/flutter_app/assets/audio/day24_zh.mp3 differ diff --git a/flutter_app/assets/audio/day25_en.mp3 b/flutter_app/assets/audio/day25_en.mp3 index 76a4a9e..c023963 100644 Binary files a/flutter_app/assets/audio/day25_en.mp3 and b/flutter_app/assets/audio/day25_en.mp3 differ diff --git a/flutter_app/assets/audio/day25_zh.mp3 b/flutter_app/assets/audio/day25_zh.mp3 index 54d46d7..84e4d9f 100644 Binary files a/flutter_app/assets/audio/day25_zh.mp3 and b/flutter_app/assets/audio/day25_zh.mp3 differ diff --git a/flutter_app/assets/audio/day26_en.mp3 b/flutter_app/assets/audio/day26_en.mp3 index 16a5c4b..5e943bd 100644 Binary files a/flutter_app/assets/audio/day26_en.mp3 and b/flutter_app/assets/audio/day26_en.mp3 differ diff --git a/flutter_app/assets/audio/day26_zh.mp3 b/flutter_app/assets/audio/day26_zh.mp3 index 25c2b77..35ea440 100644 Binary files a/flutter_app/assets/audio/day26_zh.mp3 and b/flutter_app/assets/audio/day26_zh.mp3 differ diff --git a/flutter_app/assets/audio/day27_en.mp3 b/flutter_app/assets/audio/day27_en.mp3 index a799fff..0ca52b8 100644 Binary files a/flutter_app/assets/audio/day27_en.mp3 and b/flutter_app/assets/audio/day27_en.mp3 differ diff --git a/flutter_app/assets/audio/day27_zh.mp3 b/flutter_app/assets/audio/day27_zh.mp3 index ca7dbb7..40bb582 100644 Binary files a/flutter_app/assets/audio/day27_zh.mp3 and b/flutter_app/assets/audio/day27_zh.mp3 differ diff --git a/flutter_app/assets/audio/day28_en.mp3 b/flutter_app/assets/audio/day28_en.mp3 index e20e573..2e6469e 100644 Binary files a/flutter_app/assets/audio/day28_en.mp3 and b/flutter_app/assets/audio/day28_en.mp3 differ diff --git a/flutter_app/assets/audio/day28_zh.mp3 b/flutter_app/assets/audio/day28_zh.mp3 index 9bc1050..b3d1eaf 100644 Binary files a/flutter_app/assets/audio/day28_zh.mp3 and b/flutter_app/assets/audio/day28_zh.mp3 differ diff --git a/flutter_app/assets/audio/day29_en.mp3 b/flutter_app/assets/audio/day29_en.mp3 index 79f45e7..96f8239 100644 Binary files a/flutter_app/assets/audio/day29_en.mp3 and b/flutter_app/assets/audio/day29_en.mp3 differ diff --git a/flutter_app/assets/audio/day29_zh.mp3 b/flutter_app/assets/audio/day29_zh.mp3 index 2cdac99..f04a5a2 100644 Binary files a/flutter_app/assets/audio/day29_zh.mp3 and b/flutter_app/assets/audio/day29_zh.mp3 differ diff --git a/flutter_app/assets/audio/day2_en.mp3 b/flutter_app/assets/audio/day2_en.mp3 index e64ca14..03b5882 100644 Binary files a/flutter_app/assets/audio/day2_en.mp3 and b/flutter_app/assets/audio/day2_en.mp3 differ diff --git a/flutter_app/assets/audio/day2_zh.mp3 b/flutter_app/assets/audio/day2_zh.mp3 index 66367af..12eee59 100644 Binary files a/flutter_app/assets/audio/day2_zh.mp3 and b/flutter_app/assets/audio/day2_zh.mp3 differ diff --git a/flutter_app/assets/audio/day30_en.mp3 b/flutter_app/assets/audio/day30_en.mp3 index 5c1f9a0..05a6a1c 100644 Binary files a/flutter_app/assets/audio/day30_en.mp3 and b/flutter_app/assets/audio/day30_en.mp3 differ diff --git a/flutter_app/assets/audio/day30_zh.mp3 b/flutter_app/assets/audio/day30_zh.mp3 index b0aab73..1ef7331 100644 Binary files a/flutter_app/assets/audio/day30_zh.mp3 and b/flutter_app/assets/audio/day30_zh.mp3 differ diff --git a/flutter_app/assets/audio/day31_en.mp3 b/flutter_app/assets/audio/day31_en.mp3 index 287cd57..5a833d7 100644 Binary files a/flutter_app/assets/audio/day31_en.mp3 and b/flutter_app/assets/audio/day31_en.mp3 differ diff --git a/flutter_app/assets/audio/day31_zh.mp3 b/flutter_app/assets/audio/day31_zh.mp3 index 6ee4644..9881dda 100644 Binary files a/flutter_app/assets/audio/day31_zh.mp3 and b/flutter_app/assets/audio/day31_zh.mp3 differ diff --git a/flutter_app/assets/audio/day32_en.mp3 b/flutter_app/assets/audio/day32_en.mp3 index 173be23..8186bc4 100644 Binary files a/flutter_app/assets/audio/day32_en.mp3 and b/flutter_app/assets/audio/day32_en.mp3 differ diff --git a/flutter_app/assets/audio/day32_zh.mp3 b/flutter_app/assets/audio/day32_zh.mp3 index 7079f40..1d64f11 100644 Binary files a/flutter_app/assets/audio/day32_zh.mp3 and b/flutter_app/assets/audio/day32_zh.mp3 differ diff --git a/flutter_app/assets/audio/day33_en.mp3 b/flutter_app/assets/audio/day33_en.mp3 index 53a8b31..68b2d5d 100644 Binary files a/flutter_app/assets/audio/day33_en.mp3 and b/flutter_app/assets/audio/day33_en.mp3 differ diff --git a/flutter_app/assets/audio/day33_zh.mp3 b/flutter_app/assets/audio/day33_zh.mp3 index 1af0e7c..482e7ef 100644 Binary files a/flutter_app/assets/audio/day33_zh.mp3 and b/flutter_app/assets/audio/day33_zh.mp3 differ diff --git a/flutter_app/assets/audio/day34_en.mp3 b/flutter_app/assets/audio/day34_en.mp3 index 0d8f0a6..51e725d 100644 Binary files a/flutter_app/assets/audio/day34_en.mp3 and b/flutter_app/assets/audio/day34_en.mp3 differ diff --git a/flutter_app/assets/audio/day34_zh.mp3 b/flutter_app/assets/audio/day34_zh.mp3 index fc2ce78..aec4e05 100644 Binary files a/flutter_app/assets/audio/day34_zh.mp3 and b/flutter_app/assets/audio/day34_zh.mp3 differ diff --git a/flutter_app/assets/audio/day35_en.mp3 b/flutter_app/assets/audio/day35_en.mp3 index 757b3ac..82d8019 100644 Binary files a/flutter_app/assets/audio/day35_en.mp3 and b/flutter_app/assets/audio/day35_en.mp3 differ diff --git a/flutter_app/assets/audio/day35_zh.mp3 b/flutter_app/assets/audio/day35_zh.mp3 index 284e461..305a3e0 100644 Binary files a/flutter_app/assets/audio/day35_zh.mp3 and b/flutter_app/assets/audio/day35_zh.mp3 differ diff --git a/flutter_app/assets/audio/day36_en.mp3 b/flutter_app/assets/audio/day36_en.mp3 index 284367a..0598ffc 100644 Binary files a/flutter_app/assets/audio/day36_en.mp3 and b/flutter_app/assets/audio/day36_en.mp3 differ diff --git a/flutter_app/assets/audio/day36_zh.mp3 b/flutter_app/assets/audio/day36_zh.mp3 index f459a3f..d0f7d2d 100644 Binary files a/flutter_app/assets/audio/day36_zh.mp3 and b/flutter_app/assets/audio/day36_zh.mp3 differ diff --git a/flutter_app/assets/audio/day37_en.mp3 b/flutter_app/assets/audio/day37_en.mp3 index 280efab..a59e23d 100644 Binary files a/flutter_app/assets/audio/day37_en.mp3 and b/flutter_app/assets/audio/day37_en.mp3 differ diff --git a/flutter_app/assets/audio/day37_zh.mp3 b/flutter_app/assets/audio/day37_zh.mp3 index f578ad9..7092b83 100644 Binary files a/flutter_app/assets/audio/day37_zh.mp3 and b/flutter_app/assets/audio/day37_zh.mp3 differ diff --git a/flutter_app/assets/audio/day38_en.mp3 b/flutter_app/assets/audio/day38_en.mp3 index 134cc84..67c7f06 100644 Binary files a/flutter_app/assets/audio/day38_en.mp3 and b/flutter_app/assets/audio/day38_en.mp3 differ diff --git a/flutter_app/assets/audio/day38_zh.mp3 b/flutter_app/assets/audio/day38_zh.mp3 index b793c72..724d8cf 100644 Binary files a/flutter_app/assets/audio/day38_zh.mp3 and b/flutter_app/assets/audio/day38_zh.mp3 differ diff --git a/flutter_app/assets/audio/day39_en.mp3 b/flutter_app/assets/audio/day39_en.mp3 index fc3e9cc..c7e7658 100644 Binary files a/flutter_app/assets/audio/day39_en.mp3 and b/flutter_app/assets/audio/day39_en.mp3 differ diff --git a/flutter_app/assets/audio/day39_zh.mp3 b/flutter_app/assets/audio/day39_zh.mp3 index 83b709f..26d379b 100644 Binary files a/flutter_app/assets/audio/day39_zh.mp3 and b/flutter_app/assets/audio/day39_zh.mp3 differ diff --git a/flutter_app/assets/audio/day3_en.mp3 b/flutter_app/assets/audio/day3_en.mp3 index eedfff6..2296f9d 100644 Binary files a/flutter_app/assets/audio/day3_en.mp3 and b/flutter_app/assets/audio/day3_en.mp3 differ diff --git a/flutter_app/assets/audio/day3_zh.mp3 b/flutter_app/assets/audio/day3_zh.mp3 index 69468cb..e1b0a1e 100644 Binary files a/flutter_app/assets/audio/day3_zh.mp3 and b/flutter_app/assets/audio/day3_zh.mp3 differ diff --git a/flutter_app/assets/audio/day40_en.mp3 b/flutter_app/assets/audio/day40_en.mp3 index 63ac2fd..cef5a7e 100644 Binary files a/flutter_app/assets/audio/day40_en.mp3 and b/flutter_app/assets/audio/day40_en.mp3 differ diff --git a/flutter_app/assets/audio/day40_zh.mp3 b/flutter_app/assets/audio/day40_zh.mp3 index 922f0ca..787eef7 100644 Binary files a/flutter_app/assets/audio/day40_zh.mp3 and b/flutter_app/assets/audio/day40_zh.mp3 differ diff --git a/flutter_app/assets/audio/day4_en.mp3 b/flutter_app/assets/audio/day4_en.mp3 index 48cf771..2cd1698 100644 Binary files a/flutter_app/assets/audio/day4_en.mp3 and b/flutter_app/assets/audio/day4_en.mp3 differ diff --git a/flutter_app/assets/audio/day4_zh.mp3 b/flutter_app/assets/audio/day4_zh.mp3 index 0575145..188c22f 100644 Binary files a/flutter_app/assets/audio/day4_zh.mp3 and b/flutter_app/assets/audio/day4_zh.mp3 differ diff --git a/flutter_app/assets/audio/day5_en.mp3 b/flutter_app/assets/audio/day5_en.mp3 index 5657333..7d66ea9 100644 Binary files a/flutter_app/assets/audio/day5_en.mp3 and b/flutter_app/assets/audio/day5_en.mp3 differ diff --git a/flutter_app/assets/audio/day5_zh.mp3 b/flutter_app/assets/audio/day5_zh.mp3 index c147d3c..15be90a 100644 Binary files a/flutter_app/assets/audio/day5_zh.mp3 and b/flutter_app/assets/audio/day5_zh.mp3 differ diff --git a/flutter_app/assets/audio/day6_en.mp3 b/flutter_app/assets/audio/day6_en.mp3 index 0f1db95..970b706 100644 Binary files a/flutter_app/assets/audio/day6_en.mp3 and b/flutter_app/assets/audio/day6_en.mp3 differ diff --git a/flutter_app/assets/audio/day6_zh.mp3 b/flutter_app/assets/audio/day6_zh.mp3 index 444fe61..a2beafc 100644 Binary files a/flutter_app/assets/audio/day6_zh.mp3 and b/flutter_app/assets/audio/day6_zh.mp3 differ diff --git a/flutter_app/assets/audio/day7_en.mp3 b/flutter_app/assets/audio/day7_en.mp3 index afc556f..0826854 100644 Binary files a/flutter_app/assets/audio/day7_en.mp3 and b/flutter_app/assets/audio/day7_en.mp3 differ diff --git a/flutter_app/assets/audio/day7_zh.mp3 b/flutter_app/assets/audio/day7_zh.mp3 index 9b869d1..3d154d4 100644 Binary files a/flutter_app/assets/audio/day7_zh.mp3 and b/flutter_app/assets/audio/day7_zh.mp3 differ diff --git a/flutter_app/assets/audio/day8_en.mp3 b/flutter_app/assets/audio/day8_en.mp3 index 6516150..95d4879 100644 Binary files a/flutter_app/assets/audio/day8_en.mp3 and b/flutter_app/assets/audio/day8_en.mp3 differ diff --git a/flutter_app/assets/audio/day8_zh.mp3 b/flutter_app/assets/audio/day8_zh.mp3 index 3beed21..2d6cdad 100644 Binary files a/flutter_app/assets/audio/day8_zh.mp3 and b/flutter_app/assets/audio/day8_zh.mp3 differ diff --git a/flutter_app/assets/audio/day9_en.mp3 b/flutter_app/assets/audio/day9_en.mp3 index 1c00262..5b35e87 100644 Binary files a/flutter_app/assets/audio/day9_en.mp3 and b/flutter_app/assets/audio/day9_en.mp3 differ diff --git a/flutter_app/assets/audio/day9_zh.mp3 b/flutter_app/assets/audio/day9_zh.mp3 index f6e229b..0c22090 100644 Binary files a/flutter_app/assets/audio/day9_zh.mp3 and b/flutter_app/assets/audio/day9_zh.mp3 differ diff --git a/flutter_app/assets/audio/reading/advanced_environmental_protection_en.mp3 b/flutter_app/assets/audio/reading/advanced_environmental_protection_en.mp3 index 5020e78..ffdc733 100644 Binary files a/flutter_app/assets/audio/reading/advanced_environmental_protection_en.mp3 and b/flutter_app/assets/audio/reading/advanced_environmental_protection_en.mp3 differ diff --git a/flutter_app/assets/audio/reading/advanced_environmental_protection_zh.mp3 b/flutter_app/assets/audio/reading/advanced_environmental_protection_zh.mp3 index 4e80fa2..1e80844 100644 Binary files a/flutter_app/assets/audio/reading/advanced_environmental_protection_zh.mp3 and b/flutter_app/assets/audio/reading/advanced_environmental_protection_zh.mp3 differ diff --git a/flutter_app/assets/audio/reading/beginner_daily_routine_en.mp3 b/flutter_app/assets/audio/reading/beginner_daily_routine_en.mp3 index 4c65a8d..0ae93ee 100644 Binary files a/flutter_app/assets/audio/reading/beginner_daily_routine_en.mp3 and b/flutter_app/assets/audio/reading/beginner_daily_routine_en.mp3 differ diff --git a/flutter_app/assets/audio/reading/beginner_daily_routine_zh.mp3 b/flutter_app/assets/audio/reading/beginner_daily_routine_zh.mp3 index 8a2d85d..be49f06 100644 Binary files a/flutter_app/assets/audio/reading/beginner_daily_routine_zh.mp3 and b/flutter_app/assets/audio/reading/beginner_daily_routine_zh.mp3 differ diff --git a/flutter_app/assets/audio/reading/beginner_self_introduction_en.mp3 b/flutter_app/assets/audio/reading/beginner_self_introduction_en.mp3 index 72b767b..7f4dd42 100644 Binary files a/flutter_app/assets/audio/reading/beginner_self_introduction_en.mp3 and b/flutter_app/assets/audio/reading/beginner_self_introduction_en.mp3 differ diff --git a/flutter_app/assets/audio/reading/beginner_self_introduction_zh.mp3 b/flutter_app/assets/audio/reading/beginner_self_introduction_zh.mp3 index 709749e..b384cf7 100644 Binary files a/flutter_app/assets/audio/reading/beginner_self_introduction_zh.mp3 and b/flutter_app/assets/audio/reading/beginner_self_introduction_zh.mp3 differ diff --git a/flutter_app/assets/audio/reading/intermediate_at_the_restaurant_en.mp3 b/flutter_app/assets/audio/reading/intermediate_at_the_restaurant_en.mp3 index 378ce2a..7172288 100644 Binary files a/flutter_app/assets/audio/reading/intermediate_at_the_restaurant_en.mp3 and b/flutter_app/assets/audio/reading/intermediate_at_the_restaurant_en.mp3 differ diff --git a/flutter_app/assets/audio/reading/intermediate_at_the_restaurant_zh.mp3 b/flutter_app/assets/audio/reading/intermediate_at_the_restaurant_zh.mp3 index b2da255..3a8d81a 100644 Binary files a/flutter_app/assets/audio/reading/intermediate_at_the_restaurant_zh.mp3 and b/flutter_app/assets/audio/reading/intermediate_at_the_restaurant_zh.mp3 differ diff --git a/flutter_app/assets/audio/reading/intermediate_weekend_plans_en.mp3 b/flutter_app/assets/audio/reading/intermediate_weekend_plans_en.mp3 index b32b1b8..3b1be80 100644 Binary files a/flutter_app/assets/audio/reading/intermediate_weekend_plans_en.mp3 and b/flutter_app/assets/audio/reading/intermediate_weekend_plans_en.mp3 differ diff --git a/flutter_app/assets/audio/reading/intermediate_weekend_plans_zh.mp3 b/flutter_app/assets/audio/reading/intermediate_weekend_plans_zh.mp3 index 523ba9e..d29e970 100644 Binary files a/flutter_app/assets/audio/reading/intermediate_weekend_plans_zh.mp3 and b/flutter_app/assets/audio/reading/intermediate_weekend_plans_zh.mp3 differ diff --git a/flutter_app/assets/audio/supplementary/comparisons_en.mp3 b/flutter_app/assets/audio/supplementary/comparisons_en.mp3 index 7c4e435..f011947 100644 Binary files a/flutter_app/assets/audio/supplementary/comparisons_en.mp3 and b/flutter_app/assets/audio/supplementary/comparisons_en.mp3 differ diff --git a/flutter_app/assets/audio/supplementary/comparisons_zh.mp3 b/flutter_app/assets/audio/supplementary/comparisons_zh.mp3 index 0d0005a..82f319e 100644 Binary files a/flutter_app/assets/audio/supplementary/comparisons_zh.mp3 and b/flutter_app/assets/audio/supplementary/comparisons_zh.mp3 differ diff --git a/flutter_app/assets/audio/supplementary/daily_life_en.mp3 b/flutter_app/assets/audio/supplementary/daily_life_en.mp3 index 47ab2d0..b4ef73f 100644 Binary files a/flutter_app/assets/audio/supplementary/daily_life_en.mp3 and b/flutter_app/assets/audio/supplementary/daily_life_en.mp3 differ diff --git a/flutter_app/assets/audio/supplementary/daily_life_zh.mp3 b/flutter_app/assets/audio/supplementary/daily_life_zh.mp3 index 514fdba..39b2855 100644 Binary files a/flutter_app/assets/audio/supplementary/daily_life_zh.mp3 and b/flutter_app/assets/audio/supplementary/daily_life_zh.mp3 differ diff --git a/flutter_app/assets/audio/supplementary/education_en.mp3 b/flutter_app/assets/audio/supplementary/education_en.mp3 index 50abaae..8795e26 100644 Binary files a/flutter_app/assets/audio/supplementary/education_en.mp3 and b/flutter_app/assets/audio/supplementary/education_en.mp3 differ diff --git a/flutter_app/assets/audio/supplementary/education_zh.mp3 b/flutter_app/assets/audio/supplementary/education_zh.mp3 index 56d2746..4e8f5b1 100644 Binary files a/flutter_app/assets/audio/supplementary/education_zh.mp3 and b/flutter_app/assets/audio/supplementary/education_zh.mp3 differ diff --git a/flutter_app/assets/audio/supplementary/emotions_en.mp3 b/flutter_app/assets/audio/supplementary/emotions_en.mp3 index e6e3e98..6e6e6a7 100644 Binary files a/flutter_app/assets/audio/supplementary/emotions_en.mp3 and b/flutter_app/assets/audio/supplementary/emotions_en.mp3 differ diff --git a/flutter_app/assets/audio/supplementary/emotions_zh.mp3 b/flutter_app/assets/audio/supplementary/emotions_zh.mp3 index 5634643..c101561 100644 Binary files a/flutter_app/assets/audio/supplementary/emotions_zh.mp3 and b/flutter_app/assets/audio/supplementary/emotions_zh.mp3 differ diff --git a/flutter_app/assets/audio/supplementary/hobbies_en.mp3 b/flutter_app/assets/audio/supplementary/hobbies_en.mp3 index 8e4b6ca..8e60999 100644 Binary files a/flutter_app/assets/audio/supplementary/hobbies_en.mp3 and b/flutter_app/assets/audio/supplementary/hobbies_en.mp3 differ diff --git a/flutter_app/assets/audio/supplementary/hobbies_zh.mp3 b/flutter_app/assets/audio/supplementary/hobbies_zh.mp3 index b884427..2640fd6 100644 Binary files a/flutter_app/assets/audio/supplementary/hobbies_zh.mp3 and b/flutter_app/assets/audio/supplementary/hobbies_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_basic_strokes_en.mp3 b/flutter_app/assets/audio/writing/character_basic_strokes_en.mp3 index c1f2fc5..d4dfc9b 100644 Binary files a/flutter_app/assets/audio/writing/character_basic_strokes_en.mp3 and b/flutter_app/assets/audio/writing/character_basic_strokes_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_basic_strokes_zh.mp3 b/flutter_app/assets/audio/writing/character_basic_strokes_zh.mp3 index 0ed5e07..fa3ab61 100644 Binary files a/flutter_app/assets/audio/writing/character_basic_strokes_zh.mp3 and b/flutter_app/assets/audio/writing/character_basic_strokes_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_common_radicals_en.mp3 b/flutter_app/assets/audio/writing/character_common_radicals_en.mp3 index 582db96..dfe83af 100644 Binary files a/flutter_app/assets/audio/writing/character_common_radicals_en.mp3 and b/flutter_app/assets/audio/writing/character_common_radicals_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_common_radicals_zh.mp3 b/flutter_app/assets/audio/writing/character_common_radicals_zh.mp3 index d3b0f64..f9bbcdd 100644 Binary files a/flutter_app/assets/audio/writing/character_common_radicals_zh.mp3 and b/flutter_app/assets/audio/writing/character_common_radicals_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_1_en.mp3 b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_1_en.mp3 index bde7f6d..fa33450 100644 Binary files a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_1_en.mp3 and b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_1_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_1_zh.mp3 b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_1_zh.mp3 index e40f30d..486b98a 100644 Binary files a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_1_zh.mp3 and b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_1_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_2_en.mp3 b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_2_en.mp3 index c5de2ff..7bc24b4 100644 Binary files a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_2_en.mp3 and b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_2_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_2_zh.mp3 b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_2_zh.mp3 index b8260b1..b0504de 100644 Binary files a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_2_zh.mp3 and b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_2_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_3_en.mp3 b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_3_en.mp3 index f2f3949..a014555 100644 Binary files a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_3_en.mp3 and b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_3_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_3_zh.mp3 b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_3_zh.mp3 index 3835b30..296e07f 100644 Binary files a/flutter_app/assets/audio/writing/character_complete_radicals_-_group_3_zh.mp3 and b/flutter_app/assets/audio/writing/character_complete_radicals_-_group_3_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_hsk1_-_essential_en.mp3 b/flutter_app/assets/audio/writing/character_hsk1_-_essential_en.mp3 index 3234921..f3da86c 100644 Binary files a/flutter_app/assets/audio/writing/character_hsk1_-_essential_en.mp3 and b/flutter_app/assets/audio/writing/character_hsk1_-_essential_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_hsk1_-_essential_zh.mp3 b/flutter_app/assets/audio/writing/character_hsk1_-_essential_zh.mp3 index b4823ac..a6d8bde 100644 Binary files a/flutter_app/assets/audio/writing/character_hsk1_-_essential_zh.mp3 and b/flutter_app/assets/audio/writing/character_hsk1_-_essential_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_hsk2_-_basic_en.mp3 b/flutter_app/assets/audio/writing/character_hsk2_-_basic_en.mp3 index 65949d0..7f893fd 100644 Binary files a/flutter_app/assets/audio/writing/character_hsk2_-_basic_en.mp3 and b/flutter_app/assets/audio/writing/character_hsk2_-_basic_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_hsk2_-_basic_zh.mp3 b/flutter_app/assets/audio/writing/character_hsk2_-_basic_zh.mp3 index bab350e..8ad847c 100644 Binary files a/flutter_app/assets/audio/writing/character_hsk2_-_basic_zh.mp3 and b/flutter_app/assets/audio/writing/character_hsk2_-_basic_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_hsk3_-_intermediate_en.mp3 b/flutter_app/assets/audio/writing/character_hsk3_-_intermediate_en.mp3 index 93537bc..7719015 100644 Binary files a/flutter_app/assets/audio/writing/character_hsk3_-_intermediate_en.mp3 and b/flutter_app/assets/audio/writing/character_hsk3_-_intermediate_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_hsk3_-_intermediate_zh.mp3 b/flutter_app/assets/audio/writing/character_hsk3_-_intermediate_zh.mp3 index 47b8586..45b6c49 100644 Binary files a/flutter_app/assets/audio/writing/character_hsk3_-_intermediate_zh.mp3 and b/flutter_app/assets/audio/writing/character_hsk3_-_intermediate_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_numbers_en.mp3 b/flutter_app/assets/audio/writing/character_numbers_en.mp3 index ff568f3..1cca0ac 100644 Binary files a/flutter_app/assets/audio/writing/character_numbers_en.mp3 and b/flutter_app/assets/audio/writing/character_numbers_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_numbers_zh.mp3 b/flutter_app/assets/audio/writing/character_numbers_zh.mp3 index 6d2750b..013c177 100644 Binary files a/flutter_app/assets/audio/writing/character_numbers_zh.mp3 and b/flutter_app/assets/audio/writing/character_numbers_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_theme_-_family_en.mp3 b/flutter_app/assets/audio/writing/character_theme_-_family_en.mp3 index 5adb798..60b5da5 100644 Binary files a/flutter_app/assets/audio/writing/character_theme_-_family_en.mp3 and b/flutter_app/assets/audio/writing/character_theme_-_family_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_theme_-_family_zh.mp3 b/flutter_app/assets/audio/writing/character_theme_-_family_zh.mp3 index e04f613..2535c8d 100644 Binary files a/flutter_app/assets/audio/writing/character_theme_-_family_zh.mp3 and b/flutter_app/assets/audio/writing/character_theme_-_family_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_theme_-_food_en.mp3 b/flutter_app/assets/audio/writing/character_theme_-_food_en.mp3 index 61a43d9..4eebc18 100644 Binary files a/flutter_app/assets/audio/writing/character_theme_-_food_en.mp3 and b/flutter_app/assets/audio/writing/character_theme_-_food_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_theme_-_food_zh.mp3 b/flutter_app/assets/audio/writing/character_theme_-_food_zh.mp3 index bdb87ae..841601b 100644 Binary files a/flutter_app/assets/audio/writing/character_theme_-_food_zh.mp3 and b/flutter_app/assets/audio/writing/character_theme_-_food_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_theme_-_travel_en.mp3 b/flutter_app/assets/audio/writing/character_theme_-_travel_en.mp3 index 094598c..6cf03f3 100644 Binary files a/flutter_app/assets/audio/writing/character_theme_-_travel_en.mp3 and b/flutter_app/assets/audio/writing/character_theme_-_travel_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/character_theme_-_travel_zh.mp3 b/flutter_app/assets/audio/writing/character_theme_-_travel_zh.mp3 index 2fd62aa..d204054 100644 Binary files a/flutter_app/assets/audio/writing/character_theme_-_travel_zh.mp3 and b/flutter_app/assets/audio/writing/character_theme_-_travel_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/sentence_advanced_en.mp3 b/flutter_app/assets/audio/writing/sentence_advanced_en.mp3 index e50b110..b0d0184 100644 Binary files a/flutter_app/assets/audio/writing/sentence_advanced_en.mp3 and b/flutter_app/assets/audio/writing/sentence_advanced_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/sentence_advanced_zh.mp3 b/flutter_app/assets/audio/writing/sentence_advanced_zh.mp3 index ca23573..7923cc0 100644 Binary files a/flutter_app/assets/audio/writing/sentence_advanced_zh.mp3 and b/flutter_app/assets/audio/writing/sentence_advanced_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/sentence_beginner_en.mp3 b/flutter_app/assets/audio/writing/sentence_beginner_en.mp3 index e036d42..9c7f8de 100644 Binary files a/flutter_app/assets/audio/writing/sentence_beginner_en.mp3 and b/flutter_app/assets/audio/writing/sentence_beginner_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/sentence_beginner_zh.mp3 b/flutter_app/assets/audio/writing/sentence_beginner_zh.mp3 index 86f8c2d..61d61c5 100644 Binary files a/flutter_app/assets/audio/writing/sentence_beginner_zh.mp3 and b/flutter_app/assets/audio/writing/sentence_beginner_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/sentence_intermediate_en.mp3 b/flutter_app/assets/audio/writing/sentence_intermediate_en.mp3 index 0a33079..3032597 100644 Binary files a/flutter_app/assets/audio/writing/sentence_intermediate_en.mp3 and b/flutter_app/assets/audio/writing/sentence_intermediate_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/sentence_intermediate_zh.mp3 b/flutter_app/assets/audio/writing/sentence_intermediate_zh.mp3 index 4466aa5..72770c8 100644 Binary files a/flutter_app/assets/audio/writing/sentence_intermediate_zh.mp3 and b/flutter_app/assets/audio/writing/sentence_intermediate_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/translation_advanced_en.mp3 b/flutter_app/assets/audio/writing/translation_advanced_en.mp3 index b0ad5e1..1e85b64 100644 Binary files a/flutter_app/assets/audio/writing/translation_advanced_en.mp3 and b/flutter_app/assets/audio/writing/translation_advanced_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/translation_advanced_zh.mp3 b/flutter_app/assets/audio/writing/translation_advanced_zh.mp3 index b88d403..604ab72 100644 Binary files a/flutter_app/assets/audio/writing/translation_advanced_zh.mp3 and b/flutter_app/assets/audio/writing/translation_advanced_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/translation_beginner_en.mp3 b/flutter_app/assets/audio/writing/translation_beginner_en.mp3 index 7fc7a12..56ae062 100644 Binary files a/flutter_app/assets/audio/writing/translation_beginner_en.mp3 and b/flutter_app/assets/audio/writing/translation_beginner_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/translation_beginner_zh.mp3 b/flutter_app/assets/audio/writing/translation_beginner_zh.mp3 index 12cb83d..79e9bf7 100644 Binary files a/flutter_app/assets/audio/writing/translation_beginner_zh.mp3 and b/flutter_app/assets/audio/writing/translation_beginner_zh.mp3 differ diff --git a/flutter_app/assets/audio/writing/translation_intermediate_en.mp3 b/flutter_app/assets/audio/writing/translation_intermediate_en.mp3 index b365219..5a53fd7 100644 Binary files a/flutter_app/assets/audio/writing/translation_intermediate_en.mp3 and b/flutter_app/assets/audio/writing/translation_intermediate_en.mp3 differ diff --git a/flutter_app/assets/audio/writing/translation_intermediate_zh.mp3 b/flutter_app/assets/audio/writing/translation_intermediate_zh.mp3 index b785d3e..8eff079 100644 Binary files a/flutter_app/assets/audio/writing/translation_intermediate_zh.mp3 and b/flutter_app/assets/audio/writing/translation_intermediate_zh.mp3 differ diff --git a/flutter_app/assets/reading/advanced_environmental_protection_en.txt b/flutter_app/assets/reading/advanced_environmental_protection_en.txt new file mode 100644 index 0000000..cc1cd82 --- /dev/null +++ b/flutter_app/assets/reading/advanced_environmental_protection_en.txt @@ -0,0 +1,47 @@ +Reading Exercise +--------------- + +In recent years, environmental protection has become an important topic of global concern. With the development of industrialization and urbanization, environmental problems such as air pollution, water pollution, and soil pollution are becoming increasingly serious. Many countries have begun to take measures to reduce carbon emissions and develop renewable energy sources such as solar and wind energy. Individuals can also contribute to environmental protection by reducing the use of plastic bags, conserving water and electricity, using public transportation, and other methods. Protecting the environment is not only the responsibility of the government but also the duty of every citizen. + +生词表 / Vocabulary +-------------------- + +• environmental protection (huánjìng bǎohù) - 环境保护 +• global (quánqiú) - 全球 +• to pay attention to (guānzhù) - 关注 +• topic (huàtí) - 话题 +• industrialization (gōngyèhuà) - 工业化 +• urbanization (chéngshìhuà) - 城市化 +• development (fāzhǎn) - 发展 +• air pollution (kōngqì wūrǎn) - 空气污染 +• water pollution (shuǐ wūrǎn) - 水污染 +• soil pollution (tǔrǎng wūrǎn) - 土壤污染 +• increasingly (rìyì) - 日益 +• serious (yánzhòng) - 严重 +• to take measures (cǎiqǔ cuòshī) - 采取措施 +• to reduce (jiǎnshǎo) - 减少 +• carbon emissions (tàn pái fàng) - 碳排放 +• renewable energy (kě zàishēng néngyuán) - 可再生能源 +• solar energy (tàiyángnéng) - 太阳能 +• wind energy (fēngnéng) - 风能 +• plastic bag (sùliào dài) - 塑料袋 +• to conserve (jiéyuē) - 节约 +• public transportation (gōnggòng jiāotōng gōngjù) - 公共交通工具 +• contribution (gòngxiàn) - 贡献 +• responsibility (zérèn) - 责任 +• citizen (gōngmín) - 公民 +• duty (yìwù) - 义务 + + +理解问题 / Comprehension Questions +------------------------------ + +【Question 1】 Why has environmental protection become an important topic? +Answer: 因为随着工业化和城市化的发展,环境问题日益严重。 + +【Question 2】 What measures have countries taken to protect the environment? +Answer: 减少碳排放,发展可再生能源,如太阳能和风能。 + +【Question 3】 How can individuals contribute to environmental protection? +Answer: 减少使用塑料袋、节约用水和用电、使用公共交通工具等。 + diff --git a/flutter_app/assets/reading/advanced_environmental_protection_pinyin.txt b/flutter_app/assets/reading/advanced_environmental_protection_pinyin.txt new file mode 100644 index 0000000..87e0311 --- /dev/null +++ b/flutter_app/assets/reading/advanced_environmental_protection_pinyin.txt @@ -0,0 +1,47 @@ +Reading Exercise (Pinyin) +-------------------- + +Jìn niánlái, huánjìng bǎohù yǐjīng chéngwéi quánqiú guānzhù de zhòngyào huàtí. Suízhe gōngyèhuà hé chéngshìhuà de fāzhǎn, kōngqì wūrǎn, shuǐ wūrǎn hé tǔrǎng wūrǎn děng huánjìng wèntí rìyì yánzhòng. Xǔduō guójiā kāishǐ cǎiqǔ cuòshī jiǎnshǎo tàn pái fàng, fāzhǎn kě zàishēng néngyuán, rú tàiyángnéng hé fēngnéng. Gèrén yě kěyǐ tōngguò jiǎnshǎo shǐyòng sùliào dài, jiéyuē yòngshuǐ hé yòngdiàn, shǐyòng gōnggòng jiāotōng gōngjù děng fāngshì wèi huánbǎo zuò chū gòngxiàn. Bǎohù huánjìng bùjǐn shì zhèngfǔ de zérèn, yěshì měi gè gōngmín de yìwù. + +生词表 / Vocabulary +-------------------- + +• huánjìng bǎohù (环境保护) - environmental protection +• quánqiú (全球) - global +• guānzhù (关注) - to pay attention to +• huàtí (话题) - topic +• gōngyèhuà (工业化) - industrialization +• chéngshìhuà (城市化) - urbanization +• fāzhǎn (发展) - development +• kōngqì wūrǎn (空气污染) - air pollution +• shuǐ wūrǎn (水污染) - water pollution +• tǔrǎng wūrǎn (土壤污染) - soil pollution +• rìyì (日益) - increasingly +• yánzhòng (严重) - serious +• cǎiqǔ cuòshī (采取措施) - to take measures +• jiǎnshǎo (减少) - to reduce +• tàn pái fàng (碳排放) - carbon emissions +• kě zàishēng néngyuán (可再生能源) - renewable energy +• tàiyángnéng (太阳能) - solar energy +• fēngnéng (风能) - wind energy +• sùliào dài (塑料袋) - plastic bag +• jiéyuē (节约) - to conserve +• gōnggòng jiāotōng gōngjù (公共交通工具) - public transportation +• gòngxiàn (贡献) - contribution +• zérèn (责任) - responsibility +• gōngmín (公民) - citizen +• yìwù (义务) - duty + + +理解问题 / Comprehension Questions +------------------------------ + +【Question 1】 Huánjìng bǎohù wèishénme chéngwéi zhòngyào huàtí? +Answer: 因为随着工业化和城市化的发展,环境问题日益严重。 + +【Question 2】 Guójiā cǎiqǔle nǎxiē cuòshī bǎohù huánjìng? +Answer: 减少碳排放,发展可再生能源,如太阳能和风能。 + +【Question 3】 Gèrén rúhé wèi huánbǎo zuò gòngxiàn? +Answer: 减少使用塑料袋、节约用水和用电、使用公共交通工具等。 + diff --git a/flutter_app/assets/reading/advanced_environmental_protection_zh.txt b/flutter_app/assets/reading/advanced_environmental_protection_zh.txt new file mode 100644 index 0000000..7cb8990 --- /dev/null +++ b/flutter_app/assets/reading/advanced_environmental_protection_zh.txt @@ -0,0 +1,47 @@ +阅读练习 +---------- + +近年来,环境保护已经成为全球关注的重要话题。随着工业化和城市化的发展,空气污染、水污染和土壤污染等环境问题日益严重。许多国家开始采取措施减少碳排放,发展可再生能源,如太阳能和风能。个人也可以通过减少使用塑料袋、节约用水和用电、使用公共交通工具等方式为环保做出贡献。保护环境不仅是政府的责任,也是每个公民的义务。 + +生词表 / Vocabulary +-------------------- + +• 环境保护 (huánjìng bǎohù) - environmental protection +• 全球 (quánqiú) - global +• 关注 (guānzhù) - to pay attention to +• 话题 (huàtí) - topic +• 工业化 (gōngyèhuà) - industrialization +• 城市化 (chéngshìhuà) - urbanization +• 发展 (fāzhǎn) - development +• 空气污染 (kōngqì wūrǎn) - air pollution +• 水污染 (shuǐ wūrǎn) - water pollution +• 土壤污染 (tǔrǎng wūrǎn) - soil pollution +• 日益 (rìyì) - increasingly +• 严重 (yánzhòng) - serious +• 采取措施 (cǎiqǔ cuòshī) - to take measures +• 减少 (jiǎnshǎo) - to reduce +• 碳排放 (tàn pái fàng) - carbon emissions +• 可再生能源 (kě zàishēng néngyuán) - renewable energy +• 太阳能 (tàiyángnéng) - solar energy +• 风能 (fēngnéng) - wind energy +• 塑料袋 (sùliào dài) - plastic bag +• 节约 (jiéyuē) - to conserve +• 公共交通工具 (gōnggòng jiāotōng gōngjù) - public transportation +• 贡献 (gòngxiàn) - contribution +• 责任 (zérèn) - responsibility +• 公民 (gōngmín) - citizen +• 义务 (yìwù) - duty + + +理解问题 / Comprehension Questions +------------------------------ + +【问题 1】 环境保护为什么成为重要话题? +答案: 因为随着工业化和城市化的发展,环境问题日益严重。 + +【问题 2】 国家采取了哪些措施保护环境? +答案: 减少碳排放,发展可再生能源,如太阳能和风能。 + +【问题 3】 个人如何为环保做贡献? +答案: 减少使用塑料袋、节约用水和用电、使用公共交通工具等。 + diff --git a/flutter_app/assets/reading/beginner_daily_routine_en.txt b/flutter_app/assets/reading/beginner_daily_routine_en.txt new file mode 100644 index 0000000..eb1c939 --- /dev/null +++ b/flutter_app/assets/reading/beginner_daily_routine_en.txt @@ -0,0 +1,36 @@ +Reading Exercise +--------------- + +I get up at 6:00 every morning. I eat breakfast at 7:00. I go to school at 8:00. I eat lunch at 12:00 noon. I finish class at 3:00 in the afternoon. I eat dinner at 6:00 in the evening. I go to bed at 10:00 at night. + +生词表 / Vocabulary +-------------------- + +• every day (měitiān) - 每天 +• morning (zǎoshang) - 早上 +• to get up (qǐchuáng) - 起床 +• to eat (chī) - 吃 +• breakfast (zǎofàn) - 早饭 +• to go (qù) - 去 +• school (xuéxiào) - 学校 +• noon (zhōngwǔ) - 中午 +• lunch (wǔfàn) - 午饭 +• afternoon (xiàwǔ) - 下午 +• to finish class (xiàkè) - 下课 +• evening (wǎnshang) - 晚上 +• dinner (wǎnfàn) - 晚饭 +• to sleep (shuìjiào) - 睡觉 + + +理解问题 / Comprehension Questions +------------------------------ + +【Question 1】 What time do they get up? +Answer: 早上六点起床。 + +【Question 2】 What time do they go to school? +Answer: 八点去学校。 + +【Question 3】 What time do they go to bed? +Answer: 晚上十点睡觉。 + diff --git a/flutter_app/assets/reading/beginner_daily_routine_pinyin.txt b/flutter_app/assets/reading/beginner_daily_routine_pinyin.txt new file mode 100644 index 0000000..8de604b --- /dev/null +++ b/flutter_app/assets/reading/beginner_daily_routine_pinyin.txt @@ -0,0 +1,36 @@ +Reading Exercise (Pinyin) +-------------------- + +Wǒ měitiān zǎoshang liù diǎn qǐchuáng. Wǒ qī diǎn chī zǎofàn. Bā diǎn qù xuéxiào. Zhōngwǔ shí'èr diǎn chī wǔfàn. Xiàwǔ sān diǎn xiàkè. Wǎnshang liù diǎn chī wǎnfàn. Wǎnshang shí diǎn shuìjiào. + +生词表 / Vocabulary +-------------------- + +• měitiān (每天) - every day +• zǎoshang (早上) - morning +• qǐchuáng (起床) - to get up +• chī (吃) - to eat +• zǎofàn (早饭) - breakfast +• qù (去) - to go +• xuéxiào (学校) - school +• zhōngwǔ (中午) - noon +• wǔfàn (午饭) - lunch +• xiàwǔ (下午) - afternoon +• xiàkè (下课) - to finish class +• wǎnshang (晚上) - evening +• wǎnfàn (晚饭) - dinner +• shuìjiào (睡觉) - to sleep + + +理解问题 / Comprehension Questions +------------------------------ + +【Question 1】 Jǐ diǎn qǐchuáng? +Answer: 早上六点起床。 + +【Question 2】 Jǐ diǎn qù xuéxiào? +Answer: 八点去学校。 + +【Question 3】 Jǐ diǎn shuìjiào? +Answer: 晚上十点睡觉。 + diff --git a/flutter_app/assets/reading/beginner_daily_routine_zh.txt b/flutter_app/assets/reading/beginner_daily_routine_zh.txt new file mode 100644 index 0000000..1b3a497 --- /dev/null +++ b/flutter_app/assets/reading/beginner_daily_routine_zh.txt @@ -0,0 +1,36 @@ +阅读练习 +---------- + +我每天早上六点起床。我七点吃早饭。八点去学校。中午十二点吃午饭。下午三点下课。晚上六点吃晚饭。晚上十点睡觉。 + +生词表 / Vocabulary +-------------------- + +• 每天 (měitiān) - every day +• 早上 (zǎoshang) - morning +• 起床 (qǐchuáng) - to get up +• 吃 (chī) - to eat +• 早饭 (zǎofàn) - breakfast +• 去 (qù) - to go +• 学校 (xuéxiào) - school +• 中午 (zhōngwǔ) - noon +• 午饭 (wǔfàn) - lunch +• 下午 (xiàwǔ) - afternoon +• 下课 (xiàkè) - to finish class +• 晚上 (wǎnshang) - evening +• 晚饭 (wǎnfàn) - dinner +• 睡觉 (shuìjiào) - to sleep + + +理解问题 / Comprehension Questions +------------------------------ + +【问题 1】 几点起床? +答案: 早上六点起床。 + +【问题 2】 几点去学校? +答案: 八点去学校。 + +【问题 3】 几点睡觉? +答案: 晚上十点睡觉。 + diff --git a/flutter_app/assets/reading/beginner_self_introduction_en.txt b/flutter_app/assets/reading/beginner_self_introduction_en.txt new file mode 100644 index 0000000..ecf9cc6 --- /dev/null +++ b/flutter_app/assets/reading/beginner_self_introduction_en.txt @@ -0,0 +1,35 @@ +Reading Exercise +--------------- + +My name is Li Ming. I am a student. I am twenty years old. I like learning Chinese. I also like listening to music and watching movies. + +生词表 / Vocabulary +-------------------- + +• I, me (wǒ) - 我 +• to be called (jiào) - 叫 +• student (xuésheng) - 学生 +• this year (jīnnián) - 今年 +• years old (suì) - 岁 +• to like (xǐhuan) - 喜欢 +• to study (xuéxí) - 学习 +• Chinese language (zhōngwén) - 中文 +• also (yě) - 也 +• to listen (tīng) - 听 +• music (yīnyuè) - 音乐 +• to watch (kàn) - 看 +• movie (diànyǐng) - 电影 + + +理解问题 / Comprehension Questions +------------------------------ + +【Question 1】 Who is Li Ming? +Answer: 他是学生。 + +【Question 2】 How old is Li Ming? +Answer: 他二十岁。 + +【Question 3】 What does Li Ming like? +Answer: 他喜欢学习中文、听音乐和看电影。 + diff --git a/flutter_app/assets/reading/beginner_self_introduction_pinyin.txt b/flutter_app/assets/reading/beginner_self_introduction_pinyin.txt new file mode 100644 index 0000000..10a4fe7 --- /dev/null +++ b/flutter_app/assets/reading/beginner_self_introduction_pinyin.txt @@ -0,0 +1,35 @@ +Reading Exercise (Pinyin) +-------------------- + +Wǒ jiào Lǐ Míng. Wǒ shì xuésheng. Wǒ jīnnián èrshí suì. Wǒ xǐhuan xuéxí zhōngwén. Wǒ yě xǐhuan tīng yīnyuè hé kàn diànyǐng. + +生词表 / Vocabulary +-------------------- + +• wǒ (我) - I, me +• jiào (叫) - to be called +• xuésheng (学生) - student +• jīnnián (今年) - this year +• suì (岁) - years old +• xǐhuan (喜欢) - to like +• xuéxí (学习) - to study +• zhōngwén (中文) - Chinese language +• yě (也) - also +• tīng (听) - to listen +• yīnyuè (音乐) - music +• kàn (看) - to watch +• diànyǐng (电影) - movie + + +理解问题 / Comprehension Questions +------------------------------ + +【Question 1】 Lǐ Míng shì shéi? +Answer: 他是学生。 + +【Question 2】 Lǐ Míng duō dà? +Answer: 他二十岁。 + +【Question 3】 Lǐ Míng xǐhuan shénme? +Answer: 他喜欢学习中文、听音乐和看电影。 + diff --git a/flutter_app/assets/reading/beginner_self_introduction_zh.txt b/flutter_app/assets/reading/beginner_self_introduction_zh.txt new file mode 100644 index 0000000..504b7fa --- /dev/null +++ b/flutter_app/assets/reading/beginner_self_introduction_zh.txt @@ -0,0 +1,35 @@ +阅读练习 +---------- + +我叫李明。我是学生。我今年二十岁。我喜欢学习中文。我也喜欢听音乐和看电影。 + +生词表 / Vocabulary +-------------------- + +• 我 (wǒ) - I, me +• 叫 (jiào) - to be called +• 学生 (xuésheng) - student +• 今年 (jīnnián) - this year +• 岁 (suì) - years old +• 喜欢 (xǐhuan) - to like +• 学习 (xuéxí) - to study +• 中文 (zhōngwén) - Chinese language +• 也 (yě) - also +• 听 (tīng) - to listen +• 音乐 (yīnyuè) - music +• 看 (kàn) - to watch +• 电影 (diànyǐng) - movie + + +理解问题 / Comprehension Questions +------------------------------ + +【问题 1】 李明是谁? +答案: 他是学生。 + +【问题 2】 李明多大? +答案: 他二十岁。 + +【问题 3】 李明喜欢什么? +答案: 他喜欢学习中文、听音乐和看电影。 + diff --git a/flutter_app/assets/reading/intermediate_at_the_restaurant_en.txt b/flutter_app/assets/reading/intermediate_at_the_restaurant_en.txt new file mode 100644 index 0000000..674ba61 --- /dev/null +++ b/flutter_app/assets/reading/intermediate_at_the_restaurant_en.txt @@ -0,0 +1,40 @@ +Reading Exercise +--------------- + +Last night, my friend and I went to a Chinese restaurant. This restaurant is famous, and the food is delicious. We ordered Peking duck, Kung Pao chicken, and egg fried rice. The waiter recommended that we try their special tea. After the meal, we also had dessert. This meal cost a total of 300 yuan. + +生词表 / Vocabulary +-------------------- + +• yesterday (zuótiān) - 昨天 +• friend (péngyou) - 朋友 +• restaurant (cāntīng) - 餐厅 +• famous (yǒumíng) - 有名 +• dish, food (cài) - 菜 +• delicious (hǎochī) - 好吃 +• to order (diǎn) - 点 +• Peking duck (běijīng kǎoyā) - 北京烤鸭 +• Kung Pao chicken (gōngbǎo jīdīng) - 宫保鸡丁 +• egg fried rice (dàn chǎofàn) - 蛋炒饭 +• waiter (fúwùyuán) - 服务员 +• to recommend (tuījiàn) - 推荐 +• special, characteristic (tèsè) - 特色 +• after meal (fàn hòu) - 饭后 +• dessert (tiándiǎn) - 甜点 +• in total (zǒnggòng) - 总共 +• to spend (money) (huā) - 花 +• yuan (Chinese currency) (yuán) - 元 + + +理解问题 / Comprehension Questions +------------------------------ + +【Question 1】 Where did they go? +Answer: 他们去了一家中国餐厅。 + +【Question 2】 What dishes did they order? +Answer: 他们点了北京烤鸭、宫保鸡丁和蛋炒饭。 + +【Question 3】 How much did the meal cost? +Answer: 这顿饭总共花了三百元。 + diff --git a/flutter_app/assets/reading/intermediate_at_the_restaurant_pinyin.txt b/flutter_app/assets/reading/intermediate_at_the_restaurant_pinyin.txt new file mode 100644 index 0000000..3809ffe --- /dev/null +++ b/flutter_app/assets/reading/intermediate_at_the_restaurant_pinyin.txt @@ -0,0 +1,40 @@ +Reading Exercise (Pinyin) +-------------------- + +Zuótiān wǎnshang, wǒ hé péngyou qùle yī jiā zhōngguó cāntīng. Zhè jiā cāntīng hěn yǒumíng, cài hěn hǎochī. Wǒmen diǎnle běijīng kǎoyā, gōngbǎo jīdīng hé dàn chǎofàn. Fúwùyuán tuījiàn wǒmen chángshì tāmen de tèsè chá. Fàn hòu, wǒmen hái chīle tiándiǎn. Zhè dùn fàn zǒnggòng huāle sānbǎi yuán. + +生词表 / Vocabulary +-------------------- + +• zuótiān (昨天) - yesterday +• péngyou (朋友) - friend +• cāntīng (餐厅) - restaurant +• yǒumíng (有名) - famous +• cài (菜) - dish, food +• hǎochī (好吃) - delicious +• diǎn (点) - to order +• běijīng kǎoyā (北京烤鸭) - Peking duck +• gōngbǎo jīdīng (宫保鸡丁) - Kung Pao chicken +• dàn chǎofàn (蛋炒饭) - egg fried rice +• fúwùyuán (服务员) - waiter +• tuījiàn (推荐) - to recommend +• tèsè (特色) - special, characteristic +• fàn hòu (饭后) - after meal +• tiándiǎn (甜点) - dessert +• zǒnggòng (总共) - in total +• huā (花) - to spend (money) +• yuán (元) - yuan (Chinese currency) + + +理解问题 / Comprehension Questions +------------------------------ + +【Question 1】 Tāmen qùle shénme dìfang? +Answer: 他们去了一家中国餐厅。 + +【Question 2】 Tāmen diǎnle shénme cài? +Answer: 他们点了北京烤鸭、宫保鸡丁和蛋炒饭。 + +【Question 3】 Zhè dùn fàn huāle duōshao qián? +Answer: 这顿饭总共花了三百元。 + diff --git a/flutter_app/assets/reading/intermediate_at_the_restaurant_zh.txt b/flutter_app/assets/reading/intermediate_at_the_restaurant_zh.txt new file mode 100644 index 0000000..1cc3230 --- /dev/null +++ b/flutter_app/assets/reading/intermediate_at_the_restaurant_zh.txt @@ -0,0 +1,40 @@ +阅读练习 +---------- + +昨天晚上,我和朋友去了一家中国餐厅。这家餐厅很有名,菜很好吃。我们点了北京烤鸭、宫保鸡丁和蛋炒饭。服务员推荐我们尝试他们的特色茶。饭后,我们还吃了甜点。这顿饭总共花了三百元。 + +生词表 / Vocabulary +-------------------- + +• 昨天 (zuótiān) - yesterday +• 朋友 (péngyou) - friend +• 餐厅 (cāntīng) - restaurant +• 有名 (yǒumíng) - famous +• 菜 (cài) - dish, food +• 好吃 (hǎochī) - delicious +• 点 (diǎn) - to order +• 北京烤鸭 (běijīng kǎoyā) - Peking duck +• 宫保鸡丁 (gōngbǎo jīdīng) - Kung Pao chicken +• 蛋炒饭 (dàn chǎofàn) - egg fried rice +• 服务员 (fúwùyuán) - waiter +• 推荐 (tuījiàn) - to recommend +• 特色 (tèsè) - special, characteristic +• 饭后 (fàn hòu) - after meal +• 甜点 (tiándiǎn) - dessert +• 总共 (zǒnggòng) - in total +• 花 (huā) - to spend (money) +• 元 (yuán) - yuan (Chinese currency) + + +理解问题 / Comprehension Questions +------------------------------ + +【问题 1】 他们去了什么地方? +答案: 他们去了一家中国餐厅。 + +【问题 2】 他们点了什么菜? +答案: 他们点了北京烤鸭、宫保鸡丁和蛋炒饭。 + +【问题 3】 这顿饭花了多少钱? +答案: 这顿饭总共花了三百元。 + diff --git a/flutter_app/assets/reading/intermediate_weekend_plans_en.txt b/flutter_app/assets/reading/intermediate_weekend_plans_en.txt new file mode 100644 index 0000000..6cbe23a --- /dev/null +++ b/flutter_app/assets/reading/intermediate_weekend_plans_en.txt @@ -0,0 +1,37 @@ +Reading Exercise +--------------- + +I have many plans for this weekend. Saturday morning, I will go to the library to study Chinese. At noon, I will have lunch with my classmates. In the afternoon, we plan to go watch a movie. In the evening, I will attend my friend's birthday party. On Sunday, I want to rest at home, maybe read books or listen to music. + +生词表 / Vocabulary +-------------------- + +• weekend (zhōumò) - 周末 +• plan (jìhuà) - 计划 +• Saturday (xīngqíliù) - 星期六 +• morning (shàngwǔ) - 上午 +• library (túshūguǎn) - 图书馆 +• classmate (tóngxué) - 同学 +• together (yìqǐ) - 一起 +• to plan (dǎsuàn) - 打算 +• to attend (cānjiā) - 参加 +• birthday (shēngrì) - 生日 +• party (jùhuì) - 聚会 +• Sunday (xīngqítiān) - 星期天 +• to rest (xiūxi) - 休息 +• maybe (kěnéng) - 可能 +• or (huòzhě) - 或者 + + +理解问题 / Comprehension Questions +------------------------------ + +【Question 1】 What will they do on Saturday morning? +Answer: 星期六上午要去图书馆学习中文。 + +【Question 2】 What is the plan for Saturday afternoon? +Answer: 星期六下午打算去看电影。 + +【Question 3】 What will they do on Sunday? +Answer: 星期天想在家休息,可能会看书或者听音乐。 + diff --git a/flutter_app/assets/reading/intermediate_weekend_plans_pinyin.txt b/flutter_app/assets/reading/intermediate_weekend_plans_pinyin.txt new file mode 100644 index 0000000..b5a578e --- /dev/null +++ b/flutter_app/assets/reading/intermediate_weekend_plans_pinyin.txt @@ -0,0 +1,37 @@ +Reading Exercise (Pinyin) +-------------------- + +Zhège zhōumò wǒ yǒu hěnduō jìhuà. Xīngqíliù shàngwǔ, wǒ yào qù túshūguǎn xuéxí zhōngwén. Zhōngwǔ, wǒ hé tóngxué yìqǐ chī wǔfàn. Xiàwǔ, wǒmen dǎsuàn qù kàn diànyǐng. Wǎnshang, wǒ yào cānjiā péngyou de shēngrì jùhuì. Xīngqítiān, wǒ xiǎng zài jiā xiūxi, kěnéng huì kàn shū huòzhě tīng yīnyuè. + +生词表 / Vocabulary +-------------------- + +• zhōumò (周末) - weekend +• jìhuà (计划) - plan +• xīngqíliù (星期六) - Saturday +• shàngwǔ (上午) - morning +• túshūguǎn (图书馆) - library +• tóngxué (同学) - classmate +• yìqǐ (一起) - together +• dǎsuàn (打算) - to plan +• cānjiā (参加) - to attend +• shēngrì (生日) - birthday +• jùhuì (聚会) - party +• xīngqítiān (星期天) - Sunday +• xiūxi (休息) - to rest +• kěnéng (可能) - maybe +• huòzhě (或者) - or + + +理解问题 / Comprehension Questions +------------------------------ + +【Question 1】 Xīngqíliù shàngwǔ yào zuò shénme? +Answer: 星期六上午要去图书馆学习中文。 + +【Question 2】 Xīngqíliù xiàwǔ de jìhuà shì shénme? +Answer: 星期六下午打算去看电影。 + +【Question 3】 Xīngqítiān yào zuò shénme? +Answer: 星期天想在家休息,可能会看书或者听音乐。 + diff --git a/flutter_app/assets/reading/intermediate_weekend_plans_zh.txt b/flutter_app/assets/reading/intermediate_weekend_plans_zh.txt new file mode 100644 index 0000000..7679cf2 --- /dev/null +++ b/flutter_app/assets/reading/intermediate_weekend_plans_zh.txt @@ -0,0 +1,37 @@ +阅读练习 +---------- + +这个周末我有很多计划。星期六上午,我要去图书馆学习中文。中午,我和同学一起吃午饭。下午,我们打算去看电影。晚上,我要参加朋友的生日聚会。星期天,我想在家休息,可能会看书或者听音乐。 + +生词表 / Vocabulary +-------------------- + +• 周末 (zhōumò) - weekend +• 计划 (jìhuà) - plan +• 星期六 (xīngqíliù) - Saturday +• 上午 (shàngwǔ) - morning +• 图书馆 (túshūguǎn) - library +• 同学 (tóngxué) - classmate +• 一起 (yìqǐ) - together +• 打算 (dǎsuàn) - to plan +• 参加 (cānjiā) - to attend +• 生日 (shēngrì) - birthday +• 聚会 (jùhuì) - party +• 星期天 (xīngqítiān) - Sunday +• 休息 (xiūxi) - to rest +• 可能 (kěnéng) - maybe +• 或者 (huòzhě) - or + + +理解问题 / Comprehension Questions +------------------------------ + +【问题 1】 星期六上午要做什么? +答案: 星期六上午要去图书馆学习中文。 + +【问题 2】 星期六下午的计划是什么? +答案: 星期六下午打算去看电影。 + +【问题 3】 星期天要做什么? +答案: 星期天想在家休息,可能会看书或者听音乐。 + diff --git a/flutter_app/assets/text/text_files/day10_en.txt b/flutter_app/assets/text/text_files/day10_en.txt deleted file mode 100644 index 6eec704..0000000 --- a/flutter_app/assets/text/text_files/day10_en.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Food Items ----------- -rice -noodles -chicken -beef -pork -vegetables -fruit - -Restaurant Phrases ------------------- -menu -I'd like to order -waiter/waitress -check please -Is this delicious? -I want a glass of water diff --git a/flutter_app/assets/text/text_files/day10_pinyin.txt b/flutter_app/assets/text/text_files/day10_pinyin.txt deleted file mode 100644 index 9e71df7..0000000 --- a/flutter_app/assets/text/text_files/day10_pinyin.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Food Items ----------- -mǐfàn -miàntiáo -jīròu -niúròu -zhūròu -shūcài -shuǐguǒ - -Restaurant Phrases ------------------- -càidān -wǒ xiǎng diǎn cài -fúwùyuán -mǎidān -zhège hǎochī ma? -wǒ yào yī bēi shuǐ diff --git a/flutter_app/assets/text/text_files/day10_zh.txt b/flutter_app/assets/text/text_files/day10_zh.txt deleted file mode 100644 index 940a998..0000000 --- a/flutter_app/assets/text/text_files/day10_zh.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Food Items ----------- -米饭 -面条 -鸡肉 -牛肉 -猪肉 -蔬菜 -水果 - -Restaurant Phrases ------------------- -菜单 -我想点菜 -服务员 -买单 -这个好吃吗? -我要一杯水 diff --git a/flutter_app/assets/text/text_files/day11_en.txt b/flutter_app/assets/text/text_files/day11_en.txt deleted file mode 100644 index 616d55c..0000000 --- a/flutter_app/assets/text/text_files/day11_en.txt +++ /dev/null @@ -1,20 +0,0 @@ - -Direction Words ---------------- -left side -right side -in front -behind -above -below -inside -outside - -Asking for Directions ---------------------- -Excuse me, where is the bank? -How do I get to the train station? -go straight -turn left -turn right -How far to walk? diff --git a/flutter_app/assets/text/text_files/day11_pinyin.txt b/flutter_app/assets/text/text_files/day11_pinyin.txt deleted file mode 100644 index cb04725..0000000 --- a/flutter_app/assets/text/text_files/day11_pinyin.txt +++ /dev/null @@ -1,20 +0,0 @@ - -Direction Words ---------------- -zuǒbiān -yòubiān -qiánmiàn -hòumiàn -shàngmiàn -xiàmiàn -lǐmiàn -wàimiàn - -Asking for Directions ---------------------- -qǐngwèn, yínháng zài nǎlǐ? -zěnme qù huǒchēzhàn? -zhí zǒu -wǎng zuǒ guǎi -wǎng yòu guǎi -zǒu duō yuǎn? diff --git a/flutter_app/assets/text/text_files/day11_zh.txt b/flutter_app/assets/text/text_files/day11_zh.txt deleted file mode 100644 index 5492328..0000000 --- a/flutter_app/assets/text/text_files/day11_zh.txt +++ /dev/null @@ -1,20 +0,0 @@ - -Direction Words ---------------- -左边 -右边 -前面 -后面 -上面 -下面 -里面 -外面 - -Asking for Directions ---------------------- -请问,银行在哪里? -怎么去火车站? -直走 -往左拐 -往右拐 -走多远? diff --git a/flutter_app/assets/text/text_files/day12_en.txt b/flutter_app/assets/text/text_files/day12_en.txt deleted file mode 100644 index 5f1f79d..0000000 --- a/flutter_app/assets/text/text_files/day12_en.txt +++ /dev/null @@ -1,21 +0,0 @@ - -Subject-Verb-Object -------------------- -I eat rice -He drinks water -We learn Chinese -She reads a book - -Question Patterns ------------------ -Are you a student? -Do you like Chinese food? -Can you speak English? -What is this? - -Negation Patterns ------------------ -I am not Chinese -He doesn't have time -I don't like coffee -She can't swim diff --git a/flutter_app/assets/text/text_files/day12_pinyin.txt b/flutter_app/assets/text/text_files/day12_pinyin.txt deleted file mode 100644 index 4d32f18..0000000 --- a/flutter_app/assets/text/text_files/day12_pinyin.txt +++ /dev/null @@ -1,21 +0,0 @@ - -Subject-Verb-Object -------------------- -wǒ chī fàn -tā hē shuǐ -wǒmen xué zhōngwén -tā kàn shū - -Question Patterns ------------------ -nǐ shì xuésheng ma? -nǐ xǐhuan zhōngguó cài ma? -nǐ huì shuō yīngyǔ ma? -zhè shì shénme? - -Negation Patterns ------------------ -wǒ bú shì zhōngguó rén -tā méiyǒu shíjiān -wǒ bù xǐhuan kāfēi -tā bú huì yóuyǒng diff --git a/flutter_app/assets/text/text_files/day12_zh.txt b/flutter_app/assets/text/text_files/day12_zh.txt deleted file mode 100644 index 8c7547e..0000000 --- a/flutter_app/assets/text/text_files/day12_zh.txt +++ /dev/null @@ -1,21 +0,0 @@ - -Subject-Verb-Object -------------------- -我吃饭 -他喝水 -我们学中文 -她看书 - -Question Patterns ------------------ -你是学生吗? -你喜欢中国菜吗? -你会说英语吗? -这是什么? - -Negation Patterns ------------------ -我不是中国人 -他没有时间 -我不喜欢咖啡 -她不会游泳 diff --git a/flutter_app/assets/text/text_files/day13_en.txt b/flutter_app/assets/text/text_files/day13_en.txt deleted file mode 100644 index 711ac52..0000000 --- a/flutter_app/assets/text/text_files/day13_en.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Emergency Phrases ------------------ -Help! (emergency) -I need help -I'm lost -I'm sick -Please call a doctor -Please call the police - -Hotel Phrases -------------- -I have a reservation -I would like a room -room key -check out -luggage diff --git a/flutter_app/assets/text/text_files/day13_pinyin.txt b/flutter_app/assets/text/text_files/day13_pinyin.txt deleted file mode 100644 index 5927ed0..0000000 --- a/flutter_app/assets/text/text_files/day13_pinyin.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Emergency Phrases ------------------ -jiùmìng! -wǒ xūyào bāngzhù -wǒ mílù le -wǒ shēngbìng le -qǐng jiào yīshēng -qǐng jiào jǐngchá - -Hotel Phrases -------------- -wǒ yǒu yùdìng -wǒ xiǎng yào yī gè fángjiān -fángjiān yàoshi -tuìfáng -xíngli diff --git a/flutter_app/assets/text/text_files/day13_zh.txt b/flutter_app/assets/text/text_files/day13_zh.txt deleted file mode 100644 index 0ee4221..0000000 --- a/flutter_app/assets/text/text_files/day13_zh.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Emergency Phrases ------------------ -救命! -我需要帮助 -我迷路了 -我生病了 -请叫医生 -请叫警察 - -Hotel Phrases -------------- -我有预订 -我想要一个房间 -房间钥匙 -退房 -行李 diff --git a/flutter_app/assets/text/text_files/day14_en.txt b/flutter_app/assets/text/text_files/day14_en.txt deleted file mode 100644 index cdc7928..0000000 --- a/flutter_app/assets/text/text_files/day14_en.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Travel Documents ----------------- -passport -visa -airplane ticket -boarding pass -customs - -Useful Expressions ------------------- -I don't understand -Please say it again -Please speak more slowly -Do you speak English? -Thank you for your help -It doesn't matter/It's OK diff --git a/flutter_app/assets/text/text_files/day14_pinyin.txt b/flutter_app/assets/text/text_files/day14_pinyin.txt deleted file mode 100644 index 40b325b..0000000 --- a/flutter_app/assets/text/text_files/day14_pinyin.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Travel Documents ----------------- -hùzhào -qiānzhèng -jīpiào -dēngjī pái -hǎiguān - -Useful Expressions ------------------- -wǒ bù míngbai -qǐng zài shuō yībiàn -qǐng shuō màn yīdiǎn -nǐ huì shuō yīngyǔ ma? -xièxie nǐ de bāngzhù -méi guānxi diff --git a/flutter_app/assets/text/text_files/day14_zh.txt b/flutter_app/assets/text/text_files/day14_zh.txt deleted file mode 100644 index bf9431f..0000000 --- a/flutter_app/assets/text/text_files/day14_zh.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Travel Documents ----------------- -护照 -签证 -机票 -登机牌 -海关 - -Useful Expressions ------------------- -我不明白 -请再说一遍 -请说慢一点 -你会说英语吗? -谢谢你的帮助 -没关系 diff --git a/flutter_app/assets/text/text_files/day15_en.txt b/flutter_app/assets/text/text_files/day15_en.txt deleted file mode 100644 index 73c423b..0000000 --- a/flutter_app/assets/text/text_files/day15_en.txt +++ /dev/null @@ -1,22 +0,0 @@ - -Immediate Family ----------------- -father -mother -older brother -older sister -younger brother -younger sister -son -daughter - -Extended Family ---------------- -paternal grandfather -paternal grandmother -maternal grandfather -maternal grandmother -uncle (father's younger brother) -aunt (mother's sister) -male paternal cousin -male maternal cousin diff --git a/flutter_app/assets/text/text_files/day15_pinyin.txt b/flutter_app/assets/text/text_files/day15_pinyin.txt deleted file mode 100644 index ea25e00..0000000 --- a/flutter_app/assets/text/text_files/day15_pinyin.txt +++ /dev/null @@ -1,22 +0,0 @@ - -Immediate Family ----------------- -bàba -māma -gēge -jiějie -dìdi -mèimei -érzi -nǚ'ér - -Extended Family ---------------- -yéye -nǎinai -wàigōng -wàipó -shūshu -āyí -táng xiōngdì -biǎo xiōngdì diff --git a/flutter_app/assets/text/text_files/day15_zh.txt b/flutter_app/assets/text/text_files/day15_zh.txt deleted file mode 100644 index cad59b9..0000000 --- a/flutter_app/assets/text/text_files/day15_zh.txt +++ /dev/null @@ -1,22 +0,0 @@ - -Immediate Family ----------------- -爸爸 -妈妈 -哥哥 -姐姐 -弟弟 -妹妹 -儿子 -女儿 - -Extended Family ---------------- -爷爷 -奶奶 -外公 -外婆 -叔叔 -阿姨 -堂兄弟 -表兄弟 diff --git a/flutter_app/assets/text/text_files/day16_en.txt b/flutter_app/assets/text/text_files/day16_en.txt deleted file mode 100644 index e98017c..0000000 --- a/flutter_app/assets/text/text_files/day16_en.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Greetings and Farewells ------------------------ -How have you been lately? -Long time no see -Nice to meet you -See you later -Take care - -Social Phrases --------------- -Excuse me/Sorry to bother you -It's okay/No problem -Good luck to you -Cheers (when drinking) -Whatever/It doesn't matter diff --git a/flutter_app/assets/text/text_files/day16_pinyin.txt b/flutter_app/assets/text/text_files/day16_pinyin.txt deleted file mode 100644 index 639a918..0000000 --- a/flutter_app/assets/text/text_files/day16_pinyin.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Greetings and Farewells ------------------------ -nǐ zuìjìn zěnme yàng? -hǎojiǔ bú jiàn -rènshi nǐ hěn gāoxìng -huítóu jiàn -bǎozhòng - -Social Phrases --------------- -dǎrǎo le -méi guānxi -zhù nǐ hǎo yùn -gānbēi -suíbiàn diff --git a/flutter_app/assets/text/text_files/day16_zh.txt b/flutter_app/assets/text/text_files/day16_zh.txt deleted file mode 100644 index b402842..0000000 --- a/flutter_app/assets/text/text_files/day16_zh.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Greetings and Farewells ------------------------ -你最近怎么样? -好久不见 -认识你很高兴 -回头见 -保重 - -Social Phrases --------------- -打扰了 -没关系 -祝你好运 -干杯 -随便 diff --git a/flutter_app/assets/text/text_files/day17_en.txt b/flutter_app/assets/text/text_files/day17_en.txt deleted file mode 100644 index 249b29c..0000000 --- a/flutter_app/assets/text/text_files/day17_en.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Polite Expressions ------------------- -please -thank you -you're welcome -sorry -it's okay - -Cultural Etiquette ------------------- -When in Rome, do as the Romans do -to serve tea (as a sign of respect) -to give gifts -respect the elderly and care for the young -modesty/humility diff --git a/flutter_app/assets/text/text_files/day17_pinyin.txt b/flutter_app/assets/text/text_files/day17_pinyin.txt deleted file mode 100644 index 5e6fd80..0000000 --- a/flutter_app/assets/text/text_files/day17_pinyin.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Polite Expressions ------------------- -qǐng -xièxie -bú kèqi -duìbùqǐ -méi guānxi - -Cultural Etiquette ------------------- -rù xiāng suí sú -jìng chá -sòng lǐwù -zūn lǎo ài yòu -qiānxū diff --git a/flutter_app/assets/text/text_files/day17_zh.txt b/flutter_app/assets/text/text_files/day17_zh.txt deleted file mode 100644 index dbbf117..0000000 --- a/flutter_app/assets/text/text_files/day17_zh.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Polite Expressions ------------------- -请 -谢谢 -不客气 -对不起 -没关系 - -Cultural Etiquette ------------------- -入乡随俗 -敬茶 -送礼物 -尊老爱幼 -谦虚 diff --git a/flutter_app/assets/text/text_files/day18_en.txt b/flutter_app/assets/text/text_files/day18_en.txt deleted file mode 100644 index 9e1efe6..0000000 --- a/flutter_app/assets/text/text_files/day18_en.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Major Festivals ---------------- -Spring Festival/Chinese New Year -Mid-Autumn Festival -Dragon Boat Festival -Tomb Sweeping Day -Lantern Festival - -Festival Traditions -------------------- -red envelope (with money) -dumplings -mooncake -rice dumpling -dragon and lion dance -set off firecrackers diff --git a/flutter_app/assets/text/text_files/day18_pinyin.txt b/flutter_app/assets/text/text_files/day18_pinyin.txt deleted file mode 100644 index b7bdc20..0000000 --- a/flutter_app/assets/text/text_files/day18_pinyin.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Major Festivals ---------------- -Chūnjié -Zhōngqiū jié -Duānwǔ jié -Qīngmíng jié -Yuánxiāo jié - -Festival Traditions -------------------- -hóngbāo -jiǎozi -yuèbǐng -zòngzi -wǔ lóng wǔ shī -fàng biānpào diff --git a/flutter_app/assets/text/text_files/day18_zh.txt b/flutter_app/assets/text/text_files/day18_zh.txt deleted file mode 100644 index c48150d..0000000 --- a/flutter_app/assets/text/text_files/day18_zh.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Major Festivals ---------------- -春节 -中秋节 -端午节 -清明节 -元宵节 - -Festival Traditions -------------------- -红包 -饺子 -月饼 -粽子 -舞龙舞狮 -放鞭炮 diff --git a/flutter_app/assets/text/text_files/day19_en.txt b/flutter_app/assets/text/text_files/day19_en.txt deleted file mode 100644 index 733b8a0..0000000 --- a/flutter_app/assets/text/text_files/day19_en.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Rooms and Areas ---------------- -living room -bedroom -kitchen -bathroom -balcony -garden - -Household Items ---------------- -table -chair -bed -sofa -television -refrigerator -air conditioner diff --git a/flutter_app/assets/text/text_files/day19_pinyin.txt b/flutter_app/assets/text/text_files/day19_pinyin.txt deleted file mode 100644 index 68506f9..0000000 --- a/flutter_app/assets/text/text_files/day19_pinyin.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Rooms and Areas ---------------- -kètīng -wòshì -chúfáng -yùshì -yángtái -huāyuán - -Household Items ---------------- -zhuōzi -yǐzi -chuáng -shāfā -diànshì -bīngxiāng -kòngtiáo diff --git a/flutter_app/assets/text/text_files/day19_zh.txt b/flutter_app/assets/text/text_files/day19_zh.txt deleted file mode 100644 index 5ce34b0..0000000 --- a/flutter_app/assets/text/text_files/day19_zh.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Rooms and Areas ---------------- -客厅 -卧室 -厨房 -浴室 -阳台 -花园 - -Household Items ---------------- -桌子 -椅子 -床 -沙发 -电视 -冰箱 -空调 diff --git a/flutter_app/assets/text/text_files/day1_en.txt b/flutter_app/assets/text/text_files/day1_en.txt deleted file mode 100644 index 4f3abf3..0000000 --- a/flutter_app/assets/text/text_files/day1_en.txt +++ /dev/null @@ -1,22 +0,0 @@ - -Basic Greetings & Common Phrases --------------------------------- -Hello -Good morning -Good afternoon -Good evening -Goodbye - -Self Introduction ------------------ -My name is... -Nice to meet you -I am American -And you? - -Basic Questions ---------------- -How are you? -What is your nationality? -Do you speak English? -Do you understand Chinese? diff --git a/flutter_app/assets/text/text_files/day1_pinyin.txt b/flutter_app/assets/text/text_files/day1_pinyin.txt deleted file mode 100644 index ed56c68..0000000 --- a/flutter_app/assets/text/text_files/day1_pinyin.txt +++ /dev/null @@ -1,22 +0,0 @@ - -Basic Greetings & Common Phrases --------------------------------- -Nǐ hǎo -Zǎoshang hǎo -Xiàwǔ hǎo -Wǎnshang hǎo -Zàijiàn - -Self Introduction ------------------ -Wǒ jiào... -Hěn gāoxìng rènshi nǐ -Wǒ shì měiguó rén -Nǐ ne? - -Basic Questions ---------------- -Nǐ hǎo ma? -Nǐ shì nǎ guó rén? -Nǐ huì shuō yīngyǔ ma? -Nǐ dǒng zhōngwén ma? diff --git a/flutter_app/assets/text/text_files/day1_zh.txt b/flutter_app/assets/text/text_files/day1_zh.txt deleted file mode 100644 index 3cf5952..0000000 --- a/flutter_app/assets/text/text_files/day1_zh.txt +++ /dev/null @@ -1,22 +0,0 @@ - -Basic Greetings & Common Phrases --------------------------------- -你好 -早上好 -下午好 -晚上好 -再见 - -Self Introduction ------------------ -我叫... -很高兴认识你 -我是美国人 -你呢? - -Basic Questions ---------------- -你好吗? -你是哪国人? -你会说英语吗? -你懂中文吗? diff --git a/flutter_app/assets/text/text_files/day20_en.txt b/flutter_app/assets/text/text_files/day20_en.txt deleted file mode 100644 index 6fbe663..0000000 --- a/flutter_app/assets/text/text_files/day20_en.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Common Places -------------- -hospital -school -library -park -bank -post office -restaurant - -Public Communication --------------------- -Can I take photos here? -Where is the restroom? -Is there WiFi here? -What are the business hours? -I need help diff --git a/flutter_app/assets/text/text_files/day20_pinyin.txt b/flutter_app/assets/text/text_files/day20_pinyin.txt deleted file mode 100644 index 8bfc735..0000000 --- a/flutter_app/assets/text/text_files/day20_pinyin.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Common Places -------------- -yīyuàn -xuéxiào -túshūguǎn -gōngyuán -yínháng -yóujú -cāntīng - -Public Communication --------------------- -zhèlǐ kěyǐ pāizhào ma? -qǐngwèn xǐshǒujiān zài nǎlǐ? -zhèlǐ yǒu WiFi ma? -yíngyè shíjiān shì jǐ diǎn dào jǐ diǎn? -wǒ xūyào bāngzhù diff --git a/flutter_app/assets/text/text_files/day20_zh.txt b/flutter_app/assets/text/text_files/day20_zh.txt deleted file mode 100644 index b4c5a33..0000000 --- a/flutter_app/assets/text/text_files/day20_zh.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Common Places -------------- -医院 -学校 -图书馆 -公园 -银行 -邮局 -餐厅 - -Public Communication --------------------- -这里可以拍照吗? -请问洗手间在哪里? -这里有WiFi吗? -营业时间是几点到几点? -我需要帮助 diff --git a/flutter_app/assets/text/text_files/day21_en.txt b/flutter_app/assets/text/text_files/day21_en.txt deleted file mode 100644 index c485032..0000000 --- a/flutter_app/assets/text/text_files/day21_en.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Cultural Concepts ------------------ -face (reputation/dignity) -relationships/connections -filial piety -harmony -the doctrine of the mean (moderation) - -Traditional Arts ----------------- -calligraphy -traditional Chinese painting -tai chi -Beijing opera -paper cutting -traditional Chinese medicine diff --git a/flutter_app/assets/text/text_files/day21_pinyin.txt b/flutter_app/assets/text/text_files/day21_pinyin.txt deleted file mode 100644 index 159e87e..0000000 --- a/flutter_app/assets/text/text_files/day21_pinyin.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Cultural Concepts ------------------ -miànzi -guānxi -xiàoshùn -héxié -zhōngyōng zhī dào - -Traditional Arts ----------------- -shūfǎ -guóhuà -tàijíquán -jīngjù -jiǎnzhǐ -zhōngyī diff --git a/flutter_app/assets/text/text_files/day21_zh.txt b/flutter_app/assets/text/text_files/day21_zh.txt deleted file mode 100644 index 54f28a5..0000000 --- a/flutter_app/assets/text/text_files/day21_zh.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Cultural Concepts ------------------ -面子 -关系 -孝顺 -和谐 -中庸之道 - -Traditional Arts ----------------- -书法 -国画 -太极拳 -京剧 -剪纸 -中医 diff --git a/flutter_app/assets/text/text_files/day22_en.txt b/flutter_app/assets/text/text_files/day22_en.txt deleted file mode 100644 index 3db02ee..0000000 --- a/flutter_app/assets/text/text_files/day22_en.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Daily Expressions ------------------ -good morning -good night -you've worked hard -take care (when someone is leaving) -just kidding -don't worry - -Communication Strategies ------------------------- -I don't understand -please say it again -can you speak more slowly? -how do you say this in Chinese? -I'm learning Chinese diff --git a/flutter_app/assets/text/text_files/day22_pinyin.txt b/flutter_app/assets/text/text_files/day22_pinyin.txt deleted file mode 100644 index 8205c38..0000000 --- a/flutter_app/assets/text/text_files/day22_pinyin.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Daily Expressions ------------------ -zǎo'ān -wǎn'ān -xīnkǔ le -màn zǒu -kāi wánxiào -bié dānxīn - -Communication Strategies ------------------------- -wǒ tīng bù dǒng -qǐng zài shuō yībiàn -nǐ néng shuō màn yīdiǎn ma? -zhège yòng zhōngwén zěnme shuō? -wǒ zhèngzài xué zhōngwén diff --git a/flutter_app/assets/text/text_files/day22_zh.txt b/flutter_app/assets/text/text_files/day22_zh.txt deleted file mode 100644 index 5c14a11..0000000 --- a/flutter_app/assets/text/text_files/day22_zh.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Daily Expressions ------------------ -早安 -晚安 -辛苦了 -慢走 -开玩笑 -别担心 - -Communication Strategies ------------------------- -我听不懂 -请再说一遍 -你能说慢一点吗? -这个用中文怎么说? -我正在学中文 diff --git a/flutter_app/assets/text/text_files/day23_en.txt b/flutter_app/assets/text/text_files/day23_en.txt deleted file mode 100644 index 2d2e2ba..0000000 --- a/flutter_app/assets/text/text_files/day23_en.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Job Titles ----------- -manager -boss -colleague -secretary -engineer -sales -human resources - -Office Items ------------- -computer -printer -document -meeting room -office -business card diff --git a/flutter_app/assets/text/text_files/day23_pinyin.txt b/flutter_app/assets/text/text_files/day23_pinyin.txt deleted file mode 100644 index f9dfe6a..0000000 --- a/flutter_app/assets/text/text_files/day23_pinyin.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Job Titles ----------- -jīnglǐ -lǎobǎn -tóngshì -mìshū -gōngchéngshī -xiāoshòu -rénlì zīyuán - -Office Items ------------- -diànnǎo -dǎyìnjī -wénjiàn -huìyì shì -bàngōngshì -míngpiàn diff --git a/flutter_app/assets/text/text_files/day23_zh.txt b/flutter_app/assets/text/text_files/day23_zh.txt deleted file mode 100644 index 667a47c..0000000 --- a/flutter_app/assets/text/text_files/day23_zh.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Job Titles ----------- -经理 -老板 -同事 -秘书 -工程师 -销售 -人力资源 - -Office Items ------------- -电脑 -打印机 -文件 -会议室 -办公室 -名片 diff --git a/flutter_app/assets/text/text_files/day24_en.txt b/flutter_app/assets/text/text_files/day24_en.txt deleted file mode 100644 index 0a0d2b5..0000000 --- a/flutter_app/assets/text/text_files/day24_en.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Meeting Etiquette ------------------ -on time -self-introduction -handshake -exchange business cards -respect - -Business Phrases ----------------- -It's an honor to meet you -Please take care of me (business context) -Happy cooperation -Looking forward to seeing you again -Sorry to disturb you diff --git a/flutter_app/assets/text/text_files/day24_pinyin.txt b/flutter_app/assets/text/text_files/day24_pinyin.txt deleted file mode 100644 index 3fbf1e7..0000000 --- a/flutter_app/assets/text/text_files/day24_pinyin.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Meeting Etiquette ------------------ -zhǔnshí -zìwǒ jièshào -wòshǒu -jiāohuàn míngpiàn -zūnzhòng - -Business Phrases ----------------- -hěn róngxìng rènshi nín -qǐng duō guānzhào -hézuò yúkuài -qīdài yǔ nín zàicì jiànmiàn -dǎrǎo le diff --git a/flutter_app/assets/text/text_files/day24_zh.txt b/flutter_app/assets/text/text_files/day24_zh.txt deleted file mode 100644 index 6bfb1e7..0000000 --- a/flutter_app/assets/text/text_files/day24_zh.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Meeting Etiquette ------------------ -准时 -自我介绍 -握手 -交换名片 -尊重 - -Business Phrases ----------------- -很荣幸认识您 -请多关照 -合作愉快 -期待与您再次见面 -打扰了 diff --git a/flutter_app/assets/text/text_files/day25_en.txt b/flutter_app/assets/text/text_files/day25_en.txt deleted file mode 100644 index 3648ba6..0000000 --- a/flutter_app/assets/text/text_files/day25_en.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Remote Work Terms ------------------ -remote work -work from home -flexible working hours -video conference -internet connection - -Remote Work Phrases -------------------- -My microphone has no sound -Can you hear me speaking? -My internet is not very stable -Can we start now? -Please share your screen diff --git a/flutter_app/assets/text/text_files/day25_pinyin.txt b/flutter_app/assets/text/text_files/day25_pinyin.txt deleted file mode 100644 index 6ed4901..0000000 --- a/flutter_app/assets/text/text_files/day25_pinyin.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Remote Work Terms ------------------ -yuǎnchéng gōngzuò -zài jiā gōngzuò -línghuó gōngzuò shíjiān -shìpín huìyì -wǎngluò liánjiē - -Remote Work Phrases -------------------- -wǒ de màikèfēng méiyǒu shēngyīn -nǐ néng tīng dào wǒ shuōhuà ma? -wǒ de wǎngluò bú tài wěndìng -wǒmen kěyǐ kāishǐ le ma? -qǐng fēnxiǎng nǐ de píngmù diff --git a/flutter_app/assets/text/text_files/day25_zh.txt b/flutter_app/assets/text/text_files/day25_zh.txt deleted file mode 100644 index c97158b..0000000 --- a/flutter_app/assets/text/text_files/day25_zh.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Remote Work Terms ------------------ -远程工作 -在家工作 -灵活工作时间 -视频会议 -网络连接 - -Remote Work Phrases -------------------- -我的麦克风没有声音 -你能听到我说话吗? -我的网络不太稳定 -我们可以开始了吗? -请分享你的屏幕 diff --git a/flutter_app/assets/text/text_files/day26_en.txt b/flutter_app/assets/text/text_files/day26_en.txt deleted file mode 100644 index b324809..0000000 --- a/flutter_app/assets/text/text_files/day26_en.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Meeting Vocabulary ------------------- -agenda -meeting minutes -discussion -decision -participant -host/moderator - -Meeting Phrases ---------------- -Let's begin -Are there any questions? -I have a question -I agree -I disagree -When is the next meeting? diff --git a/flutter_app/assets/text/text_files/day26_pinyin.txt b/flutter_app/assets/text/text_files/day26_pinyin.txt deleted file mode 100644 index 98e4423..0000000 --- a/flutter_app/assets/text/text_files/day26_pinyin.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Meeting Vocabulary ------------------- -yìchéng -huìyì jìlù -tǎolùn -juédìng -cānyùzhě -zhǔchí rén - -Meeting Phrases ---------------- -wǒmen kāishǐ ba -yǒu shénme wèntí ma? -wǒ yǒu yī gè wèntí -wǒ tóngyì -wǒ bù tóngyì -xià cì huìyì shì shénme shíhou? diff --git a/flutter_app/assets/text/text_files/day26_zh.txt b/flutter_app/assets/text/text_files/day26_zh.txt deleted file mode 100644 index b559948..0000000 --- a/flutter_app/assets/text/text_files/day26_zh.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Meeting Vocabulary ------------------- -议程 -会议记录 -讨论 -决定 -参与者 -主持人 - -Meeting Phrases ---------------- -我们开始吧 -有什么问题吗? -我有一个问题 -我同意 -我不同意 -下次会议是什么时候? diff --git a/flutter_app/assets/text/text_files/day27_en.txt b/flutter_app/assets/text/text_files/day27_en.txt deleted file mode 100644 index 3b535fa..0000000 --- a/flutter_app/assets/text/text_files/day27_en.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Email Vocabulary ----------------- -email -recipient -sender -subject -attachment -CC (carbon copy) - -Email Phrases -------------- -Dear Sir/Madam -Thank you for your email -Please check the attachment -Looking forward to your reply -Sincerely -Regards diff --git a/flutter_app/assets/text/text_files/day27_pinyin.txt b/flutter_app/assets/text/text_files/day27_pinyin.txt deleted file mode 100644 index c8121b2..0000000 --- a/flutter_app/assets/text/text_files/day27_pinyin.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Email Vocabulary ----------------- -diànzǐ yóujiàn -shōujiàn rén -fājiàn rén -zhǔtí -fùjiàn -chāosòng - -Email Phrases -------------- -zūnjìng de xiānsheng/nǚshì -gǎnxiè nín de yóujiàn -qǐng chá shōu fùjiàn -qīdài nín de huífù -cǐ zhì -jìng shàng diff --git a/flutter_app/assets/text/text_files/day27_zh.txt b/flutter_app/assets/text/text_files/day27_zh.txt deleted file mode 100644 index 668c6c3..0000000 --- a/flutter_app/assets/text/text_files/day27_zh.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Email Vocabulary ----------------- -电子邮件 -收件人 -发件人 -主题 -附件 -抄送 - -Email Phrases -------------- -尊敬的先生/女士 -感谢您的邮件 -请查收附件 -期待您的回复 -此致 -敬上 diff --git a/flutter_app/assets/text/text_files/day28_en.txt b/flutter_app/assets/text/text_files/day28_en.txt deleted file mode 100644 index e8f7e2e..0000000 --- a/flutter_app/assets/text/text_files/day28_en.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Presentation Vocabulary ------------------------ -speech/presentation -slides -chart -data -conclusion -Q&A session - -Presentation Phrases --------------------- -Today I will talk about... -firstly -secondly -finally -to summarize -Are there any questions? diff --git a/flutter_app/assets/text/text_files/day28_pinyin.txt b/flutter_app/assets/text/text_files/day28_pinyin.txt deleted file mode 100644 index 0701df6..0000000 --- a/flutter_app/assets/text/text_files/day28_pinyin.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Presentation Vocabulary ------------------------ -yǎnjiǎng -huàndēng piàn -túbiǎo -shùjù -jiélùn -wèn dá huánjié - -Presentation Phrases --------------------- -jīntiān wǒ yào jiǎng de shì... -shǒuxiān -qícì -zuìhòu -zǒngjié yīxià -yǒu shénme wèntí ma? diff --git a/flutter_app/assets/text/text_files/day28_zh.txt b/flutter_app/assets/text/text_files/day28_zh.txt deleted file mode 100644 index 4c22ae0..0000000 --- a/flutter_app/assets/text/text_files/day28_zh.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Presentation Vocabulary ------------------------ -演讲 -幻灯片 -图表 -数据 -结论 -问答环节 - -Presentation Phrases --------------------- -今天我要讲的是... -首先 -其次 -最后 -总结一下 -有什么问题吗? diff --git a/flutter_app/assets/text/text_files/day29_en.txt b/flutter_app/assets/text/text_files/day29_en.txt deleted file mode 100644 index 06b5959..0000000 --- a/flutter_app/assets/text/text_files/day29_en.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Technical Vocabulary --------------------- -software -hardware -program -database -network -cloud computing -artificial intelligence - -Technical Phrases ------------------ -The system crashed -Need to update -Backup data -Restart the computer -Download files -Upload files diff --git a/flutter_app/assets/text/text_files/day29_pinyin.txt b/flutter_app/assets/text/text_files/day29_pinyin.txt deleted file mode 100644 index fac771c..0000000 --- a/flutter_app/assets/text/text_files/day29_pinyin.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Technical Vocabulary --------------------- -ruǎnjiàn -yìngjiàn -chéngxù -shùjùkù -wǎngluò -yún jìsuàn -réngōng zhìnéng - -Technical Phrases ------------------ -xìtǒng bēngkuì le -xūyào gēngxīn -bèifèn shùjù -chóngqǐ diànnǎo -xiàzài wénjiàn -shàngchuán wénjiàn diff --git a/flutter_app/assets/text/text_files/day29_zh.txt b/flutter_app/assets/text/text_files/day29_zh.txt deleted file mode 100644 index 74ef6a4..0000000 --- a/flutter_app/assets/text/text_files/day29_zh.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Technical Vocabulary --------------------- -软件 -硬件 -程序 -数据库 -网络 -云计算 -人工智能 - -Technical Phrases ------------------ -系统崩溃了 -需要更新 -备份数据 -重启电脑 -下载文件 -上传文件 diff --git a/flutter_app/assets/text/text_files/day2_en.txt b/flutter_app/assets/text/text_files/day2_en.txt deleted file mode 100644 index 84434c5..0000000 --- a/flutter_app/assets/text/text_files/day2_en.txt +++ /dev/null @@ -1,21 +0,0 @@ - -Numbers 0-10 ------------- -zero -one -two -three -four -five -six -seven -eight -nine -ten - -Basic Counting Phrases ----------------------- -How many/much? -in total -first -second diff --git a/flutter_app/assets/text/text_files/day2_pinyin.txt b/flutter_app/assets/text/text_files/day2_pinyin.txt deleted file mode 100644 index 1eb264a..0000000 --- a/flutter_app/assets/text/text_files/day2_pinyin.txt +++ /dev/null @@ -1,21 +0,0 @@ - -Numbers 0-10 ------------- -líng -yī -èr -sān -sì -wǔ -liù -qī -bā -jiǔ -shí - -Basic Counting Phrases ----------------------- -duōshao? -yīgòng -dì-yī -dì-èr diff --git a/flutter_app/assets/text/text_files/day2_zh.txt b/flutter_app/assets/text/text_files/day2_zh.txt deleted file mode 100644 index f078508..0000000 --- a/flutter_app/assets/text/text_files/day2_zh.txt +++ /dev/null @@ -1,21 +0,0 @@ - -Numbers 0-10 ------------- -零 -一 -二 -三 -四 -五 -六 -七 -八 -九 -十 - -Basic Counting Phrases ----------------------- -多少? -一共 -第一 -第二 diff --git a/flutter_app/assets/text/text_files/day30_en.txt b/flutter_app/assets/text/text_files/day30_en.txt deleted file mode 100644 index f54bbf3..0000000 --- a/flutter_app/assets/text/text_files/day30_en.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Negotiation Terms ------------------ -negotiation -contract -terms -agreement -price -discount -partner - -Negotiation Phrases -------------------- -Can we discuss the price? -We can accept this condition -We need to think about it more -This is our final offer -win-win -sign the contract diff --git a/flutter_app/assets/text/text_files/day30_pinyin.txt b/flutter_app/assets/text/text_files/day30_pinyin.txt deleted file mode 100644 index fb87eb6..0000000 --- a/flutter_app/assets/text/text_files/day30_pinyin.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Negotiation Terms ------------------ -tánpàn -hétong -tiáokuǎn -xiéyì -jiàgé -zhékòu -hézuò huǒbàn - -Negotiation Phrases -------------------- -wǒmen kěyǐ tǎolùn yīxià jiàgé ma? -zhège tiáojiàn wǒmen kěyǐ jiēshòu -wǒmen xūyào zài kǎolǜ yīxià -zhè shì wǒmen de zuìzhōng bàojià -shuāng yíng -qiānshǔ hétong diff --git a/flutter_app/assets/text/text_files/day30_zh.txt b/flutter_app/assets/text/text_files/day30_zh.txt deleted file mode 100644 index f6028ac..0000000 --- a/flutter_app/assets/text/text_files/day30_zh.txt +++ /dev/null @@ -1,19 +0,0 @@ - -Negotiation Terms ------------------ -谈判 -合同 -条款 -协议 -价格 -折扣 -合作伙伴 - -Negotiation Phrases -------------------- -我们可以讨论一下价格吗? -这个条件我们可以接受 -我们需要再考虑一下 -这是我们的最终报价 -双赢 -签署合同 diff --git a/flutter_app/assets/text/text_files/day31_en.txt b/flutter_app/assets/text/text_files/day31_en.txt deleted file mode 100644 index 70eb390..0000000 --- a/flutter_app/assets/text/text_files/day31_en.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Common Idioms -------------- -kill two birds with one stone -when in Rome, do as the Romans do -wait for opportunities without making effort -add unnecessary details (lit: draw a snake and add feet) -cast pearls before swine (lit: play the lute to a cow) -a blessing in disguise - -Using Idioms ------------- -This method kills two birds with one stone -We should follow local customs -Don't just wait for opportunities -This is adding unnecessary details diff --git a/flutter_app/assets/text/text_files/day31_pinyin.txt b/flutter_app/assets/text/text_files/day31_pinyin.txt deleted file mode 100644 index 43c8bb2..0000000 --- a/flutter_app/assets/text/text_files/day31_pinyin.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Common Idioms -------------- -yī jǔ liǎng dé -rù xiāng suí sú -shǒu zhū dài tù -huà shé tiān zú -duì niú tán qín -sài wēng shī mǎ - -Using Idioms ------------- -zhège fāngfǎ yī jǔ liǎng dé -wǒmen yīnggāi rù xiāng suí sú -bùyào shǒu zhū dài tù -zhè shì huà shé tiān zú diff --git a/flutter_app/assets/text/text_files/day31_zh.txt b/flutter_app/assets/text/text_files/day31_zh.txt deleted file mode 100644 index 96a5b31..0000000 --- a/flutter_app/assets/text/text_files/day31_zh.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Common Idioms -------------- -一举两得 -入乡随俗 -守株待兔 -画蛇添足 -对牛弹琴 -塞翁失马 - -Using Idioms ------------- -这个方法一举两得 -我们应该入乡随俗 -不要守株待兔 -这是画蛇添足 diff --git a/flutter_app/assets/text/text_files/day32_en.txt b/flutter_app/assets/text/text_files/day32_en.txt deleted file mode 100644 index a7040be..0000000 --- a/flutter_app/assets/text/text_files/day32_en.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Internet Slang --------------- -awesome/skilled (gaming slang) -to cheer for someone -super cute -homebody/geek (male) -homebody/geek (female) -bystander/onlooker (lit: melon-eating masses) - -Youth Expressions ------------------ -awesome/amazing -uncertain/no idea -awesome/powerful -too tired to care anymore -laid-back/whatever will be, will be -that hurt (emotionally) diff --git a/flutter_app/assets/text/text_files/day32_pinyin.txt b/flutter_app/assets/text/text_files/day32_pinyin.txt deleted file mode 100644 index 766c6a5..0000000 --- a/flutter_app/assets/text/text_files/day32_pinyin.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Internet Slang --------------- -liù liù liù -dǎ call -méng méng dā -zhái nán -zhái nǚ -chī guā qúnzhòng - -Youth Expressions ------------------ -lìhai le -méi pǔ -gěi lì -lèi jué bù ài -fó xì -zhā xīn le diff --git a/flutter_app/assets/text/text_files/day32_zh.txt b/flutter_app/assets/text/text_files/day32_zh.txt deleted file mode 100644 index 5a546a8..0000000 --- a/flutter_app/assets/text/text_files/day32_zh.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Internet Slang --------------- -666 -打call -萌萌哒 -宅男 -宅女 -吃瓜群众 - -Youth Expressions ------------------ -厉害了 -没谱 -给力 -累觉不爱 -佛系 -扎心了 diff --git a/flutter_app/assets/text/text_files/day33_en.txt b/flutter_app/assets/text/text_files/day33_en.txt deleted file mode 100644 index d249405..0000000 --- a/flutter_app/assets/text/text_files/day33_en.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Formal Greetings ----------------- -respected/dear -respected ladies and gentlemen -thank you for your care/support -I've long heard of your reputation -it's my greatest honor - -Formal Phrases --------------- -I/me (humble) -I/me (humble) -my/our company (humble) -your company (respectful) -looking forward to your good news -extremely grateful diff --git a/flutter_app/assets/text/text_files/day33_pinyin.txt b/flutter_app/assets/text/text_files/day33_pinyin.txt deleted file mode 100644 index abcdf98..0000000 --- a/flutter_app/assets/text/text_files/day33_pinyin.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Formal Greetings ----------------- -jìng'ài de -zūnjìng de gèwèi -chéngméng guānzhào -jiǔyǎng dàmíng -róngxìng zhī zhì - -Formal Phrases --------------- -zàixià -bǐrén -bì gōngsī -guì gōngsī -gōng hòu jiāyīn -bùshèng gǎnjī diff --git a/flutter_app/assets/text/text_files/day33_zh.txt b/flutter_app/assets/text/text_files/day33_zh.txt deleted file mode 100644 index 2e5dd5e..0000000 --- a/flutter_app/assets/text/text_files/day33_zh.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Formal Greetings ----------------- -敬爱的 -尊敬的各位 -承蒙关照 -久仰大名 -荣幸之至 - -Formal Phrases --------------- -在下 -鄙人 -敝公司 -贵公司 -恭候佳音 -不胜感激 diff --git a/flutter_app/assets/text/text_files/day34_en.txt b/flutter_app/assets/text/text_files/day34_en.txt deleted file mode 100644 index d225335..0000000 --- a/flutter_app/assets/text/text_files/day34_en.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Discussion Terms ----------------- -viewpoint -argument/point -evidence -refute/rebut -debate -stance/position - -Discussion Phrases ------------------- -I think/believe -based on my experience -I disagree because... -there's one point I'd like to add -let's think from another perspective -to summarize diff --git a/flutter_app/assets/text/text_files/day34_pinyin.txt b/flutter_app/assets/text/text_files/day34_pinyin.txt deleted file mode 100644 index 1b80682..0000000 --- a/flutter_app/assets/text/text_files/day34_pinyin.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Discussion Terms ----------------- -guāndiǎn -lùndiǎn -zhèngjù -fǎnbó -biànlùn -lìchǎng - -Discussion Phrases ------------------- -wǒ rènwéi -gēnjù wǒ de jīngyàn -wǒ bù tóngyì, yīnwèi... -yǒu yīdiǎn wǒ xiǎng bǔchōng -ràng wǒmen huàn gè jiǎodù sīkǎo -zǒngjié yīxià diff --git a/flutter_app/assets/text/text_files/day34_zh.txt b/flutter_app/assets/text/text_files/day34_zh.txt deleted file mode 100644 index 83ce934..0000000 --- a/flutter_app/assets/text/text_files/day34_zh.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Discussion Terms ----------------- -观点 -论点 -证据 -反驳 -辩论 -立场 - -Discussion Phrases ------------------- -我认为 -根据我的经验 -我不同意,因为... -有一点我想补充 -让我们换个角度思考 -总结一下 diff --git a/flutter_app/assets/text/text_files/day35_en.txt b/flutter_app/assets/text/text_files/day35_en.txt deleted file mode 100644 index c876831..0000000 --- a/flutter_app/assets/text/text_files/day35_en.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Narrative Elements ------------------- -story -character -plot -background/setting -theme -ending - -Storytelling Phrases --------------------- -once upon a time there was... -one day -suddenly -next/then -finally/in the end -the moral of the story is diff --git a/flutter_app/assets/text/text_files/day35_pinyin.txt b/flutter_app/assets/text/text_files/day35_pinyin.txt deleted file mode 100644 index 087005f..0000000 --- a/flutter_app/assets/text/text_files/day35_pinyin.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Narrative Elements ------------------- -gùshi -rénwù -qíngjié -bèijǐng -zhǔtí -jiéjú - -Storytelling Phrases --------------------- -cóngqián yǒu yī gè... -yǒu yī tiān -tūrán -jiē xià lái -zuìhòu -gùshi de yùyì shì diff --git a/flutter_app/assets/text/text_files/day35_zh.txt b/flutter_app/assets/text/text_files/day35_zh.txt deleted file mode 100644 index 9959773..0000000 --- a/flutter_app/assets/text/text_files/day35_zh.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Narrative Elements ------------------- -故事 -人物 -情节 -背景 -主题 -结局 - -Storytelling Phrases --------------------- -从前有一个... -有一天 -突然 -接下来 -最后 -故事的寓意是 diff --git a/flutter_app/assets/text/text_files/day36_en.txt b/flutter_app/assets/text/text_files/day36_en.txt deleted file mode 100644 index b081cb0..0000000 --- a/flutter_app/assets/text/text_files/day36_en.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Persuasion Techniques ---------------------- -persuade -influence -attract -emphasize -suggest -explain - -Persuasive Phrases ------------------- -I strongly suggest -without a doubt -please consider -most importantly -as everyone knows -facts prove that diff --git a/flutter_app/assets/text/text_files/day36_pinyin.txt b/flutter_app/assets/text/text_files/day36_pinyin.txt deleted file mode 100644 index 8e01da4..0000000 --- a/flutter_app/assets/text/text_files/day36_pinyin.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Persuasion Techniques ---------------------- -shuōfú -yǐngxiǎng -xīyǐn -qiángdiào -jiànyì -shuōmíng - -Persuasive Phrases ------------------- -wǒ qiángliè jiànyì -háo wú yíwèn -qǐng kǎolǜ yīxià -zuì zhòngyào de shì -zhòng suǒ zhōu zhī -shìshí zhèngmíng diff --git a/flutter_app/assets/text/text_files/day36_zh.txt b/flutter_app/assets/text/text_files/day36_zh.txt deleted file mode 100644 index 9d09c83..0000000 --- a/flutter_app/assets/text/text_files/day36_zh.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Persuasion Techniques ---------------------- -说服 -影响 -吸引 -强调 -建议 -说明 - -Persuasive Phrases ------------------- -我强烈建议 -毫无疑问 -请考虑一下 -最重要的是 -众所周知 -事实证明 diff --git a/flutter_app/assets/text/text_files/day37_en.txt b/flutter_app/assets/text/text_files/day37_en.txt deleted file mode 100644 index 78543ed..0000000 --- a/flutter_app/assets/text/text_files/day37_en.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Restaurant Dialogue 1 ---------------------- -Waiter: Hello, how many people? -Customer: Two people, thank you. -Waiter: Please follow me. -Customer: Do you have a menu? -Waiter: Here you are, please take your time. - -Restaurant Dialogue 2 ---------------------- -Customer: I'd like to order. -Waiter: What would you like to order? -Customer: I want one Kung Pao Chicken and a bowl of rice. -Waiter: OK, anything else? -Customer: Also a cup of tea, thank you. diff --git a/flutter_app/assets/text/text_files/day37_pinyin.txt b/flutter_app/assets/text/text_files/day37_pinyin.txt deleted file mode 100644 index 37049cf..0000000 --- a/flutter_app/assets/text/text_files/day37_pinyin.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Restaurant Dialogue 1 ---------------------- -Fúwùyuán: Nín hǎo, jǐ wèi? -Gùkè: Liǎng wèi, xièxie. -Fúwùyuán: Qǐng gēn wǒ lái. -Gùkè: Yǒu càidān ma? -Fúwùyuán: Gěi nín, qǐng màn yòng. - -Restaurant Dialogue 2 ---------------------- -Gùkè: Wǒ xiǎng diǎn cài. -Fúwùyuán: Nín xiǎng diǎn shénme? -Gùkè: Wǒ yào yī fèn gōngbǎo jīdīng hé yī wǎn mǐfàn. -Fúwùyuán: Hǎo de, hái xūyào shénme ma? -Gùkè: Zài lái yī bēi chá, xièxie. diff --git a/flutter_app/assets/text/text_files/day37_zh.txt b/flutter_app/assets/text/text_files/day37_zh.txt deleted file mode 100644 index 2e93d44..0000000 --- a/flutter_app/assets/text/text_files/day37_zh.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Restaurant Dialogue 1 ---------------------- -服务员:您好,几位? -顾客:两位,谢谢。 -服务员:请跟我来。 -顾客:有菜单吗? -服务员:给您,请慢用。 - -Restaurant Dialogue 2 ---------------------- -顾客:我想点菜。 -服务员:您想点什么? -顾客:我要一份宫保鸡丁和一碗米饭。 -服务员:好的,还需要什么吗? -顾客:再来一杯茶,谢谢。 diff --git a/flutter_app/assets/text/text_files/day38_en.txt b/flutter_app/assets/text/text_files/day38_en.txt deleted file mode 100644 index 17d0823..0000000 --- a/flutter_app/assets/text/text_files/day38_en.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Shopping Dialogue 1 -------------------- -Customer: How much is this piece of clothing? -Clerk: 200 yuan. -Customer: That's too expensive. Can you make it cheaper? -Clerk: 180 yuan, can't go any lower. -Customer: OK, I'll take it. - -Shopping Dialogue 2 -------------------- -Customer: Excuse me, where is the fitting room? -Clerk: Over there, turn right. -Customer: Do you have this in a larger size? -Clerk: Let me check. Yes, here's an XL. -Customer: Thanks, I'll try it on. diff --git a/flutter_app/assets/text/text_files/day38_pinyin.txt b/flutter_app/assets/text/text_files/day38_pinyin.txt deleted file mode 100644 index 8d6deee..0000000 --- a/flutter_app/assets/text/text_files/day38_pinyin.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Shopping Dialogue 1 -------------------- -Gùkè: Zhè jiàn yīfu duōshao qián? -Diànyuán: Liǎng bǎi yuán. -Gùkè: Tài guì le, néng piányi yīdiǎn ma? -Diànyuán: Yī bǎi bā shí yuán, bù néng zài dī le. -Gùkè: Hǎo ba, wǒ mǎi le. - -Shopping Dialogue 2 -------------------- -Gùkè: Qǐngwèn, shì yī jiān zài nǎlǐ? -Diànyuán: Zài nàbiān, yòu zhuǎn. -Gùkè: Zhè jiàn yǒu méiyǒu dà yīdiǎn de chǐmǎ? -Diànyuán: Ràng wǒ kànkan. Yǒu de, zhè shì XL hào de. -Gùkè: Xièxie, wǒ shì shìkan. diff --git a/flutter_app/assets/text/text_files/day38_zh.txt b/flutter_app/assets/text/text_files/day38_zh.txt deleted file mode 100644 index e82c540..0000000 --- a/flutter_app/assets/text/text_files/day38_zh.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Shopping Dialogue 1 -------------------- -顾客:这件衣服多少钱? -店员:两百元。 -顾客:太贵了,能便宜一点吗? -店员:一百八十元,不能再低了。 -顾客:好吧,我买了。 - -Shopping Dialogue 2 -------------------- -顾客:请问,试衣间在哪里? -店员:在那边,右转。 -顾客:这件有没有大一点的尺码? -店员:让我看看。有的,这是XL号的。 -顾客:谢谢,我试试看。 diff --git a/flutter_app/assets/text/text_files/day39_en.txt b/flutter_app/assets/text/text_files/day39_en.txt deleted file mode 100644 index 08047c3..0000000 --- a/flutter_app/assets/text/text_files/day39_en.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Business Meeting Dialogue 1 ---------------------------- -Mr. Li: Good morning, thank you all for attending today's meeting. -Ms. Wang: What are we discussing today? -Mr. Li: We need to discuss the progress of the new project. -Mr. Zhang: I have prepared the report. -Mr. Li: Great, please begin. - -Business Meeting Dialogue 2 ---------------------------- -Mr. Zhang: According to the data, our sales have increased by 20%. -Ms. Wang: That's good news, but our costs have also increased. -Mr. Li: We need to find ways to reduce costs. -Mr. Zhang: I have several suggestions. -Mr. Li: Please go ahead. diff --git a/flutter_app/assets/text/text_files/day39_pinyin.txt b/flutter_app/assets/text/text_files/day39_pinyin.txt deleted file mode 100644 index fd18382..0000000 --- a/flutter_app/assets/text/text_files/day39_pinyin.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Business Meeting Dialogue 1 ---------------------------- -Lǐ xiānsheng: Zǎoshang hǎo, gǎnxiè gèwèi lái cānjiā jīntiān de huìyì. -Wáng nǚshì: Wǒmen jīntiān yào tǎolùn shénme? -Lǐ xiānsheng: Wǒmen xūyào tǎolùn xīn xiàngmù de jìnzhǎn. -Zhāng xiānsheng: Wǒ yǐjīng zhǔnbèi hǎo le bàogào. -Lǐ xiānsheng: Tài hǎo le, qǐng kāishǐ ba. - -Business Meeting Dialogue 2 ---------------------------- -Zhāng xiānsheng: Gēnjù shùjù, wǒmen de xiāoshòu zēngzhǎng le 20%. -Wáng nǚshì: Zhè shì gè hǎo xiāoxi, dàn wǒmen de chéngběn yě zēngjiā le. -Lǐ xiānsheng: Wǒmen xūyào zhǎodào jiàngdī chéngběn de fāngfǎ. -Zhāng xiānsheng: Wǒ yǒu jǐ gè jiànyì. -Lǐ xiānsheng: Qǐng shuō. diff --git a/flutter_app/assets/text/text_files/day39_zh.txt b/flutter_app/assets/text/text_files/day39_zh.txt deleted file mode 100644 index b9c8bab..0000000 --- a/flutter_app/assets/text/text_files/day39_zh.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Business Meeting Dialogue 1 ---------------------------- -李先生:早上好,感谢各位来参加今天的会议。 -王女士:我们今天要讨论什么? -李先生:我们需要讨论新项目的进展。 -张先生:我已经准备好了报告。 -李先生:太好了,请开始吧。 - -Business Meeting Dialogue 2 ---------------------------- -张先生:根据数据,我们的销售增长了20%。 -王女士:这是个好消息,但我们的成本也增加了。 -李先生:我们需要找到降低成本的方法。 -张先生:我有几个建议。 -李先生:请说。 diff --git a/flutter_app/assets/text/text_files/day3_en.txt b/flutter_app/assets/text/text_files/day3_en.txt deleted file mode 100644 index 087ff72..0000000 --- a/flutter_app/assets/text/text_files/day3_en.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Time Words ----------- -now -today -tomorrow -yesterday -morning -afternoon -evening - -Asking Time ------------ -What time is it? -It's 3 o'clock now -When? -What day of the week? diff --git a/flutter_app/assets/text/text_files/day3_pinyin.txt b/flutter_app/assets/text/text_files/day3_pinyin.txt deleted file mode 100644 index 9fe1446..0000000 --- a/flutter_app/assets/text/text_files/day3_pinyin.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Time Words ----------- -xiànzài -jīntiān -míngtiān -zuótiān -shàngwǔ -xiàwǔ -wǎnshang - -Asking Time ------------ -jǐ diǎn le? -xiànzài shì sān diǎn -shénme shíhou? -xīngqī jǐ? diff --git a/flutter_app/assets/text/text_files/day3_zh.txt b/flutter_app/assets/text/text_files/day3_zh.txt deleted file mode 100644 index 4ec6bb0..0000000 --- a/flutter_app/assets/text/text_files/day3_zh.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Time Words ----------- -现在 -今天 -明天 -昨天 -上午 -下午 -晚上 - -Asking Time ------------ -几点了? -现在是三点 -什么时候? -星期几? diff --git a/flutter_app/assets/text/text_files/day40_en.txt b/flutter_app/assets/text/text_files/day40_en.txt deleted file mode 100644 index fb05c61..0000000 --- a/flutter_app/assets/text/text_files/day40_en.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Travel Dialogue 1 ------------------ -Tourist: Excuse me, how do I get to the Great Wall? -Local: You can take the subway to Beijing North Station, then transfer to bus route 916. -Tourist: Approximately how long will it take? -Local: About two hours. -Tourist: Thank you for your help! - -Travel Dialogue 2 ------------------ -Tourist: What time does this attraction close? -Staff: We close at 8 PM. -Tourist: How much is the admission ticket? -Staff: Adult tickets are 100 yuan, student tickets are half price. -Tourist: I'm a student, here's my student ID. diff --git a/flutter_app/assets/text/text_files/day40_pinyin.txt b/flutter_app/assets/text/text_files/day40_pinyin.txt deleted file mode 100644 index ff204ab..0000000 --- a/flutter_app/assets/text/text_files/day40_pinyin.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Travel Dialogue 1 ------------------ -Yóukè: Qǐngwèn, zěnme qù Chángchéng? -Dāngdì rén: Nǐ kěyǐ zuò dìtiě dào Běijīng běi zhàn, ránhòu huànchéng 916 lù gōngjiāo chē. -Yóukè: Dàgài xūyào duō cháng shíjiān? -Dāngdì rén: Dàyuē liǎng gè xiǎoshí. -Yóukè: Xièxiè nín de bāngzhù! - -Travel Dialogue 2 ------------------ -Yóukè: Zhège jǐngdiǎn jǐ diǎn guānmén? -Gōngzuò rényuán: Wǒmen wǎnshang bā diǎn guānmén. -Yóukè: Ménpiào duōshao qián? -Gōngzuò rényuán: Chéngrén piào yī bǎi yuán, xuésheng piào bàn jià. -Yóukè: Wǒ shì xuésheng, zhè shì wǒ de xuésheng zhèng. diff --git a/flutter_app/assets/text/text_files/day40_zh.txt b/flutter_app/assets/text/text_files/day40_zh.txt deleted file mode 100644 index 733f8fc..0000000 --- a/flutter_app/assets/text/text_files/day40_zh.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Travel Dialogue 1 ------------------ -游客:请问,怎么去长城? -当地人:你可以坐地铁到北京北站,然后换乘916路公交车。 -游客:大概需要多长时间? -当地人:大约两个小时。 -游客:谢谢您的帮助! - -Travel Dialogue 2 ------------------ -游客:这个景点几点关门? -工作人员:我们晚上八点关门。 -游客:门票多少钱? -工作人员:成人票一百元,学生票半价。 -游客:我是学生,这是我的学生证。 diff --git a/flutter_app/assets/text/text_files/day4_en.txt b/flutter_app/assets/text/text_files/day4_en.txt deleted file mode 100644 index 0244095..0000000 --- a/flutter_app/assets/text/text_files/day4_en.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Common Verbs ------------- -to be -to have -to want/to think -to go -to come -to eat -to drink -to speak/to say - -Simple Sentences ----------------- -I want to go there -Do you have time? -Let's go eat -I don't know diff --git a/flutter_app/assets/text/text_files/day4_pinyin.txt b/flutter_app/assets/text/text_files/day4_pinyin.txt deleted file mode 100644 index ba4a964..0000000 --- a/flutter_app/assets/text/text_files/day4_pinyin.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Common Verbs ------------- -shì -yǒu -xiǎng -qù -lái -chī -hē -shuō - -Simple Sentences ----------------- -wǒ xiǎng qù nàlǐ -nǐ yǒu shíjiān ma? -wǒmen qù chīfàn ba -wǒ bù zhīdào diff --git a/flutter_app/assets/text/text_files/day4_zh.txt b/flutter_app/assets/text/text_files/day4_zh.txt deleted file mode 100644 index ec8f05c..0000000 --- a/flutter_app/assets/text/text_files/day4_zh.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Common Verbs ------------- -是 -有 -想 -去 -来 -吃 -喝 -说 - -Simple Sentences ----------------- -我想去那里 -你有时间吗? -我们去吃饭吧 -我不知道 diff --git a/flutter_app/assets/text/text_files/day5_en.txt b/flutter_app/assets/text/text_files/day5_en.txt deleted file mode 100644 index 2b6c262..0000000 --- a/flutter_app/assets/text/text_files/day5_en.txt +++ /dev/null @@ -1,20 +0,0 @@ - -Common Adjectives ------------------ -good -bad -big -small -many/much -few/little -hot -cold -new -old (for objects) - -Descriptive Phrases -------------------- -very good -too expensive -very beautiful -not too far diff --git a/flutter_app/assets/text/text_files/day5_pinyin.txt b/flutter_app/assets/text/text_files/day5_pinyin.txt deleted file mode 100644 index 72ba895..0000000 --- a/flutter_app/assets/text/text_files/day5_pinyin.txt +++ /dev/null @@ -1,20 +0,0 @@ - -Common Adjectives ------------------ -hǎo -huài -dà -xiǎo -duō -shǎo -rè -lěng -xīn -jiù - -Descriptive Phrases -------------------- -hěn hǎo -tài guì le -fēicháng piàoliang -bú tài yuǎn diff --git a/flutter_app/assets/text/text_files/day5_zh.txt b/flutter_app/assets/text/text_files/day5_zh.txt deleted file mode 100644 index abf5878..0000000 --- a/flutter_app/assets/text/text_files/day5_zh.txt +++ /dev/null @@ -1,20 +0,0 @@ - -Common Adjectives ------------------ -好 -坏 -大 -小 -多 -少 -热 -冷 -新 -旧 - -Descriptive Phrases -------------------- -很好 -太贵了 -非常漂亮 -不太远 diff --git a/flutter_app/assets/text/text_files/day6_en.txt b/flutter_app/assets/text/text_files/day6_en.txt deleted file mode 100644 index 78f8337..0000000 --- a/flutter_app/assets/text/text_files/day6_en.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Question Words --------------- -what -who -where -why -how -how many/how much - -Common Questions ----------------- -What is this? -Who is that? -What is your name? -How much is this? -Where is the bathroom? diff --git a/flutter_app/assets/text/text_files/day6_pinyin.txt b/flutter_app/assets/text/text_files/day6_pinyin.txt deleted file mode 100644 index 14c0e60..0000000 --- a/flutter_app/assets/text/text_files/day6_pinyin.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Question Words --------------- -shénme -shuí/shéi -nǎlǐ -wèishénme -zěnme -duōshao - -Common Questions ----------------- -zhè shì shénme? -nà shì shuí? -nǐ jiào shénme míngzi? -zhège duōshao qián? -xǐshǒujiān zài nǎlǐ? diff --git a/flutter_app/assets/text/text_files/day6_zh.txt b/flutter_app/assets/text/text_files/day6_zh.txt deleted file mode 100644 index d89aaef..0000000 --- a/flutter_app/assets/text/text_files/day6_zh.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Question Words --------------- -什么 -谁 -哪里 -为什么 -怎么 -多少 - -Common Questions ----------------- -这是什么? -那是谁? -你叫什么名字? -这个多少钱? -洗手间在哪里? diff --git a/flutter_app/assets/text/text_files/day7_en.txt b/flutter_app/assets/text/text_files/day7_en.txt deleted file mode 100644 index 16167de..0000000 --- a/flutter_app/assets/text/text_files/day7_en.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Common Radicals ---------------- -person radical -mouth radical -woman radical -water radical -tree/wood radical -fire radical -heart radical - -Character Components --------------------- -good = woman + child -bright = sun + moon -rest = person + tree -man = field + strength -forest = tree + tree + tree diff --git a/flutter_app/assets/text/text_files/day7_pinyin.txt b/flutter_app/assets/text/text_files/day7_pinyin.txt deleted file mode 100644 index 9ae25ab..0000000 --- a/flutter_app/assets/text/text_files/day7_pinyin.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Common Radicals ---------------- -rén -kǒu -nǚ -shuǐ -mù -huǒ -xīn - -Character Components --------------------- -hǎo = nǚ + zǐ -míng = rì + yuè -xiū = rén + mù -nán = tián + lì -sēn = mù + mù + mù diff --git a/flutter_app/assets/text/text_files/day7_zh.txt b/flutter_app/assets/text/text_files/day7_zh.txt deleted file mode 100644 index c67119c..0000000 --- a/flutter_app/assets/text/text_files/day7_zh.txt +++ /dev/null @@ -1,18 +0,0 @@ - -Common Radicals ---------------- -人 -口 -女 -水 -木 -火 -心 - -Character Components --------------------- -好 = 女 + 子 -明 = 日 + 月 -休 = 人 + 木 -男 = 田 + 力 -森 = 木 + 木 + 木 diff --git a/flutter_app/assets/text/text_files/day8_en.txt b/flutter_app/assets/text/text_files/day8_en.txt deleted file mode 100644 index 4f1f802..0000000 --- a/flutter_app/assets/text/text_files/day8_en.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Shopping Places ---------------- -store -supermarket -market -department store -shopping mall - -Shopping Phrases ----------------- -How much money? -Too expensive -A little cheaper -I want this one -I'm just looking diff --git a/flutter_app/assets/text/text_files/day8_pinyin.txt b/flutter_app/assets/text/text_files/day8_pinyin.txt deleted file mode 100644 index a908e6c..0000000 --- a/flutter_app/assets/text/text_files/day8_pinyin.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Shopping Places ---------------- -shāngdiàn -chāoshì -shìchǎng -bǎihuò shāngdiàn -gòuwù zhōngxīn - -Shopping Phrases ----------------- -duōshao qián? -tài guì le -piányi yīdiǎn -wǒ yào zhège -wǒ zhǐshì kànkan diff --git a/flutter_app/assets/text/text_files/day8_zh.txt b/flutter_app/assets/text/text_files/day8_zh.txt deleted file mode 100644 index 4711940..0000000 --- a/flutter_app/assets/text/text_files/day8_zh.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Shopping Places ---------------- -商店 -超市 -市场 -百货商店 -购物中心 - -Shopping Phrases ----------------- -多少钱? -太贵了 -便宜一点 -我要这个 -我只是看看 diff --git a/flutter_app/assets/text/text_files/day9_en.txt b/flutter_app/assets/text/text_files/day9_en.txt deleted file mode 100644 index 1277c77..0000000 --- a/flutter_app/assets/text/text_files/day9_en.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Transportation Types --------------------- -bus -subway -taxi -train -airplane -bicycle - -Transportation Phrases ----------------------- -How do I get to the airport? -Where is the bus stop? -Please take me to this address -How much is one ticket? -When does the next bus come? diff --git a/flutter_app/assets/text/text_files/day9_pinyin.txt b/flutter_app/assets/text/text_files/day9_pinyin.txt deleted file mode 100644 index e6ebfc8..0000000 --- a/flutter_app/assets/text/text_files/day9_pinyin.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Transportation Types --------------------- -gōnggòng qìchē -dìtiě -chūzū chē -huǒchē -fēijī -zìxíngchē - -Transportation Phrases ----------------------- -qù jīchǎng zěnme zǒu? -gōnggòng qìchē zhàn zài nǎlǐ? -qǐng dài wǒ qù zhège dìzhǐ -yī zhāng piào duōshao qián? -xià yī bān chē shénme shíhou lái? diff --git a/flutter_app/assets/text/text_files/day9_zh.txt b/flutter_app/assets/text/text_files/day9_zh.txt deleted file mode 100644 index 5059dab..0000000 --- a/flutter_app/assets/text/text_files/day9_zh.txt +++ /dev/null @@ -1,17 +0,0 @@ - -Transportation Types --------------------- -公共汽车 -地铁 -出租车 -火车 -飞机 -自行车 - -Transportation Phrases ----------------------- -去机场怎么走? -公共汽车站在哪里? -请带我去这个地址 -一张票多少钱? -下一班车什么时候来? diff --git a/flutter_app/assets/text/text_files/supplementary/comparisons_en.txt b/flutter_app/assets/text/text_files/supplementary/comparisons_en.txt deleted file mode 100644 index 5fdc35c..0000000 --- a/flutter_app/assets/text/text_files/supplementary/comparisons_en.txt +++ /dev/null @@ -1,14 +0,0 @@ - -Basic Comparisons ------------------ -more... than -not as... as -same as... -the most... - -Example Sentences ------------------ -this is more expensive than that -today is not as hot as yesterday -these two are equally good -this is the best choice diff --git a/flutter_app/assets/text/text_files/supplementary/comparisons_pinyin.txt b/flutter_app/assets/text/text_files/supplementary/comparisons_pinyin.txt deleted file mode 100644 index 6726006..0000000 --- a/flutter_app/assets/text/text_files/supplementary/comparisons_pinyin.txt +++ /dev/null @@ -1,14 +0,0 @@ - -Basic Comparisons ------------------ -bǐ... gèng -méiyǒu... nàme -gēn... yīyàng -zuì... - -Example Sentences ------------------ -zhège bǐ nàge guì -jīntiān méiyǒu zuótiān rè -zhè liǎng ge yīyàng hǎo -zhè shì zuì hǎo de xuǎnzé diff --git a/flutter_app/assets/text/text_files/supplementary/comparisons_zh.txt b/flutter_app/assets/text/text_files/supplementary/comparisons_zh.txt deleted file mode 100644 index 50e36ac..0000000 --- a/flutter_app/assets/text/text_files/supplementary/comparisons_zh.txt +++ /dev/null @@ -1,14 +0,0 @@ - -Basic Comparisons ------------------ -比...更 -没有...那么 -跟...一样 -最... - -Example Sentences ------------------ -这个比那个贵 -今天没有昨天热 -这两个一样好 -这是最好的选择 diff --git a/flutter_app/assets/text/text_files/supplementary/daily_life_en.txt b/flutter_app/assets/text/text_files/supplementary/daily_life_en.txt deleted file mode 100644 index a2c1beb..0000000 --- a/flutter_app/assets/text/text_files/supplementary/daily_life_en.txt +++ /dev/null @@ -1,26 +0,0 @@ - -Weather Conditions ------------------- -sunny day -raining -cloudy -windy -snowing -humid - -Daily Routines --------------- -get up -brush teeth -take a shower -eat breakfast -go to work -get off work - -Shopping Types --------------- -clothing store -bookstore -pharmacy -bakery -fruit store diff --git a/flutter_app/assets/text/text_files/supplementary/daily_life_pinyin.txt b/flutter_app/assets/text/text_files/supplementary/daily_life_pinyin.txt deleted file mode 100644 index 502fb36..0000000 --- a/flutter_app/assets/text/text_files/supplementary/daily_life_pinyin.txt +++ /dev/null @@ -1,26 +0,0 @@ - -Weather Conditions ------------------- -qíngtiān -xiàyǔ -duōyún -guāfēng -xiàxuě -cháoshī - -Daily Routines --------------- -qǐchuáng -shuāyá -xǐzǎo -chī zǎofàn -shàngbān -xiàbān - -Shopping Types --------------- -fúzhuāng diàn -shūdiàn -yàodiàn -miànbāo diàn -shuǐguǒ diàn diff --git a/flutter_app/assets/text/text_files/supplementary/daily_life_zh.txt b/flutter_app/assets/text/text_files/supplementary/daily_life_zh.txt deleted file mode 100644 index 79aad09..0000000 --- a/flutter_app/assets/text/text_files/supplementary/daily_life_zh.txt +++ /dev/null @@ -1,26 +0,0 @@ - -Weather Conditions ------------------- -晴天 -下雨 -多云 -刮风 -下雪 -潮湿 - -Daily Routines --------------- -起床 -刷牙 -洗澡 -吃早饭 -上班 -下班 - -Shopping Types --------------- -服装店 -书店 -药店 -面包店 -水果店 diff --git a/flutter_app/assets/text/text_files/supplementary/education_en.txt b/flutter_app/assets/text/text_files/supplementary/education_en.txt deleted file mode 100644 index f3b8026..0000000 --- a/flutter_app/assets/text/text_files/supplementary/education_en.txt +++ /dev/null @@ -1,18 +0,0 @@ - -School Subjects ---------------- -mathematics -physics -chemistry -biology -history -geography -literature - -Classroom Phrases ------------------ -please raise your hand -I don't understand -Can you explain again? -class is over -exam diff --git a/flutter_app/assets/text/text_files/supplementary/education_pinyin.txt b/flutter_app/assets/text/text_files/supplementary/education_pinyin.txt deleted file mode 100644 index 8419930..0000000 --- a/flutter_app/assets/text/text_files/supplementary/education_pinyin.txt +++ /dev/null @@ -1,18 +0,0 @@ - -School Subjects ---------------- -shùxué -wùlǐ -huàxué -shēngwù -lìshǐ -dìlǐ -wénxué - -Classroom Phrases ------------------ -qǐng jǔshǒu -wǒ bù míngbai -néng zài jiěshì yībiàn ma? -xià kè le -kǎoshì diff --git a/flutter_app/assets/text/text_files/supplementary/education_zh.txt b/flutter_app/assets/text/text_files/supplementary/education_zh.txt deleted file mode 100644 index 34a06cb..0000000 --- a/flutter_app/assets/text/text_files/supplementary/education_zh.txt +++ /dev/null @@ -1,18 +0,0 @@ - -School Subjects ---------------- -数学 -物理 -化学 -生物 -历史 -地理 -文学 - -Classroom Phrases ------------------ -请举手 -我不明白 -能再解释一遍吗? -下课了 -考试 diff --git a/flutter_app/assets/text/text_files/supplementary/emotions_en.txt b/flutter_app/assets/text/text_files/supplementary/emotions_en.txt deleted file mode 100644 index 3fb016d..0000000 --- a/flutter_app/assets/text/text_files/supplementary/emotions_en.txt +++ /dev/null @@ -1,24 +0,0 @@ - -Basic Emotions --------------- -happy -sad -angry -afraid -nervous -excited - -Complex Feelings ----------------- -disappointed -proud -moved/touched -confused -worried - -Expressing Feelings -------------------- -I feel very... -makes me happy -I'm a bit... -in a bad mood diff --git a/flutter_app/assets/text/text_files/supplementary/emotions_pinyin.txt b/flutter_app/assets/text/text_files/supplementary/emotions_pinyin.txt deleted file mode 100644 index 96539a5..0000000 --- a/flutter_app/assets/text/text_files/supplementary/emotions_pinyin.txt +++ /dev/null @@ -1,24 +0,0 @@ - -Basic Emotions --------------- -gāoxìng -shāngxīn -shēngqì -hàipà -jǐnzhāng -xīngfèn - -Complex Feelings ----------------- -shīwàng -jiāo'ào -gǎndòng -kùnhuò -dānxīn - -Expressing Feelings -------------------- -wǒ juéde hěn... -ràng wǒ hěn kāixīn -wǒ yǒu diǎnr... -xīnqíng bù hǎo diff --git a/flutter_app/assets/text/text_files/supplementary/emotions_zh.txt b/flutter_app/assets/text/text_files/supplementary/emotions_zh.txt deleted file mode 100644 index 3184d64..0000000 --- a/flutter_app/assets/text/text_files/supplementary/emotions_zh.txt +++ /dev/null @@ -1,24 +0,0 @@ - -Basic Emotions --------------- -高兴 -伤心 -生气 -害怕 -紧张 -兴奋 - -Complex Feelings ----------------- -失望 -骄傲 -感动 -困惑 -担心 - -Expressing Feelings -------------------- -我觉得很... -让我很开心 -我有点儿... -心情不好 diff --git a/flutter_app/assets/text/text_files/supplementary/hobbies_en.txt b/flutter_app/assets/text/text_files/supplementary/hobbies_en.txt deleted file mode 100644 index 6942ac2..0000000 --- a/flutter_app/assets/text/text_files/supplementary/hobbies_en.txt +++ /dev/null @@ -1,24 +0,0 @@ - -Sports ------- -football/soccer -basketball -swimming -tennis -running - -Arts & Entertainment --------------------- -watch movies -listen to music -painting -photography -play piano - -Reading & Literature --------------------- -novel -poetry -magazine -comics -science fiction diff --git a/flutter_app/assets/text/text_files/supplementary/hobbies_pinyin.txt b/flutter_app/assets/text/text_files/supplementary/hobbies_pinyin.txt deleted file mode 100644 index b005ed8..0000000 --- a/flutter_app/assets/text/text_files/supplementary/hobbies_pinyin.txt +++ /dev/null @@ -1,24 +0,0 @@ - -Sports ------- -zúqiú -lánqiú -yóuyǒng -wǎngqiú -pǎobù - -Arts & Entertainment --------------------- -kàn diànyǐng -tīng yīnyuè -huàhuà -shèyǐng -tán gāngqín - -Reading & Literature --------------------- -xiǎoshuō -shīgē -zázhì -mànhuà -kēhuàn xiǎoshuō diff --git a/flutter_app/assets/text/text_files/supplementary/hobbies_zh.txt b/flutter_app/assets/text/text_files/supplementary/hobbies_zh.txt deleted file mode 100644 index b37487c..0000000 --- a/flutter_app/assets/text/text_files/supplementary/hobbies_zh.txt +++ /dev/null @@ -1,24 +0,0 @@ - -Sports ------- -足球 -篮球 -游泳 -网球 -跑步 - -Arts & Entertainment --------------------- -看电影 -听音乐 -画画 -摄影 -弹钢琴 - -Reading & Literature --------------------- -小说 -诗歌 -杂志 -漫画 -科幻小说 diff --git a/flutter_app/assets/timing/day10_en.json b/flutter_app/assets/timing/day10_en.json new file mode 100644 index 0000000..4787d88 --- /dev/null +++ b/flutter_app/assets/timing/day10_en.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 10, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Food Items", + "start": 0.0, + "end": 1.584 + }, + { + "i": 1, + "section": "Food Items", + "start": 1.584, + "end": 3.216 + }, + { + "i": 2, + "section": "Food Items", + "start": 3.216, + "end": 4.728 + }, + { + "i": 3, + "section": "Food Items", + "start": 4.728, + "end": 6.192 + }, + { + "i": 4, + "section": "Food Items", + "start": 6.192, + "end": 7.728 + }, + { + "i": 5, + "section": "Food Items", + "start": 7.728, + "end": 9.552 + }, + { + "i": 6, + "section": "Food Items", + "start": 9.552, + "end": 11.064 + }, + { + "i": 7, + "section": "Restaurant Phrases", + "start": 11.064, + "end": 12.6 + }, + { + "i": 8, + "section": "Restaurant Phrases", + "start": 12.6, + "end": 14.568 + }, + { + "i": 9, + "section": "Restaurant Phrases", + "start": 14.568, + "end": 16.92 + }, + { + "i": 10, + "section": "Restaurant Phrases", + "start": 16.92, + "end": 18.744 + }, + { + "i": 11, + "section": "Restaurant Phrases", + "start": 18.744, + "end": 20.832 + }, + { + "i": 12, + "section": "Restaurant Phrases", + "start": 20.832, + "end": 23.16 + } + ] +} diff --git a/flutter_app/assets/timing/day10_zh.json b/flutter_app/assets/timing/day10_zh.json new file mode 100644 index 0000000..444b741 --- /dev/null +++ b/flutter_app/assets/timing/day10_zh.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 10, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Food Items", + "start": 0.0, + "end": 1.248 + }, + { + "i": 1, + "section": "Food Items", + "start": 1.248, + "end": 2.544 + }, + { + "i": 2, + "section": "Food Items", + "start": 2.544, + "end": 3.792 + }, + { + "i": 3, + "section": "Food Items", + "start": 3.792, + "end": 5.064 + }, + { + "i": 4, + "section": "Food Items", + "start": 5.064, + "end": 6.312 + }, + { + "i": 5, + "section": "Food Items", + "start": 6.312, + "end": 7.632 + }, + { + "i": 6, + "section": "Food Items", + "start": 7.632, + "end": 9.0 + }, + { + "i": 7, + "section": "Restaurant Phrases", + "start": 9.0, + "end": 10.248 + }, + { + "i": 8, + "section": "Restaurant Phrases", + "start": 10.248, + "end": 11.832 + }, + { + "i": 9, + "section": "Restaurant Phrases", + "start": 11.832, + "end": 13.296 + }, + { + "i": 10, + "section": "Restaurant Phrases", + "start": 13.296, + "end": 14.496 + }, + { + "i": 11, + "section": "Restaurant Phrases", + "start": 14.496, + "end": 16.152 + }, + { + "i": 12, + "section": "Restaurant Phrases", + "start": 16.152, + "end": 17.856 + } + ] +} diff --git a/flutter_app/assets/timing/day11_en.json b/flutter_app/assets/timing/day11_en.json new file mode 100644 index 0000000..ed3513c --- /dev/null +++ b/flutter_app/assets/timing/day11_en.json @@ -0,0 +1,91 @@ +{ + "version": 1, + "day": 11, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Direction Words", + "start": 0.0, + "end": 1.824 + }, + { + "i": 1, + "section": "Direction Words", + "start": 1.824, + "end": 3.6 + }, + { + "i": 2, + "section": "Direction Words", + "start": 3.6, + "end": 5.28 + }, + { + "i": 3, + "section": "Direction Words", + "start": 5.28, + "end": 6.864 + }, + { + "i": 4, + "section": "Direction Words", + "start": 6.864, + "end": 8.376 + }, + { + "i": 5, + "section": "Direction Words", + "start": 8.376, + "end": 9.96 + }, + { + "i": 6, + "section": "Direction Words", + "start": 9.96, + "end": 11.616 + }, + { + "i": 7, + "section": "Direction Words", + "start": 11.616, + "end": 13.248 + }, + { + "i": 8, + "section": "Asking for Directions", + "start": 13.248, + "end": 16.008 + }, + { + "i": 9, + "section": "Asking for Directions", + "start": 16.008, + "end": 18.624 + }, + { + "i": 10, + "section": "Asking for Directions", + "start": 18.624, + "end": 20.424 + }, + { + "i": 11, + "section": "Asking for Directions", + "start": 20.424, + "end": 22.152 + }, + { + "i": 12, + "section": "Asking for Directions", + "start": 22.152, + "end": 23.832 + }, + { + "i": 13, + "section": "Asking for Directions", + "start": 23.832, + "end": 25.848 + } + ] +} diff --git a/flutter_app/assets/timing/day11_zh.json b/flutter_app/assets/timing/day11_zh.json new file mode 100644 index 0000000..df52833 --- /dev/null +++ b/flutter_app/assets/timing/day11_zh.json @@ -0,0 +1,91 @@ +{ + "version": 1, + "day": 11, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Direction Words", + "start": 0.0, + "end": 1.248 + }, + { + "i": 1, + "section": "Direction Words", + "start": 1.248, + "end": 2.496 + }, + { + "i": 2, + "section": "Direction Words", + "start": 2.496, + "end": 3.792 + }, + { + "i": 3, + "section": "Direction Words", + "start": 3.792, + "end": 5.04 + }, + { + "i": 4, + "section": "Direction Words", + "start": 5.04, + "end": 6.36 + }, + { + "i": 5, + "section": "Direction Words", + "start": 6.36, + "end": 7.656 + }, + { + "i": 6, + "section": "Direction Words", + "start": 7.656, + "end": 8.88 + }, + { + "i": 7, + "section": "Direction Words", + "start": 8.88, + "end": 10.104 + }, + { + "i": 8, + "section": "Asking for Directions", + "start": 10.104, + "end": 12.504 + }, + { + "i": 9, + "section": "Asking for Directions", + "start": 12.504, + "end": 14.304 + }, + { + "i": 10, + "section": "Asking for Directions", + "start": 14.304, + "end": 15.576 + }, + { + "i": 11, + "section": "Asking for Directions", + "start": 15.576, + "end": 17.04 + }, + { + "i": 12, + "section": "Asking for Directions", + "start": 17.04, + "end": 18.504 + }, + { + "i": 13, + "section": "Asking for Directions", + "start": 18.504, + "end": 19.968 + } + ] +} diff --git a/flutter_app/assets/timing/day12_en.json b/flutter_app/assets/timing/day12_en.json new file mode 100644 index 0000000..d54047e --- /dev/null +++ b/flutter_app/assets/timing/day12_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 12, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Subject-Verb-Object", + "start": 0.0, + "end": 1.92 + }, + { + "i": 1, + "section": "Subject-Verb-Object", + "start": 1.92, + "end": 3.912 + }, + { + "i": 2, + "section": "Subject-Verb-Object", + "start": 3.912, + "end": 6.048 + }, + { + "i": 3, + "section": "Subject-Verb-Object", + "start": 6.048, + "end": 8.016 + }, + { + "i": 4, + "section": "Question Patterns", + "start": 8.016, + "end": 9.96 + }, + { + "i": 5, + "section": "Question Patterns", + "start": 9.96, + "end": 12.216 + }, + { + "i": 6, + "section": "Question Patterns", + "start": 12.216, + "end": 14.304 + }, + { + "i": 7, + "section": "Question Patterns", + "start": 14.304, + "end": 16.104 + }, + { + "i": 8, + "section": "Negation Patterns", + "start": 16.104, + "end": 18.312 + }, + { + "i": 9, + "section": "Negation Patterns", + "start": 18.312, + "end": 20.496 + }, + { + "i": 10, + "section": "Negation Patterns", + "start": 20.496, + "end": 22.56 + }, + { + "i": 11, + "section": "Negation Patterns", + "start": 22.56, + "end": 24.576 + } + ] +} diff --git a/flutter_app/assets/timing/day12_zh.json b/flutter_app/assets/timing/day12_zh.json new file mode 100644 index 0000000..944339a --- /dev/null +++ b/flutter_app/assets/timing/day12_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 12, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Subject-Verb-Object", + "start": 0.0, + "end": 1.416 + }, + { + "i": 1, + "section": "Subject-Verb-Object", + "start": 1.416, + "end": 2.88 + }, + { + "i": 2, + "section": "Subject-Verb-Object", + "start": 2.88, + "end": 4.536 + }, + { + "i": 3, + "section": "Subject-Verb-Object", + "start": 4.536, + "end": 5.976 + }, + { + "i": 4, + "section": "Question Patterns", + "start": 5.976, + "end": 7.656 + }, + { + "i": 5, + "section": "Question Patterns", + "start": 7.656, + "end": 9.72 + }, + { + "i": 6, + "section": "Question Patterns", + "start": 9.72, + "end": 11.568 + }, + { + "i": 7, + "section": "Question Patterns", + "start": 11.568, + "end": 13.056 + }, + { + "i": 8, + "section": "Negation Patterns", + "start": 13.056, + "end": 14.904 + }, + { + "i": 9, + "section": "Negation Patterns", + "start": 14.904, + "end": 16.608 + }, + { + "i": 10, + "section": "Negation Patterns", + "start": 16.608, + "end": 18.432 + }, + { + "i": 11, + "section": "Negation Patterns", + "start": 18.432, + "end": 20.16 + } + ] +} diff --git a/flutter_app/assets/timing/day13_en.json b/flutter_app/assets/timing/day13_en.json new file mode 100644 index 0000000..8a582aa --- /dev/null +++ b/flutter_app/assets/timing/day13_en.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 13, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Emergency Phrases", + "start": 0.0, + "end": 3.168 + }, + { + "i": 1, + "section": "Emergency Phrases", + "start": 3.168, + "end": 4.944 + }, + { + "i": 2, + "section": "Emergency Phrases", + "start": 4.944, + "end": 6.672 + }, + { + "i": 3, + "section": "Emergency Phrases", + "start": 6.672, + "end": 8.376 + }, + { + "i": 4, + "section": "Emergency Phrases", + "start": 8.376, + "end": 10.584 + }, + { + "i": 5, + "section": "Emergency Phrases", + "start": 10.584, + "end": 12.792 + }, + { + "i": 6, + "section": "Hotel Phrases", + "start": 12.792, + "end": 15.0 + }, + { + "i": 7, + "section": "Hotel Phrases", + "start": 15.0, + "end": 17.016 + }, + { + "i": 8, + "section": "Hotel Phrases", + "start": 17.016, + "end": 18.72 + }, + { + "i": 9, + "section": "Hotel Phrases", + "start": 18.72, + "end": 20.4 + }, + { + "i": 10, + "section": "Hotel Phrases", + "start": 20.4, + "end": 22.08 + } + ] +} diff --git a/flutter_app/assets/timing/day13_zh.json b/flutter_app/assets/timing/day13_zh.json new file mode 100644 index 0000000..63568e6 --- /dev/null +++ b/flutter_app/assets/timing/day13_zh.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 13, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Emergency Phrases", + "start": 0.0, + "end": 1.224 + }, + { + "i": 1, + "section": "Emergency Phrases", + "start": 1.224, + "end": 2.904 + }, + { + "i": 2, + "section": "Emergency Phrases", + "start": 2.904, + "end": 4.44 + }, + { + "i": 3, + "section": "Emergency Phrases", + "start": 4.44, + "end": 5.976 + }, + { + "i": 4, + "section": "Emergency Phrases", + "start": 5.976, + "end": 7.56 + }, + { + "i": 5, + "section": "Emergency Phrases", + "start": 7.56, + "end": 9.168 + }, + { + "i": 6, + "section": "Hotel Phrases", + "start": 9.168, + "end": 10.656 + }, + { + "i": 7, + "section": "Hotel Phrases", + "start": 10.656, + "end": 12.624 + }, + { + "i": 8, + "section": "Hotel Phrases", + "start": 12.624, + "end": 14.304 + }, + { + "i": 9, + "section": "Hotel Phrases", + "start": 14.304, + "end": 15.6 + }, + { + "i": 10, + "section": "Hotel Phrases", + "start": 15.6, + "end": 16.896 + } + ] +} diff --git a/flutter_app/assets/timing/day14_en.json b/flutter_app/assets/timing/day14_en.json new file mode 100644 index 0000000..4ea79cc --- /dev/null +++ b/flutter_app/assets/timing/day14_en.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 14, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Travel Documents", + "start": 0.0, + "end": 1.752 + }, + { + "i": 1, + "section": "Travel Documents", + "start": 1.752, + "end": 3.288 + }, + { + "i": 2, + "section": "Travel Documents", + "start": 3.288, + "end": 5.28 + }, + { + "i": 3, + "section": "Travel Documents", + "start": 5.28, + "end": 7.248 + }, + { + "i": 4, + "section": "Travel Documents", + "start": 7.248, + "end": 8.952 + }, + { + "i": 5, + "section": "Useful Expressions", + "start": 8.952, + "end": 10.992 + }, + { + "i": 6, + "section": "Useful Expressions", + "start": 10.992, + "end": 13.056 + }, + { + "i": 7, + "section": "Useful Expressions", + "start": 13.056, + "end": 15.408 + }, + { + "i": 8, + "section": "Useful Expressions", + "start": 15.408, + "end": 17.472 + }, + { + "i": 9, + "section": "Useful Expressions", + "start": 17.472, + "end": 19.56 + }, + { + "i": 10, + "section": "Useful Expressions", + "start": 19.56, + "end": 22.392 + } + ] +} diff --git a/flutter_app/assets/timing/day14_zh.json b/flutter_app/assets/timing/day14_zh.json new file mode 100644 index 0000000..f817754 --- /dev/null +++ b/flutter_app/assets/timing/day14_zh.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 14, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Travel Documents", + "start": 0.0, + "end": 1.296 + }, + { + "i": 1, + "section": "Travel Documents", + "start": 1.296, + "end": 2.568 + }, + { + "i": 2, + "section": "Travel Documents", + "start": 2.568, + "end": 3.864 + }, + { + "i": 3, + "section": "Travel Documents", + "start": 3.864, + "end": 5.328 + }, + { + "i": 4, + "section": "Travel Documents", + "start": 5.328, + "end": 6.624 + }, + { + "i": 5, + "section": "Useful Expressions", + "start": 6.624, + "end": 8.136 + }, + { + "i": 6, + "section": "Useful Expressions", + "start": 8.136, + "end": 9.84 + }, + { + "i": 7, + "section": "Useful Expressions", + "start": 9.84, + "end": 11.592 + }, + { + "i": 8, + "section": "Useful Expressions", + "start": 11.592, + "end": 13.44 + }, + { + "i": 9, + "section": "Useful Expressions", + "start": 13.44, + "end": 15.264 + }, + { + "i": 10, + "section": "Useful Expressions", + "start": 15.264, + "end": 16.728 + } + ] +} diff --git a/flutter_app/assets/timing/day15_en.json b/flutter_app/assets/timing/day15_en.json new file mode 100644 index 0000000..2663f38 --- /dev/null +++ b/flutter_app/assets/timing/day15_en.json @@ -0,0 +1,103 @@ +{ + "version": 1, + "day": 15, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Immediate Family", + "start": 0.0, + "end": 1.584 + }, + { + "i": 1, + "section": "Immediate Family", + "start": 1.584, + "end": 3.096 + }, + { + "i": 2, + "section": "Immediate Family", + "start": 3.096, + "end": 4.896 + }, + { + "i": 3, + "section": "Immediate Family", + "start": 4.896, + "end": 6.84 + }, + { + "i": 4, + "section": "Immediate Family", + "start": 6.84, + "end": 8.664 + }, + { + "i": 5, + "section": "Immediate Family", + "start": 8.664, + "end": 10.608 + }, + { + "i": 6, + "section": "Immediate Family", + "start": 10.608, + "end": 12.12 + }, + { + "i": 7, + "section": "Immediate Family", + "start": 12.12, + "end": 13.632 + }, + { + "i": 8, + "section": "Extended Family", + "start": 13.632, + "end": 15.84 + }, + { + "i": 9, + "section": "Extended Family", + "start": 15.84, + "end": 17.952 + }, + { + "i": 10, + "section": "Extended Family", + "start": 17.952, + "end": 20.16 + }, + { + "i": 11, + "section": "Extended Family", + "start": 20.16, + "end": 22.296 + }, + { + "i": 12, + "section": "Extended Family", + "start": 22.296, + "end": 25.128 + }, + { + "i": 13, + "section": "Extended Family", + "start": 25.128, + "end": 27.576 + }, + { + "i": 14, + "section": "Extended Family", + "start": 27.576, + "end": 29.832 + }, + { + "i": 15, + "section": "Extended Family", + "start": 29.832, + "end": 32.088 + } + ] +} diff --git a/flutter_app/assets/timing/day15_zh.json b/flutter_app/assets/timing/day15_zh.json new file mode 100644 index 0000000..78f6f0e --- /dev/null +++ b/flutter_app/assets/timing/day15_zh.json @@ -0,0 +1,103 @@ +{ + "version": 1, + "day": 15, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Immediate Family", + "start": 0.0, + "end": 1.224 + }, + { + "i": 1, + "section": "Immediate Family", + "start": 1.224, + "end": 2.448 + }, + { + "i": 2, + "section": "Immediate Family", + "start": 2.448, + "end": 3.696 + }, + { + "i": 3, + "section": "Immediate Family", + "start": 3.696, + "end": 4.92 + }, + { + "i": 4, + "section": "Immediate Family", + "start": 4.92, + "end": 6.12 + }, + { + "i": 5, + "section": "Immediate Family", + "start": 6.12, + "end": 7.344 + }, + { + "i": 6, + "section": "Immediate Family", + "start": 7.344, + "end": 8.592 + }, + { + "i": 7, + "section": "Immediate Family", + "start": 8.592, + "end": 9.72 + }, + { + "i": 8, + "section": "Extended Family", + "start": 9.72, + "end": 10.968 + }, + { + "i": 9, + "section": "Extended Family", + "start": 10.968, + "end": 12.192 + }, + { + "i": 10, + "section": "Extended Family", + "start": 12.192, + "end": 13.416 + }, + { + "i": 11, + "section": "Extended Family", + "start": 13.416, + "end": 14.712 + }, + { + "i": 12, + "section": "Extended Family", + "start": 14.712, + "end": 16.032 + }, + { + "i": 13, + "section": "Extended Family", + "start": 16.032, + "end": 17.256 + }, + { + "i": 14, + "section": "Extended Family", + "start": 17.256, + "end": 18.72 + }, + { + "i": 15, + "section": "Extended Family", + "start": 18.72, + "end": 20.136 + } + ] +} diff --git a/flutter_app/assets/timing/day16_en.json b/flutter_app/assets/timing/day16_en.json new file mode 100644 index 0000000..6407b77 --- /dev/null +++ b/flutter_app/assets/timing/day16_en.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 16, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Greetings and Farewells", + "start": 0.0, + "end": 2.136 + }, + { + "i": 1, + "section": "Greetings and Farewells", + "start": 2.136, + "end": 4.32 + }, + { + "i": 2, + "section": "Greetings and Farewells", + "start": 4.32, + "end": 6.288 + }, + { + "i": 3, + "section": "Greetings and Farewells", + "start": 6.288, + "end": 8.136 + }, + { + "i": 4, + "section": "Greetings and Farewells", + "start": 8.136, + "end": 9.864 + }, + { + "i": 5, + "section": "Social Phrases", + "start": 9.864, + "end": 12.888 + }, + { + "i": 6, + "section": "Social Phrases", + "start": 12.888, + "end": 15.48 + }, + { + "i": 7, + "section": "Social Phrases", + "start": 15.48, + "end": 17.376 + }, + { + "i": 8, + "section": "Social Phrases", + "start": 17.376, + "end": 19.776 + }, + { + "i": 9, + "section": "Social Phrases", + "start": 19.776, + "end": 22.464 + } + ] +} diff --git a/flutter_app/assets/timing/day16_zh.json b/flutter_app/assets/timing/day16_zh.json new file mode 100644 index 0000000..d61ce7f --- /dev/null +++ b/flutter_app/assets/timing/day16_zh.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 16, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Greetings and Farewells", + "start": 0.0, + "end": 1.704 + }, + { + "i": 1, + "section": "Greetings and Farewells", + "start": 1.704, + "end": 3.312 + }, + { + "i": 2, + "section": "Greetings and Farewells", + "start": 3.312, + "end": 5.232 + }, + { + "i": 3, + "section": "Greetings and Farewells", + "start": 5.232, + "end": 6.696 + }, + { + "i": 4, + "section": "Greetings and Farewells", + "start": 6.696, + "end": 7.92 + }, + { + "i": 5, + "section": "Social Phrases", + "start": 7.92, + "end": 9.312 + }, + { + "i": 6, + "section": "Social Phrases", + "start": 9.312, + "end": 10.776 + }, + { + "i": 7, + "section": "Social Phrases", + "start": 10.776, + "end": 12.336 + }, + { + "i": 8, + "section": "Social Phrases", + "start": 12.336, + "end": 13.56 + }, + { + "i": 9, + "section": "Social Phrases", + "start": 13.56, + "end": 14.904 + } + ] +} diff --git a/flutter_app/assets/timing/day17_en.json b/flutter_app/assets/timing/day17_en.json new file mode 100644 index 0000000..c5a3df6 --- /dev/null +++ b/flutter_app/assets/timing/day17_en.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 17, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Polite Expressions", + "start": 0.0, + "end": 1.512 + }, + { + "i": 1, + "section": "Polite Expressions", + "start": 1.512, + "end": 3.12 + }, + { + "i": 2, + "section": "Polite Expressions", + "start": 3.12, + "end": 4.896 + }, + { + "i": 3, + "section": "Polite Expressions", + "start": 4.896, + "end": 6.48 + }, + { + "i": 4, + "section": "Polite Expressions", + "start": 6.48, + "end": 8.232 + }, + { + "i": 5, + "section": "Cultural Etiquette", + "start": 8.232, + "end": 11.328 + }, + { + "i": 6, + "section": "Cultural Etiquette", + "start": 11.328, + "end": 14.544 + }, + { + "i": 7, + "section": "Cultural Etiquette", + "start": 14.544, + "end": 16.536 + }, + { + "i": 8, + "section": "Cultural Etiquette", + "start": 16.536, + "end": 19.656 + }, + { + "i": 9, + "section": "Cultural Etiquette", + "start": 19.656, + "end": 22.176 + } + ] +} diff --git a/flutter_app/assets/timing/day17_zh.json b/flutter_app/assets/timing/day17_zh.json new file mode 100644 index 0000000..0903123 --- /dev/null +++ b/flutter_app/assets/timing/day17_zh.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 17, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Polite Expressions", + "start": 0.0, + "end": 1.056 + }, + { + "i": 1, + "section": "Polite Expressions", + "start": 1.056, + "end": 2.328 + }, + { + "i": 2, + "section": "Polite Expressions", + "start": 2.328, + "end": 3.768 + }, + { + "i": 3, + "section": "Polite Expressions", + "start": 3.768, + "end": 5.136 + }, + { + "i": 4, + "section": "Polite Expressions", + "start": 5.136, + "end": 6.6 + }, + { + "i": 5, + "section": "Cultural Etiquette", + "start": 6.6, + "end": 8.376 + }, + { + "i": 6, + "section": "Cultural Etiquette", + "start": 8.376, + "end": 9.672 + }, + { + "i": 7, + "section": "Cultural Etiquette", + "start": 9.672, + "end": 11.16 + }, + { + "i": 8, + "section": "Cultural Etiquette", + "start": 11.16, + "end": 12.768 + }, + { + "i": 9, + "section": "Cultural Etiquette", + "start": 12.768, + "end": 14.088 + } + ] +} diff --git a/flutter_app/assets/timing/day18_en.json b/flutter_app/assets/timing/day18_en.json new file mode 100644 index 0000000..3b13bf3 --- /dev/null +++ b/flutter_app/assets/timing/day18_en.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 18, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Major Festivals", + "start": 0.0, + "end": 3.24 + }, + { + "i": 1, + "section": "Major Festivals", + "start": 3.24, + "end": 5.376 + }, + { + "i": 2, + "section": "Major Festivals", + "start": 5.376, + "end": 7.68 + }, + { + "i": 3, + "section": "Major Festivals", + "start": 7.68, + "end": 9.744 + }, + { + "i": 4, + "section": "Major Festivals", + "start": 9.744, + "end": 11.832 + }, + { + "i": 5, + "section": "Festival Traditions", + "start": 11.832, + "end": 14.4 + }, + { + "i": 6, + "section": "Festival Traditions", + "start": 14.4, + "end": 16.176 + }, + { + "i": 7, + "section": "Festival Traditions", + "start": 16.176, + "end": 17.88 + }, + { + "i": 8, + "section": "Festival Traditions", + "start": 17.88, + "end": 19.776 + }, + { + "i": 9, + "section": "Festival Traditions", + "start": 19.776, + "end": 22.2 + }, + { + "i": 10, + "section": "Festival Traditions", + "start": 22.2, + "end": 24.6 + } + ] +} diff --git a/flutter_app/assets/timing/day18_zh.json b/flutter_app/assets/timing/day18_zh.json new file mode 100644 index 0000000..8f101d4 --- /dev/null +++ b/flutter_app/assets/timing/day18_zh.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 18, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Major Festivals", + "start": 0.0, + "end": 1.32 + }, + { + "i": 1, + "section": "Major Festivals", + "start": 1.32, + "end": 2.832 + }, + { + "i": 2, + "section": "Major Festivals", + "start": 2.832, + "end": 4.248 + }, + { + "i": 3, + "section": "Major Festivals", + "start": 4.248, + "end": 5.736 + }, + { + "i": 4, + "section": "Major Festivals", + "start": 5.736, + "end": 7.248 + }, + { + "i": 5, + "section": "Festival Traditions", + "start": 7.248, + "end": 8.496 + }, + { + "i": 6, + "section": "Festival Traditions", + "start": 8.496, + "end": 9.72 + }, + { + "i": 7, + "section": "Festival Traditions", + "start": 9.72, + "end": 10.944 + }, + { + "i": 8, + "section": "Festival Traditions", + "start": 10.944, + "end": 12.168 + }, + { + "i": 9, + "section": "Festival Traditions", + "start": 12.168, + "end": 13.728 + }, + { + "i": 10, + "section": "Festival Traditions", + "start": 13.728, + "end": 15.24 + } + ] +} diff --git a/flutter_app/assets/timing/day19_en.json b/flutter_app/assets/timing/day19_en.json new file mode 100644 index 0000000..569e478 --- /dev/null +++ b/flutter_app/assets/timing/day19_en.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 19, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Rooms and Areas", + "start": 0.0, + "end": 1.728 + }, + { + "i": 1, + "section": "Rooms and Areas", + "start": 1.728, + "end": 3.312 + }, + { + "i": 2, + "section": "Rooms and Areas", + "start": 3.312, + "end": 4.848 + }, + { + "i": 3, + "section": "Rooms and Areas", + "start": 4.848, + "end": 6.48 + }, + { + "i": 4, + "section": "Rooms and Areas", + "start": 6.48, + "end": 8.136 + }, + { + "i": 5, + "section": "Rooms and Areas", + "start": 8.136, + "end": 9.624 + }, + { + "i": 6, + "section": "Household Items", + "start": 9.624, + "end": 11.136 + }, + { + "i": 7, + "section": "Household Items", + "start": 11.136, + "end": 12.6 + }, + { + "i": 8, + "section": "Household Items", + "start": 12.6, + "end": 14.016 + }, + { + "i": 9, + "section": "Household Items", + "start": 14.016, + "end": 15.624 + }, + { + "i": 10, + "section": "Household Items", + "start": 15.624, + "end": 17.376 + }, + { + "i": 11, + "section": "Household Items", + "start": 17.376, + "end": 19.248 + }, + { + "i": 12, + "section": "Household Items", + "start": 19.248, + "end": 21.168 + } + ] +} diff --git a/flutter_app/assets/timing/day19_zh.json b/flutter_app/assets/timing/day19_zh.json new file mode 100644 index 0000000..65cec95 --- /dev/null +++ b/flutter_app/assets/timing/day19_zh.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 19, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Rooms and Areas", + "start": 0.0, + "end": 1.296 + }, + { + "i": 1, + "section": "Rooms and Areas", + "start": 1.296, + "end": 2.592 + }, + { + "i": 2, + "section": "Rooms and Areas", + "start": 2.592, + "end": 3.864 + }, + { + "i": 3, + "section": "Rooms and Areas", + "start": 3.864, + "end": 5.16 + }, + { + "i": 4, + "section": "Rooms and Areas", + "start": 5.16, + "end": 6.48 + }, + { + "i": 5, + "section": "Rooms and Areas", + "start": 6.48, + "end": 7.8 + }, + { + "i": 6, + "section": "Household Items", + "start": 7.8, + "end": 9.048 + }, + { + "i": 7, + "section": "Household Items", + "start": 9.048, + "end": 10.248 + }, + { + "i": 8, + "section": "Household Items", + "start": 10.248, + "end": 11.328 + }, + { + "i": 9, + "section": "Household Items", + "start": 11.328, + "end": 12.672 + }, + { + "i": 10, + "section": "Household Items", + "start": 12.672, + "end": 13.992 + }, + { + "i": 11, + "section": "Household Items", + "start": 13.992, + "end": 15.288 + }, + { + "i": 12, + "section": "Household Items", + "start": 15.288, + "end": 16.536 + } + ] +} diff --git a/flutter_app/assets/timing/day1_en.json b/flutter_app/assets/timing/day1_en.json new file mode 100644 index 0000000..be03af3 --- /dev/null +++ b/flutter_app/assets/timing/day1_en.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 1, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Basic Greetings & Common Phrases", + "start": 0.0, + "end": 1.56 + }, + { + "i": 1, + "section": "Basic Greetings & Common Phrases", + "start": 1.56, + "end": 3.288 + }, + { + "i": 2, + "section": "Basic Greetings & Common Phrases", + "start": 3.288, + "end": 5.088 + }, + { + "i": 3, + "section": "Basic Greetings & Common Phrases", + "start": 5.088, + "end": 6.72 + }, + { + "i": 4, + "section": "Basic Greetings & Common Phrases", + "start": 6.72, + "end": 8.256 + }, + { + "i": 5, + "section": "Self Introduction", + "start": 8.256, + "end": 10.056 + }, + { + "i": 6, + "section": "Self Introduction", + "start": 10.056, + "end": 12.024 + }, + { + "i": 7, + "section": "Self Introduction", + "start": 12.024, + "end": 13.992 + }, + { + "i": 8, + "section": "Self Introduction", + "start": 13.992, + "end": 15.576 + }, + { + "i": 9, + "section": "Basic Questions", + "start": 15.576, + "end": 17.304 + }, + { + "i": 10, + "section": "Basic Questions", + "start": 17.304, + "end": 19.584 + }, + { + "i": 11, + "section": "Basic Questions", + "start": 19.584, + "end": 21.648 + }, + { + "i": 12, + "section": "Basic Questions", + "start": 21.648, + "end": 24.048 + } + ] +} diff --git a/flutter_app/assets/timing/day1_zh.json b/flutter_app/assets/timing/day1_zh.json new file mode 100644 index 0000000..9624a2f --- /dev/null +++ b/flutter_app/assets/timing/day1_zh.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 1, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Basic Greetings & Common Phrases", + "start": 0.0, + "end": 1.2 + }, + { + "i": 1, + "section": "Basic Greetings & Common Phrases", + "start": 1.2, + "end": 2.616 + }, + { + "i": 2, + "section": "Basic Greetings & Common Phrases", + "start": 2.616, + "end": 4.056 + }, + { + "i": 3, + "section": "Basic Greetings & Common Phrases", + "start": 4.056, + "end": 5.496 + }, + { + "i": 4, + "section": "Basic Greetings & Common Phrases", + "start": 5.496, + "end": 6.72 + }, + { + "i": 5, + "section": "Self Introduction", + "start": 6.72, + "end": 7.872 + }, + { + "i": 6, + "section": "Self Introduction", + "start": 7.872, + "end": 9.792 + }, + { + "i": 7, + "section": "Self Introduction", + "start": 9.792, + "end": 11.52 + }, + { + "i": 8, + "section": "Self Introduction", + "start": 11.52, + "end": 12.696 + }, + { + "i": 9, + "section": "Basic Questions", + "start": 12.696, + "end": 14.016 + }, + { + "i": 10, + "section": "Basic Questions", + "start": 14.016, + "end": 15.744 + }, + { + "i": 11, + "section": "Basic Questions", + "start": 15.744, + "end": 17.592 + }, + { + "i": 12, + "section": "Basic Questions", + "start": 17.592, + "end": 19.248 + } + ] +} diff --git a/flutter_app/assets/timing/day20_en.json b/flutter_app/assets/timing/day20_en.json new file mode 100644 index 0000000..7e18503 --- /dev/null +++ b/flutter_app/assets/timing/day20_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 20, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Common Places", + "start": 0.0, + "end": 1.704 + }, + { + "i": 1, + "section": "Common Places", + "start": 1.704, + "end": 3.312 + }, + { + "i": 2, + "section": "Common Places", + "start": 3.312, + "end": 4.992 + }, + { + "i": 3, + "section": "Common Places", + "start": 4.992, + "end": 6.48 + }, + { + "i": 4, + "section": "Common Places", + "start": 6.48, + "end": 7.944 + }, + { + "i": 5, + "section": "Common Places", + "start": 7.944, + "end": 9.864 + }, + { + "i": 6, + "section": "Common Places", + "start": 9.864, + "end": 11.544 + }, + { + "i": 7, + "section": "Public Communication", + "start": 11.544, + "end": 13.728 + }, + { + "i": 8, + "section": "Public Communication", + "start": 13.728, + "end": 15.792 + }, + { + "i": 9, + "section": "Public Communication", + "start": 15.792, + "end": 17.88 + }, + { + "i": 10, + "section": "Public Communication", + "start": 17.88, + "end": 20.208 + }, + { + "i": 11, + "section": "Public Communication", + "start": 20.208, + "end": 21.984 + } + ] +} diff --git a/flutter_app/assets/timing/day20_zh.json b/flutter_app/assets/timing/day20_zh.json new file mode 100644 index 0000000..d449595 --- /dev/null +++ b/flutter_app/assets/timing/day20_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 20, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Common Places", + "start": 0.0, + "end": 1.248 + }, + { + "i": 1, + "section": "Common Places", + "start": 1.248, + "end": 2.592 + }, + { + "i": 2, + "section": "Common Places", + "start": 2.592, + "end": 4.08 + }, + { + "i": 3, + "section": "Common Places", + "start": 4.08, + "end": 5.328 + }, + { + "i": 4, + "section": "Common Places", + "start": 5.328, + "end": 6.552 + }, + { + "i": 5, + "section": "Common Places", + "start": 6.552, + "end": 7.872 + }, + { + "i": 6, + "section": "Common Places", + "start": 7.872, + "end": 9.12 + }, + { + "i": 7, + "section": "Public Communication", + "start": 9.12, + "end": 11.064 + }, + { + "i": 8, + "section": "Public Communication", + "start": 11.064, + "end": 13.488 + }, + { + "i": 9, + "section": "Public Communication", + "start": 13.488, + "end": 15.288 + }, + { + "i": 10, + "section": "Public Communication", + "start": 15.288, + "end": 18.024 + }, + { + "i": 11, + "section": "Public Communication", + "start": 18.024, + "end": 19.704 + } + ] +} diff --git a/flutter_app/assets/timing/day21_en.json b/flutter_app/assets/timing/day21_en.json new file mode 100644 index 0000000..edc11d7 --- /dev/null +++ b/flutter_app/assets/timing/day21_en.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 21, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Cultural Concepts", + "start": 0.0, + "end": 3.144 + }, + { + "i": 1, + "section": "Cultural Concepts", + "start": 3.144, + "end": 6.048 + }, + { + "i": 2, + "section": "Cultural Concepts", + "start": 6.048, + "end": 8.136 + }, + { + "i": 3, + "section": "Cultural Concepts", + "start": 8.136, + "end": 9.744 + }, + { + "i": 4, + "section": "Cultural Concepts", + "start": 9.744, + "end": 12.696 + }, + { + "i": 5, + "section": "Traditional Arts", + "start": 12.696, + "end": 14.472 + }, + { + "i": 6, + "section": "Traditional Arts", + "start": 14.472, + "end": 17.064 + }, + { + "i": 7, + "section": "Traditional Arts", + "start": 17.064, + "end": 18.84 + }, + { + "i": 8, + "section": "Traditional Arts", + "start": 18.84, + "end": 20.712 + }, + { + "i": 9, + "section": "Traditional Arts", + "start": 20.712, + "end": 22.56 + }, + { + "i": 10, + "section": "Traditional Arts", + "start": 22.56, + "end": 25.176 + } + ] +} diff --git a/flutter_app/assets/timing/day21_zh.json b/flutter_app/assets/timing/day21_zh.json new file mode 100644 index 0000000..cbf00b5 --- /dev/null +++ b/flutter_app/assets/timing/day21_zh.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 21, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Cultural Concepts", + "start": 0.0, + "end": 1.224 + }, + { + "i": 1, + "section": "Cultural Concepts", + "start": 1.224, + "end": 2.472 + }, + { + "i": 2, + "section": "Cultural Concepts", + "start": 2.472, + "end": 3.84 + }, + { + "i": 3, + "section": "Cultural Concepts", + "start": 3.84, + "end": 5.136 + }, + { + "i": 4, + "section": "Cultural Concepts", + "start": 5.136, + "end": 6.72 + }, + { + "i": 5, + "section": "Traditional Arts", + "start": 6.72, + "end": 8.04 + }, + { + "i": 6, + "section": "Traditional Arts", + "start": 8.04, + "end": 9.264 + }, + { + "i": 7, + "section": "Traditional Arts", + "start": 9.264, + "end": 10.752 + }, + { + "i": 8, + "section": "Traditional Arts", + "start": 10.752, + "end": 11.976 + }, + { + "i": 9, + "section": "Traditional Arts", + "start": 11.976, + "end": 13.272 + }, + { + "i": 10, + "section": "Traditional Arts", + "start": 13.272, + "end": 14.52 + } + ] +} diff --git a/flutter_app/assets/timing/day22_en.json b/flutter_app/assets/timing/day22_en.json new file mode 100644 index 0000000..b96936a --- /dev/null +++ b/flutter_app/assets/timing/day22_en.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 22, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Daily Expressions", + "start": 0.0, + "end": 1.728 + }, + { + "i": 1, + "section": "Daily Expressions", + "start": 1.728, + "end": 3.36 + }, + { + "i": 2, + "section": "Daily Expressions", + "start": 3.36, + "end": 5.28 + }, + { + "i": 3, + "section": "Daily Expressions", + "start": 5.28, + "end": 8.232 + }, + { + "i": 4, + "section": "Daily Expressions", + "start": 8.232, + "end": 10.008 + }, + { + "i": 5, + "section": "Daily Expressions", + "start": 10.008, + "end": 11.712 + }, + { + "i": 6, + "section": "Communication Strategies", + "start": 11.712, + "end": 13.752 + }, + { + "i": 7, + "section": "Communication Strategies", + "start": 13.752, + "end": 15.816 + }, + { + "i": 8, + "section": "Communication Strategies", + "start": 15.816, + "end": 18.12 + }, + { + "i": 9, + "section": "Communication Strategies", + "start": 18.12, + "end": 20.736 + }, + { + "i": 10, + "section": "Communication Strategies", + "start": 20.736, + "end": 22.968 + } + ] +} diff --git a/flutter_app/assets/timing/day22_zh.json b/flutter_app/assets/timing/day22_zh.json new file mode 100644 index 0000000..1b0f418 --- /dev/null +++ b/flutter_app/assets/timing/day22_zh.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 22, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Daily Expressions", + "start": 0.0, + "end": 1.176 + }, + { + "i": 1, + "section": "Daily Expressions", + "start": 1.176, + "end": 2.352 + }, + { + "i": 2, + "section": "Daily Expressions", + "start": 2.352, + "end": 3.816 + }, + { + "i": 3, + "section": "Daily Expressions", + "start": 3.816, + "end": 5.064 + }, + { + "i": 4, + "section": "Daily Expressions", + "start": 5.064, + "end": 6.48 + }, + { + "i": 5, + "section": "Daily Expressions", + "start": 6.48, + "end": 7.896 + }, + { + "i": 6, + "section": "Communication Strategies", + "start": 7.896, + "end": 9.408 + }, + { + "i": 7, + "section": "Communication Strategies", + "start": 9.408, + "end": 11.112 + }, + { + "i": 8, + "section": "Communication Strategies", + "start": 11.112, + "end": 13.008 + }, + { + "i": 9, + "section": "Communication Strategies", + "start": 13.008, + "end": 15.144 + }, + { + "i": 10, + "section": "Communication Strategies", + "start": 15.144, + "end": 17.04 + } + ] +} diff --git a/flutter_app/assets/timing/day23_en.json b/flutter_app/assets/timing/day23_en.json new file mode 100644 index 0000000..91b6804 --- /dev/null +++ b/flutter_app/assets/timing/day23_en.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 23, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Job Titles", + "start": 0.0, + "end": 1.656 + }, + { + "i": 1, + "section": "Job Titles", + "start": 1.656, + "end": 3.168 + }, + { + "i": 2, + "section": "Job Titles", + "start": 3.168, + "end": 4.704 + }, + { + "i": 3, + "section": "Job Titles", + "start": 4.704, + "end": 6.552 + }, + { + "i": 4, + "section": "Job Titles", + "start": 6.552, + "end": 8.232 + }, + { + "i": 5, + "section": "Job Titles", + "start": 8.232, + "end": 9.888 + }, + { + "i": 6, + "section": "Job Titles", + "start": 9.888, + "end": 12.096 + }, + { + "i": 7, + "section": "Office Items", + "start": 12.096, + "end": 13.752 + }, + { + "i": 8, + "section": "Office Items", + "start": 13.752, + "end": 15.312 + }, + { + "i": 9, + "section": "Office Items", + "start": 15.312, + "end": 17.064 + }, + { + "i": 10, + "section": "Office Items", + "start": 17.064, + "end": 18.816 + }, + { + "i": 11, + "section": "Office Items", + "start": 18.816, + "end": 20.4 + }, + { + "i": 12, + "section": "Office Items", + "start": 20.4, + "end": 22.224 + } + ] +} diff --git a/flutter_app/assets/timing/day23_zh.json b/flutter_app/assets/timing/day23_zh.json new file mode 100644 index 0000000..ef0370e --- /dev/null +++ b/flutter_app/assets/timing/day23_zh.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 23, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Job Titles", + "start": 0.0, + "end": 1.248 + }, + { + "i": 1, + "section": "Job Titles", + "start": 1.248, + "end": 2.496 + }, + { + "i": 2, + "section": "Job Titles", + "start": 2.496, + "end": 3.792 + }, + { + "i": 3, + "section": "Job Titles", + "start": 3.792, + "end": 5.064 + }, + { + "i": 4, + "section": "Job Titles", + "start": 5.064, + "end": 6.528 + }, + { + "i": 5, + "section": "Job Titles", + "start": 6.528, + "end": 7.872 + }, + { + "i": 6, + "section": "Job Titles", + "start": 7.872, + "end": 9.552 + }, + { + "i": 7, + "section": "Office Items", + "start": 9.552, + "end": 10.776 + }, + { + "i": 8, + "section": "Office Items", + "start": 10.776, + "end": 12.216 + }, + { + "i": 9, + "section": "Office Items", + "start": 12.216, + "end": 13.464 + }, + { + "i": 10, + "section": "Office Items", + "start": 13.464, + "end": 14.928 + }, + { + "i": 11, + "section": "Office Items", + "start": 14.928, + "end": 16.368 + }, + { + "i": 12, + "section": "Office Items", + "start": 16.368, + "end": 17.664 + } + ] +} diff --git a/flutter_app/assets/timing/day24_en.json b/flutter_app/assets/timing/day24_en.json new file mode 100644 index 0000000..eab0b1f --- /dev/null +++ b/flutter_app/assets/timing/day24_en.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 24, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Meeting Etiquette", + "start": 0.0, + "end": 1.704 + }, + { + "i": 1, + "section": "Meeting Etiquette", + "start": 1.704, + "end": 3.84 + }, + { + "i": 2, + "section": "Meeting Etiquette", + "start": 3.84, + "end": 5.544 + }, + { + "i": 3, + "section": "Meeting Etiquette", + "start": 5.544, + "end": 8.04 + }, + { + "i": 4, + "section": "Meeting Etiquette", + "start": 8.04, + "end": 9.72 + }, + { + "i": 5, + "section": "Business Phrases", + "start": 9.72, + "end": 11.952 + }, + { + "i": 6, + "section": "Business Phrases", + "start": 11.952, + "end": 15.408 + }, + { + "i": 7, + "section": "Business Phrases", + "start": 15.408, + "end": 17.616 + }, + { + "i": 8, + "section": "Business Phrases", + "start": 17.616, + "end": 20.4 + }, + { + "i": 9, + "section": "Business Phrases", + "start": 20.4, + "end": 22.584 + } + ] +} diff --git a/flutter_app/assets/timing/day24_zh.json b/flutter_app/assets/timing/day24_zh.json new file mode 100644 index 0000000..d2ff8b9 --- /dev/null +++ b/flutter_app/assets/timing/day24_zh.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 24, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Meeting Etiquette", + "start": 0.0, + "end": 1.32 + }, + { + "i": 1, + "section": "Meeting Etiquette", + "start": 1.32, + "end": 2.952 + }, + { + "i": 2, + "section": "Meeting Etiquette", + "start": 2.952, + "end": 4.224 + }, + { + "i": 3, + "section": "Meeting Etiquette", + "start": 4.224, + "end": 5.904 + }, + { + "i": 4, + "section": "Meeting Etiquette", + "start": 5.904, + "end": 7.128 + }, + { + "i": 5, + "section": "Business Phrases", + "start": 7.128, + "end": 8.976 + }, + { + "i": 6, + "section": "Business Phrases", + "start": 8.976, + "end": 10.584 + }, + { + "i": 7, + "section": "Business Phrases", + "start": 10.584, + "end": 12.24 + }, + { + "i": 8, + "section": "Business Phrases", + "start": 12.24, + "end": 14.688 + }, + { + "i": 9, + "section": "Business Phrases", + "start": 14.688, + "end": 16.08 + } + ] +} diff --git a/flutter_app/assets/timing/day25_en.json b/flutter_app/assets/timing/day25_en.json new file mode 100644 index 0000000..d1b0199 --- /dev/null +++ b/flutter_app/assets/timing/day25_en.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 25, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Remote Work Terms", + "start": 0.0, + "end": 1.8 + }, + { + "i": 1, + "section": "Remote Work Terms", + "start": 1.8, + "end": 3.696 + }, + { + "i": 2, + "section": "Remote Work Terms", + "start": 3.696, + "end": 6.168 + }, + { + "i": 3, + "section": "Remote Work Terms", + "start": 6.168, + "end": 8.304 + }, + { + "i": 4, + "section": "Remote Work Terms", + "start": 8.304, + "end": 10.44 + }, + { + "i": 5, + "section": "Remote Work Phrases", + "start": 10.44, + "end": 13.056 + }, + { + "i": 6, + "section": "Remote Work Phrases", + "start": 13.056, + "end": 15.168 + }, + { + "i": 7, + "section": "Remote Work Phrases", + "start": 15.168, + "end": 17.976 + }, + { + "i": 8, + "section": "Remote Work Phrases", + "start": 17.976, + "end": 19.92 + }, + { + "i": 9, + "section": "Remote Work Phrases", + "start": 19.92, + "end": 22.056 + } + ] +} diff --git a/flutter_app/assets/timing/day25_zh.json b/flutter_app/assets/timing/day25_zh.json new file mode 100644 index 0000000..42149c3 --- /dev/null +++ b/flutter_app/assets/timing/day25_zh.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 25, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Remote Work Terms", + "start": 0.0, + "end": 1.632 + }, + { + "i": 1, + "section": "Remote Work Terms", + "start": 1.632, + "end": 3.216 + }, + { + "i": 2, + "section": "Remote Work Terms", + "start": 3.216, + "end": 5.184 + }, + { + "i": 3, + "section": "Remote Work Terms", + "start": 5.184, + "end": 6.912 + }, + { + "i": 4, + "section": "Remote Work Terms", + "start": 6.912, + "end": 8.544 + }, + { + "i": 5, + "section": "Remote Work Phrases", + "start": 8.544, + "end": 10.92 + }, + { + "i": 6, + "section": "Remote Work Phrases", + "start": 10.92, + "end": 12.96 + }, + { + "i": 7, + "section": "Remote Work Phrases", + "start": 12.96, + "end": 15.144 + }, + { + "i": 8, + "section": "Remote Work Phrases", + "start": 15.144, + "end": 17.112 + }, + { + "i": 9, + "section": "Remote Work Phrases", + "start": 17.112, + "end": 19.152 + } + ] +} diff --git a/flutter_app/assets/timing/day26_en.json b/flutter_app/assets/timing/day26_en.json new file mode 100644 index 0000000..0ad42f7 --- /dev/null +++ b/flutter_app/assets/timing/day26_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 26, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Meeting Vocabulary", + "start": 0.0, + "end": 1.632 + }, + { + "i": 1, + "section": "Meeting Vocabulary", + "start": 1.632, + "end": 3.576 + }, + { + "i": 2, + "section": "Meeting Vocabulary", + "start": 3.576, + "end": 5.304 + }, + { + "i": 3, + "section": "Meeting Vocabulary", + "start": 5.304, + "end": 6.984 + }, + { + "i": 4, + "section": "Meeting Vocabulary", + "start": 6.984, + "end": 8.832 + }, + { + "i": 5, + "section": "Meeting Vocabulary", + "start": 8.832, + "end": 11.16 + }, + { + "i": 6, + "section": "Meeting Phrases", + "start": 11.16, + "end": 13.008 + }, + { + "i": 7, + "section": "Meeting Phrases", + "start": 13.008, + "end": 15.312 + }, + { + "i": 8, + "section": "Meeting Phrases", + "start": 15.312, + "end": 17.328 + }, + { + "i": 9, + "section": "Meeting Phrases", + "start": 17.328, + "end": 19.008 + }, + { + "i": 10, + "section": "Meeting Phrases", + "start": 19.008, + "end": 20.856 + }, + { + "i": 11, + "section": "Meeting Phrases", + "start": 20.856, + "end": 23.04 + } + ] +} diff --git a/flutter_app/assets/timing/day26_zh.json b/flutter_app/assets/timing/day26_zh.json new file mode 100644 index 0000000..1ea383c --- /dev/null +++ b/flutter_app/assets/timing/day26_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 26, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Meeting Vocabulary", + "start": 0.0, + "end": 1.272 + }, + { + "i": 1, + "section": "Meeting Vocabulary", + "start": 1.272, + "end": 2.856 + }, + { + "i": 2, + "section": "Meeting Vocabulary", + "start": 2.856, + "end": 4.08 + }, + { + "i": 3, + "section": "Meeting Vocabulary", + "start": 4.08, + "end": 5.304 + }, + { + "i": 4, + "section": "Meeting Vocabulary", + "start": 5.304, + "end": 6.72 + }, + { + "i": 5, + "section": "Meeting Vocabulary", + "start": 6.72, + "end": 8.136 + }, + { + "i": 6, + "section": "Meeting Phrases", + "start": 8.136, + "end": 9.792 + }, + { + "i": 7, + "section": "Meeting Phrases", + "start": 9.792, + "end": 11.496 + }, + { + "i": 8, + "section": "Meeting Phrases", + "start": 11.496, + "end": 13.224 + }, + { + "i": 9, + "section": "Meeting Phrases", + "start": 13.224, + "end": 14.64 + }, + { + "i": 10, + "section": "Meeting Phrases", + "start": 14.64, + "end": 16.176 + }, + { + "i": 11, + "section": "Meeting Phrases", + "start": 16.176, + "end": 18.576 + } + ] +} diff --git a/flutter_app/assets/timing/day27_en.json b/flutter_app/assets/timing/day27_en.json new file mode 100644 index 0000000..03be701 --- /dev/null +++ b/flutter_app/assets/timing/day27_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 27, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Email Vocabulary", + "start": 0.0, + "end": 1.536 + }, + { + "i": 1, + "section": "Email Vocabulary", + "start": 1.536, + "end": 3.312 + }, + { + "i": 2, + "section": "Email Vocabulary", + "start": 3.312, + "end": 4.92 + }, + { + "i": 3, + "section": "Email Vocabulary", + "start": 4.92, + "end": 6.648 + }, + { + "i": 4, + "section": "Email Vocabulary", + "start": 6.648, + "end": 8.448 + }, + { + "i": 5, + "section": "Email Vocabulary", + "start": 8.448, + "end": 11.112 + }, + { + "i": 6, + "section": "Email Phrases", + "start": 11.112, + "end": 13.416 + }, + { + "i": 7, + "section": "Email Phrases", + "start": 13.416, + "end": 15.624 + }, + { + "i": 8, + "section": "Email Phrases", + "start": 15.624, + "end": 18.0 + }, + { + "i": 9, + "section": "Email Phrases", + "start": 18.0, + "end": 20.616 + }, + { + "i": 10, + "section": "Email Phrases", + "start": 20.616, + "end": 22.512 + }, + { + "i": 11, + "section": "Email Phrases", + "start": 22.512, + "end": 24.216 + } + ] +} diff --git a/flutter_app/assets/timing/day27_zh.json b/flutter_app/assets/timing/day27_zh.json new file mode 100644 index 0000000..1adedc3 --- /dev/null +++ b/flutter_app/assets/timing/day27_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 27, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Email Vocabulary", + "start": 0.0, + "end": 1.584 + }, + { + "i": 1, + "section": "Email Vocabulary", + "start": 1.584, + "end": 3.072 + }, + { + "i": 2, + "section": "Email Vocabulary", + "start": 3.072, + "end": 4.512 + }, + { + "i": 3, + "section": "Email Vocabulary", + "start": 4.512, + "end": 5.784 + }, + { + "i": 4, + "section": "Email Vocabulary", + "start": 5.784, + "end": 7.08 + }, + { + "i": 5, + "section": "Email Vocabulary", + "start": 7.08, + "end": 8.328 + }, + { + "i": 6, + "section": "Email Phrases", + "start": 8.328, + "end": 10.392 + }, + { + "i": 7, + "section": "Email Phrases", + "start": 10.392, + "end": 12.24 + }, + { + "i": 8, + "section": "Email Phrases", + "start": 12.24, + "end": 14.04 + }, + { + "i": 9, + "section": "Email Phrases", + "start": 14.04, + "end": 15.936 + }, + { + "i": 10, + "section": "Email Phrases", + "start": 15.936, + "end": 17.232 + }, + { + "i": 11, + "section": "Email Phrases", + "start": 17.232, + "end": 18.48 + } + ] +} diff --git a/flutter_app/assets/timing/day28_en.json b/flutter_app/assets/timing/day28_en.json new file mode 100644 index 0000000..f010d88 --- /dev/null +++ b/flutter_app/assets/timing/day28_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 28, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Presentation Vocabulary", + "start": 0.0, + "end": 2.592 + }, + { + "i": 1, + "section": "Presentation Vocabulary", + "start": 2.592, + "end": 4.344 + }, + { + "i": 2, + "section": "Presentation Vocabulary", + "start": 4.344, + "end": 5.832 + }, + { + "i": 3, + "section": "Presentation Vocabulary", + "start": 5.832, + "end": 7.296 + }, + { + "i": 4, + "section": "Presentation Vocabulary", + "start": 7.296, + "end": 9.072 + }, + { + "i": 5, + "section": "Presentation Vocabulary", + "start": 9.072, + "end": 11.112 + }, + { + "i": 6, + "section": "Presentation Phrases", + "start": 11.112, + "end": 13.464 + }, + { + "i": 7, + "section": "Presentation Phrases", + "start": 13.464, + "end": 15.168 + }, + { + "i": 8, + "section": "Presentation Phrases", + "start": 15.168, + "end": 16.92 + }, + { + "i": 9, + "section": "Presentation Phrases", + "start": 16.92, + "end": 18.624 + }, + { + "i": 10, + "section": "Presentation Phrases", + "start": 18.624, + "end": 20.544 + }, + { + "i": 11, + "section": "Presentation Phrases", + "start": 20.544, + "end": 22.848 + } + ] +} diff --git a/flutter_app/assets/timing/day28_zh.json b/flutter_app/assets/timing/day28_zh.json new file mode 100644 index 0000000..74c7215 --- /dev/null +++ b/flutter_app/assets/timing/day28_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 28, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Presentation Vocabulary", + "start": 0.0, + "end": 1.32 + }, + { + "i": 1, + "section": "Presentation Vocabulary", + "start": 1.32, + "end": 2.808 + }, + { + "i": 2, + "section": "Presentation Vocabulary", + "start": 2.808, + "end": 4.104 + }, + { + "i": 3, + "section": "Presentation Vocabulary", + "start": 4.104, + "end": 5.424 + }, + { + "i": 4, + "section": "Presentation Vocabulary", + "start": 5.424, + "end": 6.672 + }, + { + "i": 5, + "section": "Presentation Vocabulary", + "start": 6.672, + "end": 8.328 + }, + { + "i": 6, + "section": "Presentation Phrases", + "start": 8.328, + "end": 10.44 + }, + { + "i": 7, + "section": "Presentation Phrases", + "start": 10.44, + "end": 11.784 + }, + { + "i": 8, + "section": "Presentation Phrases", + "start": 11.784, + "end": 13.08 + }, + { + "i": 9, + "section": "Presentation Phrases", + "start": 13.08, + "end": 14.352 + }, + { + "i": 10, + "section": "Presentation Phrases", + "start": 14.352, + "end": 15.888 + }, + { + "i": 11, + "section": "Presentation Phrases", + "start": 15.888, + "end": 17.592 + } + ] +} diff --git a/flutter_app/assets/timing/day29_en.json b/flutter_app/assets/timing/day29_en.json new file mode 100644 index 0000000..c60a665 --- /dev/null +++ b/flutter_app/assets/timing/day29_en.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 29, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Technical Vocabulary", + "start": 0.0, + "end": 1.704 + }, + { + "i": 1, + "section": "Technical Vocabulary", + "start": 1.704, + "end": 3.336 + }, + { + "i": 2, + "section": "Technical Vocabulary", + "start": 3.336, + "end": 4.968 + }, + { + "i": 3, + "section": "Technical Vocabulary", + "start": 4.968, + "end": 6.72 + }, + { + "i": 4, + "section": "Technical Vocabulary", + "start": 6.72, + "end": 8.376 + }, + { + "i": 5, + "section": "Technical Vocabulary", + "start": 8.376, + "end": 10.368 + }, + { + "i": 6, + "section": "Technical Vocabulary", + "start": 10.368, + "end": 12.84 + }, + { + "i": 7, + "section": "Technical Phrases", + "start": 12.84, + "end": 15.0 + }, + { + "i": 8, + "section": "Technical Phrases", + "start": 15.0, + "end": 16.944 + }, + { + "i": 9, + "section": "Technical Phrases", + "start": 16.944, + "end": 18.744 + }, + { + "i": 10, + "section": "Technical Phrases", + "start": 18.744, + "end": 20.952 + }, + { + "i": 11, + "section": "Technical Phrases", + "start": 20.952, + "end": 22.992 + }, + { + "i": 12, + "section": "Technical Phrases", + "start": 22.992, + "end": 24.96 + } + ] +} diff --git a/flutter_app/assets/timing/day29_zh.json b/flutter_app/assets/timing/day29_zh.json new file mode 100644 index 0000000..86561ed --- /dev/null +++ b/flutter_app/assets/timing/day29_zh.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 29, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Technical Vocabulary", + "start": 0.0, + "end": 1.296 + }, + { + "i": 1, + "section": "Technical Vocabulary", + "start": 1.296, + "end": 2.544 + }, + { + "i": 2, + "section": "Technical Vocabulary", + "start": 2.544, + "end": 3.864 + }, + { + "i": 3, + "section": "Technical Vocabulary", + "start": 3.864, + "end": 5.328 + }, + { + "i": 4, + "section": "Technical Vocabulary", + "start": 5.328, + "end": 6.552 + }, + { + "i": 5, + "section": "Technical Vocabulary", + "start": 6.552, + "end": 7.992 + }, + { + "i": 6, + "section": "Technical Vocabulary", + "start": 7.992, + "end": 9.6 + }, + { + "i": 7, + "section": "Technical Phrases", + "start": 9.6, + "end": 11.4 + }, + { + "i": 8, + "section": "Technical Phrases", + "start": 11.4, + "end": 13.008 + }, + { + "i": 9, + "section": "Technical Phrases", + "start": 13.008, + "end": 14.664 + }, + { + "i": 10, + "section": "Technical Phrases", + "start": 14.664, + "end": 16.248 + }, + { + "i": 11, + "section": "Technical Phrases", + "start": 16.248, + "end": 17.88 + }, + { + "i": 12, + "section": "Technical Phrases", + "start": 17.88, + "end": 19.608 + } + ] +} diff --git a/flutter_app/assets/timing/day2_en.json b/flutter_app/assets/timing/day2_en.json new file mode 100644 index 0000000..130482d --- /dev/null +++ b/flutter_app/assets/timing/day2_en.json @@ -0,0 +1,97 @@ +{ + "version": 1, + "day": 2, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Numbers 0-10", + "start": 0.0, + "end": 1.584 + }, + { + "i": 1, + "section": "Numbers 0-10", + "start": 1.584, + "end": 3.024 + }, + { + "i": 2, + "section": "Numbers 0-10", + "start": 3.024, + "end": 4.464 + }, + { + "i": 3, + "section": "Numbers 0-10", + "start": 4.464, + "end": 5.856 + }, + { + "i": 4, + "section": "Numbers 0-10", + "start": 5.856, + "end": 7.392 + }, + { + "i": 5, + "section": "Numbers 0-10", + "start": 7.392, + "end": 8.952 + }, + { + "i": 6, + "section": "Numbers 0-10", + "start": 8.952, + "end": 10.56 + }, + { + "i": 7, + "section": "Numbers 0-10", + "start": 10.56, + "end": 12.144 + }, + { + "i": 8, + "section": "Numbers 0-10", + "start": 12.144, + "end": 13.56 + }, + { + "i": 9, + "section": "Numbers 0-10", + "start": 13.56, + "end": 15.048 + }, + { + "i": 10, + "section": "Numbers 0-10", + "start": 15.048, + "end": 16.488 + }, + { + "i": 11, + "section": "Basic Counting Phrases", + "start": 16.488, + "end": 18.744 + }, + { + "i": 12, + "section": "Basic Counting Phrases", + "start": 18.744, + "end": 20.448 + }, + { + "i": 13, + "section": "Basic Counting Phrases", + "start": 20.448, + "end": 21.984 + }, + { + "i": 14, + "section": "Basic Counting Phrases", + "start": 21.984, + "end": 23.616 + } + ] +} diff --git a/flutter_app/assets/timing/day2_zh.json b/flutter_app/assets/timing/day2_zh.json new file mode 100644 index 0000000..3b8dcb0 --- /dev/null +++ b/flutter_app/assets/timing/day2_zh.json @@ -0,0 +1,97 @@ +{ + "version": 1, + "day": 2, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Numbers 0-10", + "start": 0.0, + "end": 1.032 + }, + { + "i": 1, + "section": "Numbers 0-10", + "start": 1.032, + "end": 2.064 + }, + { + "i": 2, + "section": "Numbers 0-10", + "start": 2.064, + "end": 3.144 + }, + { + "i": 3, + "section": "Numbers 0-10", + "start": 3.144, + "end": 4.272 + }, + { + "i": 4, + "section": "Numbers 0-10", + "start": 4.272, + "end": 5.4 + }, + { + "i": 5, + "section": "Numbers 0-10", + "start": 5.4, + "end": 6.432 + }, + { + "i": 6, + "section": "Numbers 0-10", + "start": 6.432, + "end": 7.512 + }, + { + "i": 7, + "section": "Numbers 0-10", + "start": 7.512, + "end": 8.616 + }, + { + "i": 8, + "section": "Numbers 0-10", + "start": 8.616, + "end": 9.672 + }, + { + "i": 9, + "section": "Numbers 0-10", + "start": 9.672, + "end": 10.728 + }, + { + "i": 10, + "section": "Numbers 0-10", + "start": 10.728, + "end": 11.88 + }, + { + "i": 11, + "section": "Basic Counting Phrases", + "start": 11.88, + "end": 13.128 + }, + { + "i": 12, + "section": "Basic Counting Phrases", + "start": 13.128, + "end": 14.352 + }, + { + "i": 13, + "section": "Basic Counting Phrases", + "start": 14.352, + "end": 15.552 + }, + { + "i": 14, + "section": "Basic Counting Phrases", + "start": 15.552, + "end": 16.8 + } + ] +} diff --git a/flutter_app/assets/timing/day30_en.json b/flutter_app/assets/timing/day30_en.json new file mode 100644 index 0000000..0e4d028 --- /dev/null +++ b/flutter_app/assets/timing/day30_en.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 30, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Negotiation Terms", + "start": 0.0, + "end": 1.992 + }, + { + "i": 1, + "section": "Negotiation Terms", + "start": 1.992, + "end": 3.72 + }, + { + "i": 2, + "section": "Negotiation Terms", + "start": 3.72, + "end": 5.232 + }, + { + "i": 3, + "section": "Negotiation Terms", + "start": 5.232, + "end": 6.936 + }, + { + "i": 4, + "section": "Negotiation Terms", + "start": 6.936, + "end": 8.544 + }, + { + "i": 5, + "section": "Negotiation Terms", + "start": 8.544, + "end": 10.248 + }, + { + "i": 6, + "section": "Negotiation Terms", + "start": 10.248, + "end": 11.832 + }, + { + "i": 7, + "section": "Negotiation Phrases", + "start": 11.832, + "end": 14.16 + }, + { + "i": 8, + "section": "Negotiation Phrases", + "start": 14.16, + "end": 16.728 + }, + { + "i": 9, + "section": "Negotiation Phrases", + "start": 16.728, + "end": 19.2 + }, + { + "i": 10, + "section": "Negotiation Phrases", + "start": 19.2, + "end": 21.528 + }, + { + "i": 11, + "section": "Negotiation Phrases", + "start": 21.528, + "end": 23.136 + }, + { + "i": 12, + "section": "Negotiation Phrases", + "start": 23.136, + "end": 25.296 + } + ] +} diff --git a/flutter_app/assets/timing/day30_zh.json b/flutter_app/assets/timing/day30_zh.json new file mode 100644 index 0000000..6fe86bf --- /dev/null +++ b/flutter_app/assets/timing/day30_zh.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "day": 30, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Negotiation Terms", + "start": 0.0, + "end": 1.272 + }, + { + "i": 1, + "section": "Negotiation Terms", + "start": 1.272, + "end": 2.568 + }, + { + "i": 2, + "section": "Negotiation Terms", + "start": 2.568, + "end": 3.864 + }, + { + "i": 3, + "section": "Negotiation Terms", + "start": 3.864, + "end": 5.184 + }, + { + "i": 4, + "section": "Negotiation Terms", + "start": 5.184, + "end": 6.48 + }, + { + "i": 5, + "section": "Negotiation Terms", + "start": 6.48, + "end": 7.776 + }, + { + "i": 6, + "section": "Negotiation Terms", + "start": 7.776, + "end": 9.432 + }, + { + "i": 7, + "section": "Negotiation Phrases", + "start": 9.432, + "end": 12.12 + }, + { + "i": 8, + "section": "Negotiation Phrases", + "start": 12.12, + "end": 14.712 + }, + { + "i": 9, + "section": "Negotiation Phrases", + "start": 14.712, + "end": 16.824 + }, + { + "i": 10, + "section": "Negotiation Phrases", + "start": 16.824, + "end": 19.152 + }, + { + "i": 11, + "section": "Negotiation Phrases", + "start": 19.152, + "end": 20.496 + }, + { + "i": 12, + "section": "Negotiation Phrases", + "start": 20.496, + "end": 22.152 + } + ] +} diff --git a/flutter_app/assets/timing/day31_en.json b/flutter_app/assets/timing/day31_en.json new file mode 100644 index 0000000..7d99c06 --- /dev/null +++ b/flutter_app/assets/timing/day31_en.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 31, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Common Idioms", + "start": 0.0, + "end": 2.712 + }, + { + "i": 1, + "section": "Common Idioms", + "start": 2.712, + "end": 5.808 + }, + { + "i": 2, + "section": "Common Idioms", + "start": 5.808, + "end": 9.096 + }, + { + "i": 3, + "section": "Common Idioms", + "start": 9.096, + "end": 13.872 + }, + { + "i": 4, + "section": "Common Idioms", + "start": 13.872, + "end": 18.216 + }, + { + "i": 5, + "section": "Common Idioms", + "start": 18.216, + "end": 20.616 + }, + { + "i": 6, + "section": "Using Idioms", + "start": 20.616, + "end": 24.024 + }, + { + "i": 7, + "section": "Using Idioms", + "start": 24.024, + "end": 26.712 + }, + { + "i": 8, + "section": "Using Idioms", + "start": 26.712, + "end": 29.52 + }, + { + "i": 9, + "section": "Using Idioms", + "start": 29.52, + "end": 32.76 + } + ] +} diff --git a/flutter_app/assets/timing/day31_zh.json b/flutter_app/assets/timing/day31_zh.json new file mode 100644 index 0000000..abf9c85 --- /dev/null +++ b/flutter_app/assets/timing/day31_zh.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 31, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Common Idioms", + "start": 0.0, + "end": 1.656 + }, + { + "i": 1, + "section": "Common Idioms", + "start": 1.656, + "end": 3.432 + }, + { + "i": 2, + "section": "Common Idioms", + "start": 3.432, + "end": 5.136 + }, + { + "i": 3, + "section": "Common Idioms", + "start": 5.136, + "end": 6.912 + }, + { + "i": 4, + "section": "Common Idioms", + "start": 6.912, + "end": 8.616 + }, + { + "i": 5, + "section": "Common Idioms", + "start": 8.616, + "end": 10.272 + }, + { + "i": 6, + "section": "Using Idioms", + "start": 10.272, + "end": 12.624 + }, + { + "i": 7, + "section": "Using Idioms", + "start": 12.624, + "end": 14.88 + }, + { + "i": 8, + "section": "Using Idioms", + "start": 14.88, + "end": 16.752 + }, + { + "i": 9, + "section": "Using Idioms", + "start": 16.752, + "end": 18.816 + } + ] +} diff --git a/flutter_app/assets/timing/day32_en.json b/flutter_app/assets/timing/day32_en.json new file mode 100644 index 0000000..9a62c85 --- /dev/null +++ b/flutter_app/assets/timing/day32_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 32, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Internet Slang", + "start": 0.0, + "end": 3.168 + }, + { + "i": 1, + "section": "Internet Slang", + "start": 3.168, + "end": 5.28 + }, + { + "i": 2, + "section": "Internet Slang", + "start": 5.28, + "end": 7.176 + }, + { + "i": 3, + "section": "Internet Slang", + "start": 7.176, + "end": 9.96 + }, + { + "i": 4, + "section": "Internet Slang", + "start": 9.96, + "end": 12.84 + }, + { + "i": 5, + "section": "Internet Slang", + "start": 12.84, + "end": 17.28 + }, + { + "i": 6, + "section": "Youth Expressions", + "start": 17.28, + "end": 19.656 + }, + { + "i": 7, + "section": "Youth Expressions", + "start": 19.656, + "end": 22.2 + }, + { + "i": 8, + "section": "Youth Expressions", + "start": 22.2, + "end": 24.576 + }, + { + "i": 9, + "section": "Youth Expressions", + "start": 24.576, + "end": 27.096 + }, + { + "i": 10, + "section": "Youth Expressions", + "start": 27.096, + "end": 30.384 + }, + { + "i": 11, + "section": "Youth Expressions", + "start": 30.384, + "end": 32.928 + } + ] +} diff --git a/flutter_app/assets/timing/day32_zh.json b/flutter_app/assets/timing/day32_zh.json new file mode 100644 index 0000000..cb46067 --- /dev/null +++ b/flutter_app/assets/timing/day32_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 32, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Internet Slang", + "start": 0.0, + "end": 1.704 + }, + { + "i": 1, + "section": "Internet Slang", + "start": 1.704, + "end": 3.048 + }, + { + "i": 2, + "section": "Internet Slang", + "start": 3.048, + "end": 4.44 + }, + { + "i": 3, + "section": "Internet Slang", + "start": 4.44, + "end": 5.736 + }, + { + "i": 4, + "section": "Internet Slang", + "start": 5.736, + "end": 7.032 + }, + { + "i": 5, + "section": "Internet Slang", + "start": 7.032, + "end": 8.688 + }, + { + "i": 6, + "section": "Youth Expressions", + "start": 8.688, + "end": 9.984 + }, + { + "i": 7, + "section": "Youth Expressions", + "start": 9.984, + "end": 11.256 + }, + { + "i": 8, + "section": "Youth Expressions", + "start": 11.256, + "end": 12.504 + }, + { + "i": 9, + "section": "Youth Expressions", + "start": 12.504, + "end": 14.112 + }, + { + "i": 10, + "section": "Youth Expressions", + "start": 14.112, + "end": 15.48 + }, + { + "i": 11, + "section": "Youth Expressions", + "start": 15.48, + "end": 16.896 + } + ] +} diff --git a/flutter_app/assets/timing/day33_en.json b/flutter_app/assets/timing/day33_en.json new file mode 100644 index 0000000..905d64e --- /dev/null +++ b/flutter_app/assets/timing/day33_en.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 33, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Formal Greetings", + "start": 0.0, + "end": 2.4 + }, + { + "i": 1, + "section": "Formal Greetings", + "start": 2.4, + "end": 5.088 + }, + { + "i": 2, + "section": "Formal Greetings", + "start": 5.088, + "end": 7.944 + }, + { + "i": 3, + "section": "Formal Greetings", + "start": 7.944, + "end": 10.632 + }, + { + "i": 4, + "section": "Formal Greetings", + "start": 10.632, + "end": 12.84 + }, + { + "i": 5, + "section": "Formal Phrases", + "start": 12.84, + "end": 15.216 + }, + { + "i": 6, + "section": "Formal Phrases", + "start": 15.216, + "end": 17.592 + }, + { + "i": 7, + "section": "Formal Phrases", + "start": 17.592, + "end": 20.352 + }, + { + "i": 8, + "section": "Formal Phrases", + "start": 20.352, + "end": 23.04 + }, + { + "i": 9, + "section": "Formal Phrases", + "start": 23.04, + "end": 25.824 + }, + { + "i": 10, + "section": "Formal Phrases", + "start": 25.824, + "end": 28.056 + } + ] +} diff --git a/flutter_app/assets/timing/day33_zh.json b/flutter_app/assets/timing/day33_zh.json new file mode 100644 index 0000000..8155b87 --- /dev/null +++ b/flutter_app/assets/timing/day33_zh.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 33, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Formal Greetings", + "start": 0.0, + "end": 1.368 + }, + { + "i": 1, + "section": "Formal Greetings", + "start": 1.368, + "end": 3.072 + }, + { + "i": 2, + "section": "Formal Greetings", + "start": 3.072, + "end": 4.728 + }, + { + "i": 3, + "section": "Formal Greetings", + "start": 4.728, + "end": 6.384 + }, + { + "i": 4, + "section": "Formal Greetings", + "start": 6.384, + "end": 8.064 + }, + { + "i": 5, + "section": "Formal Phrases", + "start": 8.064, + "end": 9.312 + }, + { + "i": 6, + "section": "Formal Phrases", + "start": 9.312, + "end": 10.488 + }, + { + "i": 7, + "section": "Formal Phrases", + "start": 10.488, + "end": 11.928 + }, + { + "i": 8, + "section": "Formal Phrases", + "start": 11.928, + "end": 13.344 + }, + { + "i": 9, + "section": "Formal Phrases", + "start": 13.344, + "end": 14.928 + }, + { + "i": 10, + "section": "Formal Phrases", + "start": 14.928, + "end": 16.584 + } + ] +} diff --git a/flutter_app/assets/timing/day34_en.json b/flutter_app/assets/timing/day34_en.json new file mode 100644 index 0000000..a0d46e4 --- /dev/null +++ b/flutter_app/assets/timing/day34_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 34, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Discussion Terms", + "start": 0.0, + "end": 1.728 + }, + { + "i": 1, + "section": "Discussion Terms", + "start": 1.728, + "end": 4.056 + }, + { + "i": 2, + "section": "Discussion Terms", + "start": 4.056, + "end": 5.736 + }, + { + "i": 3, + "section": "Discussion Terms", + "start": 5.736, + "end": 8.016 + }, + { + "i": 4, + "section": "Discussion Terms", + "start": 8.016, + "end": 9.552 + }, + { + "i": 5, + "section": "Discussion Terms", + "start": 9.552, + "end": 11.88 + }, + { + "i": 6, + "section": "Discussion Phrases", + "start": 11.88, + "end": 14.136 + }, + { + "i": 7, + "section": "Discussion Phrases", + "start": 14.136, + "end": 16.584 + }, + { + "i": 8, + "section": "Discussion Phrases", + "start": 16.584, + "end": 18.84 + }, + { + "i": 9, + "section": "Discussion Phrases", + "start": 18.84, + "end": 21.528 + }, + { + "i": 10, + "section": "Discussion Phrases", + "start": 21.528, + "end": 24.312 + }, + { + "i": 11, + "section": "Discussion Phrases", + "start": 24.312, + "end": 26.232 + } + ] +} diff --git a/flutter_app/assets/timing/day34_zh.json b/flutter_app/assets/timing/day34_zh.json new file mode 100644 index 0000000..c72f96a --- /dev/null +++ b/flutter_app/assets/timing/day34_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 34, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Discussion Terms", + "start": 0.0, + "end": 1.296 + }, + { + "i": 1, + "section": "Discussion Terms", + "start": 1.296, + "end": 2.592 + }, + { + "i": 2, + "section": "Discussion Terms", + "start": 2.592, + "end": 3.84 + }, + { + "i": 3, + "section": "Discussion Terms", + "start": 3.84, + "end": 5.112 + }, + { + "i": 4, + "section": "Discussion Terms", + "start": 5.112, + "end": 6.336 + }, + { + "i": 5, + "section": "Discussion Terms", + "start": 6.336, + "end": 7.584 + }, + { + "i": 6, + "section": "Discussion Phrases", + "start": 7.584, + "end": 8.976 + }, + { + "i": 7, + "section": "Discussion Phrases", + "start": 8.976, + "end": 10.8 + }, + { + "i": 8, + "section": "Discussion Phrases", + "start": 10.8, + "end": 12.888 + }, + { + "i": 9, + "section": "Discussion Phrases", + "start": 12.888, + "end": 14.856 + }, + { + "i": 10, + "section": "Discussion Phrases", + "start": 14.856, + "end": 17.16 + }, + { + "i": 11, + "section": "Discussion Phrases", + "start": 17.16, + "end": 18.696 + } + ] +} diff --git a/flutter_app/assets/timing/day35_en.json b/flutter_app/assets/timing/day35_en.json new file mode 100644 index 0000000..69159d6 --- /dev/null +++ b/flutter_app/assets/timing/day35_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 35, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Narrative Elements", + "start": 0.0, + "end": 1.632 + }, + { + "i": 1, + "section": "Narrative Elements", + "start": 1.632, + "end": 3.312 + }, + { + "i": 2, + "section": "Narrative Elements", + "start": 3.312, + "end": 4.824 + }, + { + "i": 3, + "section": "Narrative Elements", + "start": 4.824, + "end": 7.128 + }, + { + "i": 4, + "section": "Narrative Elements", + "start": 7.128, + "end": 8.52 + }, + { + "i": 5, + "section": "Narrative Elements", + "start": 8.52, + "end": 10.008 + }, + { + "i": 6, + "section": "Storytelling Phrases", + "start": 10.008, + "end": 12.552 + }, + { + "i": 7, + "section": "Storytelling Phrases", + "start": 12.552, + "end": 14.208 + }, + { + "i": 8, + "section": "Storytelling Phrases", + "start": 14.208, + "end": 15.912 + }, + { + "i": 9, + "section": "Storytelling Phrases", + "start": 15.912, + "end": 18.024 + }, + { + "i": 10, + "section": "Storytelling Phrases", + "start": 18.024, + "end": 20.544 + }, + { + "i": 11, + "section": "Storytelling Phrases", + "start": 20.544, + "end": 22.968 + } + ] +} diff --git a/flutter_app/assets/timing/day35_zh.json b/flutter_app/assets/timing/day35_zh.json new file mode 100644 index 0000000..f999477 --- /dev/null +++ b/flutter_app/assets/timing/day35_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 35, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Narrative Elements", + "start": 0.0, + "end": 1.248 + }, + { + "i": 1, + "section": "Narrative Elements", + "start": 1.248, + "end": 2.496 + }, + { + "i": 2, + "section": "Narrative Elements", + "start": 2.496, + "end": 3.792 + }, + { + "i": 3, + "section": "Narrative Elements", + "start": 3.792, + "end": 5.088 + }, + { + "i": 4, + "section": "Narrative Elements", + "start": 5.088, + "end": 6.36 + }, + { + "i": 5, + "section": "Narrative Elements", + "start": 6.36, + "end": 7.656 + }, + { + "i": 6, + "section": "Storytelling Phrases", + "start": 7.656, + "end": 9.288 + }, + { + "i": 7, + "section": "Storytelling Phrases", + "start": 9.288, + "end": 10.656 + }, + { + "i": 8, + "section": "Storytelling Phrases", + "start": 10.656, + "end": 11.904 + }, + { + "i": 9, + "section": "Storytelling Phrases", + "start": 11.904, + "end": 13.248 + }, + { + "i": 10, + "section": "Storytelling Phrases", + "start": 13.248, + "end": 14.52 + }, + { + "i": 11, + "section": "Storytelling Phrases", + "start": 14.52, + "end": 16.416 + } + ] +} diff --git a/flutter_app/assets/timing/day36_en.json b/flutter_app/assets/timing/day36_en.json new file mode 100644 index 0000000..f3bd5cf --- /dev/null +++ b/flutter_app/assets/timing/day36_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 36, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Persuasion Techniques", + "start": 0.0, + "end": 1.632 + }, + { + "i": 1, + "section": "Persuasion Techniques", + "start": 1.632, + "end": 3.432 + }, + { + "i": 2, + "section": "Persuasion Techniques", + "start": 3.432, + "end": 5.088 + }, + { + "i": 3, + "section": "Persuasion Techniques", + "start": 5.088, + "end": 6.936 + }, + { + "i": 4, + "section": "Persuasion Techniques", + "start": 6.936, + "end": 8.712 + }, + { + "i": 5, + "section": "Persuasion Techniques", + "start": 8.712, + "end": 10.416 + }, + { + "i": 6, + "section": "Persuasive Phrases", + "start": 10.416, + "end": 12.816 + }, + { + "i": 7, + "section": "Persuasive Phrases", + "start": 12.816, + "end": 14.76 + }, + { + "i": 8, + "section": "Persuasive Phrases", + "start": 14.76, + "end": 16.68 + }, + { + "i": 9, + "section": "Persuasive Phrases", + "start": 16.68, + "end": 18.768 + }, + { + "i": 10, + "section": "Persuasive Phrases", + "start": 18.768, + "end": 20.976 + }, + { + "i": 11, + "section": "Persuasive Phrases", + "start": 20.976, + "end": 23.04 + } + ] +} diff --git a/flutter_app/assets/timing/day36_zh.json b/flutter_app/assets/timing/day36_zh.json new file mode 100644 index 0000000..b22274b --- /dev/null +++ b/flutter_app/assets/timing/day36_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 36, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Persuasion Techniques", + "start": 0.0, + "end": 1.368 + }, + { + "i": 1, + "section": "Persuasion Techniques", + "start": 1.368, + "end": 2.664 + }, + { + "i": 2, + "section": "Persuasion Techniques", + "start": 2.664, + "end": 3.984 + }, + { + "i": 3, + "section": "Persuasion Techniques", + "start": 3.984, + "end": 5.28 + }, + { + "i": 4, + "section": "Persuasion Techniques", + "start": 5.28, + "end": 6.504 + }, + { + "i": 5, + "section": "Persuasion Techniques", + "start": 6.504, + "end": 7.824 + }, + { + "i": 6, + "section": "Persuasive Phrases", + "start": 7.824, + "end": 9.6 + }, + { + "i": 7, + "section": "Persuasive Phrases", + "start": 9.6, + "end": 11.136 + }, + { + "i": 8, + "section": "Persuasive Phrases", + "start": 11.136, + "end": 12.816 + }, + { + "i": 9, + "section": "Persuasive Phrases", + "start": 12.816, + "end": 14.52 + }, + { + "i": 10, + "section": "Persuasive Phrases", + "start": 14.52, + "end": 16.2 + }, + { + "i": 11, + "section": "Persuasive Phrases", + "start": 16.2, + "end": 17.928 + } + ] +} diff --git a/flutter_app/assets/timing/day37_en.json b/flutter_app/assets/timing/day37_en.json new file mode 100644 index 0000000..87ee812 --- /dev/null +++ b/flutter_app/assets/timing/day37_en.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 37, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Restaurant Dialogue 1", + "start": 0.0, + "end": 3.096 + }, + { + "i": 1, + "section": "Restaurant Dialogue 1", + "start": 3.096, + "end": 6.24 + }, + { + "i": 2, + "section": "Restaurant Dialogue 1", + "start": 6.24, + "end": 8.784 + }, + { + "i": 3, + "section": "Restaurant Dialogue 1", + "start": 8.784, + "end": 11.448 + }, + { + "i": 4, + "section": "Restaurant Dialogue 1", + "start": 11.448, + "end": 15.144 + }, + { + "i": 5, + "section": "Restaurant Dialogue 2", + "start": 15.144, + "end": 17.808 + }, + { + "i": 6, + "section": "Restaurant Dialogue 2", + "start": 17.808, + "end": 20.64 + }, + { + "i": 7, + "section": "Restaurant Dialogue 2", + "start": 20.64, + "end": 24.96 + }, + { + "i": 8, + "section": "Restaurant Dialogue 2", + "start": 24.96, + "end": 28.104 + }, + { + "i": 9, + "section": "Restaurant Dialogue 2", + "start": 28.104, + "end": 31.68 + } + ] +} diff --git a/flutter_app/assets/timing/day37_zh.json b/flutter_app/assets/timing/day37_zh.json new file mode 100644 index 0000000..61625cf --- /dev/null +++ b/flutter_app/assets/timing/day37_zh.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 37, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Restaurant Dialogue 1", + "start": 0.0, + "end": 2.688 + }, + { + "i": 1, + "section": "Restaurant Dialogue 1", + "start": 2.688, + "end": 5.328 + }, + { + "i": 2, + "section": "Restaurant Dialogue 1", + "start": 5.328, + "end": 7.632 + }, + { + "i": 3, + "section": "Restaurant Dialogue 1", + "start": 7.632, + "end": 9.864 + }, + { + "i": 4, + "section": "Restaurant Dialogue 1", + "start": 9.864, + "end": 12.744 + }, + { + "i": 5, + "section": "Restaurant Dialogue 2", + "start": 12.744, + "end": 15.024 + }, + { + "i": 6, + "section": "Restaurant Dialogue 2", + "start": 15.024, + "end": 17.52 + }, + { + "i": 7, + "section": "Restaurant Dialogue 2", + "start": 17.52, + "end": 21.456 + }, + { + "i": 8, + "section": "Restaurant Dialogue 2", + "start": 21.456, + "end": 24.576 + }, + { + "i": 9, + "section": "Restaurant Dialogue 2", + "start": 24.576, + "end": 27.696 + } + ] +} diff --git a/flutter_app/assets/timing/day38_en.json b/flutter_app/assets/timing/day38_en.json new file mode 100644 index 0000000..9948ae4 --- /dev/null +++ b/flutter_app/assets/timing/day38_en.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 38, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Shopping Dialogue 1", + "start": 0.0, + "end": 3.312 + }, + { + "i": 1, + "section": "Shopping Dialogue 1", + "start": 3.312, + "end": 6.0 + }, + { + "i": 2, + "section": "Shopping Dialogue 1", + "start": 6.0, + "end": 10.92 + }, + { + "i": 3, + "section": "Shopping Dialogue 1", + "start": 10.92, + "end": 15.168 + }, + { + "i": 4, + "section": "Shopping Dialogue 1", + "start": 15.168, + "end": 18.288 + }, + { + "i": 5, + "section": "Shopping Dialogue 2", + "start": 18.288, + "end": 21.984 + }, + { + "i": 6, + "section": "Shopping Dialogue 2", + "start": 21.984, + "end": 25.128 + }, + { + "i": 7, + "section": "Shopping Dialogue 2", + "start": 25.128, + "end": 28.584 + }, + { + "i": 8, + "section": "Shopping Dialogue 2", + "start": 28.584, + "end": 33.528 + }, + { + "i": 9, + "section": "Shopping Dialogue 2", + "start": 33.528, + "end": 36.696 + } + ] +} diff --git a/flutter_app/assets/timing/day38_zh.json b/flutter_app/assets/timing/day38_zh.json new file mode 100644 index 0000000..be11211 --- /dev/null +++ b/flutter_app/assets/timing/day38_zh.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 38, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Shopping Dialogue 1", + "start": 0.0, + "end": 2.808 + }, + { + "i": 1, + "section": "Shopping Dialogue 1", + "start": 2.808, + "end": 4.992 + }, + { + "i": 2, + "section": "Shopping Dialogue 1", + "start": 4.992, + "end": 8.304 + }, + { + "i": 3, + "section": "Shopping Dialogue 1", + "start": 8.304, + "end": 11.808 + }, + { + "i": 4, + "section": "Shopping Dialogue 1", + "start": 11.808, + "end": 14.448 + }, + { + "i": 5, + "section": "Shopping Dialogue 2", + "start": 14.448, + "end": 17.64 + }, + { + "i": 6, + "section": "Shopping Dialogue 2", + "start": 17.64, + "end": 20.472 + }, + { + "i": 7, + "section": "Shopping Dialogue 2", + "start": 20.472, + "end": 23.808 + }, + { + "i": 8, + "section": "Shopping Dialogue 2", + "start": 23.808, + "end": 28.56 + }, + { + "i": 9, + "section": "Shopping Dialogue 2", + "start": 28.56, + "end": 31.512 + } + ] +} diff --git a/flutter_app/assets/timing/day39_en.json b/flutter_app/assets/timing/day39_en.json new file mode 100644 index 0000000..3efcb0c --- /dev/null +++ b/flutter_app/assets/timing/day39_en.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 39, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Business Meeting Dialogue 1", + "start": 0.0, + "end": 4.608 + }, + { + "i": 1, + "section": "Business Meeting Dialogue 1", + "start": 4.608, + "end": 7.752 + }, + { + "i": 2, + "section": "Business Meeting Dialogue 1", + "start": 7.752, + "end": 11.976 + }, + { + "i": 3, + "section": "Business Meeting Dialogue 1", + "start": 11.976, + "end": 15.312 + }, + { + "i": 4, + "section": "Business Meeting Dialogue 1", + "start": 15.312, + "end": 18.576 + }, + { + "i": 5, + "section": "Business Meeting Dialogue 2", + "start": 18.576, + "end": 24.072 + }, + { + "i": 6, + "section": "Business Meeting Dialogue 2", + "start": 24.072, + "end": 28.752 + }, + { + "i": 7, + "section": "Business Meeting Dialogue 2", + "start": 28.752, + "end": 32.64 + }, + { + "i": 8, + "section": "Business Meeting Dialogue 2", + "start": 32.64, + "end": 36.168 + }, + { + "i": 9, + "section": "Business Meeting Dialogue 2", + "start": 36.168, + "end": 38.904 + } + ] +} diff --git a/flutter_app/assets/timing/day39_zh.json b/flutter_app/assets/timing/day39_zh.json new file mode 100644 index 0000000..1747ebd --- /dev/null +++ b/flutter_app/assets/timing/day39_zh.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 39, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Business Meeting Dialogue 1", + "start": 0.0, + "end": 4.776 + }, + { + "i": 1, + "section": "Business Meeting Dialogue 1", + "start": 4.776, + "end": 7.92 + }, + { + "i": 2, + "section": "Business Meeting Dialogue 1", + "start": 7.92, + "end": 11.616 + }, + { + "i": 3, + "section": "Business Meeting Dialogue 1", + "start": 11.616, + "end": 14.736 + }, + { + "i": 4, + "section": "Business Meeting Dialogue 1", + "start": 14.736, + "end": 17.976 + }, + { + "i": 5, + "section": "Business Meeting Dialogue 2", + "start": 17.976, + "end": 23.04 + }, + { + "i": 6, + "section": "Business Meeting Dialogue 2", + "start": 23.04, + "end": 27.816 + }, + { + "i": 7, + "section": "Business Meeting Dialogue 2", + "start": 27.816, + "end": 31.656 + }, + { + "i": 8, + "section": "Business Meeting Dialogue 2", + "start": 31.656, + "end": 34.344 + }, + { + "i": 9, + "section": "Business Meeting Dialogue 2", + "start": 34.344, + "end": 36.48 + } + ] +} diff --git a/flutter_app/assets/timing/day3_en.json b/flutter_app/assets/timing/day3_en.json new file mode 100644 index 0000000..5901447 --- /dev/null +++ b/flutter_app/assets/timing/day3_en.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 3, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Time Words", + "start": 0.0, + "end": 1.44 + }, + { + "i": 1, + "section": "Time Words", + "start": 1.44, + "end": 2.952 + }, + { + "i": 2, + "section": "Time Words", + "start": 2.952, + "end": 4.632 + }, + { + "i": 3, + "section": "Time Words", + "start": 4.632, + "end": 6.36 + }, + { + "i": 4, + "section": "Time Words", + "start": 6.36, + "end": 7.92 + }, + { + "i": 5, + "section": "Time Words", + "start": 7.92, + "end": 9.624 + }, + { + "i": 6, + "section": "Time Words", + "start": 9.624, + "end": 11.136 + }, + { + "i": 7, + "section": "Asking Time", + "start": 11.136, + "end": 13.08 + }, + { + "i": 8, + "section": "Asking Time", + "start": 13.08, + "end": 15.288 + }, + { + "i": 9, + "section": "Asking Time", + "start": 15.288, + "end": 16.728 + }, + { + "i": 10, + "section": "Asking Time", + "start": 16.728, + "end": 18.768 + } + ] +} diff --git a/flutter_app/assets/timing/day3_zh.json b/flutter_app/assets/timing/day3_zh.json new file mode 100644 index 0000000..caec6ea --- /dev/null +++ b/flutter_app/assets/timing/day3_zh.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 3, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Time Words", + "start": 0.0, + "end": 1.296 + }, + { + "i": 1, + "section": "Time Words", + "start": 1.296, + "end": 2.592 + }, + { + "i": 2, + "section": "Time Words", + "start": 2.592, + "end": 3.888 + }, + { + "i": 3, + "section": "Time Words", + "start": 3.888, + "end": 5.184 + }, + { + "i": 4, + "section": "Time Words", + "start": 5.184, + "end": 6.48 + }, + { + "i": 5, + "section": "Time Words", + "start": 6.48, + "end": 7.776 + }, + { + "i": 6, + "section": "Time Words", + "start": 7.776, + "end": 9.024 + }, + { + "i": 7, + "section": "Asking Time", + "start": 9.024, + "end": 10.416 + }, + { + "i": 8, + "section": "Asking Time", + "start": 10.416, + "end": 12.264 + }, + { + "i": 9, + "section": "Asking Time", + "start": 12.264, + "end": 13.752 + }, + { + "i": 10, + "section": "Asking Time", + "start": 13.752, + "end": 15.264 + } + ] +} diff --git a/flutter_app/assets/timing/day40_en.json b/flutter_app/assets/timing/day40_en.json new file mode 100644 index 0000000..1f18b06 --- /dev/null +++ b/flutter_app/assets/timing/day40_en.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 40, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Travel Dialogue 1", + "start": 0.0, + "end": 3.984 + }, + { + "i": 1, + "section": "Travel Dialogue 1", + "start": 3.984, + "end": 10.632 + }, + { + "i": 2, + "section": "Travel Dialogue 1", + "start": 10.632, + "end": 14.208 + }, + { + "i": 3, + "section": "Travel Dialogue 1", + "start": 14.208, + "end": 16.992 + }, + { + "i": 4, + "section": "Travel Dialogue 1", + "start": 16.992, + "end": 19.8 + }, + { + "i": 5, + "section": "Travel Dialogue 2", + "start": 19.8, + "end": 23.376 + }, + { + "i": 6, + "section": "Travel Dialogue 2", + "start": 23.376, + "end": 26.496 + }, + { + "i": 7, + "section": "Travel Dialogue 2", + "start": 26.496, + "end": 29.76 + }, + { + "i": 8, + "section": "Travel Dialogue 2", + "start": 29.76, + "end": 35.184 + }, + { + "i": 9, + "section": "Travel Dialogue 2", + "start": 35.184, + "end": 38.976 + } + ] +} diff --git a/flutter_app/assets/timing/day40_zh.json b/flutter_app/assets/timing/day40_zh.json new file mode 100644 index 0000000..66bf06a --- /dev/null +++ b/flutter_app/assets/timing/day40_zh.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 40, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Travel Dialogue 1", + "start": 0.0, + "end": 3.168 + }, + { + "i": 1, + "section": "Travel Dialogue 1", + "start": 3.168, + "end": 9.312 + }, + { + "i": 2, + "section": "Travel Dialogue 1", + "start": 9.312, + "end": 12.288 + }, + { + "i": 3, + "section": "Travel Dialogue 1", + "start": 12.288, + "end": 15.12 + }, + { + "i": 4, + "section": "Travel Dialogue 1", + "start": 15.12, + "end": 17.64 + }, + { + "i": 5, + "section": "Travel Dialogue 2", + "start": 17.64, + "end": 20.664 + }, + { + "i": 6, + "section": "Travel Dialogue 2", + "start": 20.664, + "end": 23.976 + }, + { + "i": 7, + "section": "Travel Dialogue 2", + "start": 23.976, + "end": 26.52 + }, + { + "i": 8, + "section": "Travel Dialogue 2", + "start": 26.52, + "end": 30.864 + }, + { + "i": 9, + "section": "Travel Dialogue 2", + "start": 30.864, + "end": 34.608 + } + ] +} diff --git a/flutter_app/assets/timing/day4_en.json b/flutter_app/assets/timing/day4_en.json new file mode 100644 index 0000000..9094ba0 --- /dev/null +++ b/flutter_app/assets/timing/day4_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 4, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Common Verbs", + "start": 0.0, + "end": 1.536 + }, + { + "i": 1, + "section": "Common Verbs", + "start": 1.536, + "end": 3.144 + }, + { + "i": 2, + "section": "Common Verbs", + "start": 3.144, + "end": 5.424 + }, + { + "i": 3, + "section": "Common Verbs", + "start": 5.424, + "end": 7.008 + }, + { + "i": 4, + "section": "Common Verbs", + "start": 7.008, + "end": 8.592 + }, + { + "i": 5, + "section": "Common Verbs", + "start": 8.592, + "end": 10.176 + }, + { + "i": 6, + "section": "Common Verbs", + "start": 10.176, + "end": 11.856 + }, + { + "i": 7, + "section": "Common Verbs", + "start": 11.856, + "end": 14.208 + }, + { + "i": 8, + "section": "Simple Sentences", + "start": 14.208, + "end": 16.2 + }, + { + "i": 9, + "section": "Simple Sentences", + "start": 16.2, + "end": 18.072 + }, + { + "i": 10, + "section": "Simple Sentences", + "start": 18.072, + "end": 19.968 + }, + { + "i": 11, + "section": "Simple Sentences", + "start": 19.968, + "end": 21.696 + } + ] +} diff --git a/flutter_app/assets/timing/day4_zh.json b/flutter_app/assets/timing/day4_zh.json new file mode 100644 index 0000000..66b899a --- /dev/null +++ b/flutter_app/assets/timing/day4_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 4, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Common Verbs", + "start": 0.0, + "end": 1.128 + }, + { + "i": 1, + "section": "Common Verbs", + "start": 1.128, + "end": 2.184 + }, + { + "i": 2, + "section": "Common Verbs", + "start": 2.184, + "end": 3.312 + }, + { + "i": 3, + "section": "Common Verbs", + "start": 3.312, + "end": 4.416 + }, + { + "i": 4, + "section": "Common Verbs", + "start": 4.416, + "end": 5.472 + }, + { + "i": 5, + "section": "Common Verbs", + "start": 5.472, + "end": 6.552 + }, + { + "i": 6, + "section": "Common Verbs", + "start": 6.552, + "end": 7.608 + }, + { + "i": 7, + "section": "Common Verbs", + "start": 7.608, + "end": 8.736 + }, + { + "i": 8, + "section": "Simple Sentences", + "start": 8.736, + "end": 10.392 + }, + { + "i": 9, + "section": "Simple Sentences", + "start": 10.392, + "end": 12.048 + }, + { + "i": 10, + "section": "Simple Sentences", + "start": 12.048, + "end": 13.824 + }, + { + "i": 11, + "section": "Simple Sentences", + "start": 13.824, + "end": 15.312 + } + ] +} diff --git a/flutter_app/assets/timing/day5_en.json b/flutter_app/assets/timing/day5_en.json new file mode 100644 index 0000000..5c41cfe --- /dev/null +++ b/flutter_app/assets/timing/day5_en.json @@ -0,0 +1,91 @@ +{ + "version": 1, + "day": 5, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Common Adjectives", + "start": 0.0, + "end": 1.416 + }, + { + "i": 1, + "section": "Common Adjectives", + "start": 1.416, + "end": 2.856 + }, + { + "i": 2, + "section": "Common Adjectives", + "start": 2.856, + "end": 4.248 + }, + { + "i": 3, + "section": "Common Adjectives", + "start": 4.248, + "end": 5.832 + }, + { + "i": 4, + "section": "Common Adjectives", + "start": 5.832, + "end": 7.992 + }, + { + "i": 5, + "section": "Common Adjectives", + "start": 7.992, + "end": 10.056 + }, + { + "i": 6, + "section": "Common Adjectives", + "start": 10.056, + "end": 11.52 + }, + { + "i": 7, + "section": "Common Adjectives", + "start": 11.52, + "end": 12.96 + }, + { + "i": 8, + "section": "Common Adjectives", + "start": 12.96, + "end": 14.424 + }, + { + "i": 9, + "section": "Common Adjectives", + "start": 14.424, + "end": 16.872 + }, + { + "i": 10, + "section": "Descriptive Phrases", + "start": 16.872, + "end": 18.624 + }, + { + "i": 11, + "section": "Descriptive Phrases", + "start": 18.624, + "end": 20.592 + }, + { + "i": 12, + "section": "Descriptive Phrases", + "start": 20.592, + "end": 22.56 + }, + { + "i": 13, + "section": "Descriptive Phrases", + "start": 22.56, + "end": 24.552 + } + ] +} diff --git a/flutter_app/assets/timing/day5_zh.json b/flutter_app/assets/timing/day5_zh.json new file mode 100644 index 0000000..7887cc6 --- /dev/null +++ b/flutter_app/assets/timing/day5_zh.json @@ -0,0 +1,91 @@ +{ + "version": 1, + "day": 5, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Common Adjectives", + "start": 0.0, + "end": 1.032 + }, + { + "i": 1, + "section": "Common Adjectives", + "start": 1.032, + "end": 2.136 + }, + { + "i": 2, + "section": "Common Adjectives", + "start": 2.136, + "end": 3.192 + }, + { + "i": 3, + "section": "Common Adjectives", + "start": 3.192, + "end": 4.296 + }, + { + "i": 4, + "section": "Common Adjectives", + "start": 4.296, + "end": 5.328 + }, + { + "i": 5, + "section": "Common Adjectives", + "start": 5.328, + "end": 6.456 + }, + { + "i": 6, + "section": "Common Adjectives", + "start": 6.456, + "end": 7.536 + }, + { + "i": 7, + "section": "Common Adjectives", + "start": 7.536, + "end": 8.568 + }, + { + "i": 8, + "section": "Common Adjectives", + "start": 8.568, + "end": 9.672 + }, + { + "i": 9, + "section": "Common Adjectives", + "start": 9.672, + "end": 10.752 + }, + { + "i": 10, + "section": "Descriptive Phrases", + "start": 10.752, + "end": 12.048 + }, + { + "i": 11, + "section": "Descriptive Phrases", + "start": 12.048, + "end": 13.464 + }, + { + "i": 12, + "section": "Descriptive Phrases", + "start": 13.464, + "end": 15.096 + }, + { + "i": 13, + "section": "Descriptive Phrases", + "start": 15.096, + "end": 16.56 + } + ] +} diff --git a/flutter_app/assets/timing/day6_en.json b/flutter_app/assets/timing/day6_en.json new file mode 100644 index 0000000..ece4f65 --- /dev/null +++ b/flutter_app/assets/timing/day6_en.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 6, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Question Words", + "start": 0.0, + "end": 1.464 + }, + { + "i": 1, + "section": "Question Words", + "start": 1.464, + "end": 2.88 + }, + { + "i": 2, + "section": "Question Words", + "start": 2.88, + "end": 4.344 + }, + { + "i": 3, + "section": "Question Words", + "start": 4.344, + "end": 5.76 + }, + { + "i": 4, + "section": "Question Words", + "start": 5.76, + "end": 7.152 + }, + { + "i": 5, + "section": "Question Words", + "start": 7.152, + "end": 9.6 + }, + { + "i": 6, + "section": "Common Questions", + "start": 9.6, + "end": 11.4 + }, + { + "i": 7, + "section": "Common Questions", + "start": 11.4, + "end": 13.176 + }, + { + "i": 8, + "section": "Common Questions", + "start": 13.176, + "end": 15.024 + }, + { + "i": 9, + "section": "Common Questions", + "start": 15.024, + "end": 17.064 + }, + { + "i": 10, + "section": "Common Questions", + "start": 17.064, + "end": 19.08 + } + ] +} diff --git a/flutter_app/assets/timing/day6_zh.json b/flutter_app/assets/timing/day6_zh.json new file mode 100644 index 0000000..54cc414 --- /dev/null +++ b/flutter_app/assets/timing/day6_zh.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 6, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Question Words", + "start": 0.0, + "end": 1.2 + }, + { + "i": 1, + "section": "Question Words", + "start": 1.2, + "end": 2.304 + }, + { + "i": 2, + "section": "Question Words", + "start": 2.304, + "end": 3.504 + }, + { + "i": 3, + "section": "Question Words", + "start": 3.504, + "end": 4.824 + }, + { + "i": 4, + "section": "Question Words", + "start": 4.824, + "end": 5.976 + }, + { + "i": 5, + "section": "Question Words", + "start": 5.976, + "end": 7.248 + }, + { + "i": 6, + "section": "Common Questions", + "start": 7.248, + "end": 8.736 + }, + { + "i": 7, + "section": "Common Questions", + "start": 8.736, + "end": 10.128 + }, + { + "i": 8, + "section": "Common Questions", + "start": 10.128, + "end": 11.928 + }, + { + "i": 9, + "section": "Common Questions", + "start": 11.928, + "end": 13.68 + }, + { + "i": 10, + "section": "Common Questions", + "start": 13.68, + "end": 15.648 + } + ] +} diff --git a/flutter_app/assets/timing/day7_en.json b/flutter_app/assets/timing/day7_en.json new file mode 100644 index 0000000..363819e --- /dev/null +++ b/flutter_app/assets/timing/day7_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 7, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Common Radicals", + "start": 0.0, + "end": 1.968 + }, + { + "i": 1, + "section": "Common Radicals", + "start": 1.968, + "end": 3.888 + }, + { + "i": 2, + "section": "Common Radicals", + "start": 3.888, + "end": 5.832 + }, + { + "i": 3, + "section": "Common Radicals", + "start": 5.832, + "end": 7.776 + }, + { + "i": 4, + "section": "Common Radicals", + "start": 7.776, + "end": 10.152 + }, + { + "i": 5, + "section": "Common Radicals", + "start": 10.152, + "end": 12.168 + }, + { + "i": 6, + "section": "Common Radicals", + "start": 12.168, + "end": 14.016 + }, + { + "i": 7, + "section": "Character Components", + "start": 14.016, + "end": 16.608 + }, + { + "i": 8, + "section": "Character Components", + "start": 16.608, + "end": 19.224 + }, + { + "i": 9, + "section": "Character Components", + "start": 19.224, + "end": 21.984 + }, + { + "i": 10, + "section": "Character Components", + "start": 21.984, + "end": 24.744 + }, + { + "i": 11, + "section": "Character Components", + "start": 24.744, + "end": 28.056 + } + ] +} diff --git a/flutter_app/assets/timing/day7_zh.json b/flutter_app/assets/timing/day7_zh.json new file mode 100644 index 0000000..6fd16ea --- /dev/null +++ b/flutter_app/assets/timing/day7_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "day": 7, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Common Radicals", + "start": 0.0, + "end": 1.032 + }, + { + "i": 1, + "section": "Common Radicals", + "start": 1.032, + "end": 2.088 + }, + { + "i": 2, + "section": "Common Radicals", + "start": 2.088, + "end": 3.12 + }, + { + "i": 3, + "section": "Common Radicals", + "start": 3.12, + "end": 4.248 + }, + { + "i": 4, + "section": "Common Radicals", + "start": 4.248, + "end": 5.28 + }, + { + "i": 5, + "section": "Common Radicals", + "start": 5.28, + "end": 6.384 + }, + { + "i": 6, + "section": "Common Radicals", + "start": 6.384, + "end": 7.488 + }, + { + "i": 7, + "section": "Character Components", + "start": 7.488, + "end": 9.432 + }, + { + "i": 8, + "section": "Character Components", + "start": 9.432, + "end": 11.352 + }, + { + "i": 9, + "section": "Character Components", + "start": 11.352, + "end": 13.248 + }, + { + "i": 10, + "section": "Character Components", + "start": 13.248, + "end": 15.192 + }, + { + "i": 11, + "section": "Character Components", + "start": 15.192, + "end": 17.664 + } + ] +} diff --git a/flutter_app/assets/timing/day8_en.json b/flutter_app/assets/timing/day8_en.json new file mode 100644 index 0000000..8db0380 --- /dev/null +++ b/flutter_app/assets/timing/day8_en.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 8, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Shopping Places", + "start": 0.0, + "end": 1.536 + }, + { + "i": 1, + "section": "Shopping Places", + "start": 1.536, + "end": 3.456 + }, + { + "i": 2, + "section": "Shopping Places", + "start": 3.456, + "end": 5.088 + }, + { + "i": 3, + "section": "Shopping Places", + "start": 5.088, + "end": 7.056 + }, + { + "i": 4, + "section": "Shopping Places", + "start": 7.056, + "end": 8.904 + }, + { + "i": 5, + "section": "Shopping Phrases", + "start": 8.904, + "end": 10.8 + }, + { + "i": 6, + "section": "Shopping Phrases", + "start": 10.8, + "end": 12.768 + }, + { + "i": 7, + "section": "Shopping Phrases", + "start": 12.768, + "end": 14.712 + }, + { + "i": 8, + "section": "Shopping Phrases", + "start": 14.712, + "end": 16.68 + }, + { + "i": 9, + "section": "Shopping Phrases", + "start": 16.68, + "end": 18.6 + } + ] +} diff --git a/flutter_app/assets/timing/day8_zh.json b/flutter_app/assets/timing/day8_zh.json new file mode 100644 index 0000000..b5beb47 --- /dev/null +++ b/flutter_app/assets/timing/day8_zh.json @@ -0,0 +1,67 @@ +{ + "version": 1, + "day": 8, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Shopping Places", + "start": 0.0, + "end": 1.32 + }, + { + "i": 1, + "section": "Shopping Places", + "start": 1.32, + "end": 2.664 + }, + { + "i": 2, + "section": "Shopping Places", + "start": 2.664, + "end": 3.984 + }, + { + "i": 3, + "section": "Shopping Places", + "start": 3.984, + "end": 5.64 + }, + { + "i": 4, + "section": "Shopping Places", + "start": 5.64, + "end": 7.176 + }, + { + "i": 5, + "section": "Shopping Phrases", + "start": 7.176, + "end": 8.616 + }, + { + "i": 6, + "section": "Shopping Phrases", + "start": 8.616, + "end": 10.032 + }, + { + "i": 7, + "section": "Shopping Phrases", + "start": 10.032, + "end": 11.616 + }, + { + "i": 8, + "section": "Shopping Phrases", + "start": 11.616, + "end": 13.152 + }, + { + "i": 9, + "section": "Shopping Phrases", + "start": 13.152, + "end": 14.88 + } + ] +} diff --git a/flutter_app/assets/timing/day9_en.json b/flutter_app/assets/timing/day9_en.json new file mode 100644 index 0000000..8ec6234 --- /dev/null +++ b/flutter_app/assets/timing/day9_en.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 9, + "lang": "en", + "phrases": [ + { + "i": 0, + "section": "Transportation Types", + "start": 0.0, + "end": 1.464 + }, + { + "i": 1, + "section": "Transportation Types", + "start": 1.464, + "end": 3.096 + }, + { + "i": 2, + "section": "Transportation Types", + "start": 3.096, + "end": 4.728 + }, + { + "i": 3, + "section": "Transportation Types", + "start": 4.728, + "end": 6.216 + }, + { + "i": 4, + "section": "Transportation Types", + "start": 6.216, + "end": 7.848 + }, + { + "i": 5, + "section": "Transportation Types", + "start": 7.848, + "end": 9.576 + }, + { + "i": 6, + "section": "Transportation Phrases", + "start": 9.576, + "end": 11.952 + }, + { + "i": 7, + "section": "Transportation Phrases", + "start": 11.952, + "end": 14.064 + }, + { + "i": 8, + "section": "Transportation Phrases", + "start": 14.064, + "end": 16.632 + }, + { + "i": 9, + "section": "Transportation Phrases", + "start": 16.632, + "end": 18.912 + }, + { + "i": 10, + "section": "Transportation Phrases", + "start": 18.912, + "end": 21.336 + } + ] +} diff --git a/flutter_app/assets/timing/day9_zh.json b/flutter_app/assets/timing/day9_zh.json new file mode 100644 index 0000000..6587af9 --- /dev/null +++ b/flutter_app/assets/timing/day9_zh.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "day": 9, + "lang": "zh", + "phrases": [ + { + "i": 0, + "section": "Transportation Types", + "start": 0.0, + "end": 1.608 + }, + { + "i": 1, + "section": "Transportation Types", + "start": 1.608, + "end": 2.928 + }, + { + "i": 2, + "section": "Transportation Types", + "start": 2.928, + "end": 4.344 + }, + { + "i": 3, + "section": "Transportation Types", + "start": 4.344, + "end": 5.664 + }, + { + "i": 4, + "section": "Transportation Types", + "start": 5.664, + "end": 6.96 + }, + { + "i": 5, + "section": "Transportation Types", + "start": 6.96, + "end": 8.424 + }, + { + "i": 6, + "section": "Transportation Phrases", + "start": 8.424, + "end": 10.272 + }, + { + "i": 7, + "section": "Transportation Phrases", + "start": 10.272, + "end": 12.72 + }, + { + "i": 8, + "section": "Transportation Phrases", + "start": 12.72, + "end": 14.832 + }, + { + "i": 9, + "section": "Transportation Phrases", + "start": 14.832, + "end": 16.848 + }, + { + "i": 10, + "section": "Transportation Phrases", + "start": 16.848, + "end": 19.176 + } + ] +} diff --git a/flutter_app/assets/timing/reading/advanced_environmental_protection_en.json b/flutter_app/assets/timing/reading/advanced_environmental_protection_en.json new file mode 100644 index 0000000..d4bcf23 --- /dev/null +++ b/flutter_app/assets/timing/reading/advanced_environmental_protection_en.json @@ -0,0 +1,39 @@ +{ + "version": 1, + "phrases": [ + { + "section": "reading", + "i": 0, + "start": 0.0, + "end": 6.24 + }, + { + "section": "reading", + "i": 1, + "start": 6.24, + "end": 17.376 + }, + { + "section": "reading", + "i": 2, + "start": 17.376, + "end": 25.944 + }, + { + "section": "reading", + "i": 3, + "start": 25.944, + "end": 37.728 + }, + { + "section": "reading", + "i": 4, + "start": 37.728, + "end": 44.52 + } + ], + "level": "advanced", + "topic": "environmental_protection", + "lang": "en", + "kind": "reading" +} diff --git a/flutter_app/assets/timing/reading/advanced_environmental_protection_zh.json b/flutter_app/assets/timing/reading/advanced_environmental_protection_zh.json new file mode 100644 index 0000000..b1f7c36 --- /dev/null +++ b/flutter_app/assets/timing/reading/advanced_environmental_protection_zh.json @@ -0,0 +1,39 @@ +{ + "version": 1, + "phrases": [ + { + "section": "reading", + "i": 0, + "start": 0.0, + "end": 5.016 + }, + { + "section": "reading", + "i": 1, + "start": 5.016, + "end": 12.936 + }, + { + "section": "reading", + "i": 2, + "start": 12.936, + "end": 20.568 + }, + { + "section": "reading", + "i": 3, + "start": 20.568, + "end": 29.736 + }, + { + "section": "reading", + "i": 4, + "start": 29.736, + "end": 34.632 + } + ], + "level": "advanced", + "topic": "environmental_protection", + "lang": "zh", + "kind": "reading" +} diff --git a/flutter_app/assets/timing/reading/beginner_daily_routine_en.json b/flutter_app/assets/timing/reading/beginner_daily_routine_en.json new file mode 100644 index 0000000..b4e0c1e --- /dev/null +++ b/flutter_app/assets/timing/reading/beginner_daily_routine_en.json @@ -0,0 +1,51 @@ +{ + "version": 1, + "phrases": [ + { + "section": "reading", + "i": 0, + "start": 0.0, + "end": 3.048 + }, + { + "section": "reading", + "i": 1, + "start": 3.048, + "end": 5.976 + }, + { + "section": "reading", + "i": 2, + "start": 5.976, + "end": 8.544 + }, + { + "section": "reading", + "i": 3, + "start": 8.544, + "end": 11.472 + }, + { + "section": "reading", + "i": 4, + "start": 11.472, + "end": 14.976 + }, + { + "section": "reading", + "i": 5, + "start": 14.976, + "end": 18.288 + }, + { + "section": "reading", + "i": 6, + "start": 18.288, + "end": 21.168 + } + ], + "level": "beginner", + "topic": "daily_routine", + "lang": "en", + "kind": "reading" +} diff --git a/flutter_app/assets/timing/reading/beginner_daily_routine_zh.json b/flutter_app/assets/timing/reading/beginner_daily_routine_zh.json new file mode 100644 index 0000000..b3677a0 --- /dev/null +++ b/flutter_app/assets/timing/reading/beginner_daily_routine_zh.json @@ -0,0 +1,51 @@ +{ + "version": 1, + "phrases": [ + { + "section": "reading", + "i": 0, + "start": 0.0, + "end": 2.544 + }, + { + "section": "reading", + "i": 1, + "start": 2.544, + "end": 4.44 + }, + { + "section": "reading", + "i": 2, + "start": 4.44, + "end": 6.192 + }, + { + "section": "reading", + "i": 3, + "start": 6.192, + "end": 8.4 + }, + { + "section": "reading", + "i": 4, + "start": 8.4, + "end": 10.392 + }, + { + "section": "reading", + "i": 5, + "start": 10.392, + "end": 12.528 + }, + { + "section": "reading", + "i": 6, + "start": 12.528, + "end": 14.568 + } + ], + "level": "beginner", + "topic": "daily_routine", + "lang": "zh", + "kind": "reading" +} diff --git a/flutter_app/assets/timing/reading/beginner_self_introduction_en.json b/flutter_app/assets/timing/reading/beginner_self_introduction_en.json new file mode 100644 index 0000000..4eb1cc9 --- /dev/null +++ b/flutter_app/assets/timing/reading/beginner_self_introduction_en.json @@ -0,0 +1,39 @@ +{ + "version": 1, + "phrases": [ + { + "section": "reading", + "i": 0, + "start": 0.0, + "end": 2.208 + }, + { + "section": "reading", + "i": 1, + "start": 2.208, + "end": 4.176 + }, + { + "section": "reading", + "i": 2, + "start": 4.176, + "end": 6.528 + }, + { + "section": "reading", + "i": 3, + "start": 6.528, + "end": 8.952 + }, + { + "section": "reading", + "i": 4, + "start": 8.952, + "end": 12.672 + } + ], + "level": "beginner", + "topic": "self_introduction", + "lang": "en", + "kind": "reading" +} diff --git a/flutter_app/assets/timing/reading/beginner_self_introduction_zh.json b/flutter_app/assets/timing/reading/beginner_self_introduction_zh.json new file mode 100644 index 0000000..5529196 --- /dev/null +++ b/flutter_app/assets/timing/reading/beginner_self_introduction_zh.json @@ -0,0 +1,39 @@ +{ + "version": 1, + "phrases": [ + { + "section": "reading", + "i": 0, + "start": 0.0, + "end": 1.56 + }, + { + "section": "reading", + "i": 1, + "start": 1.56, + "end": 3.144 + }, + { + "section": "reading", + "i": 2, + "start": 3.144, + "end": 4.992 + }, + { + "section": "reading", + "i": 3, + "start": 4.992, + "end": 7.056 + }, + { + "section": "reading", + "i": 4, + "start": 7.056, + "end": 9.768 + } + ], + "level": "beginner", + "topic": "self_introduction", + "lang": "zh", + "kind": "reading" +} diff --git a/flutter_app/assets/timing/reading/intermediate_at_the_restaurant_en.json b/flutter_app/assets/timing/reading/intermediate_at_the_restaurant_en.json new file mode 100644 index 0000000..68e47d1 --- /dev/null +++ b/flutter_app/assets/timing/reading/intermediate_at_the_restaurant_en.json @@ -0,0 +1,45 @@ +{ + "version": 1, + "phrases": [ + { + "section": "reading", + "i": 0, + "start": 0.0, + "end": 4.416 + }, + { + "section": "reading", + "i": 1, + "start": 4.416, + "end": 8.496 + }, + { + "section": "reading", + "i": 2, + "start": 8.496, + "end": 13.2 + }, + { + "section": "reading", + "i": 3, + "start": 13.2, + "end": 16.848 + }, + { + "section": "reading", + "i": 4, + "start": 16.848, + "end": 20.064 + }, + { + "section": "reading", + "i": 5, + "start": 20.064, + "end": 23.568 + } + ], + "level": "intermediate", + "topic": "at_the_restaurant", + "lang": "en", + "kind": "reading" +} diff --git a/flutter_app/assets/timing/reading/intermediate_at_the_restaurant_zh.json b/flutter_app/assets/timing/reading/intermediate_at_the_restaurant_zh.json new file mode 100644 index 0000000..6f9ae2d --- /dev/null +++ b/flutter_app/assets/timing/reading/intermediate_at_the_restaurant_zh.json @@ -0,0 +1,45 @@ +{ + "version": 1, + "phrases": [ + { + "section": "reading", + "i": 0, + "start": 0.0, + "end": 4.032 + }, + { + "section": "reading", + "i": 1, + "start": 4.032, + "end": 7.248 + }, + { + "section": "reading", + "i": 2, + "start": 7.248, + "end": 11.352 + }, + { + "section": "reading", + "i": 3, + "start": 11.352, + "end": 15.072 + }, + { + "section": "reading", + "i": 4, + "start": 15.072, + "end": 17.736 + }, + { + "section": "reading", + "i": 5, + "start": 17.736, + "end": 20.568 + } + ], + "level": "intermediate", + "topic": "at_the_restaurant", + "lang": "zh", + "kind": "reading" +} diff --git a/flutter_app/assets/timing/reading/intermediate_weekend_plans_en.json b/flutter_app/assets/timing/reading/intermediate_weekend_plans_en.json new file mode 100644 index 0000000..60a2021 --- /dev/null +++ b/flutter_app/assets/timing/reading/intermediate_weekend_plans_en.json @@ -0,0 +1,45 @@ +{ + "version": 1, + "phrases": [ + { + "section": "reading", + "i": 0, + "start": 0.0, + "end": 2.952 + }, + { + "section": "reading", + "i": 1, + "start": 2.952, + "end": 7.608 + }, + { + "section": "reading", + "i": 2, + "start": 7.608, + "end": 11.232 + }, + { + "section": "reading", + "i": 3, + "start": 11.232, + "end": 14.832 + }, + { + "section": "reading", + "i": 4, + "start": 14.832, + "end": 18.696 + }, + { + "section": "reading", + "i": 5, + "start": 18.696, + "end": 23.976 + } + ], + "level": "intermediate", + "topic": "weekend_plans", + "lang": "en", + "kind": "reading" +} diff --git a/flutter_app/assets/timing/reading/intermediate_weekend_plans_zh.json b/flutter_app/assets/timing/reading/intermediate_weekend_plans_zh.json new file mode 100644 index 0000000..4deb9a1 --- /dev/null +++ b/flutter_app/assets/timing/reading/intermediate_weekend_plans_zh.json @@ -0,0 +1,45 @@ +{ + "version": 1, + "phrases": [ + { + "section": "reading", + "i": 0, + "start": 0.0, + "end": 2.688 + }, + { + "section": "reading", + "i": 1, + "start": 2.688, + "end": 6.48 + }, + { + "section": "reading", + "i": 2, + "start": 6.48, + "end": 9.504 + }, + { + "section": "reading", + "i": 3, + "start": 9.504, + "end": 12.384 + }, + { + "section": "reading", + "i": 4, + "start": 12.384, + "end": 15.672 + }, + { + "section": "reading", + "i": 5, + "start": 15.672, + "end": 20.688 + } + ], + "level": "intermediate", + "topic": "weekend_plans", + "lang": "zh", + "kind": "reading" +} diff --git a/flutter_app/assets/timing/supplementary/comparisons_en.json b/flutter_app/assets/timing/supplementary/comparisons_en.json new file mode 100644 index 0000000..0c28fa3 --- /dev/null +++ b/flutter_app/assets/timing/supplementary/comparisons_en.json @@ -0,0 +1,55 @@ +{ + "version": 1, + "phrases": [ + { + "section": "Basic Comparisons", + "i": 0, + "start": 0.0, + "end": 2.088 + }, + { + "section": "Basic Comparisons", + "i": 1, + "start": 2.088, + "end": 4.296 + }, + { + "section": "Basic Comparisons", + "i": 2, + "start": 4.296, + "end": 6.048 + }, + { + "section": "Basic Comparisons", + "i": 3, + "start": 6.048, + "end": 7.68 + }, + { + "section": "Example Sentences", + "i": 4, + "start": 7.68, + "end": 10.32 + }, + { + "section": "Example Sentences", + "i": 5, + "start": 10.32, + "end": 13.032 + }, + { + "section": "Example Sentences", + "i": 6, + "start": 13.032, + "end": 15.48 + }, + { + "section": "Example Sentences", + "i": 7, + "start": 15.48, + "end": 17.88 + } + ], + "category": "comparisons", + "lang": "en" +} diff --git a/flutter_app/assets/timing/supplementary/comparisons_zh.json b/flutter_app/assets/timing/supplementary/comparisons_zh.json new file mode 100644 index 0000000..8410c44 --- /dev/null +++ b/flutter_app/assets/timing/supplementary/comparisons_zh.json @@ -0,0 +1,55 @@ +{ + "version": 1, + "phrases": [ + { + "section": "Basic Comparisons", + "i": 0, + "start": 0.0, + "end": 1.368 + }, + { + "section": "Basic Comparisons", + "i": 1, + "start": 1.368, + "end": 2.904 + }, + { + "section": "Basic Comparisons", + "i": 2, + "start": 2.904, + "end": 4.344 + }, + { + "section": "Basic Comparisons", + "i": 3, + "start": 4.344, + "end": 5.304 + }, + { + "section": "Example Sentences", + "i": 4, + "start": 5.304, + "end": 7.128 + }, + { + "section": "Example Sentences", + "i": 5, + "start": 7.128, + "end": 9.144 + }, + { + "section": "Example Sentences", + "i": 6, + "start": 9.144, + "end": 10.944 + }, + { + "section": "Example Sentences", + "i": 7, + "start": 10.944, + "end": 12.984 + } + ], + "category": "comparisons", + "lang": "zh" +} diff --git a/flutter_app/assets/timing/supplementary/daily_life_en.json b/flutter_app/assets/timing/supplementary/daily_life_en.json new file mode 100644 index 0000000..ec1cef8 --- /dev/null +++ b/flutter_app/assets/timing/supplementary/daily_life_en.json @@ -0,0 +1,109 @@ +{ + "version": 1, + "phrases": [ + { + "section": "Weather Conditions", + "i": 0, + "start": 0.0, + "end": 1.776 + }, + { + "section": "Weather Conditions", + "i": 1, + "start": 1.776, + "end": 3.288 + }, + { + "section": "Weather Conditions", + "i": 2, + "start": 3.288, + "end": 4.824 + }, + { + "section": "Weather Conditions", + "i": 3, + "start": 4.824, + "end": 6.36 + }, + { + "section": "Weather Conditions", + "i": 4, + "start": 6.36, + "end": 7.968 + }, + { + "section": "Weather Conditions", + "i": 5, + "start": 7.968, + "end": 9.456 + }, + { + "section": "Daily Routines", + "i": 6, + "start": 9.456, + "end": 10.944 + }, + { + "section": "Daily Routines", + "i": 7, + "start": 10.944, + "end": 12.744 + }, + { + "section": "Daily Routines", + "i": 8, + "start": 12.744, + "end": 14.592 + }, + { + "section": "Daily Routines", + "i": 9, + "start": 14.592, + "end": 16.536 + }, + { + "section": "Daily Routines", + "i": 10, + "start": 16.536, + "end": 18.288 + }, + { + "section": "Daily Routines", + "i": 11, + "start": 18.288, + "end": 20.088 + }, + { + "section": "Shopping Types", + "i": 12, + "start": 20.088, + "end": 21.984 + }, + { + "section": "Shopping Types", + "i": 13, + "start": 21.984, + "end": 23.664 + }, + { + "section": "Shopping Types", + "i": 14, + "start": 23.664, + "end": 25.416 + }, + { + "section": "Shopping Types", + "i": 15, + "start": 25.416, + "end": 27.024 + }, + { + "section": "Shopping Types", + "i": 16, + "start": 27.024, + "end": 28.824 + } + ], + "category": "daily_life", + "lang": "en" +} diff --git a/flutter_app/assets/timing/supplementary/daily_life_zh.json b/flutter_app/assets/timing/supplementary/daily_life_zh.json new file mode 100644 index 0000000..0c6a739 --- /dev/null +++ b/flutter_app/assets/timing/supplementary/daily_life_zh.json @@ -0,0 +1,109 @@ +{ + "version": 1, + "phrases": [ + { + "section": "Weather Conditions", + "i": 0, + "start": 0.0, + "end": 1.32 + }, + { + "section": "Weather Conditions", + "i": 1, + "start": 1.32, + "end": 2.64 + }, + { + "section": "Weather Conditions", + "i": 2, + "start": 2.64, + "end": 3.888 + }, + { + "section": "Weather Conditions", + "i": 3, + "start": 3.888, + "end": 5.136 + }, + { + "section": "Weather Conditions", + "i": 4, + "start": 5.136, + "end": 6.456 + }, + { + "section": "Weather Conditions", + "i": 5, + "start": 6.456, + "end": 7.776 + }, + { + "section": "Daily Routines", + "i": 6, + "start": 7.776, + "end": 9.024 + }, + { + "section": "Daily Routines", + "i": 7, + "start": 9.024, + "end": 10.368 + }, + { + "section": "Daily Routines", + "i": 8, + "start": 10.368, + "end": 11.712 + }, + { + "section": "Daily Routines", + "i": 9, + "start": 11.712, + "end": 13.152 + }, + { + "section": "Daily Routines", + "i": 10, + "start": 13.152, + "end": 14.448 + }, + { + "section": "Daily Routines", + "i": 11, + "start": 14.448, + "end": 15.72 + }, + { + "section": "Shopping Types", + "i": 12, + "start": 15.72, + "end": 17.184 + }, + { + "section": "Shopping Types", + "i": 13, + "start": 17.184, + "end": 18.504 + }, + { + "section": "Shopping Types", + "i": 14, + "start": 18.504, + "end": 19.752 + }, + { + "section": "Shopping Types", + "i": 15, + "start": 19.752, + "end": 21.168 + }, + { + "section": "Shopping Types", + "i": 16, + "start": 21.168, + "end": 22.656 + } + ], + "category": "daily_life", + "lang": "zh" +} diff --git a/flutter_app/assets/timing/supplementary/education_en.json b/flutter_app/assets/timing/supplementary/education_en.json new file mode 100644 index 0000000..7d31579 --- /dev/null +++ b/flutter_app/assets/timing/supplementary/education_en.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "phrases": [ + { + "section": "School Subjects", + "i": 0, + "start": 0.0, + "end": 1.944 + }, + { + "section": "School Subjects", + "i": 1, + "start": 1.944, + "end": 3.696 + }, + { + "section": "School Subjects", + "i": 2, + "start": 3.696, + "end": 5.4 + }, + { + "section": "School Subjects", + "i": 3, + "start": 5.4, + "end": 7.2 + }, + { + "section": "School Subjects", + "i": 4, + "start": 7.2, + "end": 8.808 + }, + { + "section": "School Subjects", + "i": 5, + "start": 8.808, + "end": 10.584 + }, + { + "section": "School Subjects", + "i": 6, + "start": 10.584, + "end": 12.36 + }, + { + "section": "Classroom Phrases", + "i": 7, + "start": 12.36, + "end": 14.448 + }, + { + "section": "Classroom Phrases", + "i": 8, + "start": 14.448, + "end": 16.488 + }, + { + "section": "Classroom Phrases", + "i": 9, + "start": 16.488, + "end": 18.6 + }, + { + "section": "Classroom Phrases", + "i": 10, + "start": 18.6, + "end": 20.544 + }, + { + "section": "Classroom Phrases", + "i": 11, + "start": 20.544, + "end": 22.176 + } + ], + "category": "education", + "lang": "en" +} diff --git a/flutter_app/assets/timing/supplementary/education_zh.json b/flutter_app/assets/timing/supplementary/education_zh.json new file mode 100644 index 0000000..4627651 --- /dev/null +++ b/flutter_app/assets/timing/supplementary/education_zh.json @@ -0,0 +1,79 @@ +{ + "version": 1, + "phrases": [ + { + "section": "School Subjects", + "i": 0, + "start": 0.0, + "end": 1.368 + }, + { + "section": "School Subjects", + "i": 1, + "start": 1.368, + "end": 2.592 + }, + { + "section": "School Subjects", + "i": 2, + "start": 2.592, + "end": 3.912 + }, + { + "section": "School Subjects", + "i": 3, + "start": 3.912, + "end": 5.208 + }, + { + "section": "School Subjects", + "i": 4, + "start": 5.208, + "end": 6.528 + }, + { + "section": "School Subjects", + "i": 5, + "start": 6.528, + "end": 7.752 + }, + { + "section": "School Subjects", + "i": 6, + "start": 7.752, + "end": 9.048 + }, + { + "section": "Classroom Phrases", + "i": 7, + "start": 9.048, + "end": 10.512 + }, + { + "section": "Classroom Phrases", + "i": 8, + "start": 10.512, + "end": 12.024 + }, + { + "section": "Classroom Phrases", + "i": 9, + "start": 12.024, + "end": 14.016 + }, + { + "section": "Classroom Phrases", + "i": 10, + "start": 14.016, + "end": 15.48 + }, + { + "section": "Classroom Phrases", + "i": 11, + "start": 15.48, + "end": 16.8 + } + ], + "category": "education", + "lang": "zh" +} diff --git a/flutter_app/assets/timing/supplementary/emotions_en.json b/flutter_app/assets/timing/supplementary/emotions_en.json new file mode 100644 index 0000000..5fb242a --- /dev/null +++ b/flutter_app/assets/timing/supplementary/emotions_en.json @@ -0,0 +1,97 @@ +{ + "version": 1, + "phrases": [ + { + "section": "Basic Emotions", + "i": 0, + "start": 0.0, + "end": 1.512 + }, + { + "section": "Basic Emotions", + "i": 1, + "start": 1.512, + "end": 3.024 + }, + { + "section": "Basic Emotions", + "i": 2, + "start": 3.024, + "end": 4.584 + }, + { + "section": "Basic Emotions", + "i": 3, + "start": 4.584, + "end": 6.168 + }, + { + "section": "Basic Emotions", + "i": 4, + "start": 6.168, + "end": 7.8 + }, + { + "section": "Basic Emotions", + "i": 5, + "start": 7.8, + "end": 9.456 + }, + { + "section": "Complex Feelings", + "i": 6, + "start": 9.456, + "end": 11.256 + }, + { + "section": "Complex Feelings", + "i": 7, + "start": 11.256, + "end": 12.744 + }, + { + "section": "Complex Feelings", + "i": 8, + "start": 12.744, + "end": 15.024 + }, + { + "section": "Complex Feelings", + "i": 9, + "start": 15.024, + "end": 16.704 + }, + { + "section": "Complex Feelings", + "i": 10, + "start": 16.704, + "end": 18.192 + }, + { + "section": "Expressing Feelings", + "i": 11, + "start": 18.192, + "end": 20.112 + }, + { + "section": "Expressing Feelings", + "i": 12, + "start": 20.112, + "end": 22.008 + }, + { + "section": "Expressing Feelings", + "i": 13, + "start": 22.008, + "end": 23.664 + }, + { + "section": "Expressing Feelings", + "i": 14, + "start": 23.664, + "end": 25.56 + } + ], + "category": "emotions", + "lang": "en" +} diff --git a/flutter_app/assets/timing/supplementary/emotions_zh.json b/flutter_app/assets/timing/supplementary/emotions_zh.json new file mode 100644 index 0000000..addb4e9 --- /dev/null +++ b/flutter_app/assets/timing/supplementary/emotions_zh.json @@ -0,0 +1,97 @@ +{ + "version": 1, + "phrases": [ + { + "section": "Basic Emotions", + "i": 0, + "start": 0.0, + "end": 1.272 + }, + { + "section": "Basic Emotions", + "i": 1, + "start": 1.272, + "end": 2.592 + }, + { + "section": "Basic Emotions", + "i": 2, + "start": 2.592, + "end": 3.96 + }, + { + "section": "Basic Emotions", + "i": 3, + "start": 3.96, + "end": 5.208 + }, + { + "section": "Basic Emotions", + "i": 4, + "start": 5.208, + "end": 6.432 + }, + { + "section": "Basic Emotions", + "i": 5, + "start": 6.432, + "end": 7.728 + }, + { + "section": "Complex Feelings", + "i": 6, + "start": 7.728, + "end": 9.0 + }, + { + "section": "Complex Feelings", + "i": 7, + "start": 9.0, + "end": 10.224 + }, + { + "section": "Complex Feelings", + "i": 8, + "start": 10.224, + "end": 11.448 + }, + { + "section": "Complex Feelings", + "i": 9, + "start": 11.448, + "end": 12.744 + }, + { + "section": "Complex Feelings", + "i": 10, + "start": 12.744, + "end": 13.968 + }, + { + "section": "Expressing Feelings", + "i": 11, + "start": 13.968, + "end": 15.384 + }, + { + "section": "Expressing Feelings", + "i": 12, + "start": 15.384, + "end": 17.088 + }, + { + "section": "Expressing Feelings", + "i": 13, + "start": 17.088, + "end": 18.336 + }, + { + "section": "Expressing Feelings", + "i": 14, + "start": 18.336, + "end": 19.992 + } + ], + "category": "emotions", + "lang": "zh" +} diff --git a/flutter_app/assets/timing/supplementary/hobbies_en.json b/flutter_app/assets/timing/supplementary/hobbies_en.json new file mode 100644 index 0000000..d497632 --- /dev/null +++ b/flutter_app/assets/timing/supplementary/hobbies_en.json @@ -0,0 +1,97 @@ +{ + "version": 1, + "phrases": [ + { + "section": "Sports", + "i": 0, + "start": 0.0, + "end": 2.28 + }, + { + "section": "Sports", + "i": 1, + "start": 2.28, + "end": 4.08 + }, + { + "section": "Sports", + "i": 2, + "start": 4.08, + "end": 5.664 + }, + { + "section": "Sports", + "i": 3, + "start": 5.664, + "end": 7.248 + }, + { + "section": "Sports", + "i": 4, + "start": 7.248, + "end": 8.76 + }, + { + "section": "Arts & Entertainment", + "i": 5, + "start": 8.76, + "end": 10.704 + }, + { + "section": "Arts & Entertainment", + "i": 6, + "start": 10.704, + "end": 12.768 + }, + { + "section": "Arts & Entertainment", + "i": 7, + "start": 12.768, + "end": 14.376 + }, + { + "section": "Arts & Entertainment", + "i": 8, + "start": 14.376, + "end": 16.224 + }, + { + "section": "Arts & Entertainment", + "i": 9, + "start": 16.224, + "end": 18.072 + }, + { + "section": "Reading & Literature", + "i": 10, + "start": 18.072, + "end": 19.608 + }, + { + "section": "Reading & Literature", + "i": 11, + "start": 19.608, + "end": 21.288 + }, + { + "section": "Reading & Literature", + "i": 12, + "start": 21.288, + "end": 22.992 + }, + { + "section": "Reading & Literature", + "i": 13, + "start": 22.992, + "end": 24.672 + }, + { + "section": "Reading & Literature", + "i": 14, + "start": 24.672, + "end": 26.712 + } + ], + "category": "hobbies", + "lang": "en" +} diff --git a/flutter_app/assets/timing/supplementary/hobbies_zh.json b/flutter_app/assets/timing/supplementary/hobbies_zh.json new file mode 100644 index 0000000..daf7d14 --- /dev/null +++ b/flutter_app/assets/timing/supplementary/hobbies_zh.json @@ -0,0 +1,97 @@ +{ + "version": 1, + "phrases": [ + { + "section": "Sports", + "i": 0, + "start": 0.0, + "end": 1.296 + }, + { + "section": "Sports", + "i": 1, + "start": 1.296, + "end": 2.64 + }, + { + "section": "Sports", + "i": 2, + "start": 2.64, + "end": 3.912 + }, + { + "section": "Sports", + "i": 3, + "start": 3.912, + "end": 5.208 + }, + { + "section": "Sports", + "i": 4, + "start": 5.208, + "end": 6.456 + }, + { + "section": "Arts & Entertainment", + "i": 5, + "start": 6.456, + "end": 7.92 + }, + { + "section": "Arts & Entertainment", + "i": 6, + "start": 7.92, + "end": 9.36 + }, + { + "section": "Arts & Entertainment", + "i": 7, + "start": 9.36, + "end": 10.632 + }, + { + "section": "Arts & Entertainment", + "i": 8, + "start": 10.632, + "end": 12.0 + }, + { + "section": "Arts & Entertainment", + "i": 9, + "start": 12.0, + "end": 13.512 + }, + { + "section": "Reading & Literature", + "i": 10, + "start": 13.512, + "end": 14.856 + }, + { + "section": "Reading & Literature", + "i": 11, + "start": 14.856, + "end": 16.176 + }, + { + "section": "Reading & Literature", + "i": 12, + "start": 16.176, + "end": 17.496 + }, + { + "section": "Reading & Literature", + "i": 13, + "start": 17.496, + "end": 18.744 + }, + { + "section": "Reading & Literature", + "i": 14, + "start": 18.744, + "end": 20.448 + } + ], + "category": "hobbies", + "lang": "zh" +} diff --git a/flutter_app/assets/timing/writing/character_basic_strokes_en.json b/flutter_app/assets/timing/writing/character_basic_strokes_en.json new file mode 100644 index 0000000..a2d44fb --- /dev/null +++ b/flutter_app/assets/timing/writing/character_basic_strokes_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.064 + }, + { + "section": "description", + "i": 1, + "start": 2.064, + "end": 6.408 + } + ], + "activity_type": "character", + "level": "basic_strokes", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_basic_strokes_zh.json b/flutter_app/assets/timing/writing/character_basic_strokes_zh.json new file mode 100644 index 0000000..aaa7b0e --- /dev/null +++ b/flutter_app/assets/timing/writing/character_basic_strokes_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.632 + }, + { + "section": "description", + "i": 1, + "start": 1.632, + "end": 4.752 + } + ], + "activity_type": "character", + "level": "basic_strokes", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_common_radicals_en.json b/flutter_app/assets/timing/writing/character_common_radicals_en.json new file mode 100644 index 0000000..fc0644a --- /dev/null +++ b/flutter_app/assets/timing/writing/character_common_radicals_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.088 + }, + { + "section": "description", + "i": 1, + "start": 2.088, + "end": 7.152 + } + ], + "activity_type": "character", + "level": "common_radicals", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_common_radicals_zh.json b/flutter_app/assets/timing/writing/character_common_radicals_zh.json new file mode 100644 index 0000000..e401b78 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_common_radicals_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.632 + }, + { + "section": "description", + "i": 1, + "start": 1.632, + "end": 5.856 + } + ], + "activity_type": "character", + "level": "common_radicals", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_complete_radicals_-_group_1_en.json b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_1_en.json new file mode 100644 index 0000000..d68b814 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_1_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.76 + }, + { + "section": "description", + "i": 1, + "start": 2.76, + "end": 8.448 + } + ], + "activity_type": "character", + "level": "complete_radicals_-_group_1", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_complete_radicals_-_group_1_zh.json b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_1_zh.json new file mode 100644 index 0000000..d303563 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_1_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.28 + }, + { + "section": "description", + "i": 1, + "start": 2.28, + "end": 7.488 + } + ], + "activity_type": "character", + "level": "complete_radicals_-_group_1", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_complete_radicals_-_group_2_en.json b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_2_en.json new file mode 100644 index 0000000..15f132f --- /dev/null +++ b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_2_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.784 + }, + { + "section": "description", + "i": 1, + "start": 2.784, + "end": 8.904 + } + ], + "activity_type": "character", + "level": "complete_radicals_-_group_2", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_complete_radicals_-_group_2_zh.json b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_2_zh.json new file mode 100644 index 0000000..4b4e6fa --- /dev/null +++ b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_2_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.28 + }, + { + "section": "description", + "i": 1, + "start": 2.28, + "end": 7.872 + } + ], + "activity_type": "character", + "level": "complete_radicals_-_group_2", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_complete_radicals_-_group_3_en.json b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_3_en.json new file mode 100644 index 0000000..18d70ac --- /dev/null +++ b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_3_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.832 + }, + { + "section": "description", + "i": 1, + "start": 2.832, + "end": 8.952 + } + ], + "activity_type": "character", + "level": "complete_radicals_-_group_3", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_complete_radicals_-_group_3_zh.json b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_3_zh.json new file mode 100644 index 0000000..1275745 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_complete_radicals_-_group_3_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.304 + }, + { + "section": "description", + "i": 1, + "start": 2.304, + "end": 7.848 + } + ], + "activity_type": "character", + "level": "complete_radicals_-_group_3", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_hsk1_-_essential_en.json b/flutter_app/assets/timing/writing/character_hsk1_-_essential_en.json new file mode 100644 index 0000000..181e6c5 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_hsk1_-_essential_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 3.192 + }, + { + "section": "description", + "i": 1, + "start": 3.192, + "end": 7.512 + } + ], + "activity_type": "character", + "level": "hsk1_-_essential", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_hsk1_-_essential_zh.json b/flutter_app/assets/timing/writing/character_hsk1_-_essential_zh.json new file mode 100644 index 0000000..e025863 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_hsk1_-_essential_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.592 + }, + { + "section": "description", + "i": 1, + "start": 2.592, + "end": 6.456 + } + ], + "activity_type": "character", + "level": "hsk1_-_essential", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_hsk2_-_basic_en.json b/flutter_app/assets/timing/writing/character_hsk2_-_basic_en.json new file mode 100644 index 0000000..54d3375 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_hsk2_-_basic_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 3.144 + }, + { + "section": "description", + "i": 1, + "start": 3.144, + "end": 7.056 + } + ], + "activity_type": "character", + "level": "hsk2_-_basic", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_hsk2_-_basic_zh.json b/flutter_app/assets/timing/writing/character_hsk2_-_basic_zh.json new file mode 100644 index 0000000..6cabf77 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_hsk2_-_basic_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.592 + }, + { + "section": "description", + "i": 1, + "start": 2.592, + "end": 6.24 + } + ], + "activity_type": "character", + "level": "hsk2_-_basic", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_hsk3_-_intermediate_en.json b/flutter_app/assets/timing/writing/character_hsk3_-_intermediate_en.json new file mode 100644 index 0000000..1b5d9b0 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_hsk3_-_intermediate_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 3.552 + }, + { + "section": "description", + "i": 1, + "start": 3.552, + "end": 7.872 + } + ], + "activity_type": "character", + "level": "hsk3_-_intermediate", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_hsk3_-_intermediate_zh.json b/flutter_app/assets/timing/writing/character_hsk3_-_intermediate_zh.json new file mode 100644 index 0000000..806e303 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_hsk3_-_intermediate_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.616 + }, + { + "section": "description", + "i": 1, + "start": 2.616, + "end": 6.312 + } + ], + "activity_type": "character", + "level": "hsk3_-_intermediate", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_numbers_en.json b/flutter_app/assets/timing/writing/character_numbers_en.json new file mode 100644 index 0000000..59c79f9 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_numbers_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.752 + }, + { + "section": "description", + "i": 1, + "start": 1.752, + "end": 4.656 + } + ], + "activity_type": "character", + "level": "numbers", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_numbers_zh.json b/flutter_app/assets/timing/writing/character_numbers_zh.json new file mode 100644 index 0000000..d86e291 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_numbers_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.32 + }, + { + "section": "description", + "i": 1, + "start": 1.32, + "end": 3.744 + } + ], + "activity_type": "character", + "level": "numbers", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_theme_-_family_en.json b/flutter_app/assets/timing/writing/character_theme_-_family_en.json new file mode 100644 index 0000000..738cc7d --- /dev/null +++ b/flutter_app/assets/timing/writing/character_theme_-_family_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.016 + }, + { + "section": "description", + "i": 1, + "start": 2.016, + "end": 6.528 + } + ], + "activity_type": "character", + "level": "theme_-_family", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_theme_-_family_zh.json b/flutter_app/assets/timing/writing/character_theme_-_family_zh.json new file mode 100644 index 0000000..1fa1cdb --- /dev/null +++ b/flutter_app/assets/timing/writing/character_theme_-_family_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.824 + }, + { + "section": "description", + "i": 1, + "start": 1.824, + "end": 5.712 + } + ], + "activity_type": "character", + "level": "theme_-_family", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_theme_-_food_en.json b/flutter_app/assets/timing/writing/character_theme_-_food_en.json new file mode 100644 index 0000000..63b9a9c --- /dev/null +++ b/flutter_app/assets/timing/writing/character_theme_-_food_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.92 + }, + { + "section": "description", + "i": 1, + "start": 1.92, + "end": 5.376 + } + ], + "activity_type": "character", + "level": "theme_-_food", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_theme_-_food_zh.json b/flutter_app/assets/timing/writing/character_theme_-_food_zh.json new file mode 100644 index 0000000..e76f280 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_theme_-_food_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.752 + }, + { + "section": "description", + "i": 1, + "start": 1.752, + "end": 5.184 + } + ], + "activity_type": "character", + "level": "theme_-_food", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_theme_-_travel_en.json b/flutter_app/assets/timing/writing/character_theme_-_travel_en.json new file mode 100644 index 0000000..7398b0f --- /dev/null +++ b/flutter_app/assets/timing/writing/character_theme_-_travel_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.92 + }, + { + "section": "description", + "i": 1, + "start": 1.92, + "end": 6.024 + } + ], + "activity_type": "character", + "level": "theme_-_travel", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/character_theme_-_travel_zh.json b/flutter_app/assets/timing/writing/character_theme_-_travel_zh.json new file mode 100644 index 0000000..3ee9b51 --- /dev/null +++ b/flutter_app/assets/timing/writing/character_theme_-_travel_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.872 + }, + { + "section": "description", + "i": 1, + "start": 1.872, + "end": 5.352 + } + ], + "activity_type": "character", + "level": "theme_-_travel", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/sentence_advanced_en.json b/flutter_app/assets/timing/writing/sentence_advanced_en.json new file mode 100644 index 0000000..122d48c --- /dev/null +++ b/flutter_app/assets/timing/writing/sentence_advanced_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.784 + }, + { + "section": "description", + "i": 1, + "start": 2.784, + "end": 7.224 + } + ], + "activity_type": "sentence", + "level": "advanced", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/sentence_advanced_zh.json b/flutter_app/assets/timing/writing/sentence_advanced_zh.json new file mode 100644 index 0000000..f77fccb --- /dev/null +++ b/flutter_app/assets/timing/writing/sentence_advanced_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.944 + }, + { + "section": "description", + "i": 1, + "start": 1.944, + "end": 5.832 + } + ], + "activity_type": "sentence", + "level": "advanced", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/sentence_beginner_en.json b/flutter_app/assets/timing/writing/sentence_beginner_en.json new file mode 100644 index 0000000..46c3c34 --- /dev/null +++ b/flutter_app/assets/timing/writing/sentence_beginner_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.616 + }, + { + "section": "description", + "i": 1, + "start": 2.616, + "end": 5.928 + } + ], + "activity_type": "sentence", + "level": "beginner", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/sentence_beginner_zh.json b/flutter_app/assets/timing/writing/sentence_beginner_zh.json new file mode 100644 index 0000000..15e2033 --- /dev/null +++ b/flutter_app/assets/timing/writing/sentence_beginner_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.92 + }, + { + "section": "description", + "i": 1, + "start": 1.92, + "end": 4.608 + } + ], + "activity_type": "sentence", + "level": "beginner", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/sentence_intermediate_en.json b/flutter_app/assets/timing/writing/sentence_intermediate_en.json new file mode 100644 index 0000000..e9e699c --- /dev/null +++ b/flutter_app/assets/timing/writing/sentence_intermediate_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.88 + }, + { + "section": "description", + "i": 1, + "start": 2.88, + "end": 6.84 + } + ], + "activity_type": "sentence", + "level": "intermediate", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/sentence_intermediate_zh.json b/flutter_app/assets/timing/writing/sentence_intermediate_zh.json new file mode 100644 index 0000000..67b693b --- /dev/null +++ b/flutter_app/assets/timing/writing/sentence_intermediate_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 1.944 + }, + { + "section": "description", + "i": 1, + "start": 1.944, + "end": 5.472 + } + ], + "activity_type": "sentence", + "level": "intermediate", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/translation_advanced_en.json b/flutter_app/assets/timing/writing/translation_advanced_en.json new file mode 100644 index 0000000..ea22e54 --- /dev/null +++ b/flutter_app/assets/timing/writing/translation_advanced_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 3.192 + }, + { + "section": "description", + "i": 1, + "start": 3.192, + "end": 8.376 + } + ], + "activity_type": "translation", + "level": "advanced", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/translation_advanced_zh.json b/flutter_app/assets/timing/writing/translation_advanced_zh.json new file mode 100644 index 0000000..698cc78 --- /dev/null +++ b/flutter_app/assets/timing/writing/translation_advanced_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.088 + }, + { + "section": "description", + "i": 1, + "start": 2.088, + "end": 6.12 + } + ], + "activity_type": "translation", + "level": "advanced", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/translation_beginner_en.json b/flutter_app/assets/timing/writing/translation_beginner_en.json new file mode 100644 index 0000000..9618747 --- /dev/null +++ b/flutter_app/assets/timing/writing/translation_beginner_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 3.096 + }, + { + "section": "description", + "i": 1, + "start": 3.096, + "end": 7.224 + } + ], + "activity_type": "translation", + "level": "beginner", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/translation_beginner_zh.json b/flutter_app/assets/timing/writing/translation_beginner_zh.json new file mode 100644 index 0000000..b766358 --- /dev/null +++ b/flutter_app/assets/timing/writing/translation_beginner_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.064 + }, + { + "section": "description", + "i": 1, + "start": 2.064, + "end": 5.64 + } + ], + "activity_type": "translation", + "level": "beginner", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/translation_intermediate_en.json b/flutter_app/assets/timing/writing/translation_intermediate_en.json new file mode 100644 index 0000000..1b10834 --- /dev/null +++ b/flutter_app/assets/timing/writing/translation_intermediate_en.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 3.336 + }, + { + "section": "description", + "i": 1, + "start": 3.336, + "end": 7.896 + } + ], + "activity_type": "translation", + "level": "intermediate", + "lang": "en", + "kind": "writing" +} diff --git a/flutter_app/assets/timing/writing/translation_intermediate_zh.json b/flutter_app/assets/timing/writing/translation_intermediate_zh.json new file mode 100644 index 0000000..898bede --- /dev/null +++ b/flutter_app/assets/timing/writing/translation_intermediate_zh.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "phrases": [ + { + "section": "title", + "i": 0, + "start": 0.0, + "end": 2.064 + }, + { + "section": "description", + "i": 1, + "start": 2.064, + "end": 5.568 + } + ], + "activity_type": "translation", + "level": "intermediate", + "lang": "zh", + "kind": "writing" +} diff --git a/flutter_app/assets/writing/character_basic_strokes_en.txt b/flutter_app/assets/writing/character_basic_strokes_en.txt new file mode 100644 index 0000000..74d0d25 --- /dev/null +++ b/flutter_app/assets/writing/character_basic_strokes_en.txt @@ -0,0 +1,45 @@ +Basic Strokes +-------------------- + +Practice the fundamental strokes used in Chinese characters + +一 - yī - one +Stroke count: 1 +Stroke order: horizontal + +Write each character 5 times, paying attention to stroke order: + +一: _ _ _ _ _ + +丨 - gǔn - vertical stroke +Stroke count: 1 +Stroke order: vertical + +Write each character 5 times, paying attention to stroke order: + +丨: _ _ _ _ _ + +丿 - piě - slash +Stroke count: 1 +Stroke order: slash + +Write each character 5 times, paying attention to stroke order: + +丿: _ _ _ _ _ + +丶 - diǎn - dot +Stroke count: 1 +Stroke order: dot + +Write each character 5 times, paying attention to stroke order: + +丶: _ _ _ _ _ + +乙 - yǐ - second +Stroke count: 1 +Stroke order: hook + +Write each character 5 times, paying attention to stroke order: + +乙: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_basic_strokes_pinyin.txt b/flutter_app/assets/writing/character_basic_strokes_pinyin.txt new file mode 100644 index 0000000..3937aa7 --- /dev/null +++ b/flutter_app/assets/writing/character_basic_strokes_pinyin.txt @@ -0,0 +1,45 @@ +基本笔画 / Basic Strokes +-------------------- + +Practice the fundamental strokes used in Chinese characters + +一 - yī - one +Stroke count: 1 +Stroke order: horizontal + +Write each character 5 times, paying attention to stroke order: + +一: _ _ _ _ _ + +丨 - gǔn - vertical stroke +Stroke count: 1 +Stroke order: vertical + +Write each character 5 times, paying attention to stroke order: + +丨: _ _ _ _ _ + +丿 - piě - slash +Stroke count: 1 +Stroke order: slash + +Write each character 5 times, paying attention to stroke order: + +丿: _ _ _ _ _ + +丶 - diǎn - dot +Stroke count: 1 +Stroke order: dot + +Write each character 5 times, paying attention to stroke order: + +丶: _ _ _ _ _ + +乙 - yǐ - second +Stroke count: 1 +Stroke order: hook + +Write each character 5 times, paying attention to stroke order: + +乙: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_basic_strokes_zh.txt b/flutter_app/assets/writing/character_basic_strokes_zh.txt new file mode 100644 index 0000000..be85690 --- /dev/null +++ b/flutter_app/assets/writing/character_basic_strokes_zh.txt @@ -0,0 +1,45 @@ +基本笔画 +-------------------- + +练习汉字中使用的基本笔画 + +一 - one +笔画数: 1 +笔顺: horizontal + +Write each character 5 times, paying attention to stroke order: + +一: _ _ _ _ _ + +丨 - vertical stroke +笔画数: 1 +笔顺: vertical + +Write each character 5 times, paying attention to stroke order: + +丨: _ _ _ _ _ + +丿 - slash +笔画数: 1 +笔顺: slash + +Write each character 5 times, paying attention to stroke order: + +丿: _ _ _ _ _ + +丶 - dot +笔画数: 1 +笔顺: dot + +Write each character 5 times, paying attention to stroke order: + +丶: _ _ _ _ _ + +乙 - second +笔画数: 1 +笔顺: hook + +Write each character 5 times, paying attention to stroke order: + +乙: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_common_radicals_en.txt b/flutter_app/assets/writing/character_common_radicals_en.txt new file mode 100644 index 0000000..ded3b9b --- /dev/null +++ b/flutter_app/assets/writing/character_common_radicals_en.txt @@ -0,0 +1,45 @@ +Common Radicals +-------------------- + +Practice common radicals that form the building blocks of Chinese characters + +口 - kǒu - mouth +Stroke count: 3 +Stroke order: top, right, bottom-left + +Write each radical 5 times, paying attention to stroke order: + +口: _ _ _ _ _ + +木 - mù - tree +Stroke count: 4 +Stroke order: vertical, horizontal, left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +木: _ _ _ _ _ + +水 - shuǐ - water +Stroke count: 4 +Stroke order: left dot, right dot, left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +水: _ _ _ _ _ + +火 - huǒ - fire +Stroke count: 4 +Stroke order: dot, left diagonal, right diagonal, vertical + +Write each radical 5 times, paying attention to stroke order: + +火: _ _ _ _ _ + +人 - rén - person +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +人: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_common_radicals_pinyin.txt b/flutter_app/assets/writing/character_common_radicals_pinyin.txt new file mode 100644 index 0000000..df862e5 --- /dev/null +++ b/flutter_app/assets/writing/character_common_radicals_pinyin.txt @@ -0,0 +1,45 @@ +常用部首 / Common Radicals +-------------------- + +Practice common radicals that form the building blocks of Chinese characters + +口 - kǒu - mouth +Stroke count: 3 +Stroke order: top, right, bottom-left + +Write each radical 5 times, paying attention to stroke order: + +口: _ _ _ _ _ + +木 - mù - tree +Stroke count: 4 +Stroke order: vertical, horizontal, left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +木: _ _ _ _ _ + +水 - shuǐ - water +Stroke count: 4 +Stroke order: left dot, right dot, left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +水: _ _ _ _ _ + +火 - huǒ - fire +Stroke count: 4 +Stroke order: dot, left diagonal, right diagonal, vertical + +Write each radical 5 times, paying attention to stroke order: + +火: _ _ _ _ _ + +人 - rén - person +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +人: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_common_radicals_zh.txt b/flutter_app/assets/writing/character_common_radicals_zh.txt new file mode 100644 index 0000000..3d9d320 --- /dev/null +++ b/flutter_app/assets/writing/character_common_radicals_zh.txt @@ -0,0 +1,45 @@ +常用部首 +-------------------- + +练习构成汉字基本组成部分的常用部首 + +口 - mouth +笔画数: 3 +笔顺: top, right, bottom-left + +Write each radical 5 times, paying attention to stroke order: + +口: _ _ _ _ _ + +木 - tree +笔画数: 4 +笔顺: vertical, horizontal, left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +木: _ _ _ _ _ + +水 - water +笔画数: 4 +笔顺: left dot, right dot, left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +水: _ _ _ _ _ + +火 - fire +笔画数: 4 +笔顺: dot, left diagonal, right diagonal, vertical + +Write each radical 5 times, paying attention to stroke order: + +火: _ _ _ _ _ + +人 - person +笔画数: 2 +笔顺: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +人: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_complete_radicals_-_group_1_en.txt b/flutter_app/assets/writing/character_complete_radicals_-_group_1_en.txt new file mode 100644 index 0000000..8435de3 --- /dev/null +++ b/flutter_app/assets/writing/character_complete_radicals_-_group_1_en.txt @@ -0,0 +1,85 @@ +Complete Radicals - Group 1 +-------------------- + +Practice common radicals (1-30 of 214 Kangxi radicals) + +一 - yī - one +Stroke count: 1 +Stroke order: horizontal + +Write each radical 5 times, paying attention to stroke order: + +一: _ _ _ _ _ + +丨 - gǔn - vertical line +Stroke count: 1 +Stroke order: vertical + +Write each radical 5 times, paying attention to stroke order: + +丨: _ _ _ _ _ + +丶 - diǎn - dot +Stroke count: 1 +Stroke order: dot + +Write each radical 5 times, paying attention to stroke order: + +丶: _ _ _ _ _ + +丿 - piě - slash +Stroke count: 1 +Stroke order: slash + +Write each radical 5 times, paying attention to stroke order: + +丿: _ _ _ _ _ + +乙 - yǐ - second, twist +Stroke count: 1 +Stroke order: hook + +Write each radical 5 times, paying attention to stroke order: + +乙: _ _ _ _ _ + +亅 - jué - hook +Stroke count: 1 +Stroke order: hook + +Write each radical 5 times, paying attention to stroke order: + +亅: _ _ _ _ _ + +二 - èr - two +Stroke count: 2 +Stroke order: top horizontal, bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +二: _ _ _ _ _ + +亠 - tóu - lid +Stroke count: 2 +Stroke order: horizontal, vertical + +Write each radical 5 times, paying attention to stroke order: + +亠: _ _ _ _ _ + +人 - rén - person +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +人: _ _ _ _ _ + +儿 - ér - legs +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +儿: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_complete_radicals_-_group_1_pinyin.txt b/flutter_app/assets/writing/character_complete_radicals_-_group_1_pinyin.txt new file mode 100644 index 0000000..d465882 --- /dev/null +++ b/flutter_app/assets/writing/character_complete_radicals_-_group_1_pinyin.txt @@ -0,0 +1,85 @@ +完整部首 - 第一组 / Complete Radicals - Group 1 +-------------------- + +Practice common radicals (1-30 of 214 Kangxi radicals) + +一 - yī - one +Stroke count: 1 +Stroke order: horizontal + +Write each radical 5 times, paying attention to stroke order: + +一: _ _ _ _ _ + +丨 - gǔn - vertical line +Stroke count: 1 +Stroke order: vertical + +Write each radical 5 times, paying attention to stroke order: + +丨: _ _ _ _ _ + +丶 - diǎn - dot +Stroke count: 1 +Stroke order: dot + +Write each radical 5 times, paying attention to stroke order: + +丶: _ _ _ _ _ + +丿 - piě - slash +Stroke count: 1 +Stroke order: slash + +Write each radical 5 times, paying attention to stroke order: + +丿: _ _ _ _ _ + +乙 - yǐ - second, twist +Stroke count: 1 +Stroke order: hook + +Write each radical 5 times, paying attention to stroke order: + +乙: _ _ _ _ _ + +亅 - jué - hook +Stroke count: 1 +Stroke order: hook + +Write each radical 5 times, paying attention to stroke order: + +亅: _ _ _ _ _ + +二 - èr - two +Stroke count: 2 +Stroke order: top horizontal, bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +二: _ _ _ _ _ + +亠 - tóu - lid +Stroke count: 2 +Stroke order: horizontal, vertical + +Write each radical 5 times, paying attention to stroke order: + +亠: _ _ _ _ _ + +人 - rén - person +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +人: _ _ _ _ _ + +儿 - ér - legs +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +儿: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_complete_radicals_-_group_1_zh.txt b/flutter_app/assets/writing/character_complete_radicals_-_group_1_zh.txt new file mode 100644 index 0000000..5c5a690 --- /dev/null +++ b/flutter_app/assets/writing/character_complete_radicals_-_group_1_zh.txt @@ -0,0 +1,85 @@ +完整部首 - 第一组 +-------------------- + +练习常用部首(康熙部首214个中的1-30个) + +一 - one +笔画数: 1 +笔顺: horizontal + +Write each radical 5 times, paying attention to stroke order: + +一: _ _ _ _ _ + +丨 - vertical line +笔画数: 1 +笔顺: vertical + +Write each radical 5 times, paying attention to stroke order: + +丨: _ _ _ _ _ + +丶 - dot +笔画数: 1 +笔顺: dot + +Write each radical 5 times, paying attention to stroke order: + +丶: _ _ _ _ _ + +丿 - slash +笔画数: 1 +笔顺: slash + +Write each radical 5 times, paying attention to stroke order: + +丿: _ _ _ _ _ + +乙 - second, twist +笔画数: 1 +笔顺: hook + +Write each radical 5 times, paying attention to stroke order: + +乙: _ _ _ _ _ + +亅 - hook +笔画数: 1 +笔顺: hook + +Write each radical 5 times, paying attention to stroke order: + +亅: _ _ _ _ _ + +二 - two +笔画数: 2 +笔顺: top horizontal, bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +二: _ _ _ _ _ + +亠 - lid +笔画数: 2 +笔顺: horizontal, vertical + +Write each radical 5 times, paying attention to stroke order: + +亠: _ _ _ _ _ + +人 - person +笔画数: 2 +笔顺: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +人: _ _ _ _ _ + +儿 - legs +笔画数: 2 +笔顺: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +儿: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_complete_radicals_-_group_2_en.txt b/flutter_app/assets/writing/character_complete_radicals_-_group_2_en.txt new file mode 100644 index 0000000..0022636 --- /dev/null +++ b/flutter_app/assets/writing/character_complete_radicals_-_group_2_en.txt @@ -0,0 +1,85 @@ +Complete Radicals - Group 2 +-------------------- + +Practice common radicals (31-60 of 214 Kangxi radicals) + +入 - rù - enter +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +入: _ _ _ _ _ + +八 - bā - eight +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +八: _ _ _ _ _ + +冂 - jiōng - down box +Stroke count: 2 +Stroke order: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +冂: _ _ _ _ _ + +冖 - mì - cover +Stroke count: 2 +Stroke order: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +冖: _ _ _ _ _ + +冫 - bīng - ice +Stroke count: 2 +Stroke order: left dot, right dot + +Write each radical 5 times, paying attention to stroke order: + +冫: _ _ _ _ _ + +几 - jī - table +Stroke count: 2 +Stroke order: horizontal, curved hook + +Write each radical 5 times, paying attention to stroke order: + +几: _ _ _ _ _ + +凵 - kǎn - open box +Stroke count: 2 +Stroke order: left vertical, right vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +凵: _ _ _ _ _ + +刀 - dāo - knife +Stroke count: 2 +Stroke order: horizontal, curved hook + +Write each radical 5 times, paying attention to stroke order: + +刀: _ _ _ _ _ + +力 - lì - power +Stroke count: 2 +Stroke order: left diagonal, right hook + +Write each radical 5 times, paying attention to stroke order: + +力: _ _ _ _ _ + +勹 - bāo - wrap +Stroke count: 2 +Stroke order: dot, curved hook + +Write each radical 5 times, paying attention to stroke order: + +勹: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_complete_radicals_-_group_2_pinyin.txt b/flutter_app/assets/writing/character_complete_radicals_-_group_2_pinyin.txt new file mode 100644 index 0000000..9bc4fda --- /dev/null +++ b/flutter_app/assets/writing/character_complete_radicals_-_group_2_pinyin.txt @@ -0,0 +1,85 @@ +完整部首 - 第二组 / Complete Radicals - Group 2 +-------------------- + +Practice common radicals (31-60 of 214 Kangxi radicals) + +入 - rù - enter +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +入: _ _ _ _ _ + +八 - bā - eight +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +八: _ _ _ _ _ + +冂 - jiōng - down box +Stroke count: 2 +Stroke order: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +冂: _ _ _ _ _ + +冖 - mì - cover +Stroke count: 2 +Stroke order: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +冖: _ _ _ _ _ + +冫 - bīng - ice +Stroke count: 2 +Stroke order: left dot, right dot + +Write each radical 5 times, paying attention to stroke order: + +冫: _ _ _ _ _ + +几 - jī - table +Stroke count: 2 +Stroke order: horizontal, curved hook + +Write each radical 5 times, paying attention to stroke order: + +几: _ _ _ _ _ + +凵 - kǎn - open box +Stroke count: 2 +Stroke order: left vertical, right vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +凵: _ _ _ _ _ + +刀 - dāo - knife +Stroke count: 2 +Stroke order: horizontal, curved hook + +Write each radical 5 times, paying attention to stroke order: + +刀: _ _ _ _ _ + +力 - lì - power +Stroke count: 2 +Stroke order: left diagonal, right hook + +Write each radical 5 times, paying attention to stroke order: + +力: _ _ _ _ _ + +勹 - bāo - wrap +Stroke count: 2 +Stroke order: dot, curved hook + +Write each radical 5 times, paying attention to stroke order: + +勹: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_complete_radicals_-_group_2_zh.txt b/flutter_app/assets/writing/character_complete_radicals_-_group_2_zh.txt new file mode 100644 index 0000000..8be668f --- /dev/null +++ b/flutter_app/assets/writing/character_complete_radicals_-_group_2_zh.txt @@ -0,0 +1,85 @@ +完整部首 - 第二组 +-------------------- + +练习常用部首(康熙部首214个中的31-60个) + +入 - enter +笔画数: 2 +笔顺: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +入: _ _ _ _ _ + +八 - eight +笔画数: 2 +笔顺: left diagonal, right diagonal + +Write each radical 5 times, paying attention to stroke order: + +八: _ _ _ _ _ + +冂 - down box +笔画数: 2 +笔顺: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +冂: _ _ _ _ _ + +冖 - cover +笔画数: 2 +笔顺: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +冖: _ _ _ _ _ + +冫 - ice +笔画数: 2 +笔顺: left dot, right dot + +Write each radical 5 times, paying attention to stroke order: + +冫: _ _ _ _ _ + +几 - table +笔画数: 2 +笔顺: horizontal, curved hook + +Write each radical 5 times, paying attention to stroke order: + +几: _ _ _ _ _ + +凵 - open box +笔画数: 2 +笔顺: left vertical, right vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +凵: _ _ _ _ _ + +刀 - knife +笔画数: 2 +笔顺: horizontal, curved hook + +Write each radical 5 times, paying attention to stroke order: + +刀: _ _ _ _ _ + +力 - power +笔画数: 2 +笔顺: left diagonal, right hook + +Write each radical 5 times, paying attention to stroke order: + +力: _ _ _ _ _ + +勹 - wrap +笔画数: 2 +笔顺: dot, curved hook + +Write each radical 5 times, paying attention to stroke order: + +勹: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_complete_radicals_-_group_3_en.txt b/flutter_app/assets/writing/character_complete_radicals_-_group_3_en.txt new file mode 100644 index 0000000..f4757e2 --- /dev/null +++ b/flutter_app/assets/writing/character_complete_radicals_-_group_3_en.txt @@ -0,0 +1,85 @@ +Complete Radicals - Group 3 +-------------------- + +Practice common radicals (61-90 of 214 Kangxi radicals) + +匕 - bǐ - spoon +Stroke count: 2 +Stroke order: horizontal, vertical hook + +Write each radical 5 times, paying attention to stroke order: + +匕: _ _ _ _ _ + +匚 - fāng - right open box +Stroke count: 2 +Stroke order: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +匚: _ _ _ _ _ + +匸 - xì - hiding enclosure +Stroke count: 2 +Stroke order: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +匸: _ _ _ _ _ + +十 - shí - ten +Stroke count: 2 +Stroke order: horizontal, vertical + +Write each radical 5 times, paying attention to stroke order: + +十: _ _ _ _ _ + +卜 - bǔ - divination +Stroke count: 2 +Stroke order: dot, vertical + +Write each radical 5 times, paying attention to stroke order: + +卜: _ _ _ _ _ + +卩 - jié - seal +Stroke count: 2 +Stroke order: vertical, hook + +Write each radical 5 times, paying attention to stroke order: + +卩: _ _ _ _ _ + +厂 - hǎn - cliff +Stroke count: 2 +Stroke order: horizontal, vertical + +Write each radical 5 times, paying attention to stroke order: + +厂: _ _ _ _ _ + +厶 - sī - private +Stroke count: 2 +Stroke order: horizontal, hook + +Write each radical 5 times, paying attention to stroke order: + +厶: _ _ _ _ _ + +又 - yòu - again +Stroke count: 2 +Stroke order: horizontal, hook + +Write each radical 5 times, paying attention to stroke order: + +又: _ _ _ _ _ + +口 - kǒu - mouth +Stroke count: 3 +Stroke order: top, right, bottom-left + +Write each radical 5 times, paying attention to stroke order: + +口: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_complete_radicals_-_group_3_pinyin.txt b/flutter_app/assets/writing/character_complete_radicals_-_group_3_pinyin.txt new file mode 100644 index 0000000..592f206 --- /dev/null +++ b/flutter_app/assets/writing/character_complete_radicals_-_group_3_pinyin.txt @@ -0,0 +1,85 @@ +完整部首 - 第三组 / Complete Radicals - Group 3 +-------------------- + +Practice common radicals (61-90 of 214 Kangxi radicals) + +匕 - bǐ - spoon +Stroke count: 2 +Stroke order: horizontal, vertical hook + +Write each radical 5 times, paying attention to stroke order: + +匕: _ _ _ _ _ + +匚 - fāng - right open box +Stroke count: 2 +Stroke order: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +匚: _ _ _ _ _ + +匸 - xì - hiding enclosure +Stroke count: 2 +Stroke order: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +匸: _ _ _ _ _ + +十 - shí - ten +Stroke count: 2 +Stroke order: horizontal, vertical + +Write each radical 5 times, paying attention to stroke order: + +十: _ _ _ _ _ + +卜 - bǔ - divination +Stroke count: 2 +Stroke order: dot, vertical + +Write each radical 5 times, paying attention to stroke order: + +卜: _ _ _ _ _ + +卩 - jié - seal +Stroke count: 2 +Stroke order: vertical, hook + +Write each radical 5 times, paying attention to stroke order: + +卩: _ _ _ _ _ + +厂 - hǎn - cliff +Stroke count: 2 +Stroke order: horizontal, vertical + +Write each radical 5 times, paying attention to stroke order: + +厂: _ _ _ _ _ + +厶 - sī - private +Stroke count: 2 +Stroke order: horizontal, hook + +Write each radical 5 times, paying attention to stroke order: + +厶: _ _ _ _ _ + +又 - yòu - again +Stroke count: 2 +Stroke order: horizontal, hook + +Write each radical 5 times, paying attention to stroke order: + +又: _ _ _ _ _ + +口 - kǒu - mouth +Stroke count: 3 +Stroke order: top, right, bottom-left + +Write each radical 5 times, paying attention to stroke order: + +口: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_complete_radicals_-_group_3_zh.txt b/flutter_app/assets/writing/character_complete_radicals_-_group_3_zh.txt new file mode 100644 index 0000000..9cb0191 --- /dev/null +++ b/flutter_app/assets/writing/character_complete_radicals_-_group_3_zh.txt @@ -0,0 +1,85 @@ +完整部首 - 第三组 +-------------------- + +练习常用部首(康熙部首214个中的61-90个) + +匕 - spoon +笔画数: 2 +笔顺: horizontal, vertical hook + +Write each radical 5 times, paying attention to stroke order: + +匕: _ _ _ _ _ + +匚 - right open box +笔画数: 2 +笔顺: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +匚: _ _ _ _ _ + +匸 - hiding enclosure +笔画数: 2 +笔顺: top horizontal, vertical with bottom horizontal + +Write each radical 5 times, paying attention to stroke order: + +匸: _ _ _ _ _ + +十 - ten +笔画数: 2 +笔顺: horizontal, vertical + +Write each radical 5 times, paying attention to stroke order: + +十: _ _ _ _ _ + +卜 - divination +笔画数: 2 +笔顺: dot, vertical + +Write each radical 5 times, paying attention to stroke order: + +卜: _ _ _ _ _ + +卩 - seal +笔画数: 2 +笔顺: vertical, hook + +Write each radical 5 times, paying attention to stroke order: + +卩: _ _ _ _ _ + +厂 - cliff +笔画数: 2 +笔顺: horizontal, vertical + +Write each radical 5 times, paying attention to stroke order: + +厂: _ _ _ _ _ + +厶 - private +笔画数: 2 +笔顺: horizontal, hook + +Write each radical 5 times, paying attention to stroke order: + +厶: _ _ _ _ _ + +又 - again +笔画数: 2 +笔顺: horizontal, hook + +Write each radical 5 times, paying attention to stroke order: + +又: _ _ _ _ _ + +口 - mouth +笔画数: 3 +笔顺: top, right, bottom-left + +Write each radical 5 times, paying attention to stroke order: + +口: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_hsk1_-_essential_en.txt b/flutter_app/assets/writing/character_hsk1_-_essential_en.txt new file mode 100644 index 0000000..99e3071 --- /dev/null +++ b/flutter_app/assets/writing/character_hsk1_-_essential_en.txt @@ -0,0 +1,85 @@ +HSK1 Essential Characters +-------------------- + +Practice the most common characters from HSK Level 1 + +我 - wǒ - I, me +Stroke count: 7 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +我: _ _ _ _ _ + +你 - nǐ - you +Stroke count: 7 +Stroke order: left diagonal, right diagonal, dot, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +你: _ _ _ _ _ + +他 - tā - he +Stroke count: 5 +Stroke order: left diagonal, right diagonal, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +他: _ _ _ _ _ + +她 - tā - she +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +她: _ _ _ _ _ + +是 - shì - to be +Stroke count: 9 +Stroke order: horizontal, horizontal, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +是: _ _ _ _ _ + +不 - bù - no, not +Stroke count: 4 +Stroke order: horizontal, dot, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +不: _ _ _ _ _ + +好 - hǎo - good +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +好: _ _ _ _ _ + +人 - rén - person +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +人: _ _ _ _ _ + +名 - míng - name +Stroke count: 6 +Stroke order: vertical, horizontal, vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +名: _ _ _ _ _ + +什 - shén - what +Stroke count: 4 +Stroke order: left diagonal, right diagonal, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +什: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_hsk1_-_essential_pinyin.txt b/flutter_app/assets/writing/character_hsk1_-_essential_pinyin.txt new file mode 100644 index 0000000..51717d8 --- /dev/null +++ b/flutter_app/assets/writing/character_hsk1_-_essential_pinyin.txt @@ -0,0 +1,85 @@ +HSK1 基础汉字 / HSK1 Essential Characters +-------------------- + +Practice the most common characters from HSK Level 1 + +我 - wǒ - I, me +Stroke count: 7 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +我: _ _ _ _ _ + +你 - nǐ - you +Stroke count: 7 +Stroke order: left diagonal, right diagonal, dot, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +你: _ _ _ _ _ + +他 - tā - he +Stroke count: 5 +Stroke order: left diagonal, right diagonal, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +他: _ _ _ _ _ + +她 - tā - she +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +她: _ _ _ _ _ + +是 - shì - to be +Stroke count: 9 +Stroke order: horizontal, horizontal, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +是: _ _ _ _ _ + +不 - bù - no, not +Stroke count: 4 +Stroke order: horizontal, dot, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +不: _ _ _ _ _ + +好 - hǎo - good +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +好: _ _ _ _ _ + +人 - rén - person +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +人: _ _ _ _ _ + +名 - míng - name +Stroke count: 6 +Stroke order: vertical, horizontal, vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +名: _ _ _ _ _ + +什 - shén - what +Stroke count: 4 +Stroke order: left diagonal, right diagonal, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +什: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_hsk1_-_essential_zh.txt b/flutter_app/assets/writing/character_hsk1_-_essential_zh.txt new file mode 100644 index 0000000..7a68290 --- /dev/null +++ b/flutter_app/assets/writing/character_hsk1_-_essential_zh.txt @@ -0,0 +1,85 @@ +HSK1 基础汉字 +-------------------- + +练习HSK一级中最常用的汉字 + +我 - I, me +笔画数: 7 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +我: _ _ _ _ _ + +你 - you +笔画数: 7 +笔顺: left diagonal, right diagonal, dot, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +你: _ _ _ _ _ + +他 - he +笔画数: 5 +笔顺: left diagonal, right diagonal, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +他: _ _ _ _ _ + +她 - she +笔画数: 6 +笔顺: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +她: _ _ _ _ _ + +是 - to be +笔画数: 9 +笔顺: horizontal, horizontal, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +是: _ _ _ _ _ + +不 - no, not +笔画数: 4 +笔顺: horizontal, dot, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +不: _ _ _ _ _ + +好 - good +笔画数: 6 +笔顺: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +好: _ _ _ _ _ + +人 - person +笔画数: 2 +笔顺: left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +人: _ _ _ _ _ + +名 - name +笔画数: 6 +笔顺: vertical, horizontal, vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +名: _ _ _ _ _ + +什 - what +笔画数: 4 +笔顺: left diagonal, right diagonal, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +什: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_hsk2_-_basic_en.txt b/flutter_app/assets/writing/character_hsk2_-_basic_en.txt new file mode 100644 index 0000000..0cfa1dd --- /dev/null +++ b/flutter_app/assets/writing/character_hsk2_-_basic_en.txt @@ -0,0 +1,85 @@ +HSK2 Basic Characters +-------------------- + +Practice common characters from HSK Level 2 + +学 - xué - to learn +Stroke count: 8 +Stroke order: top, left vertical, right vertical, horizontal, left diagonal, right diagonal, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +学: _ _ _ _ _ + +生 - shēng - to be born, life +Stroke count: 5 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +生: _ _ _ _ _ + +工 - gōng - work +Stroke count: 3 +Stroke order: horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +工: _ _ _ _ _ + +作 - zuò - to do +Stroke count: 7 +Stroke order: left diagonal, right diagonal, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +作: _ _ _ _ _ + +朋 - péng - friend +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +朋: _ _ _ _ _ + +友 - yǒu - friend +Stroke count: 4 +Stroke order: left diagonal, right diagonal, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +友: _ _ _ _ _ + +明 - míng - bright +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, left diagonal, right diagonal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +明: _ _ _ _ _ + +天 - tiān - day, sky +Stroke count: 4 +Stroke order: horizontal, vertical, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +天: _ _ _ _ _ + +气 - qì - air, gas +Stroke count: 4 +Stroke order: horizontal, vertical, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +气: _ _ _ _ _ + +很 - hěn - very +Stroke count: 9 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +很: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_hsk2_-_basic_pinyin.txt b/flutter_app/assets/writing/character_hsk2_-_basic_pinyin.txt new file mode 100644 index 0000000..f979fa2 --- /dev/null +++ b/flutter_app/assets/writing/character_hsk2_-_basic_pinyin.txt @@ -0,0 +1,85 @@ +HSK2 基础汉字 / HSK2 Basic Characters +-------------------- + +Practice common characters from HSK Level 2 + +学 - xué - to learn +Stroke count: 8 +Stroke order: top, left vertical, right vertical, horizontal, left diagonal, right diagonal, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +学: _ _ _ _ _ + +生 - shēng - to be born, life +Stroke count: 5 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +生: _ _ _ _ _ + +工 - gōng - work +Stroke count: 3 +Stroke order: horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +工: _ _ _ _ _ + +作 - zuò - to do +Stroke count: 7 +Stroke order: left diagonal, right diagonal, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +作: _ _ _ _ _ + +朋 - péng - friend +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +朋: _ _ _ _ _ + +友 - yǒu - friend +Stroke count: 4 +Stroke order: left diagonal, right diagonal, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +友: _ _ _ _ _ + +明 - míng - bright +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, left diagonal, right diagonal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +明: _ _ _ _ _ + +天 - tiān - day, sky +Stroke count: 4 +Stroke order: horizontal, vertical, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +天: _ _ _ _ _ + +气 - qì - air, gas +Stroke count: 4 +Stroke order: horizontal, vertical, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +气: _ _ _ _ _ + +很 - hěn - very +Stroke count: 9 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +很: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_hsk2_-_basic_zh.txt b/flutter_app/assets/writing/character_hsk2_-_basic_zh.txt new file mode 100644 index 0000000..3fe4476 --- /dev/null +++ b/flutter_app/assets/writing/character_hsk2_-_basic_zh.txt @@ -0,0 +1,85 @@ +HSK2 基础汉字 +-------------------- + +练习HSK二级中的常用汉字 + +学 - to learn +笔画数: 8 +笔顺: top, left vertical, right vertical, horizontal, left diagonal, right diagonal, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +学: _ _ _ _ _ + +生 - to be born, life +笔画数: 5 +笔顺: horizontal, vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +生: _ _ _ _ _ + +工 - work +笔画数: 3 +笔顺: horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +工: _ _ _ _ _ + +作 - to do +笔画数: 7 +笔顺: left diagonal, right diagonal, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +作: _ _ _ _ _ + +朋 - friend +笔画数: 8 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +朋: _ _ _ _ _ + +友 - friend +笔画数: 4 +笔顺: left diagonal, right diagonal, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +友: _ _ _ _ _ + +明 - bright +笔画数: 8 +笔顺: horizontal, vertical, horizontal, vertical, left diagonal, right diagonal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +明: _ _ _ _ _ + +天 - day, sky +笔画数: 4 +笔顺: horizontal, vertical, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +天: _ _ _ _ _ + +气 - air, gas +笔画数: 4 +笔顺: horizontal, vertical, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +气: _ _ _ _ _ + +很 - very +笔画数: 9 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +很: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_hsk3_-_intermediate_en.txt b/flutter_app/assets/writing/character_hsk3_-_intermediate_en.txt new file mode 100644 index 0000000..f0cdbba --- /dev/null +++ b/flutter_app/assets/writing/character_hsk3_-_intermediate_en.txt @@ -0,0 +1,85 @@ +HSK3 Intermediate Characters +-------------------- + +Practice intermediate characters from HSK Level 3 + +因 - yīn - because +Stroke count: 6 +Stroke order: top, left vertical, right vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +因: _ _ _ _ _ + +所 - suǒ - place +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +所: _ _ _ _ _ + +以 - yǐ - by means of +Stroke count: 5 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +以: _ _ _ _ _ + +但 - dàn - but +Stroke count: 7 +Stroke order: left diagonal, right diagonal, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +但: _ _ _ _ _ + +现 - xiàn - present, now +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +现: _ _ _ _ _ + +在 - zài - at, in +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +在: _ _ _ _ _ + +做 - zuò - to do +Stroke count: 11 +Stroke order: left diagonal, right diagonal, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +做: _ _ _ _ _ + +得 - dé - to get +Stroke count: 11 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +得: _ _ _ _ _ + +和 - hé - and +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +和: _ _ _ _ _ + +时 - shí - time +Stroke count: 10 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +时: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_hsk3_-_intermediate_pinyin.txt b/flutter_app/assets/writing/character_hsk3_-_intermediate_pinyin.txt new file mode 100644 index 0000000..f5beb82 --- /dev/null +++ b/flutter_app/assets/writing/character_hsk3_-_intermediate_pinyin.txt @@ -0,0 +1,85 @@ +HSK3 中级汉字 / HSK3 Intermediate Characters +-------------------- + +Practice intermediate characters from HSK Level 3 + +因 - yīn - because +Stroke count: 6 +Stroke order: top, left vertical, right vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +因: _ _ _ _ _ + +所 - suǒ - place +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +所: _ _ _ _ _ + +以 - yǐ - by means of +Stroke count: 5 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +以: _ _ _ _ _ + +但 - dàn - but +Stroke count: 7 +Stroke order: left diagonal, right diagonal, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +但: _ _ _ _ _ + +现 - xiàn - present, now +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +现: _ _ _ _ _ + +在 - zài - at, in +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +在: _ _ _ _ _ + +做 - zuò - to do +Stroke count: 11 +Stroke order: left diagonal, right diagonal, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +做: _ _ _ _ _ + +得 - dé - to get +Stroke count: 11 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +得: _ _ _ _ _ + +和 - hé - and +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +和: _ _ _ _ _ + +时 - shí - time +Stroke count: 10 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +时: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_hsk3_-_intermediate_zh.txt b/flutter_app/assets/writing/character_hsk3_-_intermediate_zh.txt new file mode 100644 index 0000000..67385d7 --- /dev/null +++ b/flutter_app/assets/writing/character_hsk3_-_intermediate_zh.txt @@ -0,0 +1,85 @@ +HSK3 中级汉字 +-------------------- + +练习HSK三级中的中级汉字 + +因 - because +笔画数: 6 +笔顺: top, left vertical, right vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +因: _ _ _ _ _ + +所 - place +笔画数: 8 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +所: _ _ _ _ _ + +以 - by means of +笔画数: 5 +笔顺: horizontal, vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +以: _ _ _ _ _ + +但 - but +笔画数: 7 +笔顺: left diagonal, right diagonal, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +但: _ _ _ _ _ + +现 - present, now +笔画数: 8 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +现: _ _ _ _ _ + +在 - at, in +笔画数: 6 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +在: _ _ _ _ _ + +做 - to do +笔画数: 11 +笔顺: left diagonal, right diagonal, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +做: _ _ _ _ _ + +得 - to get +笔画数: 11 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +得: _ _ _ _ _ + +和 - and +笔画数: 8 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +和: _ _ _ _ _ + +时 - time +笔画数: 10 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +时: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_numbers_en.txt b/flutter_app/assets/writing/character_numbers_en.txt new file mode 100644 index 0000000..d342b42 --- /dev/null +++ b/flutter_app/assets/writing/character_numbers_en.txt @@ -0,0 +1,45 @@ +Numbers +-------------------- + +Practice writing Chinese numbers + +一 - yī - one +Stroke count: 1 +Stroke order: horizontal + +Write each number 5 times, paying attention to stroke order: + +一: _ _ _ _ _ + +二 - èr - two +Stroke count: 2 +Stroke order: top horizontal, bottom horizontal + +Write each number 5 times, paying attention to stroke order: + +二: _ _ _ _ _ + +三 - sān - three +Stroke count: 3 +Stroke order: top horizontal, middle horizontal, bottom horizontal + +Write each number 5 times, paying attention to stroke order: + +三: _ _ _ _ _ + +四 - sì - four +Stroke count: 5 +Stroke order: left horizontal, top horizontal, right vertical, middle horizontal, bottom box + +Write each number 5 times, paying attention to stroke order: + +四: _ _ _ _ _ + +五 - wǔ - five +Stroke count: 4 +Stroke order: horizontal, vertical, left horizontal, right horizontal + +Write each number 5 times, paying attention to stroke order: + +五: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_numbers_pinyin.txt b/flutter_app/assets/writing/character_numbers_pinyin.txt new file mode 100644 index 0000000..b7a45b1 --- /dev/null +++ b/flutter_app/assets/writing/character_numbers_pinyin.txt @@ -0,0 +1,45 @@ +数字 / Numbers +-------------------- + +Practice writing Chinese numbers + +一 - yī - one +Stroke count: 1 +Stroke order: horizontal + +Write each number 5 times, paying attention to stroke order: + +一: _ _ _ _ _ + +二 - èr - two +Stroke count: 2 +Stroke order: top horizontal, bottom horizontal + +Write each number 5 times, paying attention to stroke order: + +二: _ _ _ _ _ + +三 - sān - three +Stroke count: 3 +Stroke order: top horizontal, middle horizontal, bottom horizontal + +Write each number 5 times, paying attention to stroke order: + +三: _ _ _ _ _ + +四 - sì - four +Stroke count: 5 +Stroke order: left horizontal, top horizontal, right vertical, middle horizontal, bottom box + +Write each number 5 times, paying attention to stroke order: + +四: _ _ _ _ _ + +五 - wǔ - five +Stroke count: 4 +Stroke order: horizontal, vertical, left horizontal, right horizontal + +Write each number 5 times, paying attention to stroke order: + +五: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_numbers_zh.txt b/flutter_app/assets/writing/character_numbers_zh.txt new file mode 100644 index 0000000..f743771 --- /dev/null +++ b/flutter_app/assets/writing/character_numbers_zh.txt @@ -0,0 +1,45 @@ +数字 +-------------------- + +练习书写中文数字 + +一 - one +笔画数: 1 +笔顺: horizontal + +Write each number 5 times, paying attention to stroke order: + +一: _ _ _ _ _ + +二 - two +笔画数: 2 +笔顺: top horizontal, bottom horizontal + +Write each number 5 times, paying attention to stroke order: + +二: _ _ _ _ _ + +三 - three +笔画数: 3 +笔顺: top horizontal, middle horizontal, bottom horizontal + +Write each number 5 times, paying attention to stroke order: + +三: _ _ _ _ _ + +四 - four +笔画数: 5 +笔顺: left horizontal, top horizontal, right vertical, middle horizontal, bottom box + +Write each number 5 times, paying attention to stroke order: + +四: _ _ _ _ _ + +五 - five +笔画数: 4 +笔顺: horizontal, vertical, left horizontal, right horizontal + +Write each number 5 times, paying attention to stroke order: + +五: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_theme_-_family_en.txt b/flutter_app/assets/writing/character_theme_-_family_en.txt new file mode 100644 index 0000000..87cea46 --- /dev/null +++ b/flutter_app/assets/writing/character_theme_-_family_en.txt @@ -0,0 +1,85 @@ +Theme - Family +-------------------- + +Practice characters related to family members and relationships + +家 - jiā - home, family +Stroke count: 10 +Stroke order: top, left vertical, right vertical, horizontal, left diagonal, right diagonal, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +家: _ _ _ _ _ + +爸 - bà - father +Stroke count: 9 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +爸: _ _ _ _ _ + +妈 - mā - mother +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +妈: _ _ _ _ _ + +哥 - gē - older brother +Stroke count: 10 +Stroke order: top, right, bottom-left, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +哥: _ _ _ _ _ + +姐 - jiě - older sister +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +姐: _ _ _ _ _ + +弟 - dì - younger brother +Stroke count: 7 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +弟: _ _ _ _ _ + +妹 - mèi - younger sister +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +妹: _ _ _ _ _ + +儿 - ér - son, child +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +儿: _ _ _ _ _ + +女 - nǚ - female, daughter +Stroke count: 3 +Stroke order: left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +女: _ _ _ _ _ + +爱 - ài - love +Stroke count: 10 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +爱: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_theme_-_family_pinyin.txt b/flutter_app/assets/writing/character_theme_-_family_pinyin.txt new file mode 100644 index 0000000..d651abc --- /dev/null +++ b/flutter_app/assets/writing/character_theme_-_family_pinyin.txt @@ -0,0 +1,85 @@ +主题 - 家庭 / Theme - Family +-------------------- + +Practice characters related to family members and relationships + +家 - jiā - home, family +Stroke count: 10 +Stroke order: top, left vertical, right vertical, horizontal, left diagonal, right diagonal, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +家: _ _ _ _ _ + +爸 - bà - father +Stroke count: 9 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +爸: _ _ _ _ _ + +妈 - mā - mother +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +妈: _ _ _ _ _ + +哥 - gē - older brother +Stroke count: 10 +Stroke order: top, right, bottom-left, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +哥: _ _ _ _ _ + +姐 - jiě - older sister +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +姐: _ _ _ _ _ + +弟 - dì - younger brother +Stroke count: 7 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +弟: _ _ _ _ _ + +妹 - mèi - younger sister +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +妹: _ _ _ _ _ + +儿 - ér - son, child +Stroke count: 2 +Stroke order: left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +儿: _ _ _ _ _ + +女 - nǚ - female, daughter +Stroke count: 3 +Stroke order: left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +女: _ _ _ _ _ + +爱 - ài - love +Stroke count: 10 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +爱: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_theme_-_family_zh.txt b/flutter_app/assets/writing/character_theme_-_family_zh.txt new file mode 100644 index 0000000..c9c99f8 --- /dev/null +++ b/flutter_app/assets/writing/character_theme_-_family_zh.txt @@ -0,0 +1,85 @@ +主题 - 家庭 +-------------------- + +练习与家庭成员和关系相关的汉字 + +家 - home, family +笔画数: 10 +笔顺: top, left vertical, right vertical, horizontal, left diagonal, right diagonal, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +家: _ _ _ _ _ + +爸 - father +笔画数: 9 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +爸: _ _ _ _ _ + +妈 - mother +笔画数: 6 +笔顺: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +妈: _ _ _ _ _ + +哥 - older brother +笔画数: 10 +笔顺: top, right, bottom-left, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +哥: _ _ _ _ _ + +姐 - older sister +笔画数: 8 +笔顺: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +姐: _ _ _ _ _ + +弟 - younger brother +笔画数: 7 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +弟: _ _ _ _ _ + +妹 - younger sister +笔画数: 8 +笔顺: horizontal, vertical, horizontal, left diagonal, right diagonal, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +妹: _ _ _ _ _ + +儿 - son, child +笔画数: 2 +笔顺: left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +儿: _ _ _ _ _ + +女 - female, daughter +笔画数: 3 +笔顺: left diagonal, right diagonal, horizontal + +Write each character 5 times, paying attention to stroke order: + +女: _ _ _ _ _ + +爱 - love +笔画数: 10 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +爱: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_theme_-_food_en.txt b/flutter_app/assets/writing/character_theme_-_food_en.txt new file mode 100644 index 0000000..b47dd84 --- /dev/null +++ b/flutter_app/assets/writing/character_theme_-_food_en.txt @@ -0,0 +1,85 @@ +Theme - Food +-------------------- + +Practice characters related to food and dining + +吃 - chī - to eat +Stroke count: 6 +Stroke order: top, right, bottom-left, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +吃: _ _ _ _ _ + +饭 - fàn - rice, meal +Stroke count: 7 +Stroke order: left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +饭: _ _ _ _ _ + +菜 - cài - dish, vegetable +Stroke count: 11 +Stroke order: top, left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +菜: _ _ _ _ _ + +米 - mǐ - rice +Stroke count: 6 +Stroke order: top, left vertical, right vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +米: _ _ _ _ _ + +面 - miàn - noodle, face +Stroke count: 9 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +面: _ _ _ _ _ + +茶 - chá - tea +Stroke count: 9 +Stroke order: top, left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +茶: _ _ _ _ _ + +水 - shuǐ - water +Stroke count: 4 +Stroke order: left dot, right dot, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +水: _ _ _ _ _ + +果 - guǒ - fruit +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +果: _ _ _ _ _ + +鱼 - yú - fish +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +鱼: _ _ _ _ _ + +肉 - ròu - meat +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +肉: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_theme_-_food_pinyin.txt b/flutter_app/assets/writing/character_theme_-_food_pinyin.txt new file mode 100644 index 0000000..c1064e6 --- /dev/null +++ b/flutter_app/assets/writing/character_theme_-_food_pinyin.txt @@ -0,0 +1,85 @@ +主题 - 食物 / Theme - Food +-------------------- + +Practice characters related to food and dining + +吃 - chī - to eat +Stroke count: 6 +Stroke order: top, right, bottom-left, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +吃: _ _ _ _ _ + +饭 - fàn - rice, meal +Stroke count: 7 +Stroke order: left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +饭: _ _ _ _ _ + +菜 - cài - dish, vegetable +Stroke count: 11 +Stroke order: top, left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +菜: _ _ _ _ _ + +米 - mǐ - rice +Stroke count: 6 +Stroke order: top, left vertical, right vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +米: _ _ _ _ _ + +面 - miàn - noodle, face +Stroke count: 9 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +面: _ _ _ _ _ + +茶 - chá - tea +Stroke count: 9 +Stroke order: top, left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +茶: _ _ _ _ _ + +水 - shuǐ - water +Stroke count: 4 +Stroke order: left dot, right dot, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +水: _ _ _ _ _ + +果 - guǒ - fruit +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +果: _ _ _ _ _ + +鱼 - yú - fish +Stroke count: 8 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +鱼: _ _ _ _ _ + +肉 - ròu - meat +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +肉: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_theme_-_food_zh.txt b/flutter_app/assets/writing/character_theme_-_food_zh.txt new file mode 100644 index 0000000..307ddb7 --- /dev/null +++ b/flutter_app/assets/writing/character_theme_-_food_zh.txt @@ -0,0 +1,85 @@ +主题 - 食物 +-------------------- + +练习与食物和用餐相关的汉字 + +吃 - to eat +笔画数: 6 +笔顺: top, right, bottom-left, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +吃: _ _ _ _ _ + +饭 - rice, meal +笔画数: 7 +笔顺: left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +饭: _ _ _ _ _ + +菜 - dish, vegetable +笔画数: 11 +笔顺: top, left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +菜: _ _ _ _ _ + +米 - rice +笔画数: 6 +笔顺: top, left vertical, right vertical, horizontal, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +米: _ _ _ _ _ + +面 - noodle, face +笔画数: 9 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +面: _ _ _ _ _ + +茶 - tea +笔画数: 9 +笔顺: top, left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +茶: _ _ _ _ _ + +水 - water +笔画数: 4 +笔顺: left dot, right dot, left diagonal, right diagonal + +Write each character 5 times, paying attention to stroke order: + +水: _ _ _ _ _ + +果 - fruit +笔画数: 8 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +果: _ _ _ _ _ + +鱼 - fish +笔画数: 8 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +鱼: _ _ _ _ _ + +肉 - meat +笔画数: 6 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +肉: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_theme_-_travel_en.txt b/flutter_app/assets/writing/character_theme_-_travel_en.txt new file mode 100644 index 0000000..4059707 --- /dev/null +++ b/flutter_app/assets/writing/character_theme_-_travel_en.txt @@ -0,0 +1,85 @@ +Theme - Travel +-------------------- + +Practice characters related to travel and transportation + +车 - chē - car, vehicle +Stroke count: 4 +Stroke order: horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +车: _ _ _ _ _ + +飞 - fēi - to fly +Stroke count: 9 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +飞: _ _ _ _ _ + +机 - jī - machine +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +机: _ _ _ _ _ + +场 - chǎng - field, place +Stroke count: 12 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +场: _ _ _ _ _ + +路 - lù - road +Stroke count: 13 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +路: _ _ _ _ _ + +站 - zhàn - station +Stroke count: 10 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +站: _ _ _ _ _ + +票 - piào - ticket +Stroke count: 11 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +票: _ _ _ _ _ + +行 - xíng - to go, travel +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +行: _ _ _ _ _ + +李 - lǐ - plum, surname Li +Stroke count: 7 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +李: _ _ _ _ _ + +国 - guó - country +Stroke count: 8 +Stroke order: top, left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +国: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_theme_-_travel_pinyin.txt b/flutter_app/assets/writing/character_theme_-_travel_pinyin.txt new file mode 100644 index 0000000..ae53005 --- /dev/null +++ b/flutter_app/assets/writing/character_theme_-_travel_pinyin.txt @@ -0,0 +1,85 @@ +主题 - 旅行 / Theme - Travel +-------------------- + +Practice characters related to travel and transportation + +车 - chē - car, vehicle +Stroke count: 4 +Stroke order: horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +车: _ _ _ _ _ + +飞 - fēi - to fly +Stroke count: 9 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +飞: _ _ _ _ _ + +机 - jī - machine +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +机: _ _ _ _ _ + +场 - chǎng - field, place +Stroke count: 12 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +场: _ _ _ _ _ + +路 - lù - road +Stroke count: 13 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +路: _ _ _ _ _ + +站 - zhàn - station +Stroke count: 10 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +站: _ _ _ _ _ + +票 - piào - ticket +Stroke count: 11 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +票: _ _ _ _ _ + +行 - xíng - to go, travel +Stroke count: 6 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +行: _ _ _ _ _ + +李 - lǐ - plum, surname Li +Stroke count: 7 +Stroke order: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +李: _ _ _ _ _ + +国 - guó - country +Stroke count: 8 +Stroke order: top, left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +国: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/character_theme_-_travel_zh.txt b/flutter_app/assets/writing/character_theme_-_travel_zh.txt new file mode 100644 index 0000000..0fc120e --- /dev/null +++ b/flutter_app/assets/writing/character_theme_-_travel_zh.txt @@ -0,0 +1,85 @@ +主题 - 旅行 +-------------------- + +练习与旅行和交通相关的汉字 + +车 - car, vehicle +笔画数: 4 +笔顺: horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +车: _ _ _ _ _ + +飞 - to fly +笔画数: 9 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +飞: _ _ _ _ _ + +机 - machine +笔画数: 6 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +机: _ _ _ _ _ + +场 - field, place +笔画数: 12 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +场: _ _ _ _ _ + +路 - road +笔画数: 13 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +路: _ _ _ _ _ + +站 - station +笔画数: 10 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +站: _ _ _ _ _ + +票 - ticket +笔画数: 11 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +票: _ _ _ _ _ + +行 - to go, travel +笔画数: 6 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical + +Write each character 5 times, paying attention to stroke order: + +行: _ _ _ _ _ + +李 - plum, surname Li +笔画数: 7 +笔顺: horizontal, vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +李: _ _ _ _ _ + +国 - country +笔画数: 8 +笔顺: top, left vertical, right vertical, horizontal, vertical, horizontal, vertical, horizontal + +Write each character 5 times, paying attention to stroke order: + +国: _ _ _ _ _ + diff --git a/flutter_app/assets/writing/sentence_advanced_en.txt b/flutter_app/assets/writing/sentence_advanced_en.txt new file mode 100644 index 0000000..de182d5 --- /dev/null +++ b/flutter_app/assets/writing/sentence_advanced_en.txt @@ -0,0 +1,25 @@ +Advanced Sentence Completion +-------------------- + +Complete complex sentences with appropriate words or phrases + +1. 环境保护 ____ 全球关注的重要话题。(become) +Answer: 已经成为 (yǐjīng chéngwéi) +Full sentence: Environmental protection has become an important topic of global concern. + +2. 随着经济的发展,人们的生活水平 ____ 。(improve) +Answer: 不断提高 (bùduàn tígāo) +Full sentence: With the development of the economy, people's living standards are constantly improving. + +3. 尽管面临挑战,他们 ____ 取得了成功。(still) +Answer: 仍然 (réngrán) +Full sentence: Despite facing challenges, they still achieved success. + +4. 这个问题 ____ 进一步研究。(need) +Answer: 需要 (xūyào) +Full sentence: This issue needs further research. + +5. 我们应该 ____ 自然资源。(protect) +Answer: 保护 (bǎohù) +Full sentence: We should protect natural resources. + diff --git a/flutter_app/assets/writing/sentence_advanced_pinyin.txt b/flutter_app/assets/writing/sentence_advanced_pinyin.txt new file mode 100644 index 0000000..aeb36f4 --- /dev/null +++ b/flutter_app/assets/writing/sentence_advanced_pinyin.txt @@ -0,0 +1,25 @@ +高级句子完成 / Advanced Sentence Completion +-------------------- + +Complete complex sentences with appropriate words or phrases + +1. 环境保护 ____ 全球关注的重要话题。(become) +Answer: 已经成为 (yǐjīng chéngwéi) +Full sentence: 环境保护已经成为全球关注的重要话题。 + +2. 随着经济的发展,人们的生活水平 ____ 。(improve) +Answer: 不断提高 (bùduàn tígāo) +Full sentence: 随着经济的发展,人们的生活水平不断提高。 + +3. 尽管面临挑战,他们 ____ 取得了成功。(still) +Answer: 仍然 (réngrán) +Full sentence: 尽管面临挑战,他们仍然取得了成功。 + +4. 这个问题 ____ 进一步研究。(need) +Answer: 需要 (xūyào) +Full sentence: 这个问题需要进一步研究。 + +5. 我们应该 ____ 自然资源。(protect) +Answer: 保护 (bǎohù) +Full sentence: 我们应该保护自然资源。 + diff --git a/flutter_app/assets/writing/sentence_advanced_zh.txt b/flutter_app/assets/writing/sentence_advanced_zh.txt new file mode 100644 index 0000000..3a63bce --- /dev/null +++ b/flutter_app/assets/writing/sentence_advanced_zh.txt @@ -0,0 +1,25 @@ +高级句子完成 +-------------------- + +用适当的词语或短语完成复杂句子 + +1. 环境保护 ____ 全球关注的重要话题。(become) +答案: 已经成为 +完整句子: 环境保护已经成为全球关注的重要话题。 + +2. 随着经济的发展,人们的生活水平 ____ 。(improve) +答案: 不断提高 +完整句子: 随着经济的发展,人们的生活水平不断提高。 + +3. 尽管面临挑战,他们 ____ 取得了成功。(still) +答案: 仍然 +完整句子: 尽管面临挑战,他们仍然取得了成功。 + +4. 这个问题 ____ 进一步研究。(need) +答案: 需要 +完整句子: 这个问题需要进一步研究。 + +5. 我们应该 ____ 自然资源。(protect) +答案: 保护 +完整句子: 我们应该保护自然资源。 + diff --git a/flutter_app/assets/writing/sentence_beginner_en.txt b/flutter_app/assets/writing/sentence_beginner_en.txt new file mode 100644 index 0000000..75617f5 --- /dev/null +++ b/flutter_app/assets/writing/sentence_beginner_en.txt @@ -0,0 +1,25 @@ +Beginner Sentence Completion +-------------------- + +Complete sentences with appropriate words + +1. 我 ____ 中文。(study) +Answer: 学习 (xuéxí) +Full sentence: I study Chinese. + +2. 他 ____ 咖啡。(drink) +Answer: 喝 (hē) +Full sentence: He drinks coffee. + +3. 我们 ____ 去北京。(want) +Answer: 想 (xiǎng) +Full sentence: We want to go to Beijing. + +4. 她 ____ 看书。(like) +Answer: 喜欢 (xǐhuan) +Full sentence: She likes to read books. + +5. 你 ____ 多少岁?(be) +Answer: 是 (shì) +Full sentence: How old are you? + diff --git a/flutter_app/assets/writing/sentence_beginner_pinyin.txt b/flutter_app/assets/writing/sentence_beginner_pinyin.txt new file mode 100644 index 0000000..6a41f7b --- /dev/null +++ b/flutter_app/assets/writing/sentence_beginner_pinyin.txt @@ -0,0 +1,25 @@ +初级句子完成 / Beginner Sentence Completion +-------------------- + +Complete sentences with appropriate words + +1. 我 ____ 中文。(study) +Answer: 学习 (xuéxí) +Full sentence: 我学习中文。 + +2. 他 ____ 咖啡。(drink) +Answer: 喝 (hē) +Full sentence: 他喝咖啡。 + +3. 我们 ____ 去北京。(want) +Answer: 想 (xiǎng) +Full sentence: 我们想去北京。 + +4. 她 ____ 看书。(like) +Answer: 喜欢 (xǐhuan) +Full sentence: 她喜欢看书。 + +5. 你 ____ 多少岁?(be) +Answer: 是 (shì) +Full sentence: 你是多少岁? + diff --git a/flutter_app/assets/writing/sentence_beginner_zh.txt b/flutter_app/assets/writing/sentence_beginner_zh.txt new file mode 100644 index 0000000..1e30c30 --- /dev/null +++ b/flutter_app/assets/writing/sentence_beginner_zh.txt @@ -0,0 +1,25 @@ +初级句子完成 +-------------------- + +用适当的词语完成句子 + +1. 我 ____ 中文。(study) +答案: 学习 +完整句子: 我学习中文。 + +2. 他 ____ 咖啡。(drink) +答案: 喝 +完整句子: 他喝咖啡。 + +3. 我们 ____ 去北京。(want) +答案: 想 +完整句子: 我们想去北京。 + +4. 她 ____ 看书。(like) +答案: 喜欢 +完整句子: 她喜欢看书。 + +5. 你 ____ 多少岁?(be) +答案: 是 +完整句子: 你是多少岁? + diff --git a/flutter_app/assets/writing/sentence_intermediate_en.txt b/flutter_app/assets/writing/sentence_intermediate_en.txt new file mode 100644 index 0000000..9f7490d --- /dev/null +++ b/flutter_app/assets/writing/sentence_intermediate_en.txt @@ -0,0 +1,25 @@ +Intermediate Sentence Completion +-------------------- + +Complete sentences with appropriate words or phrases + +1. 如果明天 ____ ,我们就去公园。(good weather) +Answer: 天气好 (tiānqì hǎo) +Full sentence: If the weather is good tomorrow, we will go to the park. + +2. 虽然很难,但是我 ____ 学好中文。(determined) +Answer: 决心 (juéxīn) +Full sentence: Although it's difficult, I am determined to learn Chinese well. + +3. 我不但会说中文,____ 会说英文。(but also) +Answer: 而且 (érqiě) +Full sentence: I can not only speak Chinese, but also English. + +4. 他 ____ 我去机场。(help) +Answer: 帮助 (bāngzhù) +Full sentence: He helped me go to the airport. + +5. 这本书 ____ 有意思。(very) +Answer: 非常 (fēicháng) +Full sentence: This book is very interesting. + diff --git a/flutter_app/assets/writing/sentence_intermediate_pinyin.txt b/flutter_app/assets/writing/sentence_intermediate_pinyin.txt new file mode 100644 index 0000000..03294f5 --- /dev/null +++ b/flutter_app/assets/writing/sentence_intermediate_pinyin.txt @@ -0,0 +1,25 @@ +中级句子完成 / Intermediate Sentence Completion +-------------------- + +Complete sentences with appropriate words or phrases + +1. 如果明天 ____ ,我们就去公园。(good weather) +Answer: 天气好 (tiānqì hǎo) +Full sentence: 如果明天天气好,我们就去公园。 + +2. 虽然很难,但是我 ____ 学好中文。(determined) +Answer: 决心 (juéxīn) +Full sentence: 虽然很难,但是我决心学好中文。 + +3. 我不但会说中文,____ 会说英文。(but also) +Answer: 而且 (érqiě) +Full sentence: 我不但会说中文,而且会说英文。 + +4. 他 ____ 我去机场。(help) +Answer: 帮助 (bāngzhù) +Full sentence: 他帮助我去机场。 + +5. 这本书 ____ 有意思。(very) +Answer: 非常 (fēicháng) +Full sentence: 这本书非常有意思。 + diff --git a/flutter_app/assets/writing/sentence_intermediate_zh.txt b/flutter_app/assets/writing/sentence_intermediate_zh.txt new file mode 100644 index 0000000..592a6d8 --- /dev/null +++ b/flutter_app/assets/writing/sentence_intermediate_zh.txt @@ -0,0 +1,25 @@ +中级句子完成 +-------------------- + +用适当的词语或短语完成句子 + +1. 如果明天 ____ ,我们就去公园。(good weather) +答案: 天气好 +完整句子: 如果明天天气好,我们就去公园。 + +2. 虽然很难,但是我 ____ 学好中文。(determined) +答案: 决心 +完整句子: 虽然很难,但是我决心学好中文。 + +3. 我不但会说中文,____ 会说英文。(but also) +答案: 而且 +完整句子: 我不但会说中文,而且会说英文。 + +4. 他 ____ 我去机场。(help) +答案: 帮助 +完整句子: 他帮助我去机场。 + +5. 这本书 ____ 有意思。(very) +答案: 非常 +完整句子: 这本书非常有意思。 + diff --git a/flutter_app/assets/writing/translation_advanced_en.txt b/flutter_app/assets/writing/translation_advanced_en.txt new file mode 100644 index 0000000..aecaa1d --- /dev/null +++ b/flutter_app/assets/writing/translation_advanced_en.txt @@ -0,0 +1,20 @@ +Advanced Translation Exercises +-------------------- + +Translate complex sentences and paragraphs between English and Chinese + +1. Chinese: 科技的快速发展极大地改变了我们的生活方式。 +Translation: The rapid development of technology has greatly changed our way of life. + +2. Chinese: 环境保护不仅是政府的责任,也是每个公民的义务。 +Translation: Environmental protection is not only the responsibility of the government but also the duty of every citizen. + +3. Chinese: 随着全球化的发展,国家之间的文化交流变得越来越频繁。 +Translation: With the development of globalization, cultural exchange between countries has become increasingly frequent. + +4. Chinese: 尽管面临诸多挑战,他们坚持不懈地努力,最终取得了成功。 +Translation: Despite facing numerous challenges, they persisted in their efforts and finally achieved success. + +5. Chinese: 传统文化与现代元素的结合创造了独特的艺术风格。 +Translation: The combination of traditional culture and modern elements creates a unique artistic style. + diff --git a/flutter_app/assets/writing/translation_advanced_pinyin.txt b/flutter_app/assets/writing/translation_advanced_pinyin.txt new file mode 100644 index 0000000..2e367c4 --- /dev/null +++ b/flutter_app/assets/writing/translation_advanced_pinyin.txt @@ -0,0 +1,20 @@ +高级翻译练习 / Advanced Translation Exercises +-------------------- + +Translate complex sentences and paragraphs between English and Chinese + +1. English: The rapid development of technology has greatly changed our way of life. +Translation: Kējì de kuàisù fāzhǎn jídà de gǎibiànle wǒmen de shēnghuó fāngshì. + +2. English: Environmental protection is not only the responsibility of the government but also the duty of every citizen. +Translation: Huánjìng bǎohù bùjǐn shì zhèngfǔ de zérèn, yěshì měi gè gōngmín de yìwù. + +3. English: With the development of globalization, cultural exchange between countries has become increasingly frequent. +Translation: Suízhe quánqiúhuà de fāzhǎn, guójiā zhījiān de wénhuà jiāoliú biàn de yuè lái yuè pínfán. + +4. English: Despite facing numerous challenges, they persisted in their efforts and finally achieved success. +Translation: Jǐnguǎn miànlín zhūduō tiǎozhàn, tāmen jiānchí bùxiè de nǔlì, zuìzhōng qǔdéle chénggōng. + +5. English: The combination of traditional culture and modern elements creates a unique artistic style. +Translation: Chuántǒng wénhuà yǔ xiàndài yuánsù de jiéhé chuàngzàole dútè de yìshù fēnggé. + diff --git a/flutter_app/assets/writing/translation_advanced_zh.txt b/flutter_app/assets/writing/translation_advanced_zh.txt new file mode 100644 index 0000000..7df130d --- /dev/null +++ b/flutter_app/assets/writing/translation_advanced_zh.txt @@ -0,0 +1,20 @@ +高级翻译练习 +-------------------- + +翻译英文和中文之间的复杂句子和段落 + +1. 英文: The rapid development of technology has greatly changed our way of life. +翻译: 科技的快速发展极大地改变了我们的生活方式。 + +2. 英文: Environmental protection is not only the responsibility of the government but also the duty of every citizen. +翻译: 环境保护不仅是政府的责任,也是每个公民的义务。 + +3. 英文: With the development of globalization, cultural exchange between countries has become increasingly frequent. +翻译: 随着全球化的发展,国家之间的文化交流变得越来越频繁。 + +4. 英文: Despite facing numerous challenges, they persisted in their efforts and finally achieved success. +翻译: 尽管面临诸多挑战,他们坚持不懈地努力,最终取得了成功。 + +5. 英文: The combination of traditional culture and modern elements creates a unique artistic style. +翻译: 传统文化与现代元素的结合创造了独特的艺术风格。 + diff --git a/flutter_app/assets/writing/translation_beginner_en.txt b/flutter_app/assets/writing/translation_beginner_en.txt new file mode 100644 index 0000000..a6ed79e --- /dev/null +++ b/flutter_app/assets/writing/translation_beginner_en.txt @@ -0,0 +1,20 @@ +Beginner Translation Exercises +-------------------- + +Translate simple sentences between English and Chinese + +1. Chinese: 我叫李明。 +Translation: My name is Li Ming. + +2. Chinese: 我是学生。 +Translation: I am a student. + +3. Chinese: 我喜欢吃中国菜。 +Translation: I like to eat Chinese food. + +4. Chinese: 洗手间在哪里? +Translation: Where is the bathroom? + +5. Chinese: 这个多少钱? +Translation: How much does this cost? + diff --git a/flutter_app/assets/writing/translation_beginner_pinyin.txt b/flutter_app/assets/writing/translation_beginner_pinyin.txt new file mode 100644 index 0000000..eaec972 --- /dev/null +++ b/flutter_app/assets/writing/translation_beginner_pinyin.txt @@ -0,0 +1,20 @@ +初级翻译练习 / Beginner Translation Exercises +-------------------- + +Translate simple sentences between English and Chinese + +1. English: My name is Li Ming. +Translation: Wǒ jiào Lǐ Míng. + +2. English: I am a student. +Translation: Wǒ shì xuésheng. + +3. English: I like to eat Chinese food. +Translation: Wǒ xǐhuan chī zhōngguó cài. + +4. English: Where is the bathroom? +Translation: Xǐshǒujiān zài nǎlǐ? + +5. English: How much does this cost? +Translation: Zhège duōshao qián? + diff --git a/flutter_app/assets/writing/translation_beginner_zh.txt b/flutter_app/assets/writing/translation_beginner_zh.txt new file mode 100644 index 0000000..516c765 --- /dev/null +++ b/flutter_app/assets/writing/translation_beginner_zh.txt @@ -0,0 +1,20 @@ +初级翻译练习 +-------------------- + +翻译英文和中文之间的简单句子 + +1. 英文: My name is Li Ming. +翻译: 我叫李明。 + +2. 英文: I am a student. +翻译: 我是学生。 + +3. 英文: I like to eat Chinese food. +翻译: 我喜欢吃中国菜。 + +4. 英文: Where is the bathroom? +翻译: 洗手间在哪里? + +5. 英文: How much does this cost? +翻译: 这个多少钱? + diff --git a/flutter_app/assets/writing/translation_intermediate_en.txt b/flutter_app/assets/writing/translation_intermediate_en.txt new file mode 100644 index 0000000..1765725 --- /dev/null +++ b/flutter_app/assets/writing/translation_intermediate_en.txt @@ -0,0 +1,20 @@ +Intermediate Translation Exercises +-------------------- + +Translate more complex sentences between English and Chinese + +1. Chinese: 我学习中文已经三年了。 +Translation: I have been studying Chinese for three years. + +2. Chinese: 虽然很难,但是我喜欢学习中文。 +Translation: Although it's difficult, I enjoy learning Chinese. + +3. Chinese: 你能说得慢一点吗? +Translation: Could you please speak more slowly? + +4. Chinese: 我计划明年去中国旅行。 +Translation: I plan to travel to China next year. + +5. Chinese: 你最喜欢的中国菜是什么? +Translation: What's your favorite Chinese dish? + diff --git a/flutter_app/assets/writing/translation_intermediate_pinyin.txt b/flutter_app/assets/writing/translation_intermediate_pinyin.txt new file mode 100644 index 0000000..0010a51 --- /dev/null +++ b/flutter_app/assets/writing/translation_intermediate_pinyin.txt @@ -0,0 +1,20 @@ +中级翻译练习 / Intermediate Translation Exercises +-------------------- + +Translate more complex sentences between English and Chinese + +1. English: I have been studying Chinese for three years. +Translation: Wǒ xuéxí zhōngwén yǐjīng sān nián le. + +2. English: Although it's difficult, I enjoy learning Chinese. +Translation: Suīrán hěn nán, dànshì wǒ xǐhuan xuéxí zhōngwén. + +3. English: Could you please speak more slowly? +Translation: Nǐ néng shuō de màn yīdiǎn ma? + +4. English: I plan to travel to China next year. +Translation: Wǒ jìhuà míngnián qù zhōngguó lǚxíng. + +5. English: What's your favorite Chinese dish? +Translation: Nǐ zuì xǐhuan de zhōngguó cài shì shénme? + diff --git a/flutter_app/assets/writing/translation_intermediate_zh.txt b/flutter_app/assets/writing/translation_intermediate_zh.txt new file mode 100644 index 0000000..a547df6 --- /dev/null +++ b/flutter_app/assets/writing/translation_intermediate_zh.txt @@ -0,0 +1,20 @@ +中级翻译练习 +-------------------- + +翻译英文和中文之间的更复杂句子 + +1. 英文: I have been studying Chinese for three years. +翻译: 我学习中文已经三年了。 + +2. 英文: Although it's difficult, I enjoy learning Chinese. +翻译: 虽然很难,但是我喜欢学习中文。 + +3. 英文: Could you please speak more slowly? +翻译: 你能说得慢一点吗? + +4. 英文: I plan to travel to China next year. +翻译: 我计划明年去中国旅行。 + +5. 英文: What's your favorite Chinese dish? +翻译: 你最喜欢的中国菜是什么? + diff --git a/flutter_app/lib/data/content_catalog.dart b/flutter_app/lib/data/content_catalog.dart new file mode 100644 index 0000000..83e2085 --- /dev/null +++ b/flutter_app/lib/data/content_catalog.dart @@ -0,0 +1,289 @@ +import '../models/lesson.dart'; + +class ActivityInfo { + final String key; + final String title; + final String titleZh; + final String titlePinyin; + final String description; + final String descriptionZh; + final String descriptionPinyin; + final bool hasAudio; + + const ActivityInfo({ + required this.key, + required this.title, + this.titleZh = '', + this.titlePinyin = '', + this.description = '', + this.descriptionZh = '', + this.descriptionPinyin = '', + this.hasAudio = true, + }); + + String displayTitle(Language lang) { + switch (lang) { + case Language.chinese: + return titleZh.isNotEmpty ? titleZh : title; + case Language.pinyin: + return titlePinyin.isNotEmpty ? titlePinyin : title; + case Language.english: + return title; + } + } + + String displayDescription(Language lang) { + switch (lang) { + case Language.chinese: + return descriptionZh.isNotEmpty ? descriptionZh : description; + case Language.pinyin: + return descriptionPinyin.isNotEmpty ? descriptionPinyin : description; + case Language.english: + return description; + } + } +} + +class ReadingTopic { + final String name; + final ActivityInfo info; + + const ReadingTopic({required this.name, required this.info}); +} + +const readingCatalog = >{ + 'beginner': [ + ReadingTopic( + name: 'Self Introduction', + info: ActivityInfo( + key: 'self_introduction', + title: 'Self Introduction', + description: 'A simple self-introduction in Mandarin', + ), + ), + ReadingTopic( + name: 'Daily Routine', + info: ActivityInfo( + key: 'daily_routine', + title: 'Daily Routine', + description: 'Learn vocabulary related to daily activities', + ), + ), + ], + 'intermediate': [ + ReadingTopic( + name: 'At the Restaurant', + info: ActivityInfo( + key: 'at_the_restaurant', + title: 'At the Restaurant', + description: 'Vocabulary and phrases for dining out', + ), + ), + ReadingTopic( + name: 'Weekend Plans', + info: ActivityInfo( + key: 'weekend_plans', + title: 'Weekend Plans', + description: 'Discussing weekend activities and plans', + ), + ), + ], + 'advanced': [ + ReadingTopic( + name: 'Environmental Protection', + info: ActivityInfo( + key: 'environmental_protection', + title: 'Environmental Protection', + description: 'Advanced vocabulary related to environmental issues', + ), + ), + ], +}; + +const writingCatalog = >{ + 'character': { + 'Basic Strokes': ActivityInfo( + key: 'basic_strokes', + title: 'Basic Strokes', + titleZh: '基本笔画', + titlePinyin: 'Jīběn bǐhuà', + description: 'Practice the fundamental strokes used in Chinese characters', + descriptionZh: '练习汉字中使用的基本笔画', + descriptionPinyin: 'Liànxí Hànzì zhōng shǐyòng de jīběn bǐhuà', + ), + 'Common Radicals': ActivityInfo( + key: 'common_radicals', + title: 'Common Radicals', + titleZh: '常用部首', + titlePinyin: 'Chángyòng bùshǒu', + description: + 'Practice common radicals that form the building blocks of Chinese characters', + descriptionZh: '练习构成汉字基本组成部分的常用部首', + descriptionPinyin: + 'Liànxí gòuchéng Hànzì jīběn zǔchéng bùfèn de chángyòng bùshǒu', + ), + 'Numbers': ActivityInfo( + key: 'numbers', + title: 'Numbers', + titleZh: '数字', + titlePinyin: 'Shùzì', + description: 'Practice writing Chinese numbers', + descriptionZh: '练习书写中文数字', + descriptionPinyin: 'Liànxí shūxiě Zhōngwén shùzì', + ), + 'Complete Radicals - Group 1': ActivityInfo( + key: 'complete_radicals_-_group_1', + title: 'Complete Radicals - Group 1', + titleZh: '完整部首 - 第一组', + titlePinyin: 'Wánzhěng bùshǒu - Dì yī zǔ', + description: 'Practice common radicals (1-30 of 214 Kangxi radicals)', + descriptionZh: '练习常用部首(康熙部首214个中的1-30个)', + descriptionPinyin: + 'Liànxí chángyòng bùshǒu (Kāngxī bùshǒu 214 gè zhōng de 1-30 gè)', + ), + 'Complete Radicals - Group 2': ActivityInfo( + key: 'complete_radicals_-_group_2', + title: 'Complete Radicals - Group 2', + titleZh: '完整部首 - 第二组', + titlePinyin: 'Wánzhěng bùshǒu - Dì èr zǔ', + description: 'Practice common radicals (31-60 of 214 Kangxi radicals)', + descriptionZh: '练习常用部首(康熙部首214个中的31-60个)', + descriptionPinyin: + 'Liànxí chángyòng bùshǒu (Kāngxī bùshǒu 214 gè zhōng de 31-60 gè)', + ), + 'Complete Radicals - Group 3': ActivityInfo( + key: 'complete_radicals_-_group_3', + title: 'Complete Radicals - Group 3', + titleZh: '完整部首 - 第三组', + titlePinyin: 'Wánzhěng bùshǒu - Dì sān zǔ', + description: 'Practice common radicals (61-90 of 214 Kangxi radicals)', + descriptionZh: '练习常用部首(康熙部首214个中的61-90个)', + descriptionPinyin: + 'Liànxí chángyòng bùshǒu (Kāngxī bùshǒu 214 gè zhōng de 61-90 gè)', + ), + 'HSK1 - Essential': ActivityInfo( + key: 'hsk1_-_essential', + title: 'HSK1 Essential Characters', + titleZh: 'HSK1 基础汉字', + titlePinyin: 'HSK1 jīchǔ Hànzì', + description: 'Practice the most common characters from HSK Level 1', + descriptionZh: '练习HSK一级中最常用的汉字', + descriptionPinyin: 'Liànxí HSK yī jí zhōng zuì chángyòng de Hànzì', + ), + 'HSK2 - Basic': ActivityInfo( + key: 'hsk2_-_basic', + title: 'HSK2 Basic Characters', + titleZh: 'HSK2 基本汉字', + titlePinyin: 'HSK2 jīběn Hànzì', + description: 'Practice common characters from HSK Level 2', + descriptionZh: '练习HSK二级中的常用汉字', + descriptionPinyin: 'Liànxí HSK èr jí zhōng de chángyòng Hànzì', + ), + 'HSK3 - Intermediate': ActivityInfo( + key: 'hsk3_-_intermediate', + title: 'HSK3 Intermediate Characters', + titleZh: 'HSK3 中级汉字', + titlePinyin: 'HSK3 zhōngjí Hànzì', + description: 'Practice intermediate characters from HSK Level 3', + descriptionZh: '练习HSK三级中的中级汉字', + descriptionPinyin: 'Liànxí HSK sān jí zhōng de zhōngjí Hànzì', + ), + 'Theme - Family': ActivityInfo( + key: 'theme_-_family', + title: 'Theme - Family', + titleZh: '主题 - 家庭', + titlePinyin: 'Zhǔtí - Jiātíng', + description: 'Practice characters related to family members and relationships', + descriptionZh: '练习与家庭成员和关系相关的汉字', + descriptionPinyin: 'Liànxí yǔ jiātíng chéngyuán hé guānxì xiāngguān de Hànzì', + ), + 'Theme - Food': ActivityInfo( + key: 'theme_-_food', + title: 'Theme - Food', + titleZh: '主题 - 食物', + titlePinyin: 'Zhǔtí - Shíwù', + description: 'Practice characters related to food and dining', + descriptionZh: '练习与食物和用餐相关的汉字', + descriptionPinyin: 'Liànxí yǔ shíwù hé yòngcān xiāngguān de Hànzì', + ), + 'Theme - Travel': ActivityInfo( + key: 'theme_-_travel', + title: 'Theme - Travel', + titleZh: '主题 - 旅行', + titlePinyin: 'Zhǔtí - Lǚxíng', + description: 'Practice characters related to travel and transportation', + descriptionZh: '练习与旅行和交通相关的汉字', + descriptionPinyin: 'Liànxí yǔ lǚxíng hé jiāotōng xiāngguān de Hànzì', + ), + }, + 'sentence': { + 'Beginner': ActivityInfo( + key: 'beginner', + title: 'Beginner Sentence Completion', + titleZh: '初级句子完成', + titlePinyin: 'Chūjí jùzi wánchéng', + description: 'Complete sentences with appropriate words', + descriptionZh: '用适当的词语完成句子', + descriptionPinyin: 'Yòng shìdàng de cíyǔ wánchéng jùzi', + ), + 'Intermediate': ActivityInfo( + key: 'intermediate', + title: 'Intermediate Sentence Completion', + titleZh: '中级句子完成', + titlePinyin: 'Zhōngjí jùzi wánchéng', + description: 'Complete sentences with appropriate words or phrases', + descriptionZh: '用适当的词语或短语完成句子', + descriptionPinyin: 'Yòng shìdàng de cíyǔ huò duǎnyǔ wánchéng jùzi', + ), + 'Advanced': ActivityInfo( + key: 'advanced', + title: 'Advanced Sentence Completion', + titleZh: '高级句子完成', + titlePinyin: 'Gāojí jùzi wánchéng', + description: + 'Complete complex sentences with appropriate words or phrases', + descriptionZh: '用适当的词语或短语完成复杂句子', + descriptionPinyin: 'Yòng shìdàng de cíyǔ huò duǎnyǔ wánchéng fùzá jùzi', + ), + }, + 'translation': { + 'Beginner': ActivityInfo( + key: 'beginner', + title: 'Beginner Translation Exercises', + titleZh: '初级翻译练习', + titlePinyin: 'Chūjí fānyì liànxí', + description: 'Translate simple sentences between English and Chinese', + descriptionZh: '翻译英文和中文之间的简单句子', + descriptionPinyin: 'Fānyì Yīngwén hé Zhōngwén zhījiān de jiǎndān jùzi', + ), + 'Intermediate': ActivityInfo( + key: 'intermediate', + title: 'Intermediate Translation Exercises', + titleZh: '中级翻译练习', + titlePinyin: 'Zhōngjí fānyì liànxí', + description: + 'Translate more complex sentences between English and Chinese', + descriptionZh: '翻译英文和中文之间的更复杂句子', + descriptionPinyin: 'Fānyì Yīngwén hé Zhōngwén zhījiān de gèng fùzá jùzi', + ), + 'Advanced': ActivityInfo( + key: 'advanced', + title: 'Advanced Translation Exercises', + titleZh: '高级翻译练习', + titlePinyin: 'Gāojí fānyì liànxí', + description: + 'Translate complex sentences and paragraphs between English and Chinese', + descriptionZh: '翻译英文和中文之间的复杂句子和段落', + descriptionPinyin: + 'Fānyì Yīngwén hé Zhōngwén zhījiān de fùzá jùzi hé duànluò', + ), + }, +}; + +String slugify(String value) => value.toLowerCase().replaceAll(' ', '_'); + +String audioLangFor(Language lang) => lang == Language.pinyin ? 'zh' : lang.code; + +String readingTopicSlug(String topic) => slugify(topic); + +String writingLevelSlug(String level) => slugify(level); diff --git a/flutter_app/lib/data/placement_data.dart b/flutter_app/lib/data/placement_data.dart new file mode 100644 index 0000000..028d521 --- /dev/null +++ b/flutter_app/lib/data/placement_data.dart @@ -0,0 +1,139 @@ +import '../models/placement_models.dart'; + +const placementQuestions = [ + PlacementQuestion( + prompt: 'What does "你好" mean?', + options: ['Hello', 'Goodbye', 'Thank you', 'Excuse me'], + answer: 'Hello', + band: 'beginner', + ), + PlacementQuestion( + prompt: 'Choose the correct pinyin for "谢谢".', + options: ['xie xie', 'ni hao', 'zai jian', 'qing wen'], + answer: 'xie xie', + band: 'beginner', + ), + PlacementQuestion( + prompt: 'What does "我想要一杯水" mean?', + options: [ + 'I would like a glass of water', + 'I have a cup of tea', + 'Where is the water?', + 'This water is cold', + ], + answer: 'I would like a glass of water', + band: 'beginner', + ), + PlacementQuestion( + prompt: 'Which phrase asks "How much is this?"', + options: ['这个多少钱?', '洗手间在哪里?', '你叫什么名字?', '现在几点?'], + answer: '这个多少钱?', + band: 'beginner', + ), + PlacementQuestion( + prompt: 'What does "我周末想去看电影" mean?', + options: [ + 'I want to watch a movie this weekend', + 'I watched a movie yesterday', + 'I do not like movies', + 'The movie starts at noon', + ], + answer: 'I want to watch a movie this weekend', + band: 'intermediate', + ), + PlacementQuestion( + prompt: 'Choose the best translation for "菜单".', + options: ['Menu', 'Receipt', 'Reservation', 'Restaurant'], + answer: 'Menu', + band: 'intermediate', + ), + PlacementQuestion( + prompt: 'Which sentence means "I have studied Chinese for two years"?', + options: ['我学中文学了两年。', '我明年学中文。', '我两点学中文。', '我不会说中文。'], + answer: '我学中文学了两年。', + band: 'intermediate', + ), + PlacementQuestion( + prompt: 'What is the function of "因为...所以..."?', + options: [ + 'Cause and result', + 'Comparison', + 'Past action only', + 'A yes-or-no question', + ], + answer: 'Cause and result', + band: 'intermediate', + ), + PlacementQuestion( + prompt: 'What does "环境保护" mean?', + options: [ + 'Environmental protection', + 'Weekend plan', + 'Daily routine', + 'Language exchange', + ], + answer: 'Environmental protection', + band: 'advanced', + ), + PlacementQuestion( + prompt: 'Choose the best meaning of "减少浪费".', + options: ['Reduce waste', 'Increase speed', 'Protect privacy', 'Change schools'], + answer: 'Reduce waste', + band: 'advanced', + ), +]; + +PlacementResult scorePlacement(List answers) { + var score = 0; + for (var i = 0; i < placementQuestions.length; i++) { + if (answers[i] == placementQuestions[i].answer) score++; + } + final total = placementQuestions.length; + final percentage = ((score / total) * 100).round(); + final rec = _recommendation(score); + return PlacementResult( + score: score, + total: total, + percentage: percentage, + level: rec.level, + recommendedDay: rec.day, + messageZh: rec.messageZh, + messageEn: rec.messageEn, + completedAt: DateTime.now().toUtc(), + ); +} + +({String level, int day, String messageZh, String messageEn}) _recommendation( + int score, +) { + if (score <= 3) { + return ( + level: 'Beginner', + day: 1, + messageZh: '从基础开始,每天建立信心。', + messageEn: 'Start with the foundations and build daily confidence.', + ); + } + if (score <= 6) { + return ( + level: 'Upper beginner', + day: 8, + messageZh: '从第一周后开始学习,并根据需要复习前面的课程。', + messageEn: 'Begin after the first week and review earlier lessons as needed.', + ); + } + if (score <= 8) { + return ( + level: 'Intermediate', + day: 16, + messageZh: '从实用句型和较长对话开始。', + messageEn: 'Start with practical sentence patterns and longer exchanges.', + ); + } + return ( + level: 'Advanced', + day: 31, + messageZh: '进入更长的话题,并用测验进行复习。', + messageEn: 'Move into longer topics while using quizzes for review.', + ); +} diff --git a/flutter_app/lib/data/quiz_data.dart b/flutter_app/lib/data/quiz_data.dart new file mode 100644 index 0000000..12c3c87 --- /dev/null +++ b/flutter_app/lib/data/quiz_data.dart @@ -0,0 +1,127 @@ +import '../models/quiz_models.dart'; + +const quizBank = { + 1: QuizSet( + title: 'Greetings and introductions', + questions: [ + QuizQuestion( + type: 'multiple-choice', + prompt: 'What does "你好吗?" mean?', + options: ['How are you?', 'What is your name?', 'Where are you?', 'Goodbye'], + answer: 'How are you?', + ), + QuizQuestion( + type: 'multiple-choice', + prompt: 'Choose the correct pinyin for "再见".', + options: ['zai jian', 'xie xie', 'qing wen', 'ming tian'], + answer: 'zai jian', + ), + QuizQuestion( + type: 'fill-in', + prompt: 'Fill in the Mandarin for "I": ___', + answer: '我', + ), + ], + ), + 8: QuizSet( + title: 'Daily routine', + questions: [ + QuizQuestion( + type: 'multiple-choice', + prompt: 'What does "早上" mean?', + options: ['Morning', 'Afternoon', 'Evening', 'Weekend'], + answer: 'Morning', + ), + QuizQuestion( + type: 'multiple-choice', + prompt: 'Choose the phrase for "eat breakfast".', + options: ['吃早饭', '看电影', '去学校', '买东西'], + answer: '吃早饭', + ), + QuizQuestion( + type: 'fill-in', + prompt: 'Fill in the English meaning of "睡觉": ___', + answer: 'sleep', + ), + ], + ), + 16: QuizSet( + title: 'Restaurants and plans', + questions: [ + QuizQuestion( + type: 'multiple-choice', + prompt: 'What does "服务员" mean?', + options: ['Server', 'Teacher', 'Friend', 'Driver'], + answer: 'Server', + ), + QuizQuestion( + type: 'multiple-choice', + prompt: 'Which phrase means "I would like to order"?', + options: ['我想点菜', '我想回家', '我会说中文', '我喜欢周末'], + answer: '我想点菜', + ), + QuizQuestion( + type: 'fill-in', + prompt: 'Fill in the English meaning of "周末": ___', + answer: 'weekend', + ), + ], + ), + 31: QuizSet( + title: 'Longer topics', + questions: [ + QuizQuestion( + type: 'multiple-choice', + prompt: 'What does "环境" mean?', + options: ['Environment', 'Homework', 'Breakfast', 'Ticket'], + answer: 'Environment', + ), + QuizQuestion( + type: 'multiple-choice', + prompt: 'Choose the best translation for "保护".', + options: ['Protect', 'Compare', 'Reserve', 'Arrive'], + answer: 'Protect', + ), + QuizQuestion( + type: 'fill-in', + prompt: 'Fill in the English meaning of "浪费": ___', + answer: 'waste', + ), + ], + ), +}; + +QuizSet getQuizForDay(int day) { + if (quizBank.containsKey(day)) return quizBank[day]!; + final band = day <= 7 + ? quizBank[1]! + : day <= 15 + ? quizBank[8]! + : day <= 30 + ? quizBank[16]! + : quizBank[31]!; + return QuizSet(title: 'Day $day review', questions: band.questions); +} + +String normalizeAnswer(String? value) => + (value ?? '').trim().toLowerCase(); + +QuizResult scoreQuiz(int day, List answers) { + final quiz = getQuizForDay(day); + var score = 0; + for (var i = 0; i < quiz.questions.length; i++) { + if (normalizeAnswer(answers[i]) == + normalizeAnswer(quiz.questions[i].answer)) { + score++; + } + } + final total = quiz.questions.length; + return QuizResult( + day: day, + title: quiz.title, + score: score, + total: total, + percentage: ((score / total) * 100).round(), + completedAt: DateTime.now().toUtc(), + ); +} diff --git a/flutter_app/lib/l10n/strings.dart b/flutter_app/lib/l10n/strings.dart new file mode 100644 index 0000000..4bbeac7 --- /dev/null +++ b/flutter_app/lib/l10n/strings.dart @@ -0,0 +1,14 @@ +import '../models/lesson.dart'; + +class AppStrings { + static String t(Language lang, {required String zh, required String en, String? pinyin}) { + switch (lang) { + case Language.chinese: + return zh; + case Language.pinyin: + return pinyin ?? en; + case Language.english: + return en; + } + } +} diff --git a/flutter_app/lib/main.dart b/flutter_app/lib/main.dart index af68e1f..a19f4c9 100644 --- a/flutter_app/lib/main.dart +++ b/flutter_app/lib/main.dart @@ -5,6 +5,10 @@ import 'screens/home_screen.dart'; import 'screens/day_lesson_screen.dart'; import 'screens/reading_screen.dart'; import 'screens/writing_screen.dart'; +import 'screens/review_screen.dart'; +import 'screens/srs_screen.dart'; +import 'screens/placement_screen.dart'; +import 'screens/quiz_screen.dart'; import 'screens/supplementary_screen.dart'; import 'services/app_state.dart'; import 'services/storage_service.dart'; @@ -25,8 +29,8 @@ class MandarinPathwaysApp extends StatelessWidget { ChangeNotifierProvider( create: (_) => AppState( storage: StorageService(), - audio: AudioService(), - notification: NotificationService(), + audioService: AudioService(), + notificationService: NotificationService(), ), ), ], @@ -89,6 +93,10 @@ class MandarinPathwaysApp extends StatelessWidget { '/reading': (context) => const ReadingScreen(), '/writing': (context) => const WritingScreen(), '/supplementary': (context) => const SupplementaryScreen(), + '/review': (context) => const ReviewScreen(), + '/srs': (context) => const SrsScreen(), + '/placement': (context) => const PlacementScreen(), + '/quiz': (context) => const QuizScreen(), }, ), ); diff --git a/flutter_app/lib/models/achievement.dart b/flutter_app/lib/models/achievement.dart new file mode 100644 index 0000000..064cfac --- /dev/null +++ b/flutter_app/lib/models/achievement.dart @@ -0,0 +1,78 @@ +class Achievement { + final String id; + final String labelZh; + final String labelEn; + final String descriptionZh; + final String descriptionEn; + final bool Function(AchievementContext context) test; + + const Achievement({ + required this.id, + required this.labelZh, + required this.labelEn, + required this.descriptionZh, + required this.descriptionEn, + required this.test, + }); +} + +class AchievementContext { + final int completedLessonCount; + final int srsReviewCount; + + const AchievementContext({ + required this.completedLessonCount, + required this.srsReviewCount, + }); +} + +final achievementDefs = [ + Achievement( + id: 'first-lesson', + labelZh: '第一课', + labelEn: 'First lesson', + descriptionZh: '完成一节课程', + descriptionEn: 'Complete one lesson', + test: (c) => c.completedLessonCount >= 1, + ), + Achievement( + id: 'week-learner', + labelZh: '7天学习者', + labelEn: '7-day learner', + descriptionZh: '完成7节课程', + descriptionEn: 'Complete 7 lessons', + test: (c) => c.completedLessonCount >= 7, + ), + Achievement( + id: 'two-week-path', + labelZh: '两周路径', + labelEn: 'Two-week path', + descriptionZh: '完成14节课程', + descriptionEn: 'Complete 14 lessons', + test: (c) => c.completedLessonCount >= 14, + ), + Achievement( + id: 'thirty-day-build', + labelZh: '30天积累', + labelEn: '30-day build', + descriptionZh: '完成30节课程', + descriptionEn: 'Complete 30 lessons', + test: (c) => c.completedLessonCount >= 30, + ), + Achievement( + id: 'pathway-complete', + labelZh: '路径完成', + labelEn: 'Pathway complete', + descriptionZh: '完成全部40节课程', + descriptionEn: 'Complete all 40 lessons', + test: (c) => c.completedLessonCount >= 40, + ), + Achievement( + id: 'first-review', + labelZh: '第一次复习', + labelEn: 'First review', + descriptionZh: '完成一次间隔复习', + descriptionEn: 'Complete one SRS review', + test: (c) => c.srsReviewCount >= 1, + ), +]; diff --git a/flutter_app/lib/models/audio_cue.dart b/flutter_app/lib/models/audio_cue.dart new file mode 100644 index 0000000..c90401c --- /dev/null +++ b/flutter_app/lib/models/audio_cue.dart @@ -0,0 +1,36 @@ +class AudioCue { + final int index; + final double start; + final double end; + + const AudioCue({ + required this.index, + required this.start, + required this.end, + }); + + factory AudioCue.fromJson(Map json) { + return AudioCue( + index: json['i'] as int? ?? 0, + start: (json['start'] as num?)?.toDouble() ?? 0, + end: (json['end'] as num?)?.toDouble() ?? 0, + ); + } +} + +class TimingManifest { + final List phrases; + + const TimingManifest({required this.phrases}); + + factory TimingManifest.fromJson(Map json) { + final raw = json['phrases']; + if (raw is! List) return const TimingManifest(phrases: []); + return TimingManifest( + phrases: raw + .whereType>() + .map(AudioCue.fromJson) + .toList(), + ); + } +} diff --git a/flutter_app/lib/models/phrase_section.dart b/flutter_app/lib/models/phrase_section.dart new file mode 100644 index 0000000..27c320a --- /dev/null +++ b/flutter_app/lib/models/phrase_section.dart @@ -0,0 +1,13 @@ +class PhraseItem { + final int cueIndex; + final String text; + + const PhraseItem({required this.cueIndex, required this.text}); +} + +class PhraseSection { + final String title; + final List phrases; + + const PhraseSection({required this.title, required this.phrases}); +} diff --git a/flutter_app/lib/models/placement_models.dart b/flutter_app/lib/models/placement_models.dart new file mode 100644 index 0000000..c1db379 --- /dev/null +++ b/flutter_app/lib/models/placement_models.dart @@ -0,0 +1,67 @@ +class PlacementQuestion { + final String prompt; + final List options; + final String answer; + final String band; + + const PlacementQuestion({ + required this.prompt, + required this.options, + required this.answer, + required this.band, + }); +} + +class PlacementResult { + final int score; + final int total; + final int percentage; + final String level; + final int recommendedDay; + final String messageZh; + final String messageEn; + final DateTime completedAt; + + const PlacementResult({ + required this.score, + required this.total, + required this.percentage, + required this.level, + required this.recommendedDay, + required this.messageZh, + required this.messageEn, + required this.completedAt, + }); + + factory PlacementResult.fromJson(Map json) { + final message = json['message']; + String zh = ''; + String en = ''; + if (message is Map) { + zh = message['zh'] as String? ?? ''; + en = message['en'] as String? ?? ''; + } + return PlacementResult( + score: (json['score'] as num?)?.toInt() ?? 0, + total: (json['total'] as num?)?.toInt() ?? 0, + percentage: (json['percentage'] as num?)?.toInt() ?? 0, + level: json['level'] as String? ?? '', + recommendedDay: (json['recommendedDay'] as num?)?.toInt() ?? 1, + messageZh: zh, + messageEn: en, + completedAt: + DateTime.tryParse(json['completedAt'] as String? ?? '') ?? DateTime.now(), + ); + } + + Map toJson() => { + 'score': score, + 'total': total, + 'percentage': percentage, + 'level': level, + 'recommendedDay': recommendedDay, + 'startDay': recommendedDay, + 'message': {'zh': messageZh, 'en': messageEn}, + 'completedAt': completedAt.toIso8601String(), + }; +} diff --git a/flutter_app/lib/models/quiz_models.dart b/flutter_app/lib/models/quiz_models.dart new file mode 100644 index 0000000..1923854 --- /dev/null +++ b/flutter_app/lib/models/quiz_models.dart @@ -0,0 +1,58 @@ +class QuizQuestion { + final String type; + final String prompt; + final List options; + final String answer; + + const QuizQuestion({ + required this.type, + required this.prompt, + this.options = const [], + required this.answer, + }); +} + +class QuizSet { + final String title; + final List questions; + + const QuizSet({required this.title, required this.questions}); +} + +class QuizResult { + final int day; + final String title; + final int score; + final int total; + final int percentage; + final DateTime completedAt; + + const QuizResult({ + required this.day, + required this.title, + required this.score, + required this.total, + required this.percentage, + required this.completedAt, + }); + + Map toJson() => { + 'bestScore': score, + 'total': total, + 'percentage': percentage, + 'title': title, + 'completedAt': completedAt.toIso8601String(), + }; + + factory QuizResult.fromStored(int day, Map json) { + return QuizResult( + day: day, + title: json['title'] as String? ?? '', + score: (json['bestScore'] as num?)?.toInt() ?? 0, + total: (json['total'] as num?)?.toInt() ?? 0, + percentage: (json['percentage'] as num?)?.toInt() ?? 0, + completedAt: + DateTime.tryParse(json['completedAt'] as String? ?? '') ?? DateTime.now(), + ); + } +} diff --git a/flutter_app/lib/models/srs_card.dart b/flutter_app/lib/models/srs_card.dart new file mode 100644 index 0000000..9ff8988 --- /dev/null +++ b/flutter_app/lib/models/srs_card.dart @@ -0,0 +1,80 @@ +class SrsCard { + final String id; + final int? day; + final String lang; + final String front; + final String back; + final DateTime due; + final int interval; + final double ease; + final int reps; + final DateTime createdAt; + final DateTime updatedAt; + + const SrsCard({ + required this.id, + this.day, + required this.lang, + required this.front, + required this.back, + required this.due, + this.interval = 0, + this.ease = 2.5, + this.reps = 0, + required this.createdAt, + required this.updatedAt, + }); + + factory SrsCard.fromJson(Map json) { + final now = DateTime.now().toUtc(); + return SrsCard( + id: json['id'] as String? ?? '', + day: json['day'] as int?, + lang: json['lang'] as String? ?? 'zh', + front: json['front'] as String? ?? '', + back: json['back'] as String? ?? '', + due: DateTime.tryParse(json['due'] as String? ?? '') ?? now, + interval: (json['interval'] as num?)?.toInt() ?? 0, + ease: (json['ease'] as num?)?.toDouble() ?? 2.5, + reps: (json['reps'] as num?)?.toInt() ?? 0, + createdAt: DateTime.tryParse(json['createdAt'] as String? ?? '') ?? now, + updatedAt: DateTime.tryParse(json['updatedAt'] as String? ?? '') ?? now, + ); + } + + Map toJson() => { + 'id': id, + 'day': day, + 'lang': lang, + 'front': front, + 'back': back, + 'due': due.toIso8601String(), + 'interval': interval, + 'ease': ease, + 'reps': reps, + 'createdAt': createdAt.toIso8601String(), + 'updatedAt': updatedAt.toIso8601String(), + }; + + SrsCard copyWith({ + DateTime? due, + int? interval, + double? ease, + int? reps, + DateTime? updatedAt, + }) { + return SrsCard( + id: id, + day: day, + lang: lang, + front: front, + back: back, + due: due ?? this.due, + interval: interval ?? this.interval, + ease: ease ?? this.ease, + reps: reps ?? this.reps, + createdAt: createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ); + } +} diff --git a/flutter_app/lib/models/starred_phrase.dart b/flutter_app/lib/models/starred_phrase.dart new file mode 100644 index 0000000..511d87b --- /dev/null +++ b/flutter_app/lib/models/starred_phrase.dart @@ -0,0 +1,42 @@ +class StarredPhrase { + final String id; + final int day; + final String lang; + final String phrase; + final String sectionTitle; + final DateTime createdAt; + + const StarredPhrase({ + required this.id, + required this.day, + required this.lang, + required this.phrase, + required this.sectionTitle, + required this.createdAt, + }); + + factory StarredPhrase.fromJson(Map json) { + return StarredPhrase( + id: json['id'] as String? ?? '', + day: (json['day'] as num?)?.toInt() ?? 0, + lang: json['lang'] as String? ?? 'zh', + phrase: json['phrase'] as String? ?? '', + sectionTitle: json['sectionTitle'] as String? ?? '', + createdAt: DateTime.tryParse(json['createdAt'] as String? ?? '') ?? + DateTime.now().toUtc(), + ); + } + + Map toJson() => { + 'id': id, + 'day': day, + 'lang': lang, + 'phrase': phrase, + 'sectionTitle': sectionTitle, + 'createdAt': createdAt.toIso8601String(), + }; + + static String makeId(int day, String lang, String sectionTitle, String phrase) { + return '$day|$lang|$sectionTitle|$phrase'; + } +} diff --git a/flutter_app/lib/screens/day_lesson_screen.dart b/flutter_app/lib/screens/day_lesson_screen.dart index 1244f1f..29b3fe3 100644 --- a/flutter_app/lib/screens/day_lesson_screen.dart +++ b/flutter_app/lib/screens/day_lesson_screen.dart @@ -1,9 +1,12 @@ import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; -import 'package:audioplayers/audioplayers.dart' as ap; +import '../models/audio_cue.dart'; import '../models/lesson.dart'; +import '../models/phrase_section.dart'; +import '../l10n/strings.dart'; import '../services/app_state.dart'; +import '../widgets/lesson_audio_player.dart'; +import '../widgets/phrase_list.dart'; class DayLessonScreen extends StatefulWidget { const DayLessonScreen({super.key}); @@ -14,287 +17,161 @@ class DayLessonScreen extends StatefulWidget { class _DayLessonScreenState extends State { late int _dayNumber; - late Lesson _lesson; - String _lessonText = ''; - bool _isLoadingText = true; - ap.PlayerState _audioState = ap.PlayerState.stopped; - Duration _audioDuration = Duration.zero; - Duration _audioPosition = Duration.zero; + List _sections = []; + List _cues = []; + int? _activeCue; + bool _loading = true; + String? _error; @override void didChangeDependencies() { super.didChangeDependencies(); _dayNumber = ModalRoute.of(context)!.settings.arguments as int; - final appState = context.read(); - _lesson = appState.getLesson(_dayNumber); - _loadLessonText(); - _setupAudioListeners(); + _loadContent(); } - void _setupAudioListeners() { - final appState = context.read(); - appState.audioService.playerStateStream.listen((state) { - if (mounted) { - setState(() => _audioState = state); - } - }); - - appState.audioService.positionStream.listen((position) { - if (mounted) { - setState(() => _audioPosition = position); - } - }); - - appState.audioService.durationStream.listen((duration) { - if (mounted && duration != null) { - setState(() => _audioDuration = duration); - } + Future _loadContent() async { + setState(() { + _loading = true; + _error = null; }); - } - - Future _loadLessonText() async { - setState(() => _isLoadingText = true); + final appState = context.read(); + final lang = appState.currentLanguage; try { - final appState = context.read(); - final textPath = _lesson.textFiles[appState.currentLanguage.code]; - if (textPath != null) { - final text = await rootBundle.loadString('assets/$textPath'); - if (mounted) { - setState(() { - _lessonText = text; - _isLoadingText = false; - }); - } + final text = await appState.contentService.loadAssetText( + appState.contentService.dayTextPath(_dayNumber, lang), + ); + final timing = await appState.contentService.loadTiming( + appState.contentService.dayTimingPath(_dayNumber, lang), + ); + if (mounted) { + setState(() { + _sections = appState.contentService.parsePhraseSections(text); + _cues = timing?.phrases ?? []; + _loading = false; + }); } } catch (e) { if (mounted) { setState(() { - _lessonText = 'Error loading lesson text: $e'; - _isLoadingText = false; + _error = e.toString(); + _loading = false; }); } } } + void _updateCue() { + final appState = context.read(); + final pos = appState.audioService.currentPosition; + pos.then((p) { + if (!mounted || p == null) return; + final idx = appState.contentService.activeCueIndex(p, _cues); + if (idx != _activeCue) setState(() => _activeCue = idx); + }); + } + @override Widget build(BuildContext context) { + final appState = context.watch(); + final lang = appState.currentLanguage; + final lesson = appState.getLesson(_dayNumber); + final audioPath = appState.contentService.dayAudioPath(_dayNumber, lang); + return Scaffold( appBar: AppBar( title: Text('Day $_dayNumber'), actions: [ - Consumer( - builder: (context, appState, child) { - return IconButton( - icon: Text( - appState.currentLanguage.flag, - style: const TextStyle(fontSize: 24), - ), - onPressed: () => _showLanguageSelector(appState), - ); - }, + IconButton( + icon: Text(lang.flag, style: const TextStyle(fontSize: 24)), + onPressed: () => _showLanguagePicker(appState), ), ], ), - body: Consumer( - builder: (context, appState, child) { - return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - _buildSectionInfo(), - _buildAudioPlayer(appState), - _buildLessonContent(), - _buildCompletionButton(appState), - _buildNavigation(), - ], - ), - ); - }, - ), + body: _loading + ? const Center(child: CircularProgressIndicator()) + : _error != null + ? Center(child: Text('Error: $_error')) + : SingleChildScrollView( + child: Column( + children: [ + _sectionInfo(lesson), + LessonAudioPlayer( + audioPath: audioPath, + showPinyinNote: lang == Language.pinyin, + onPositionTick: _updateCue, + ), + PhraseListView( + sections: _sections, + day: _dayNumber, + activeCueIndex: _activeCue, + ), + Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Expanded( + child: ElevatedButton.icon( + onPressed: appState.isDayCompleted(_dayNumber) + ? null + : () => appState.markDayComplete(_dayNumber), + icon: const Icon(Icons.check), + label: Text( + appState.isDayCompleted(_dayNumber) + ? AppStrings.t(lang, + zh: '已完成', en: 'Completed') + : AppStrings.t(lang, + zh: '标记完成', en: 'Mark complete'), + ), + ), + ), + const SizedBox(width: 8), + OutlinedButton( + onPressed: () => Navigator.pushNamed( + context, '/quiz', arguments: _dayNumber), + child: Text( + AppStrings.t(lang, zh: '测验', en: 'Quiz'), + ), + ), + ], + ), + ), + _navButtons(), + ], + ), + ), ); } - Widget _buildSectionInfo() { + Widget _sectionInfo(Lesson lesson) { return Container( + width: double.infinity, padding: const EdgeInsets.all(16), - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.1), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - _lesson.section.title, - style: Theme.of(context).textTheme.titleLarge?.copyWith( - fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.primary, - ), - ), - const SizedBox(height: 4), - Text( - _lesson.section.description, - style: Theme.of(context).textTheme.bodyMedium, - ), + Text(lesson.section.title, + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.primary, + )), + Text(lesson.section.description), ], ), ); } - Widget _buildAudioPlayer(AppState appState) { - return Card( - margin: const EdgeInsets.all(16), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - IconButton( - icon: const Icon(Icons.replay_10), - onPressed: () { - final newPosition = _audioPosition - const Duration(seconds: 10); - appState.audioService.seek( - newPosition < Duration.zero ? Duration.zero : newPosition, - ); - }, - ), - IconButton( - iconSize: 48, - icon: Icon( - _audioState == ap.PlayerState.playing - ? Icons.pause_circle_filled - : Icons.play_circle_filled, - ), - onPressed: () => _toggleAudio(appState), - ), - IconButton( - icon: const Icon(Icons.forward_10), - onPressed: () { - final newPosition = _audioPosition + const Duration(seconds: 10); - appState.audioService.seek( - newPosition > _audioDuration ? _audioDuration : newPosition, - ); - }, - ), - ], - ), - const SizedBox(height: 8), - Slider( - value: _audioPosition.inMilliseconds.toDouble(), - max: _audioDuration.inMilliseconds.toDouble() > 0 - ? _audioDuration.inMilliseconds.toDouble() - : 1.0, - onChanged: (value) { - appState.audioService.seek(Duration(milliseconds: value.toInt())); - }, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(_formatDuration(_audioPosition)), - Text(_formatDuration(_audioDuration)), - ], - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - DropdownButton( - value: appState.audioService.playbackSpeed, - items: [0.5, 0.75, 1.0, 1.25, 1.5, 2.0].map((speed) { - return DropdownMenuItem( - value: speed, - child: Text('${speed}x'), - ); - }).toList(), - onChanged: (speed) { - if (speed != null) { - appState.setAudioSpeed(speed); - } - }, - ), - IconButton( - icon: Icon( - appState.audioService.isLooping - ? Icons.repeat_one - : Icons.repeat, - color: appState.audioService.isLooping - ? Theme.of(context).colorScheme.primary - : null, - ), - onPressed: () { - appState.setAudioLooping(!appState.audioService.isLooping); - }, - ), - ], - ), - ], - ), - ), - ); - } - - Widget _buildLessonContent() { - return Card( - margin: const EdgeInsets.all(16), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: _isLoadingText - ? const Center(child: CircularProgressIndicator()) - : SelectableText( - _lessonText, - style: Theme.of(context).textTheme.bodyLarge?.copyWith( - height: 1.8, - fontSize: 18, - ), - ), - ), - ); - } - - Widget _buildCompletionButton(AppState appState) { - final isCompleted = appState.isDayCompleted(_dayNumber); - - return Padding( - padding: const EdgeInsets.all(16.0), - child: ElevatedButton.icon( - onPressed: isCompleted - ? null - : () async { - await appState.markDayComplete(_dayNumber); - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Day $_dayNumber marked as complete! 🎉'), - backgroundColor: Colors.green, - ), - ); - } - }, - icon: Icon(isCompleted ? Icons.check_circle : Icons.check), - label: Text(isCompleted ? 'Completed' : 'Mark as Complete'), - style: ElevatedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 16), - backgroundColor: isCompleted ? Colors.grey : null, - ), - ), - ); - } - - Widget _buildNavigation() { + Widget _navButtons() { return Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ElevatedButton.icon( onPressed: _dayNumber > 1 - ? () { - Navigator.pushReplacementNamed( - context, - '/day', - arguments: _dayNumber - 1, - ); - } + ? () => Navigator.pushReplacementNamed( + context, '/day', arguments: _dayNumber - 1) : null, icon: const Icon(Icons.arrow_back), label: const Text('Previous'), @@ -305,13 +182,8 @@ class _DayLessonScreenState extends State { ), ElevatedButton.icon( onPressed: _dayNumber < 40 - ? () { - Navigator.pushReplacementNamed( - context, - '/day', - arguments: _dayNumber + 1, - ); - } + ? () => Navigator.pushReplacementNamed( + context, '/day', arguments: _dayNumber + 1) : null, icon: const Icon(Icons.arrow_forward), label: const Text('Next'), @@ -321,40 +193,22 @@ class _DayLessonScreenState extends State { ); } - Future _toggleAudio(AppState appState) async { - if (_audioState == ap.PlayerState.playing) { - await appState.audioService.pause(); - } else { - final audioPath = _lesson.audioFiles[appState.currentLanguage.code]; - if (audioPath != null) { - await appState.audioService.play(audioPath); - } - } - } - - String _formatDuration(Duration duration) { - String twoDigits(int n) => n.toString().padLeft(2, '0'); - final minutes = twoDigits(duration.inMinutes.remainder(60)); - final seconds = twoDigits(duration.inSeconds.remainder(60)); - return '$minutes:$seconds'; - } - - void _showLanguageSelector(AppState appState) { + void _showLanguagePicker(AppState appState) { showDialog( context: context, - builder: (context) => AlertDialog( + builder: (ctx) => AlertDialog( title: const Text('Select Language'), content: Column( mainAxisSize: MainAxisSize.min, - children: Language.values.map((language) { + children: Language.values.map((l) { return ListTile( - leading: Text(language.flag, style: const TextStyle(fontSize: 24)), - title: Text(language.displayName), - selected: appState.currentLanguage == language, + leading: Text(l.flag, style: const TextStyle(fontSize: 24)), + title: Text(l.displayName), + selected: appState.currentLanguage == l, onTap: () { - appState.setLanguage(language); - Navigator.pop(context); - _loadLessonText(); // Reload text in new language + appState.setLanguage(l); + Navigator.pop(ctx); + _loadContent(); }, ); }).toList(), diff --git a/flutter_app/lib/screens/home_screen.dart b/flutter_app/lib/screens/home_screen.dart index a778908..a9d3727 100644 --- a/flutter_app/lib/screens/home_screen.dart +++ b/flutter_app/lib/screens/home_screen.dart @@ -3,6 +3,7 @@ import 'package:provider/provider.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import '../models/lesson.dart'; import '../services/app_state.dart'; +import '../widgets/learning_dashboard.dart'; import '../widgets/language_card.dart'; import '../widgets/section_card.dart'; import '../widgets/benefit_card.dart'; @@ -43,6 +44,8 @@ class _HomeScreenState extends State { _buildHeroSection(context), _buildLanguageCards(appState), const SizedBox(height: 32), + const LearningDashboard(), + const SizedBox(height: 32), _buildCourseStructure(), const SizedBox(height: 32), _buildDailyLessons(appState), diff --git a/flutter_app/lib/screens/placement_screen.dart b/flutter_app/lib/screens/placement_screen.dart new file mode 100644 index 0000000..ec97d4f --- /dev/null +++ b/flutter_app/lib/screens/placement_screen.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../data/placement_data.dart'; +import '../l10n/strings.dart'; +import '../models/lesson.dart'; +import '../models/placement_models.dart'; +import '../services/app_state.dart'; + +class PlacementScreen extends StatefulWidget { + const PlacementScreen({super.key}); + + @override + State createState() => _PlacementScreenState(); +} + +class _PlacementScreenState extends State { + final _answers = {}; + bool _submitted = false; + + @override + Widget build(BuildContext context) { + final appState = context.watch(); + final lang = appState.currentLanguage; + final saved = appState.placementResult; + + return Scaffold( + appBar: AppBar( + title: Text(AppStrings.t(lang, zh: '水平测试', en: 'Placement test')), + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (saved != null && !_submitted) _resultCard(lang, saved), + ...placementQuestions.asMap().entries.map((e) { + return Card( + margin: const EdgeInsets.only(bottom: 12), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('${e.key + 1}. ${e.value.prompt}', + style: const TextStyle(fontWeight: FontWeight.w600)), + const SizedBox(height: 8), + ...e.value.options.map((opt) { + return RadioListTile( + title: Text(opt), + value: opt, + groupValue: _answers[e.key], + onChanged: (v) => + setState(() => _answers[e.key] = v), + ); + }), + ], + ), + ), + ); + }), + ElevatedButton( + onPressed: _answers.length == placementQuestions.length + ? () async { + final answers = List.generate( + placementQuestions.length, + (i) => _answers[i], + ); + final result = scorePlacement(answers); + await appState.savePlacementResult(result); + setState(() => _submitted = true); + } + : null, + child: Text(AppStrings.t(lang, zh: '提交', en: 'Submit')), + ), + if (_submitted && appState.placementResult != null) + _resultCard(lang, appState.placementResult!), + ], + ), + ), + ); + } + + Widget _resultCard(Language lang, PlacementResult result) { + return Card( + color: Theme.of(context).colorScheme.primaryContainer, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppStrings.t(lang, + zh: '建议起点:第 ${result.recommendedDay} 天', + en: 'Recommended start: Day ${result.recommendedDay}'), + style: Theme.of(context).textTheme.titleLarge, + ), + Text(AppStrings.t(lang, + zh: '得分:${result.score}/${result.total}(${result.percentage}%)', + en: 'Score: ${result.score}/${result.total} (${result.percentage}%)')), + Text(AppStrings.t(lang, + zh: result.messageZh, en: result.messageEn)), + const SizedBox(height: 12), + ElevatedButton( + onPressed: () => Navigator.pushNamed( + context, '/day', arguments: result.recommendedDay), + child: Text(AppStrings.t(lang, + zh: '开始第${result.recommendedDay}天', + en: 'Start at Day ${result.recommendedDay}')), + ), + ], + ), + ), + ); + } +} diff --git a/flutter_app/lib/screens/quiz_screen.dart b/flutter_app/lib/screens/quiz_screen.dart new file mode 100644 index 0000000..8175375 --- /dev/null +++ b/flutter_app/lib/screens/quiz_screen.dart @@ -0,0 +1,134 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../data/quiz_data.dart'; +import '../l10n/strings.dart'; +import '../services/app_state.dart'; + +class QuizScreen extends StatefulWidget { + const QuizScreen({super.key}); + + @override + State createState() => _QuizScreenState(); +} + +class _QuizScreenState extends State { + late int _day; + final _answers = {}; + bool _submitted = false; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _day = ModalRoute.of(context)?.settings.arguments as int? ?? 1; + } + + @override + Widget build(BuildContext context) { + final appState = context.watch(); + final lang = appState.currentLanguage; + final quiz = getQuizForDay(_day); + final saved = appState.getQuizScoreForDay(_day); + + return Scaffold( + appBar: AppBar( + title: Text(AppStrings.t(lang, zh: '测验', en: 'Quiz')), + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Wrap( + spacing: 8, + children: [1, 8, 16, 31].map((d) { + return ChoiceChip( + label: Text('Day $d'), + selected: _day == d, + onSelected: (_) => setState(() { + _day = d; + _answers.clear(); + _submitted = false; + }), + ); + }).toList(), + ), + const SizedBox(height: 16), + Text('Day $_day: ${quiz.title}', + style: Theme.of(context).textTheme.titleLarge), + if (saved != null && !_submitted) + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Text( + AppStrings.t(lang, + zh: '最佳成绩:${saved.score}/${saved.total}', + en: 'Best score: ${saved.score}/${saved.total}'), + ), + ), + ...quiz.questions.asMap().entries.map((e) { + final q = e.value; + return Card( + margin: const EdgeInsets.only(bottom: 12), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('${e.key + 1}. ${q.prompt}'), + const SizedBox(height: 8), + if (q.type == 'multiple-choice') + ...q.options.map((opt) { + return RadioListTile( + title: Text(opt), + value: opt, + groupValue: _answers[e.key], + onChanged: (v) => + setState(() => _answers[e.key] = v ?? ''), + ); + }) + else + TextField( + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: 'Answer', + ), + onChanged: (v) => + setState(() => _answers[e.key] = v), + ), + ], + ), + ), + ); + }), + ElevatedButton( + onPressed: _answers.length == quiz.questions.length + ? () async { + final result = scoreQuiz( + _day, + List.generate( + quiz.questions.length, + (i) => _answers[i], + ), + ); + await appState.saveQuizScore(result); + setState(() => _submitted = true); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + AppStrings.t(lang, + zh: '得分 ${result.score}/${result.total}', + en: 'Score ${result.score}/${result.total}'), + ), + ), + ); + } + } + : null, + child: Text(AppStrings.t(lang, zh: '提交', en: 'Submit')), + ), + ], + ), + ), + ); + } +} diff --git a/flutter_app/lib/screens/reading_screen.dart b/flutter_app/lib/screens/reading_screen.dart index 4a1e3ac..9ef5004 100644 --- a/flutter_app/lib/screens/reading_screen.dart +++ b/flutter_app/lib/screens/reading_screen.dart @@ -1,5 +1,12 @@ import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; +import '../data/content_catalog.dart'; +import '../models/audio_cue.dart'; +import '../models/lesson.dart'; +import '../l10n/strings.dart'; +import '../services/app_state.dart'; +import '../services/content_service.dart'; +import '../widgets/lesson_audio_player.dart'; class ReadingScreen extends StatefulWidget { const ReadingScreen({super.key}); @@ -9,89 +16,153 @@ class ReadingScreen extends StatefulWidget { } class _ReadingScreenState extends State { - String _selectedLevel = 'beginner'; - String _readingText = ''; - bool _isLoading = false; - - final Map _readingLevels = { - 'beginner': 'Beginner', - 'intermediate': 'Intermediate', - 'advanced': 'Advanced', - }; + String? _level; + String? _topic; + ParsedReadingContent? _content; + List _cues = []; + int? _activeCue; + bool _loading = false; @override - void initState() { - super.initState(); - _loadReadingMaterial(); - } + Widget build(BuildContext context) { + final appState = context.watch(); + final lang = appState.currentLanguage; - Future _loadReadingMaterial() async { - setState(() => _isLoading = true); - try { - // Load reading material from assets - final text = await rootBundle.loadString( - 'assets/text/reading_${_selectedLevel}_zh.txt', - ); - if (mounted) { - setState(() { - _readingText = text; - _isLoading = false; - }); - } - } catch (e) { - if (mounted) { - setState(() { - _readingText = 'Reading material will be available soon.\n\n' - 'This section will include:\n' - '• Short stories in Chinese\n' - '• Comprehension questions\n' - '• Vocabulary lists\n' - '• Cultural notes\n\n' - 'Practice reading authentic Chinese texts at your level.'; - _isLoading = false; - }); - } - } + return Scaffold( + appBar: AppBar(title: Text(AppStrings.t(lang, zh: '阅读技能', en: 'Reading Skills'))), + body: _level == null + ? _levelPicker() + : _topic == null + ? _topicPicker() + : _loading + ? const Center(child: CircularProgressIndicator()) + : _readingBody(appState, lang), + ); } - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Reading Skills'), - ), - body: Column( - children: [ - _buildLevelSelector(), - Expanded(child: _buildReadingContent()), - ], - ), + Widget _levelPicker() { + return ListView( + padding: const EdgeInsets.all(16), + children: readingCatalog.keys.map((level) { + return Card( + child: ListTile( + title: Text(level[0].toUpperCase() + level.substring(1)), + trailing: const Icon(Icons.chevron_right), + onTap: () => setState(() => _level = level), + ), + ); + }).toList(), ); } - Widget _buildLevelSelector() { - return Container( + Widget _topicPicker() { + final topics = readingCatalog[_level!] ?? []; + return ListView( padding: const EdgeInsets.all(16), - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - child: Row( + children: [ + TextButton( + onPressed: () => setState(() => _level = null), + child: const Text('← Back to levels'), + ), + ...topics.map((t) { + return Card( + child: ListTile( + title: Text(t.info.title), + subtitle: Text(t.info.description), + onTap: () { + setState(() => _topic = t.name); + _load(t.name); + }, + ), + ); + }), + ], + ); + } + + Future _load(String topic) async { + setState(() => _loading = true); + final appState = context.read(); + final lang = appState.currentLanguage; + final text = await appState.contentService.loadAssetText( + appState.contentService.readingTextPath(_level!, topic, lang), + ); + final timing = await appState.contentService.loadTiming( + appState.contentService.readingTimingPath(_level!, topic, lang), + ); + if (mounted) { + setState(() { + _content = appState.contentService.parseReadingContent(text, lang); + _cues = timing?.phrases ?? []; + _loading = false; + }); + } + } + + Widget _readingBody(AppState appState, Language lang) { + final content = _content!; + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - const Text('Level: ', style: TextStyle(fontWeight: FontWeight.bold)), - const SizedBox(width: 8), - Expanded( - child: SegmentedButton( - segments: _readingLevels.entries.map((entry) { - return ButtonSegment( - value: entry.key, - label: Text(entry.value), - ); - }).toList(), - selected: {_selectedLevel}, - onSelectionChanged: (Set newSelection) { + Padding( + padding: const EdgeInsets.all(16), + child: TextButton( + onPressed: () => setState(() { + _topic = null; + _content = null; + }), + child: const Text('← Back to topics'), + ), + ), + LessonAudioPlayer( + audioPath: appState.contentService + .readingAudioPath(_level!, _topic!, lang), + showPinyinNote: lang == Language.pinyin, + onPositionTick: () { + appState.audioService.currentPosition.then((p) { + if (!mounted || p == null) return; setState(() { - _selectedLevel = newSelection.first; - _loadReadingMaterial(); + _activeCue = + appState.contentService.activeCueIndex(p, _cues); }); - }, + }); + }, + ), + ...content.mainSegments.asMap().entries.map((e) { + final active = _activeCue == e.key; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), + child: Card( + color: active + ? Theme.of(context) + .colorScheme + .primary + .withValues(alpha: 0.1) + : null, + child: Padding( + padding: const EdgeInsets.all(16), + child: SelectableText(e.value, + style: const TextStyle(fontSize: 18, height: 1.8)), + ), + ), + ); + }), + if (content.vocabularyText.isNotEmpty) + _section('Vocabulary', content.vocabularyText), + if (content.questionsText.isNotEmpty) + _section('Comprehension Questions', content.questionsText), + Padding( + padding: const EdgeInsets.all(16), + child: ElevatedButton( + onPressed: appState.isReadingCompleted(_level!, _topic!) + ? null + : () => appState.markReadingComplete(_level!, _topic!), + child: Text( + appState.isReadingCompleted(_level!, _topic!) + ? AppStrings.t(lang, zh: '已完成', en: 'Completed') + : AppStrings.t(lang, zh: '标记完成', en: 'Mark complete'), + ), ), ), ], @@ -99,22 +170,22 @@ class _ReadingScreenState extends State { ); } - Widget _buildReadingContent() { - if (_isLoading) { - return const Center(child: CircularProgressIndicator()); - } - - return SingleChildScrollView( + Widget _section(String title, String body) { + return Padding( padding: const EdgeInsets.all(16), child: Card( child: Padding( - padding: const EdgeInsets.all(20.0), - child: SelectableText( - _readingText, - style: Theme.of(context).textTheme.bodyLarge?.copyWith( - height: 2.0, - fontSize: 20, - ), + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + )), + const SizedBox(height: 8), + SelectableText(body, style: const TextStyle(height: 1.8)), + ], ), ), ), diff --git a/flutter_app/lib/screens/review_screen.dart b/flutter_app/lib/screens/review_screen.dart new file mode 100644 index 0000000..f5ae0bb --- /dev/null +++ b/flutter_app/lib/screens/review_screen.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../l10n/strings.dart'; +import '../services/app_state.dart'; + +class ReviewScreen extends StatelessWidget { + const ReviewScreen({super.key}); + + @override + Widget build(BuildContext context) { + final appState = context.watch(); + final lang = appState.currentLanguage; + final items = [...appState.starredPhrases] + ..sort((a, b) => b.createdAt.compareTo(a.createdAt)); + + return Scaffold( + appBar: AppBar( + title: Text(AppStrings.t(lang, zh: '复习清单', en: 'Review starred phrases')), + ), + body: items.isEmpty + ? Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Text( + AppStrings.t(lang, + zh: '暂无收藏的短语。在每日课程中点击星标即可添加。', + en: 'No starred phrases yet. Tap the star on any daily lesson phrase.'), + textAlign: TextAlign.center, + ), + ), + ) + : ListView.builder( + padding: const EdgeInsets.all(16), + itemCount: items.length, + itemBuilder: (ctx, i) { + final entry = items[i]; + return Card( + child: ListTile( + title: Text(entry.phrase, + style: const TextStyle(fontSize: 18)), + subtitle: Text( + 'Day ${entry.day} · ${entry.lang}' + '${entry.sectionTitle.isNotEmpty ? ' — ${entry.sectionTitle}' : ''}', + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: const Icon(Icons.open_in_new), + onPressed: () => Navigator.pushNamed( + context, '/day', arguments: entry.day), + ), + IconButton( + icon: const Icon(Icons.delete_outline), + onPressed: () => + appState.removeStarredPhrase(entry.id), + ), + ], + ), + ), + ); + }, + ), + ); + } +} diff --git a/flutter_app/lib/screens/srs_screen.dart b/flutter_app/lib/screens/srs_screen.dart new file mode 100644 index 0000000..c2a18bb --- /dev/null +++ b/flutter_app/lib/screens/srs_screen.dart @@ -0,0 +1,167 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../l10n/strings.dart'; +import '../models/lesson.dart'; +import '../services/app_state.dart'; + +class SrsScreen extends StatefulWidget { + const SrsScreen({super.key}); + + @override + State createState() => _SrsScreenState(); +} + +class _SrsScreenState extends State { + int _index = 0; + bool _showBack = false; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + context.read().seedSrsFromStarred(); + }); + } + + @override + Widget build(BuildContext context) { + final appState = context.watch(); + final lang = appState.currentLanguage; + final due = appState.dueSrsCards; + final total = appState.srsCards.length; + + return Scaffold( + appBar: AppBar( + title: Text(AppStrings.t(lang, zh: '间隔复习', en: 'SRS flashcards')), + ), + body: Padding( + padding: const EdgeInsets.all(16), + child: due.isEmpty + ? _emptyState(lang) + : _index >= due.length + ? _doneState(lang) + : _cardView(appState, lang, due, total), + ), + ); + } + + Widget _emptyState(Language lang) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(AppStrings.t(lang, + zh: '今日无复习卡片', en: 'No cards due today')), + const SizedBox(height: 8), + Text(AppStrings.t(lang, + zh: '从课程中收藏短语,然后返回进行间隔复习。', + en: 'Star phrases from lessons to build your deck.')), + const SizedBox(height: 16), + ElevatedButton( + onPressed: () => Navigator.pushNamed(context, '/review'), + child: Text(AppStrings.t(lang, zh: '收藏短语', en: 'Star phrases')), + ), + ], + ), + ); + } + + Widget _doneState(Language lang) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(AppStrings.t(lang, zh: '复习完成!', en: 'Session complete!'), + style: Theme.of(context).textTheme.headlineSmall), + const SizedBox(height: 16), + ElevatedButton( + onPressed: () => Navigator.pushNamed(context, '/'), + child: Text(AppStrings.t(lang, zh: '返回课程', en: 'Go to lessons')), + ), + ], + ), + ); + } + + Widget _cardView( + AppState appState, + Language lang, + List due, + int total, + ) { + final card = due[_index]; + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + AppStrings.t(lang, + zh: '${due.length} 张卡片今日到期 · 共 $total 张', + en: '${due.length} cards due today · $total total'), + ), + const SizedBox(height: 8), + Text('Day ${card.day ?? "?"} · ${card.lang} · ${_index + 1}/${due.length}'), + const SizedBox(height: 24), + Expanded( + child: Card( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(card.front, + style: const TextStyle(fontSize: 28), + textAlign: TextAlign.center), + if (_showBack) ...[ + const Divider(height: 32), + Text(card.back.isNotEmpty ? card.back : '—', + style: const TextStyle(fontSize: 20), + textAlign: TextAlign.center), + ], + ], + ), + ), + ), + ), + const SizedBox(height: 16), + if (!_showBack) + ElevatedButton( + onPressed: () => setState(() => _showBack = true), + child: Text(AppStrings.t(lang, zh: '显示答案', en: 'Show answer')), + ) + else + Row( + children: [ + Expanded( + child: OutlinedButton( + onPressed: () => _grade(appState, card.id, 'again'), + child: Text(AppStrings.t(lang, zh: '重来', en: 'Again')), + ), + ), + const SizedBox(width: 8), + Expanded( + child: ElevatedButton( + onPressed: () => _grade(appState, card.id, 'good'), + child: Text(AppStrings.t(lang, zh: '良好', en: 'Good')), + ), + ), + const SizedBox(width: 8), + Expanded( + child: ElevatedButton( + onPressed: () => _grade(appState, card.id, 'easy'), + child: Text(AppStrings.t(lang, zh: '简单', en: 'Easy')), + ), + ), + ], + ), + ], + ); + } + + Future _grade(AppState appState, String id, String grade) async { + await appState.reviewSrsCard(id, grade); + setState(() { + _index++; + _showBack = false; + }); + } +} diff --git a/flutter_app/lib/screens/supplementary_screen.dart b/flutter_app/lib/screens/supplementary_screen.dart index f98dc9b..15e86c2 100644 --- a/flutter_app/lib/screens/supplementary_screen.dart +++ b/flutter_app/lib/screens/supplementary_screen.dart @@ -1,48 +1,111 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../models/audio_cue.dart'; +import '../models/lesson.dart'; +import '../models/phrase_section.dart'; +import '../l10n/strings.dart'; +import '../services/app_state.dart'; +import '../widgets/lesson_audio_player.dart'; +import '../widgets/phrase_list.dart'; -class SupplementaryScreen extends StatelessWidget { +class SupplementaryScreen extends StatefulWidget { const SupplementaryScreen({super.key}); + @override + State createState() => _SupplementaryScreenState(); +} + +class _SupplementaryScreenState extends State { + String? _category; + List _sections = []; + List _cues = []; + int? _activeCue; + bool _loading = true; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _category = ModalRoute.of(context)?.settings.arguments as String?; + _load(); + } + + Future _load() async { + if (_category == null) return; + setState(() => _loading = true); + final appState = context.read(); + final lang = appState.currentLanguage; + final text = await appState.contentService.loadAssetText( + appState.contentService.supplementaryTextPath(_category!, lang), + ); + final timing = await appState.contentService.loadTiming( + appState.contentService.supplementaryTimingPath(_category!, lang), + ); + if (mounted) { + setState(() { + _sections = appState.contentService.parsePhraseSections(text); + _cues = timing?.phrases ?? []; + _loading = false; + }); + } + } + + void _updateCue() { + final appState = context.read(); + appState.audioService.currentPosition.then((p) { + if (!mounted || p == null) return; + setState(() { + _activeCue = appState.contentService.activeCueIndex(p, _cues); + }); + }); + } + @override Widget build(BuildContext context) { - final String? category = - ModalRoute.of(context)?.settings.arguments as String?; + final appState = context.watch(); + final lang = appState.currentLanguage; + final title = _titleFor(_category); return Scaffold( - appBar: AppBar( - title: Text(_getCategoryTitle(category)), - ), - body: SingleChildScrollView( - padding: const EdgeInsets.all(16), - child: Card( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _getCategoryTitle(category), - style: Theme.of(context).textTheme.headlineSmall?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 16), - Text( - _getCategoryContent(category), - style: Theme.of(context).textTheme.bodyLarge?.copyWith( - height: 1.8, + appBar: AppBar(title: Text(title)), + body: _loading + ? const Center(child: CircularProgressIndicator()) + : SingleChildScrollView( + child: Column( + children: [ + LessonAudioPlayer( + audioPath: appState.contentService + .supplementaryAudioPath(_category!, lang), + showPinyinNote: lang == Language.pinyin, + onPositionTick: _updateCue, + ), + PhraseListView( + sections: _sections, + day: 0, + activeCueIndex: _activeCue, + ), + Padding( + padding: const EdgeInsets.all(16), + child: ElevatedButton.icon( + onPressed: appState.isSupplementaryCompleted(_category!) + ? null + : () => appState.markSupplementaryComplete(_category!), + icon: const Icon(Icons.check), + label: Text( + appState.isSupplementaryCompleted(_category!) + ? AppStrings.t(lang, zh: '已完成', en: 'Completed') + : AppStrings.t(lang, + zh: '标记完成', en: 'Mark complete'), ), - ), - ], + ), + ), + ], + ), ), - ), - ), - ), ); } - String _getCategoryTitle(String? category) { - switch (category) { + String _titleFor(String? cat) { + switch (cat) { case 'education': return 'Education & Academic Life'; case 'hobbies': @@ -57,41 +120,4 @@ class SupplementaryScreen extends StatelessWidget { return 'Supplementary Materials'; } } - - String _getCategoryContent(String? category) { - switch (category) { - case 'education': - return 'Learn vocabulary and phrases for academic settings:\n\n' - '• Classroom interactions\n' - '• Study-related terms\n' - '• Educational institutions\n' - '• Academic discussions'; - case 'hobbies': - return 'Express your interests and hobbies:\n\n' - '• Sports and activities\n' - '• Arts and crafts\n' - '• Music and entertainment\n' - '• Leisure activities'; - case 'emotions': - return 'Communicate your feelings effectively:\n\n' - '• Basic emotions\n' - '• Complex feelings\n' - '• Emotional expressions\n' - '• Empathy and understanding'; - case 'daily_life': - return 'Essential phrases for everyday life:\n\n' - '• Weather descriptions\n' - '• Daily routines\n' - '• Time expressions\n' - '• Common activities'; - case 'comparisons': - return 'Master comparison structures:\n\n' - '• Basic comparisons (比)\n' - '• Superlatives (最)\n' - '• Equal comparisons (跟...一样)\n' - '• Preference expressions'; - default: - return 'Select a category to view supplementary learning materials.'; - } - } } diff --git a/flutter_app/lib/screens/writing_screen.dart b/flutter_app/lib/screens/writing_screen.dart index ba8d807..fb4f06f 100644 --- a/flutter_app/lib/screens/writing_screen.dart +++ b/flutter_app/lib/screens/writing_screen.dart @@ -1,4 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../data/content_catalog.dart'; +import '../models/lesson.dart'; +import '../l10n/strings.dart'; +import '../services/app_state.dart'; +import '../services/content_service.dart'; +import '../widgets/lesson_audio_player.dart'; +import '../widgets/character_canvas.dart'; class WritingScreen extends StatefulWidget { const WritingScreen({super.key}); @@ -8,220 +16,197 @@ class WritingScreen extends StatefulWidget { } class _WritingScreenState extends State { - final TextEditingController _textController = TextEditingController(); - String _selectedExercise = 'characters'; - - final Map _exercises = { - 'characters': 'Character Practice', - 'sentences': 'Sentence Building', - 'translation': 'Translation Practice', - }; - - @override - void dispose() { - _textController.dispose(); - super.dispose(); - } + String? _type; + String? _level; + ActivityInfo? _info; + List _exercises = []; + bool _loading = false; @override Widget build(BuildContext context) { + final appState = context.watch(); + final lang = appState.currentLanguage; + return Scaffold( appBar: AppBar( - title: const Text('Writing Skills'), - ), - body: Column( - children: [ - _buildExerciseSelector(), - Expanded(child: _buildWritingArea()), - ], + title: Text(AppStrings.t(lang, zh: '写作技能', en: 'Writing Skills')), ), + body: _type == null + ? _typePicker() + : _level == null + ? _levelPicker(lang) + : _loading + ? const Center(child: CircularProgressIndicator()) + : _contentBody(appState, lang), ); } - Widget _buildExerciseSelector() { - return Container( + Widget _typePicker() { + return ListView( padding: const EdgeInsets.all(16), - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Exercise Type:', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 8), - SegmentedButton( - segments: _exercises.entries.map((entry) { - return ButtonSegment( - value: entry.key, - label: Text(entry.value), - ); - }).toList(), - selected: {_selectedExercise}, - onSelectionChanged: (Set newSelection) { - setState(() { - _selectedExercise = newSelection.first; - }); - }, - ), - ], + children: [ + _typeTile('character', 'Character Practice'), + _typeTile('sentence', 'Sentence Building'), + _typeTile('translation', 'Translation Practice'), + ], + ); + } + + Widget _typeTile(String type, String label) { + return Card( + child: ListTile( + title: Text(label), + trailing: const Icon(Icons.chevron_right), + onTap: () => setState(() => _type = type), ), ); } - Widget _buildWritingArea() { - return SingleChildScrollView( + Widget _levelPicker(Language lang) { + final levels = writingCatalog[_type!] ?? {}; + return ListView( padding: const EdgeInsets.all(16), + children: [ + TextButton( + onPressed: () => setState(() => _type = null), + child: const Text('← Back'), + ), + ...levels.entries.map((e) { + return Card( + child: ListTile( + title: Text(e.value.displayTitle(lang)), + subtitle: Text(e.value.displayDescription(lang)), + onTap: () { + setState(() { + _level = e.key; + _info = e.value; + }); + _load(e.key); + }, + ), + ); + }), + ], + ); + } + + Future _load(String level) async { + setState(() => _loading = true); + final appState = context.read(); + final lang = appState.currentLanguage; + final text = await appState.contentService.loadAssetText( + appState.contentService.writingTextPath(_type!, level, lang), + ); + if (mounted) { + setState(() { + _exercises = appState.contentService.parseWritingExercises(text); + _loading = false; + }); + } + } + + Widget _contentBody(AppState appState, Language lang) { + return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Card( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _getExerciseDescription(), - style: Theme.of(context).textTheme.bodyLarge, - ), - const SizedBox(height: 16), - Text( - _getExercisePrompt(), - style: Theme.of(context).textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - ], - ), + Padding( + padding: const EdgeInsets.all(16), + child: TextButton( + onPressed: () => setState(() { + _level = null; + _info = null; + }), + child: const Text('← Back to activities'), ), ), - const SizedBox(height: 16), - Card( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Your Answer:', - style: Theme.of(context).textTheme.titleMedium, - ), - const SizedBox(height: 8), - TextField( - controller: _textController, - maxLines: 10, - decoration: const InputDecoration( - hintText: 'Type your answer here...', - border: OutlineInputBorder(), - ), - style: const TextStyle(fontSize: 18, height: 1.8), - ), - const SizedBox(height: 16), - Row( - children: [ - ElevatedButton( - onPressed: _textController.clear, - child: const Text('Clear'), - ), - const SizedBox(width: 8), - ElevatedButton.icon( - onPressed: () { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Answer saved! Keep practicing.'), - ), - ); - }, - icon: const Icon(Icons.save), - label: const Text('Save'), - ), - ], - ), - ], + if (_info != null) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text( + _info!.displayTitle(lang), + style: Theme.of(context).textTheme.headlineSmall, + ), + ), + if (_info != null && _info!.hasAudio) + LessonAudioPlayer( + audioPath: appState.contentService + .writingAudioPath(_type!, _level!, lang), + showPinyinNote: lang == Language.pinyin, + ), + if (_type == 'character') + const Padding( + padding: EdgeInsets.all(16), + child: CharacterCanvas(), + ), + ..._exercises.map((ex) => _exerciseCard(ex)), + Padding( + padding: const EdgeInsets.all(16), + child: ElevatedButton( + onPressed: appState.isWritingCompleted(_type!, _level!) + ? null + : () => appState.markWritingComplete(_type!, _level!), + child: Text( + appState.isWritingCompleted(_type!, _level!) + ? AppStrings.t(lang, zh: '已完成', en: 'Completed') + : AppStrings.t(lang, zh: '标记完成', en: 'Mark complete'), ), ), ), - const SizedBox(height: 16), - if (_selectedExercise == 'characters') _buildCharacterGrid(), ], ), ); } - Widget _buildCharacterGrid() { - final characters = ['你', '好', '我', '是', '的', '在', '有', '不', '人', '们']; - + Widget _exerciseCard(WritingExercise ex) { + final controller = TextEditingController(); return Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - 'Common Characters:', - style: Theme.of(context).textTheme.titleMedium, + Text(ex.prompt, style: const TextStyle(fontSize: 16)), + const SizedBox(height: 8), + TextField( + controller: controller, + maxLines: 3, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: 'Your answer...', + ), ), - const SizedBox(height: 16), - Wrap( - spacing: 12, - runSpacing: 12, - children: characters.map((char) { - return InkWell( - onTap: () { - _textController.text += char; - }, - child: Container( - width: 60, - height: 60, - decoration: BoxDecoration( - border: Border.all( - color: Theme.of(context).colorScheme.primary, - ), - borderRadius: BorderRadius.circular(8), - ), - child: Center( - child: Text( - char, - style: const TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - ), + const SizedBox(height: 8), + Row( + children: [ + TextButton( + onPressed: () => controller.clear(), + child: const Text('Clear'), + ), + TextButton( + onPressed: () { + final ok = controller.text.trim().toLowerCase() == + ex.answer.trim().toLowerCase(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(ok ? 'Correct!' : 'Try again'), + backgroundColor: ok ? Colors.green : Colors.orange, ), - ), + ); + }, + child: const Text('Check'), + ), + if (ex.answer.isNotEmpty) + TextButton( + onPressed: () => controller.text = ex.answer, + child: const Text('Show answer'), ), - ); - }).toList(), + ], ), ], ), ), ); } - - String _getExerciseDescription() { - switch (_selectedExercise) { - case 'characters': - return 'Practice writing Chinese characters. Tap the characters below to add them to your answer.'; - case 'sentences': - return 'Build complete sentences using Chinese characters and grammar patterns.'; - case 'translation': - return 'Translate the given English sentence into Chinese.'; - default: - return ''; - } - } - - String _getExercisePrompt() { - switch (_selectedExercise) { - case 'characters': - return 'Write: "Hello, how are you?" in Chinese'; - case 'sentences': - return 'Build a sentence: "I like to study Chinese."'; - case 'translation': - return 'Translate: "Where is the nearest restaurant?"'; - default: - return ''; - } - } } diff --git a/flutter_app/lib/services/app_state.dart b/flutter_app/lib/services/app_state.dart index 62014f9..010480b 100644 --- a/flutter_app/lib/services/app_state.dart +++ b/flutter_app/lib/services/app_state.dart @@ -1,130 +1,115 @@ import 'package:flutter/foundation.dart'; import '../models/lesson.dart'; -import 'storage_service.dart'; +import '../models/placement_models.dart'; +import '../models/quiz_models.dart'; +import '../models/srs_card.dart'; +import '../models/starred_phrase.dart'; import 'audio_service.dart'; +import 'content_service.dart'; +import 'learning_services.dart'; import 'notification_service.dart'; +import 'storage_service.dart'; class AppState extends ChangeNotifier { - final StorageService _storage; - final AudioService _audio; - final NotificationService _notification; + final StorageService storage; + final AudioService audioService; + final NotificationService notificationService; + final ContentService contentService; + late final StreakService streakService; + late final SrsService srsService; - Progress _progress = Progress(); Language _currentLanguage = Language.chinese; bool _isLoading = true; AppState({ - required StorageService storage, - required AudioService audio, - required NotificationService notification, - }) : _storage = storage, - _audio = audio, - _notification = notification { + required this.storage, + required this.audioService, + required this.notificationService, + ContentService? contentService, + }) : contentService = contentService ?? ContentService() { + streakService = StreakService(storage); + srsService = SrsService(storage, streakService); _initialize(); } - // Getters - Progress get progress => _progress; Language get currentLanguage => _currentLanguage; bool get isLoading => _isLoading; - AudioService get audioService => _audio; - NotificationService get notificationService => _notification; - // Initialize app state + int get streakCount => storage.streakCount; + int get srsDueCount => srsService.getDueCards().length; + PlacementResult? get placementResult => storage.getPlacementResult(); + List get earnedAchievements => storage.getEarnedAchievements(); + Future _initialize() async { _isLoading = true; notifyListeners(); - try { - await _storage.init(); - await _notification.init(); - - // Load saved progress - _progress = await _storage.getProgress(); - - // Load preferred language - final langCode = await _storage.getPreferredLanguage(); - _currentLanguage = Language.fromCode(langCode); - - // Load audio settings - final audioSettings = await _storage.getAudioSettings(); - await _audio.setPlaybackSpeed(audioSettings['playbackSpeed']); - await _audio.setLooping(audioSettings['loopEnabled']); - + await storage.init(); + await notificationService.init(); + _currentLanguage = Language.fromCode(storage.getPreferredLanguage()); + final audioSettings = await storage.getAudioSettings(); + await audioService.setPlaybackSpeed(audioSettings['playbackSpeed']); + await audioService.setLooping(audioSettings['loopEnabled']); + await streakService.updateAchievements(); } catch (e) { - print('Error initializing app state: $e'); + debugPrint('Error initializing app state: $e'); } finally { _isLoading = false; notifyListeners(); } } - // Language Management Future setLanguage(Language language) async { _currentLanguage = language; - await _storage.setPreferredLanguage(language.code); + await storage.setPreferredLanguage(language.code); notifyListeners(); } - // Progress Management Future markDayComplete(int day) async { - _progress.markDayComplete(day, _currentLanguage.code); - await _storage.saveProgress(_progress); - await _notification.showCompletionNotification(day); + await storage.markDayComplete(day, _currentLanguage.code); + await streakService.recordLearningActivity(); + await notificationService.showCompletionNotification(day); notifyListeners(); } - bool isDayCompleted(int day) { - return _progress.isDayCompleted(day, _currentLanguage.code); - } - - double getProgressForLanguage(String langCode) { - return _progress.getProgressForLanguage(langCode); - } + bool isDayCompleted(int day) => + storage.isDayCompleted(day, _currentLanguage.code); - int get totalCompletedDays => _progress.totalCompleted; + double getProgressForLanguage(String langCode) => + storage.getProgressForLanguage(langCode); - int getCompletedDaysForLanguage(String langCode) { - return _progress.completedDays[langCode]?.length ?? 0; - } + int get totalCompletedDays => storage.totalUniqueCompletedDays; - // Audio Management - Future playLessonAudio(int day, String language) async { - await _audio.playLessonAudio(day, language); - } + int getCompletedDaysForLanguage(String langCode) => + storage.getCompletedDaysForLanguage(langCode); Future setAudioSpeed(double speed) async { - await _audio.setPlaybackSpeed(speed); - final settings = await _storage.getAudioSettings(); + await audioService.setPlaybackSpeed(speed); + final settings = await storage.getAudioSettings(); settings['playbackSpeed'] = speed; - await _storage.saveAudioSettings(settings); + await storage.saveAudioSettings(settings); } Future setAudioLooping(bool loop) async { - await _audio.setLooping(loop); - final settings = await _storage.getAudioSettings(); + await audioService.setLooping(loop); + final settings = await storage.getAudioSettings(); settings['loopEnabled'] = loop; - await _storage.saveAudioSettings(settings); + await storage.saveAudioSettings(settings); } - // Notification Management Future scheduleDailyReminder(int hour, int minute) async { - await _notification.scheduleDailyReminder(hour: hour, minute: minute); - await _storage.saveNotificationSettings({ + await notificationService.scheduleDailyReminder(hour: hour, minute: minute); + await storage.saveNotificationSettings({ 'enabled': true, 'time': '$hour:${minute.toString().padLeft(2, '0')}', }); } Future cancelNotifications() async { - await _notification.cancelAllNotifications(); - await _storage.saveNotificationSettings({ - 'enabled': false, - 'time': '09:00', - }); + await notificationService.cancelAllNotifications(); + await storage.saveNotificationSettings({'enabled': false, 'time': '09:00'}); } - // Lessons Data List getAllLessons() { return List.generate(40, (index) { final day = index + 1; @@ -147,12 +132,114 @@ class AppState extends ChangeNotifier { }); } - Lesson getLesson(int day) { - return getAllLessons()[day - 1]; + Lesson getLesson(int day) => getAllLessons()[day - 1]; + + // Starred phrases + List get starredPhrases => storage.getStarredPhrases(); + + Future toggleStarredPhrase({ + required int day, + required String sectionTitle, + required String phrase, + }) async { + final lang = _currentLanguage.code; + final id = StarredPhrase.makeId(day, lang, sectionTitle, phrase); + final added = await storage.toggleStarredPhrase(StarredPhrase( + id: id, + day: day, + lang: lang, + phrase: phrase, + sectionTitle: sectionTitle, + createdAt: DateTime.now().toUtc(), + )); + notifyListeners(); + return added; + } + + bool isPhraseStarred(int day, String sectionTitle, String phrase) { + final id = StarredPhrase.makeId( + day, _currentLanguage.code, sectionTitle, phrase); + return storage.isPhraseStarred(id); + } + + Future removeStarredPhrase(String id) async { + await storage.removeStarredPhrase(id); + notifyListeners(); + } + + Future addPhraseToSrs({ + required int day, + required String sectionTitle, + required String phrase, + }) async { + await srsService.upsertCard( + day: day, + lang: _currentLanguage.code, + front: phrase, + back: sectionTitle.isNotEmpty ? sectionTitle : 'Day $day', + ); + notifyListeners(); } + // SRS + List get srsCards => storage.getSrsCards(); + List get dueSrsCards => srsService.getDueCards(); + + Future seedSrsFromStarred() async { + await srsService.seedFromStarred(); + notifyListeners(); + } + + Future reviewSrsCard(String cardId, String grade) async { + final result = await srsService.reviewCard(cardId, grade); + notifyListeners(); + return result; + } + + // Supplementary / reading / writing completion + Future markSupplementaryComplete(String category) async { + await storage.markSupplementaryComplete(category, _currentLanguage.code); + await streakService.recordLearningActivity(); + notifyListeners(); + } + + bool isSupplementaryCompleted(String category) => + storage.isSupplementaryCompleted(category, _currentLanguage.code); + + Future markReadingComplete(String level, String topic) async { + await storage.markReadingComplete(level, topic, _currentLanguage.code); + await streakService.recordLearningActivity(); + notifyListeners(); + } + + bool isReadingCompleted(String level, String topic) => + storage.isReadingCompleted(level, topic, _currentLanguage.code); + + Future markWritingComplete(String type, String level) async { + await storage.markWritingComplete(type, level, _currentLanguage.code); + await streakService.recordLearningActivity(); + notifyListeners(); + } + + bool isWritingCompleted(String type, String level) => + storage.isWritingCompleted(type, level, _currentLanguage.code); + + // Placement & quiz + Future savePlacementResult(PlacementResult result) async { + await storage.savePlacementResult(result); + notifyListeners(); + } + + Future saveQuizScore(QuizResult result) async { + await storage.saveQuizScore(result); + notifyListeners(); + } + + QuizResult? getQuizScoreForDay(int day) => storage.getQuizScoreForDay(day); + + @override void dispose() { - _audio.dispose(); + audioService.dispose(); super.dispose(); } } diff --git a/flutter_app/lib/services/content_service.dart b/flutter_app/lib/services/content_service.dart new file mode 100644 index 0000000..eaa8491 --- /dev/null +++ b/flutter_app/lib/services/content_service.dart @@ -0,0 +1,195 @@ +import 'dart:convert'; +import 'package:flutter/services.dart'; +import '../models/audio_cue.dart'; +import '../models/lesson.dart'; +import '../models/phrase_section.dart'; +import '../data/content_catalog.dart'; + +class ContentService { + Future loadAssetText(String path) async { + return rootBundle.loadString('assets/$path'); + } + + Future loadTiming(String path) async { + try { + final raw = await loadAssetText(path); + return TimingManifest.fromJson( + json.decode(raw) as Map, + ); + } catch (_) { + return null; + } + } + + String dayTextPath(int day, Language lang) => 'text/day${day}_${lang.code}.txt'; + + String dayAudioPath(int day, Language lang) { + final audioLang = audioLangFor(lang); + return 'audio/day${day}_$audioLang.mp3'; + } + + String dayTimingPath(int day, Language lang) { + final audioLang = audioLangFor(lang); + return 'timing/day${day}_$audioLang.json'; + } + + String supplementaryTextPath(String category, Language lang) => + 'text/supplementary/${category}_${lang.code}.txt'; + + String supplementaryAudioPath(String category, Language lang) { + final audioLang = audioLangFor(lang); + return 'audio/supplementary/${category}_$audioLang.mp3'; + } + + String supplementaryTimingPath(String category, Language lang) { + final audioLang = audioLangFor(lang); + return 'timing/supplementary/${category}_$audioLang.json'; + } + + String readingTextPath(String level, String topic, Language lang) { + final slug = readingTopicSlug(topic); + return 'reading/${level}_${slug}_${lang.code}.txt'; + } + + String readingAudioPath(String level, String topic, Language lang) { + final slug = readingTopicSlug(topic); + final audioLang = audioLangFor(lang); + return 'audio/reading/${level}_${slug}_$audioLang.mp3'; + } + + String readingTimingPath(String level, String topic, Language lang) { + final slug = readingTopicSlug(topic); + final audioLang = audioLangFor(lang); + return 'timing/reading/${level}_${slug}_$audioLang.json'; + } + + String writingTextPath(String type, String level, Language lang) { + final slug = writingLevelSlug(level); + return 'writing/${type}_${slug}_${lang.code}.txt'; + } + + String writingAudioPath(String type, String level, Language lang) { + final slug = writingLevelSlug(level); + final audioLang = audioLangFor(lang); + return 'audio/writing/${type}_${slug}_$audioLang.mp3'; + } + + String writingTimingPath(String type, String level, Language lang) { + final slug = writingLevelSlug(level); + final audioLang = audioLangFor(lang); + return 'timing/writing/${type}_${slug}_$audioLang.json'; + } + + List parsePhraseSections(String text) { + final normalized = text.replaceAll('\r\n', '\n').replaceAll('\r', '\n'); + final sections = normalized.split(RegExp(r'\n(?=\w[^\n]+\n-+\n)')); + final result = []; + var cueIndex = 0; + + for (final section in sections) { + if (section.trim().isEmpty) continue; + final lines = section.split('\n'); + if (lines.isEmpty) continue; + final title = lines.first.trim(); + final phrases = []; + for (final line in lines.skip(1)) { + final trimmed = line.trim(); + if (trimmed.isEmpty || RegExp(r'^-+$').hasMatch(trimmed)) continue; + phrases.add(PhraseItem(cueIndex: cueIndex, text: trimmed)); + cueIndex++; + } + if (phrases.isNotEmpty) { + result.add(PhraseSection(title: title, phrases: phrases)); + } + } + return result; + } + + List splitReadingSegments(String text, Language lang) { + final t = text.trim(); + if (t.isEmpty) return []; + if (lang == Language.chinese) { + final parts = RegExp(r'[^。!?]+[。!?]?').allMatches(t); + return parts.map((m) => m.group(0)!.trim()).where((s) => s.isNotEmpty).toList(); + } + return t + .split(RegExp(r'(?<=[.!?])\s+')) + .map((s) => s.trim()) + .where((s) => s.isNotEmpty) + .toList(); + } + + ParsedReadingContent parseReadingContent(String text, Language lang) { + final sections = text.replaceAll('\r\n', '\n').split(RegExp(r'\n(?=\w[^\n]+\n-+\n)')); + String mainText = ''; + String vocabulary = ''; + String questions = ''; + + if (sections.isNotEmpty) { + final mainLines = sections[0].split('\n'); + mainText = mainLines.length > 2 ? mainLines.sublist(2).join('\n').trim() : ''; + } + if (sections.length > 1) vocabulary = sections[1]; + if (sections.length > 2) questions = sections[2]; + + return ParsedReadingContent( + mainSegments: splitReadingSegments(mainText, lang), + vocabularyText: vocabulary, + questionsText: questions, + ); + } + + List parseWritingExercises(String text) { + final lines = text.replaceAll('\r\n', '\n').split('\n'); + final exercises = []; + String? prompt; + String? answer; + + for (final line in lines) { + final trimmed = line.trim(); + if (trimmed.isEmpty) continue; + if (trimmed.startsWith('Exercise') || trimmed.startsWith('练习')) { + if (prompt != null) { + exercises.add(WritingExercise(prompt: prompt, answer: answer ?? '')); + } + prompt = trimmed; + answer = null; + } else if (trimmed.startsWith('Answer:') || trimmed.startsWith('答案:')) { + answer = trimmed.split(':').skip(1).join(':').trim(); + } else if (prompt == null) { + prompt = trimmed; + } + } + if (prompt != null) { + exercises.add(WritingExercise(prompt: prompt, answer: answer ?? '')); + } + return exercises; + } + + int? activeCueIndex(Duration position, List cues) { + final seconds = position.inMilliseconds / 1000.0; + for (final cue in cues) { + if (seconds >= cue.start && seconds < cue.end) return cue.index; + } + return null; + } +} + +class ParsedReadingContent { + final List mainSegments; + final String vocabularyText; + final String questionsText; + + const ParsedReadingContent({ + required this.mainSegments, + required this.vocabularyText, + required this.questionsText, + }); +} + +class WritingExercise { + final String prompt; + final String answer; + + const WritingExercise({required this.prompt, required this.answer}); +} diff --git a/flutter_app/lib/services/learning_services.dart b/flutter_app/lib/services/learning_services.dart new file mode 100644 index 0000000..a29a4ff --- /dev/null +++ b/flutter_app/lib/services/learning_services.dart @@ -0,0 +1,178 @@ +import '../models/achievement.dart'; +import '../models/srs_card.dart'; +import 'storage_service.dart'; + +class StreakService { + final StorageService _storage; + + StreakService(this._storage); + + String _localDateString([DateTime? date]) { + final d = date ?? DateTime.now(); + return '${d.year}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}'; + } + + int _daysBetween(String from, String to) { + final fromDate = DateTime.parse('${from}T00:00:00'); + final toDate = DateTime.parse('${to}T00:00:00'); + return toDate.difference(fromDate).inDays; + } + + Future<({String lastActiveDate, int streakCount})> recordLearningActivity([ + DateTime? date, + ]) async { + final today = _localDateString(date); + var last = _storage.lastActiveDate; + var count = _storage.streakCount; + + if (last.isEmpty) { + count = 1; + } else { + final gap = _daysBetween(last, today); + if (gap == 1) { + count += 1; + } else if (gap > 1) { + count = 1; + } + } + + last = today; + await _storage.setStreak(lastActiveDate: last, count: count); + await updateAchievements(); + return (lastActiveDate: last, streakCount: count); + } + + int getSrsReviewCount() => + _storage.getSrsCards().fold(0, (sum, c) => sum + c.reps); + + Future> updateAchievements() async { + final context = AchievementContext( + completedLessonCount: _storage.totalUniqueCompletedDays, + srsReviewCount: getSrsReviewCount(), + ); + final earned = achievementDefs + .where((a) => a.test(context)) + .map((a) => a.id) + .toList(); + await _storage.setEarnedAchievements(earned); + return earned; + } +} + +class SrsService { + final StorageService _storage; + final StreakService _streaks; + + SrsService(this._storage, this._streaks); + + static String cardId({ + int? day, + required String lang, + required String front, + String back = '', + }) { + return '${day ?? 'misc'}|$lang|$front|$back'; + } + + List getDueCards([DateTime? now]) { + final current = (now ?? DateTime.now()).toUtc(); + return _storage + .getSrsCards() + .where((c) => !c.due.isAfter(current)) + .toList() + ..sort((a, b) => a.due.compareTo(b.due)); + } + + Future upsertCard({ + String? id, + int? day, + required String lang, + required String front, + String back = '', + }) async { + if (front.trim().isEmpty) return null; + final now = DateTime.now().toUtc(); + final cards = _storage.getSrsCards(); + final cardIdValue = id ?? SrsService.cardId(day: day, lang: lang, front: front, back: back); + final existing = cards.indexWhere((c) => c.id == cardIdValue); + final card = SrsCard( + id: cardIdValue, + day: day, + lang: lang, + front: front.trim(), + back: back.trim(), + due: now, + createdAt: now, + updatedAt: now, + ); + if (existing >= 0) { + cards[existing] = SrsCard( + id: cardIdValue, + day: day ?? cards[existing].day, + lang: lang, + front: card.front, + back: card.back, + due: cards[existing].due, + interval: cards[existing].interval, + ease: cards[existing].ease, + reps: cards[existing].reps, + createdAt: cards[existing].createdAt, + updatedAt: now, + ); + } else { + cards.add(card); + } + await _storage.saveSrsCards(cards); + return card; + } + + Future seedFromStarred() async { + for (final entry in _storage.getStarredPhrases()) { + await upsertCard( + id: 'starred|${entry.id}', + day: entry.day, + lang: entry.lang, + front: entry.phrase, + back: entry.sectionTitle.isNotEmpty + ? entry.sectionTitle + : 'Day ${entry.day}', + ); + } + } + + Future reviewCard(String cardId, String grade) async { + final cards = _storage.getSrsCards(); + final index = cards.indexWhere((c) => c.id == cardId); + if (index < 0) return null; + + final card = cards[index]; + final easeDelta = grade == 'again' + ? -0.2 + : grade == 'easy' + ? 0.15 + : 0.0; + final nextEase = (card.ease + easeDelta).clamp(1.3, double.infinity); + int nextInterval; + if (grade == 'again') { + nextInterval = 0; + } else if (card.reps == 0) { + nextInterval = grade == 'easy' ? 3 : 1; + } else { + nextInterval = ((card.interval * nextEase) * (grade == 'easy' ? 1.3 : 1)) + .round() + .clamp(1, 3650); + } + + final due = DateTime.now().toUtc().add(Duration(days: nextInterval)); + cards[index] = card.copyWith( + interval: nextInterval, + ease: nextEase, + reps: card.reps + 1, + due: due, + updatedAt: DateTime.now().toUtc(), + ); + await _storage.saveSrsCards(cards); + await _streaks.recordLearningActivity(); + return cards[index]; + } +} diff --git a/flutter_app/lib/services/storage_service.dart b/flutter_app/lib/services/storage_service.dart index 762838e..ab02014 100644 --- a/flutter_app/lib/services/storage_service.dart +++ b/flutter_app/lib/services/storage_service.dart @@ -1,92 +1,347 @@ import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; import '../models/lesson.dart'; +import '../models/placement_models.dart'; +import '../models/quiz_models.dart'; +import '../models/srs_card.dart'; +import '../models/starred_phrase.dart'; +/// Mirrors PWA localStorage keys from js/data-portability.js. class StorageService { - static const String _progressKey = 'user_progress'; - static const String _preferredLanguageKey = 'preferred_language'; - static const String _notificationSettingsKey = 'notification_settings'; + static const dataExportVersion = 1; + + static const portabilityKeys = [ + 'preferredLanguage', + 'completedDays', + 'currentProgress', + 'completedReadings', + 'completedWritings', + 'completedSupplementary', + 'mandarin_pathways_notifications', + 'starredPhrases', + 'srsCards', + 'lastActiveDate', + 'streakCount', + 'earnedAchievements', + 'placementResult', + 'quizScores', + ]; late SharedPreferences _prefs; Future init() async { _prefs = await SharedPreferences.getInstance(); + await _migrateLegacyProgress(); + } + + Future _migrateLegacyProgress() async { + const legacyKey = 'user_progress'; + final legacy = _prefs.getString(legacyKey); + if (legacy == null) return; + try { + final jsonMap = json.decode(legacy) as Map; + final completedDays = jsonMap['completedDays'] as Map?; + if (completedDays != null) { + final flat = getCompletedDaysFlat(); + for (final entry in completedDays.entries) { + final lang = entry.key; + final days = (entry.value as List).cast(); + for (final day in days) { + flat['${day.toInt()}_$lang'] = true; + } + } + await setCompletedDaysFlat(flat); + } + await _prefs.remove(legacyKey); + } catch (_) {} } - // Progress Management - Future getProgress() async { - final String? progressJson = _prefs.getString(_progressKey); - if (progressJson == null) { - return Progress(); + static String normalizeLangCode(String code) { + if (code == 'zh' || code == 'zh-CN') return 'zh'; + return code; + } + + static String toWebLangCode(String code) { + if (code == 'zh') return 'zh-CN'; + return code; + } + + // --- Completed days (web flat format) --- + + Map getCompletedDaysFlat() { + final raw = _prefs.getString('completedDays'); + if (raw == null) return {}; + try { + final parsed = json.decode(raw) as Map; + return parsed.map((k, v) => MapEntry(k, v == true)); + } catch (_) { + return {}; } + } + + Future setCompletedDaysFlat(Map value) async { + await _prefs.setString('completedDays', json.encode(value)); + } + + Future markDayComplete(int day, String lang) async { + final flat = getCompletedDaysFlat(); + flat['${day}_$lang'] = true; + await setCompletedDaysFlat(flat); + await _prefs.setString( + 'currentProgress', + json.encode({'lang': lang, 'completed': _countForLang(flat, lang)}), + ); + } + + bool isDayCompleted(int day, String lang) => + getCompletedDaysFlat()['${day}_$lang'] == true; + + int _countForLang(Map flat, String lang) => + flat.keys.where((k) => k.endsWith('_$lang') && flat[k] == true).length; + + Progress getProgressView() { + final flat = getCompletedDaysFlat(); + final completedDays = >{}; + for (final entry in flat.entries) { + if (entry.value != true) continue; + final parts = entry.key.split('_'); + if (parts.length < 2) continue; + final day = int.tryParse(parts[0]); + final lang = parts.sublist(1).join('_'); + if (day == null) continue; + completedDays.putIfAbsent(lang, () => {}).add(day); + } + return Progress( + completedDays: completedDays, + preferredLanguage: normalizeLangCode(getPreferredLanguage()), + ); + } + + double getProgressForLanguage(String lang) => + _countForLang(getCompletedDaysFlat(), lang) / 40.0; + + int getCompletedDaysForLanguage(String lang) => + _countForLang(getCompletedDaysFlat(), lang); + + int get totalUniqueCompletedDays { + final days = {}; + for (final key in getCompletedDaysFlat().keys) { + if (getCompletedDaysFlat()[key] != true) continue; + final day = int.tryParse(key.split('_').first); + if (day != null) days.add(day); + } + return days.length; + } + + // --- Generic completion maps --- + + Map _getBoolMap(String key) { + final raw = _prefs.getString(key); + if (raw == null) return {}; try { - return Progress.fromJson(json.decode(progressJson)); - } catch (e) { - return Progress(); + return (json.decode(raw) as Map) + .map((k, v) => MapEntry(k, v == true)); + } catch (_) { + return {}; } } - Future saveProgress(Progress progress) async { - final String progressJson = json.encode(progress.toJson()); - return await _prefs.setString(_progressKey, progressJson); + Future _setBoolMap(String key, Map value) async { + await _prefs.setString(key, json.encode(value)); + } + + bool isReadingCompleted(String level, String topic, String lang) => + _getBoolMap('completedReadings')['${level}_${topic}_$lang'] == true; + + Future markReadingComplete(String level, String topic, String lang) async { + final map = _getBoolMap('completedReadings'); + map['${level}_${topic}_$lang'] = true; + await _setBoolMap('completedReadings', map); + } + + bool isWritingCompleted(String type, String level, String lang) => + _getBoolMap('completedWritings')['${type}_${level}_$lang'] == true; + + Future markWritingComplete(String type, String level, String lang) async { + final map = _getBoolMap('completedWritings'); + map['${type}_${level}_$lang'] = true; + await _setBoolMap('completedWritings', map); } - Future markDayComplete(int day, String language) async { - final progress = await getProgress(); - progress.markDayComplete(day, language); - return await saveProgress(progress); + bool isSupplementaryCompleted(String category, String lang) => + _getBoolMap('completedSupplementary')['${category}_$lang'] == true; + + Future markSupplementaryComplete(String category, String lang) async { + final map = _getBoolMap('completedSupplementary'); + map['${category}_$lang'] = true; + await _setBoolMap('completedSupplementary', map); } - Future isDayCompleted(int day, String language) async { - final progress = await getProgress(); - return progress.isDayCompleted(day, language); + // --- Starred phrases --- + + List getStarredPhrases() { + final raw = _prefs.getString('starredPhrases'); + if (raw == null) return []; + try { + final list = json.decode(raw) as List; + return list + .whereType>() + .map(StarredPhrase.fromJson) + .toList(); + } catch (_) { + return []; + } } - Future> getCompletedDaysCount() async { - final progress = await getProgress(); - return progress.completedDays.map( - (key, value) => MapEntry(key, value.length), + Future saveStarredPhrases(List phrases) async { + await _prefs.setString( + 'starredPhrases', + json.encode(phrases.map((p) => p.toJson()).toList()), ); } - // Language Preference - Future getPreferredLanguage() async { - return _prefs.getString(_preferredLanguageKey) ?? 'zh'; + bool isPhraseStarred(String id) => + getStarredPhrases().any((p) => p.id == id); + + Future toggleStarredPhrase(StarredPhrase entry) async { + final list = getStarredPhrases(); + final ix = list.indexWhere((p) => p.id == entry.id); + if (ix >= 0) { + list.removeAt(ix); + await saveStarredPhrases(list); + return false; + } + list.add(entry); + await saveStarredPhrases(list); + return true; } - Future setPreferredLanguage(String language) async { - return await _prefs.setString(_preferredLanguageKey, language); + Future removeStarredPhrase(String id) async { + await saveStarredPhrases( + getStarredPhrases().where((p) => p.id != id).toList(), + ); } - // Notification Settings - Future> getNotificationSettings() async { - final String? settingsJson = _prefs.getString(_notificationSettingsKey); - if (settingsJson == null) { - return { - 'enabled': true, - 'time': '09:00', - }; + // --- SRS --- + + List getSrsCards() { + final raw = _prefs.getString('srsCards'); + if (raw == null) return []; + try { + final list = json.decode(raw) as List; + return list + .whereType>() + .map(SrsCard.fromJson) + .toList(); + } catch (_) { + return []; } - return json.decode(settingsJson); } - Future saveNotificationSettings(Map settings) async { - final String settingsJson = json.encode(settings); - return await _prefs.setString(_notificationSettingsKey, settingsJson); + Future saveSrsCards(List cards) async { + await _prefs.setString( + 'srsCards', + json.encode(cards.map((c) => c.toJson()).toList()), + ); } - // User Notes (for lessons) - Future getNoteForDay(int day, String language) async { - final String key = 'note_${day}_$language'; - return _prefs.getString(key); + // --- Streaks --- + + String get lastActiveDate => _prefs.getString('lastActiveDate') ?? ''; + + int get streakCount => _prefs.getInt('streakCount') ?? 0; + + Future setStreak({required String lastActiveDate, required int count}) async { + await _prefs.setString('lastActiveDate', lastActiveDate); + await _prefs.setInt('streakCount', count); + } + + List getEarnedAchievements() { + final raw = _prefs.getString('earnedAchievements'); + if (raw == null) return []; + try { + return (json.decode(raw) as List).cast(); + } catch (_) { + return []; + } + } + + Future setEarnedAchievements(List ids) async { + await _prefs.setString('earnedAchievements', json.encode(ids.toSet().toList())); + } + + // --- Placement --- + + PlacementResult? getPlacementResult() { + final raw = _prefs.getString('placementResult'); + if (raw == null) return null; + try { + return PlacementResult.fromJson(json.decode(raw) as Map); + } catch (_) { + return null; + } + } + + Future savePlacementResult(PlacementResult result) async { + await _prefs.setString('placementResult', json.encode(result.toJson())); + } + + // --- Quiz --- + + Map getQuizScores() { + final raw = _prefs.getString('quizScores'); + if (raw == null) return {}; + try { + return json.decode(raw) as Map; + } catch (_) { + return {}; + } + } + + QuizResult? getQuizScoreForDay(int day) { + final saved = getQuizScores()['day$day']; + if (saved is! Map) return null; + return QuizResult.fromStored(day, saved); + } + + Future saveQuizScore(QuizResult result) async { + final scores = getQuizScores(); + final key = 'day${result.day}'; + final previous = scores[key]; + final previousBest = (previous is Map ? previous['bestScore'] as num? : null)?.toInt(); + if (previousBest == null || result.score >= previousBest) { + scores[key] = result.toJson(); + await _prefs.setString('quizScores', json.encode(scores)); + } } - Future saveNoteForDay(int day, String language, String note) async { - final String key = 'note_${day}_$language'; - return await _prefs.setString(key, note); + // --- Language / settings --- + + String getPreferredLanguage() { + final stored = _prefs.getString('preferredLanguage') ?? 'zh'; + return normalizeLangCode(stored); + } + + Future setPreferredLanguage(String language) async { + await _prefs.setString('preferredLanguage', toWebLangCode(language)); + } + + Future> getNotificationSettings() async { + final raw = _prefs.getString('mandarin_pathways_notifications'); + if (raw == null) { + return {'enabled': true, 'time': '09:00'}; + } + try { + return json.decode(raw) as Map; + } catch (_) { + return {'enabled': true, 'time': '09:00'}; + } + } + + Future saveNotificationSettings(Map settings) async { + await _prefs.setString('mandarin_pathways_notifications', json.encode(settings)); } - // Audio Settings Future> getAudioSettings() async { return { 'playbackSpeed': _prefs.getDouble('audio_speed') ?? 1.0, @@ -95,15 +350,54 @@ class StorageService { }; } - Future saveAudioSettings(Map settings) async { + Future saveAudioSettings(Map settings) async { await _prefs.setDouble('audio_speed', settings['playbackSpeed'] ?? 1.0); await _prefs.setBool('audio_autoplay', settings['autoPlay'] ?? false); await _prefs.setBool('audio_loop', settings['loopEnabled'] ?? false); - return true; } - // Clear all data - Future clearAll() async { - return await _prefs.clear(); + Future getNoteForDay(int day, String language) async => + _prefs.getString('note_${day}_$language'); + + Future saveNoteForDay(int day, String language, String note) async { + await _prefs.setString('note_${day}_$language', note); + } + + // --- Portability --- + + Map collectPortabilityPayload() { + final keys = {}; + for (final key in portabilityKeys) { + final value = _prefs.getString(key); + if (value != null) keys[key] = value; + final intValue = _prefs.getInt(key); + if (intValue != null) keys[key] = intValue.toString(); + } + return keys; + } + + Future importPortabilityPayload(Map keys) async { + for (final key in portabilityKeys) { + await _prefs.remove(key); + } + for (final key in portabilityKeys) { + final value = keys[key]; + if (value == null) continue; + if (key == 'streakCount') { + await _prefs.setInt(key, int.tryParse(value.toString()) ?? 0); + } else { + await _prefs.setString(key, value.toString()); + } + } } + + String exportPortabilityJson() { + return json.encode({ + 'version': dataExportVersion, + 'exportedAt': DateTime.now().toUtc().toIso8601String(), + 'keys': collectPortabilityPayload(), + }); + } + + Future clearAll() async => _prefs.clear(); } diff --git a/flutter_app/lib/widgets/character_canvas.dart b/flutter_app/lib/widgets/character_canvas.dart new file mode 100644 index 0000000..45709e0 --- /dev/null +++ b/flutter_app/lib/widgets/character_canvas.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.dart'; + +class CharacterCanvas extends StatefulWidget { + const CharacterCanvas({super.key}); + + @override + State createState() => _CharacterCanvasState(); +} + +class _CharacterCanvasState extends State { + final List _points = []; + bool _isDrawing = false; + + @override + Widget build(BuildContext context) { + return Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + const Text('Character Practice', + style: TextStyle(fontWeight: FontWeight.bold)), + const SizedBox(height: 8), + Container( + width: 200, + height: 200, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey), + color: const Color(0xFFF8F8F8), + ), + child: GestureDetector( + onPanStart: (d) { + setState(() { + _isDrawing = true; + _points.add(d.localPosition); + }); + }, + onPanUpdate: (d) { + if (_isDrawing) { + setState(() => _points.add(d.localPosition)); + } + }, + onPanEnd: (_) => setState(() => _isDrawing = false), + child: CustomPaint( + painter: _DrawingPainter(_points), + size: const Size(200, 200), + ), + ), + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton( + onPressed: () => setState(() => _points.clear()), + child: const Text('Clear'), + ), + const Text(' | '), + const Text('你 好 我 是', style: TextStyle(fontSize: 24)), + ], + ), + ], + ), + ), + ); + } +} + +class _DrawingPainter extends CustomPainter { + final List points; + _DrawingPainter(this.points); + + @override + void paint(Canvas canvas, Size size) { + final grid = Paint() + ..color = const Color(0xFFE0E0E0) + ..strokeWidth = 1; + canvas.drawLine(Offset(size.width / 2, 0), + Offset(size.width / 2, size.height), grid); + canvas.drawLine(Offset(0, size.height / 2), + Offset(size.width, size.height / 2), grid); + + final stroke = Paint() + ..color = const Color(0xFF333333) + ..strokeWidth = 3 + ..strokeCap = StrokeCap.round; + + for (var i = 0; i < points.length - 1; i++) { + canvas.drawLine(points[i], points[i + 1], stroke); + } + } + + @override + bool shouldRepaint(covariant _DrawingPainter old) => + old.points.length != points.length; +} diff --git a/flutter_app/lib/widgets/learning_dashboard.dart b/flutter_app/lib/widgets/learning_dashboard.dart new file mode 100644 index 0000000..6d4928b --- /dev/null +++ b/flutter_app/lib/widgets/learning_dashboard.dart @@ -0,0 +1,176 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../l10n/strings.dart'; +import '../models/achievement.dart'; +import '../services/app_state.dart'; + +class LearningDashboard extends StatelessWidget { + const LearningDashboard({super.key}); + + @override + Widget build(BuildContext context) { + final appState = context.watch(); + final lang = appState.currentLanguage; + final earned = appState.earnedAchievements.toSet(); + + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppStrings.t(lang, zh: '学习仪表盘', en: 'Learning Dashboard'), + style: Theme.of(context).textTheme.headlineSmall?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 12), + Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + _Stat( + value: '${appState.streakCount}', + label: AppStrings.t(lang, + zh: '连续学习天数', en: 'Day streak'), + ), + _Stat( + value: '${appState.srsDueCount}', + label: AppStrings.t(lang, + zh: '今日复习卡片', en: 'Cards due today'), + ), + _Stat( + value: appState.placementResult != null + ? '${appState.placementResult!.recommendedDay}' + : '--', + label: AppStrings.t(lang, + zh: '推荐起点', en: 'Recommended start'), + ), + ], + ), + ), + ), + const SizedBox(height: 12), + Wrap( + spacing: 8, + runSpacing: 8, + children: [ + _NavChip( + icon: Icons.layers, + label: AppStrings.t(lang, zh: '开始复习', en: 'Start SRS'), + route: '/srs', + ), + _NavChip( + icon: Icons.star, + label: AppStrings.t(lang, zh: '复习清单', en: 'Review starred'), + route: '/review', + ), + _NavChip( + icon: Icons.quiz, + label: AppStrings.t(lang, zh: '水平测试', en: 'Placement test'), + route: '/placement', + ), + _NavChip( + icon: Icons.save_alt, + label: AppStrings.t(lang, zh: '备份进度', en: 'Backup progress'), + onTap: () => _showPortability(context), + ), + ], + ), + const SizedBox(height: 16), + Text( + AppStrings.t(lang, zh: '成就', en: 'Achievements'), + style: Theme.of(context).textTheme.titleMedium, + ), + const SizedBox(height: 8), + ...achievementDefs.map((a) { + final isEarned = earned.contains(a.id); + return ListTile( + dense: true, + leading: Icon( + isEarned ? Icons.emoji_events : Icons.emoji_events_outlined, + color: isEarned ? Colors.amber : Colors.grey, + ), + title: Text(AppStrings.t(lang, zh: a.labelZh, en: a.labelEn)), + subtitle: Text( + AppStrings.t(lang, zh: a.descriptionZh, en: a.descriptionEn), + ), + ); + }), + ], + ), + ); + } + + void _showPortability(BuildContext context) { + final appState = context.read(); + final lang = appState.currentLanguage; + final json = appState.storage.exportPortabilityJson(); + + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: Text(AppStrings.t(lang, zh: '备份与恢复', en: 'Backup & restore')), + content: SingleChildScrollView( + child: SelectableText( + json, + style: const TextStyle(fontSize: 11, fontFamily: 'monospace'), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(ctx), + child: Text(AppStrings.t(lang, zh: '关闭', en: 'Close')), + ), + ], + ), + ); + } +} + +class _Stat extends StatelessWidget { + final String value; + final String label; + + const _Stat({required this.value, required this.label}); + + @override + Widget build(BuildContext context) { + return Expanded( + child: Column( + children: [ + Text(value, + style: Theme.of(context) + .textTheme + .headlineMedium + ?.copyWith(fontWeight: FontWeight.bold)), + Text(label, textAlign: TextAlign.center), + ], + ), + ); + } +} + +class _NavChip extends StatelessWidget { + final IconData icon; + final String label; + final String? route; + final VoidCallback? onTap; + + const _NavChip({ + required this.icon, + required this.label, + this.route, + this.onTap, + }); + + @override + Widget build(BuildContext context) { + return ActionChip( + avatar: Icon(icon, size: 18), + label: Text(label), + onPressed: onTap ?? () => Navigator.pushNamed(context, route!), + ); + } +} diff --git a/flutter_app/lib/widgets/lesson_audio_player.dart b/flutter_app/lib/widgets/lesson_audio_player.dart new file mode 100644 index 0000000..8e2e41a --- /dev/null +++ b/flutter_app/lib/widgets/lesson_audio_player.dart @@ -0,0 +1,167 @@ +import 'package:audioplayers/audioplayers.dart' as ap; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../services/app_state.dart'; + +class LessonAudioPlayer extends StatefulWidget { + final String audioPath; + final VoidCallback? onPositionTick; + final bool showPinyinNote; + + const LessonAudioPlayer({ + super.key, + required this.audioPath, + this.onPositionTick, + this.showPinyinNote = false, + }); + + @override + State createState() => _LessonAudioPlayerState(); +} + +class _LessonAudioPlayerState extends State { + ap.PlayerState _audioState = ap.PlayerState.stopped; + Duration _position = Duration.zero; + Duration _duration = Duration.zero; + bool _listenersAttached = false; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + if (_listenersAttached) return; + _listenersAttached = true; + final audio = context.read().audioService; + audio.playerStateStream.listen((s) { + if (mounted) setState(() => _audioState = s); + }); + audio.positionStream.listen((p) { + if (mounted) { + setState(() => _position = p); + widget.onPositionTick?.call(); + } + }); + audio.durationStream.listen((d) { + if (mounted && d != null) setState(() => _duration = d); + }); + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, appState, _) { + return Card( + margin: const EdgeInsets.all(16), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + if (widget.showPinyinNote) + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Text( + 'Using Mandarin audio for reference.', + style: Theme.of(context).textTheme.bodySmall, + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + IconButton( + icon: const Icon(Icons.replay_10), + onPressed: () { + final p = _position - const Duration(seconds: 10); + appState.audioService.seek( + p < Duration.zero ? Duration.zero : p, + ); + }, + ), + IconButton( + iconSize: 48, + icon: Icon(_audioState == ap.PlayerState.playing + ? Icons.pause_circle_filled + : Icons.play_circle_filled), + onPressed: () => _toggle(appState), + ), + IconButton( + icon: const Icon(Icons.forward_10), + onPressed: () { + final p = _position + const Duration(seconds: 10); + appState.audioService.seek( + p > _duration ? _duration : p, + ); + }, + ), + ], + ), + Slider( + value: _position.inMilliseconds.toDouble().clamp( + 0, + _duration.inMilliseconds.toDouble() > 0 + ? _duration.inMilliseconds.toDouble() + : 1, + ), + max: _duration.inMilliseconds.toDouble() > 0 + ? _duration.inMilliseconds.toDouble() + : 1, + onChanged: (v) => appState.audioService + .seek(Duration(milliseconds: v.toInt())), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(_fmt(_position)), + Text(_fmt(_duration)), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + DropdownButton( + value: appState.audioService.playbackSpeed, + items: [0.5, 0.75, 1.0, 1.25, 1.5, 2.0] + .map((s) => DropdownMenuItem( + value: s, + child: Text('${s}x'), + )) + .toList(), + onChanged: (s) { + if (s != null) appState.setAudioSpeed(s); + }, + ), + IconButton( + icon: Icon( + appState.audioService.isLooping + ? Icons.repeat_one + : Icons.repeat, + color: appState.audioService.isLooping + ? Theme.of(context).colorScheme.primary + : null, + ), + onPressed: () => appState.setAudioLooping( + !appState.audioService.isLooping, + ), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } + + Future _toggle(AppState appState) async { + if (_audioState == ap.PlayerState.playing) { + await appState.audioService.pause(); + } else { + await appState.audioService.play(widget.audioPath); + } + } + + String _fmt(Duration d) { + final m = d.inMinutes.remainder(60).toString().padLeft(2, '0'); + final s = d.inSeconds.remainder(60).toString().padLeft(2, '0'); + return '$m:$s'; + } +} diff --git a/flutter_app/lib/widgets/phrase_list.dart b/flutter_app/lib/widgets/phrase_list.dart new file mode 100644 index 0000000..e2f2384 --- /dev/null +++ b/flutter_app/lib/widgets/phrase_list.dart @@ -0,0 +1,124 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; +import '../models/lesson.dart'; +import '../models/phrase_section.dart'; +import '../l10n/strings.dart'; +import '../services/app_state.dart'; + +class PhraseListView extends StatelessWidget { + final List sections; + final int day; + final int? activeCueIndex; + + const PhraseListView({ + super.key, + required this.sections, + required this.day, + this.activeCueIndex, + }); + + @override + Widget build(BuildContext context) { + final appState = context.watch(); + final lang = appState.currentLanguage; + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: sections.map((section) { + return Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + section.title, + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.primary, + ), + ), + const SizedBox(height: 12), + ...section.phrases.map((phrase) { + final isActive = activeCueIndex == phrase.cueIndex; + final starred = appState.isPhraseStarred( + day, section.title, phrase.text); + return Container( + margin: const EdgeInsets.only(bottom: 8), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: isActive + ? Theme.of(context) + .colorScheme + .primary + .withValues(alpha: 0.12) + : Colors.grey.shade50, + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: isActive + ? Theme.of(context).colorScheme.primary + : Colors.grey.shade300, + ), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: SelectableText( + phrase.text, + style: TextStyle( + fontSize: lang == Language.chinese ? 20 : 18, + height: 1.6, + fontWeight: + isActive ? FontWeight.w600 : FontWeight.normal, + ), + ), + ), + IconButton( + icon: Icon( + starred ? Icons.star : Icons.star_border, + color: starred ? Colors.amber : null, + size: 20, + ), + onPressed: () => appState.toggleStarredPhrase( + day: day, + sectionTitle: section.title, + phrase: phrase.text, + ), + ), + IconButton( + icon: const Icon(Icons.layers, size: 20), + tooltip: 'Add to SRS', + onPressed: () => appState.addPhraseToSrs( + day: day, + sectionTitle: section.title, + phrase: phrase.text, + ), + ), + IconButton( + icon: const Icon(Icons.copy, size: 20), + onPressed: () { + Clipboard.setData( + ClipboardData(text: phrase.text)); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(AppStrings.t(lang, + zh: '短语已复制', en: 'Phrase copied')), + ), + ); + }, + ), + ], + ), + ); + }), + ], + ), + ), + ); + }).toList(), + ); + } +} diff --git a/flutter_app/pubspec.yaml b/flutter_app/pubspec.yaml index c96b18b..43f0188 100644 --- a/flutter_app/pubspec.yaml +++ b/flutter_app/pubspec.yaml @@ -44,5 +44,12 @@ flutter: assets: - assets/audio/ + - assets/audio/supplementary/ + - assets/audio/reading/ + - assets/audio/writing/ - assets/icons/ - assets/text/ + - assets/text/supplementary/ + - assets/reading/ + - assets/writing/ + - assets/timing/ diff --git a/flutter_app/test/content_service_test.dart b/flutter_app/test/content_service_test.dart new file mode 100644 index 0000000..0997d9f --- /dev/null +++ b/flutter_app/test/content_service_test.dart @@ -0,0 +1,52 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:mandarin_pathways/data/content_catalog.dart'; +import 'package:mandarin_pathways/data/placement_data.dart'; +import 'package:mandarin_pathways/data/quiz_data.dart'; +import 'package:mandarin_pathways/models/lesson.dart'; +import 'package:mandarin_pathways/services/content_service.dart'; + +void main() { + final content = ContentService(); + + test('parsePhraseSections splits day lesson text', () { + const sample = ''' +Basic Greetings +--------------- +你好 +早上好 + +Self Introduction +----------------- +我叫... +'''; + final sections = content.parsePhraseSections(sample); + expect(sections.length, 2); + expect(sections.first.title, 'Basic Greetings'); + expect(sections.first.phrases.length, 2); + expect(sections.first.phrases.first.text, '你好'); + }); + + test('pinyin uses zh audio path', () { + expect(audioLangFor(Language.pinyin), 'zh'); + expect(content.dayAudioPath(1, Language.pinyin), 'audio/day1_zh.mp3'); + expect(content.dayAudioPath(1, Language.english), 'audio/day1_en.mp3'); + }); + + test('placement scoring recommends beginner start', () { + final result = scorePlacement(List.filled(placementQuestions.length, null)); + expect(result.recommendedDay, 1); + expect(result.level, 'Beginner'); + }); + + test('quiz scoring counts correct answers', () { + final quiz = getQuizForDay(1); + final answers = quiz.questions.map((q) => q.answer).toList(); + final result = scoreQuiz(1, answers); + expect(result.score, quiz.questions.length); + }); + + test('slugify converts topic names', () { + expect(slugify('HSK1 - Essential'), 'hsk1_-_essential'); + expect(readingTopicSlug('Self Introduction'), 'self_introduction'); + }); +} diff --git a/flutter_app/test/widget_test.dart b/flutter_app/test/widget_test.dart index d9c9d18..bf3cc15 100644 --- a/flutter_app/test/widget_test.dart +++ b/flutter_app/test/widget_test.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; - import 'package:mandarin_pathways/main.dart'; void main() { diff --git a/scripts/sync_flutter_assets.py b/scripts/sync_flutter_assets.py new file mode 100644 index 0000000..d00ddcb --- /dev/null +++ b/scripts/sync_flutter_assets.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +"""Copy PWA content assets into flutter_app/assets for offline bundling.""" + +from __future__ import annotations + +import shutil +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +ASSETS = ROOT / "flutter_app" / "assets" + +COPY_MAP = [ + (ROOT / "audio_files" / "day*.mp3", ASSETS / "audio"), + (ROOT / "audio_files" / "supplementary", ASSETS / "audio" / "supplementary"), + (ROOT / "audio_files" / "reading", ASSETS / "audio" / "reading"), + (ROOT / "audio_files" / "writing", ASSETS / "audio" / "writing"), + (ROOT / "text_files" / "day*.txt", ASSETS / "text"), + (ROOT / "text_files" / "supplementary", ASSETS / "text" / "supplementary"), + (ROOT / "reading_files", ASSETS / "reading"), + (ROOT / "writing_files", ASSETS / "writing"), + (ROOT / "timing", ASSETS / "timing"), +] + + +def copy_glob(src_glob: Path, dest_dir: Path) -> int: + dest_dir.mkdir(parents=True, exist_ok=True) + count = 0 + for src in sorted(src_glob.parent.glob(src_glob.name)): + if src.is_file(): + shutil.copy2(src, dest_dir / src.name) + count += 1 + return count + + +def copy_tree(src: Path, dest: Path) -> int: + if not src.exists(): + print(f" skip missing: {src}") + return 0 + if src.is_file(): + dest.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(src, dest) + return 1 + if dest.exists(): + shutil.rmtree(dest) + shutil.copytree(src, dest) + count = sum(1 for p in dest.rglob("*") if p.is_file()) + return count + + +def main() -> None: + total = 0 + print("Syncing PWA assets into flutter_app/assets …") + for src, dest in COPY_MAP: + if "*" in str(src): + n = copy_glob(src, dest) + else: + n = copy_tree(src, dest) + print(f" {src.name}: {n} files -> {dest.relative_to(ROOT)}") + total += n + + legacy = ASSETS / "text" / "text_files" + if legacy.exists(): + shutil.rmtree(legacy) + print(f" removed legacy duplicate: {legacy.relative_to(ROOT)}") + + print(f"Done. {total} files synced.") + + +if __name__ == "__main__": + main()