@rookiestar/eng-lang-tutor 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.claude/settings.local.json +22 -0
  2. package/.gitignore +32 -0
  3. package/CHANGELOG.md +37 -0
  4. package/CLAUDE.md +275 -0
  5. package/README.md +369 -0
  6. package/SKILL.md +613 -0
  7. package/bin/eng-lang-tutor.js +177 -0
  8. package/docs/OPENCLAW_DEPLOYMENT.md +241 -0
  9. package/examples/sample_keypoint_a1.json +112 -0
  10. package/examples/sample_keypoint_a2.json +124 -0
  11. package/examples/sample_keypoint_b1.json +135 -0
  12. package/examples/sample_keypoint_b2.json +137 -0
  13. package/examples/sample_keypoint_c1.json +134 -0
  14. package/examples/sample_keypoint_c2.json +141 -0
  15. package/examples/sample_quiz_a1.json +94 -0
  16. package/examples/sample_quiz_a2.json +94 -0
  17. package/examples/sample_quiz_b1.json +92 -0
  18. package/examples/sample_quiz_b2.json +94 -0
  19. package/examples/sample_quiz_c1.json +94 -0
  20. package/examples/sample_quiz_c2.json +104 -0
  21. package/package.json +41 -0
  22. package/references/resources.md +292 -0
  23. package/requirements.txt +16 -0
  24. package/scripts/__init__.py +28 -0
  25. package/scripts/audio/__init__.py +23 -0
  26. package/scripts/audio/composer.py +367 -0
  27. package/scripts/audio/converter.py +331 -0
  28. package/scripts/audio/feishu_voice.py +404 -0
  29. package/scripts/audio/tts/__init__.py +30 -0
  30. package/scripts/audio/tts/base.py +166 -0
  31. package/scripts/audio/tts/manager.py +306 -0
  32. package/scripts/audio/tts/providers/__init__.py +12 -0
  33. package/scripts/audio/tts/providers/edge.py +111 -0
  34. package/scripts/audio/tts/providers/xunfei.py +205 -0
  35. package/scripts/audio/utils.py +63 -0
  36. package/scripts/cli/__init__.py +7 -0
  37. package/scripts/cli/cli.py +229 -0
  38. package/scripts/cli/command_parser.py +336 -0
  39. package/scripts/core/__init__.py +30 -0
  40. package/scripts/core/constants.py +125 -0
  41. package/scripts/core/error_notebook.py +308 -0
  42. package/scripts/core/gamification.py +405 -0
  43. package/scripts/core/scorer.py +295 -0
  44. package/scripts/core/state_manager.py +814 -0
  45. package/scripts/eng-lang-tutor +16 -0
  46. package/scripts/scheduling/__init__.py +6 -0
  47. package/scripts/scheduling/cron_push.py +229 -0
  48. package/scripts/utils/__init__.py +12 -0
  49. package/scripts/utils/dedup.py +331 -0
  50. package/scripts/utils/helpers.py +82 -0
  51. package/templates/keypoint_schema.json +420 -0
  52. package/templates/prompt_templates.md +73 -0
  53. package/templates/prompts/display_guide.md +106 -0
  54. package/templates/prompts/initialization.md +350 -0
  55. package/templates/prompts/keypoint_generation.md +272 -0
  56. package/templates/prompts/output_rules.md +106 -0
  57. package/templates/prompts/quiz_generation.md +190 -0
  58. package/templates/prompts/responses.md +339 -0
  59. package/templates/prompts/shared_enums.md +252 -0
  60. package/templates/quiz_schema.json +214 -0
  61. package/templates/state_schema.json +277 -0
@@ -0,0 +1,94 @@
1
+ {
2
+ "_meta": {
3
+ "prompt_version": "quiz_gen_v1.2"
4
+ },
5
+ "quiz_date": "2026-02-25",
6
+ "cefr_level": "A2",
7
+ "keypoint_fingerprint": "social_nice_to_meet_you",
8
+ "questions": [
9
+ {
10
+ "id": 1,
11
+ "type": "multiple_choice",
12
+ "question": "When do you say 'Nice to meet you'?",
13
+ "context": "Your colleague introduces you to a new team member.",
14
+ "options": [
15
+ "A. When you see an old friend",
16
+ "B. When you meet someone for the first time",
17
+ "C. When you say goodbye",
18
+ "D. When you ask for help"
19
+ ],
20
+ "correct_answer": "B",
21
+ "explanation": "'Nice to meet you' is ONLY used when meeting someone for the FIRST time. For old friends, use 'Good to see you'. For goodbye, use 'See you later'.",
22
+ "xp_value": 10,
23
+ "display": {
24
+ "type_emoji": "๐Ÿ”ค",
25
+ "type_name": "้€‰ๆ‹ฉ้ข˜ | Multiple Choice",
26
+ "question_formatted": "๐Ÿ’ฌ When do you say **'Nice to meet you'**?",
27
+ "context_formatted": "๐Ÿ‘‹ Your colleague introduces you to a new team member.",
28
+ "options_formatted": [
29
+ "โฌœ A. When you see an old friend",
30
+ "โฌœ B. When you meet someone for the first time",
31
+ "โฌœ C. When you say goodbye",
32
+ "โฌœ D. When you ask for help"
33
+ ],
34
+ "hint": "๐Ÿ’ก 'Meet' = first time introduction",
35
+ "correct_feedback": "โœ… Correct! **'Nice to meet you'** = first time only!",
36
+ "wrong_feedback": "โŒ **'Nice to meet you'** is for first-time introductions only!",
37
+ "xp_display": "๐Ÿ’Ž +10 XP"
38
+ }
39
+ },
40
+ {
41
+ "id": 2,
42
+ "type": "chinglish_fix",
43
+ "question": "Fix the mistake in this introduction:",
44
+ "chinglish_sentence": "Hi John! Nice to see you. This is our first meeting.",
45
+ "correct_answer": "Nice to meet you",
46
+ "explanation": "If this is your FIRST meeting, use 'Nice to MEET you', not 'see you'. 'See you' is for people you already know or have met before.",
47
+ "xp_value": 15,
48
+ "display": {
49
+ "type_emoji": "๐Ÿ”ง",
50
+ "type_name": "Chinglish ไฟฎๆญฃ | Fix the Chinglish",
51
+ "question_formatted": "๐Ÿ”ง Find and fix the error:",
52
+ "sentence_formatted": "๐Ÿ“ \"Hi John! **Nice to see you.** This is our first meeting.\"",
53
+ "hint": "๐Ÿ’ก If it's the FIRST meeting, 'see' or 'meet'?",
54
+ "correct_feedback": "โœ… Fixed! **'Nice to meet you!'** for first introductions! ๐ŸŽ‰",
55
+ "wrong_feedback": "โŒ First time = **'Nice to meet you'**, not 'see you'!",
56
+ "xp_display": "๐Ÿ’Ž +15 XP"
57
+ }
58
+ },
59
+ {
60
+ "id": 3,
61
+ "type": "fill_blank",
62
+ "question": "Choose the correct phrase:",
63
+ "context": "You're at a party. Your friend introduces you to someone. You say: '___!'",
64
+ "word_bank": ["Nice to meet you", "Nice to see you", "Good to know you"],
65
+ "correct_answer": "Nice to meet you",
66
+ "explanation": "'Nice to meet you' is the standard phrase for first introductions. 'Nice to see you' is for people you already know. 'Good to know you' is not commonly used.",
67
+ "xp_value": 12,
68
+ "display": {
69
+ "type_emoji": "โœ๏ธ",
70
+ "type_name": "ๅกซ็ฉบ้ข˜ | Fill in the Blank",
71
+ "question_formatted": "โœ๏ธ Complete the response:",
72
+ "context_formatted": "๐ŸŽ‰ Friend: \"This is Sarah.\" You: \"**___!**\"",
73
+ "word_bank_formatted": "๐Ÿ“ฆ Options: [ **Nice to meet you** | Nice to see you | Good to know you ]",
74
+ "hint": "๐Ÿ’ก First introduction = 'meet' or 'see'?",
75
+ "correct_feedback": "โœ… Perfect! **'Nice to meet you!'** is the standard introduction! ๐ŸŽฏ",
76
+ "wrong_feedback": "โŒ For first introductions, say **'Nice to meet you!'**",
77
+ "xp_display": "๐Ÿ’Ž +12 XP"
78
+ }
79
+ }
80
+ ],
81
+ "total_xp": 37,
82
+ "passing_score": 70,
83
+ "display": {
84
+ "header": "๐Ÿ“ ไปŠๆ—ฅๆต‹้ชŒ | Daily Quiz",
85
+ "date": "๐Ÿ“… 2026-02-25",
86
+ "difficulty": "๐Ÿ“Š Level: **A2** (ๅˆ็บง)",
87
+ "topic": "๐Ÿท๏ธ Topic: **Nice to Meet You**",
88
+ "instructions": "๐ŸŽฏ 3้“ๅฐ้ข˜๏ผŒ็ญ”ๅฏน2้“ๅฐฑ่ฟ‡ๅ…ณ๏ผ3 questions, get 2 right to pass!",
89
+ "progress_bar": "โฌœโฌœโฌœ 0/3 questions",
90
+ "xp_summary": "๐Ÿ’Ž Total XP: 37 | ๐Ÿ† Pass: 2/3 correct",
91
+ "footer": "โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n๐Ÿ’ช Good luck! ๅŠ ๆฒน! ๐Ÿš€"
92
+ },
93
+ "generated": true
94
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "quiz_date": "2026-02-20",
3
+ "cefr_level": "B1",
4
+ "keypoint_fingerprint": "workplace_touch_base",
5
+ "questions": [
6
+ {
7
+ "id": 1,
8
+ "type": "multiple_choice",
9
+ "question": "Your colleague asks to 'touch base' about a project. What do they mean?",
10
+ "context": "You receive a Slack message: 'Hey, can we touch base on the Q4 report?'",
11
+ "options": [
12
+ "A. They want to have a formal presentation",
13
+ "B. They want to have a brief check-in conversation",
14
+ "C. They want to cancel the project",
15
+ "D. They want you to write the entire report"
16
+ ],
17
+ "correct_answer": "B",
18
+ "explanation": "'Touch base' means having a brief, informal check-in. It comes from baseball and implies a quick connection, not a formal meeting.",
19
+ "xp_value": 10,
20
+ "display": {
21
+ "type_emoji": "๐Ÿ”ค",
22
+ "type_name": "้€‰ๆ‹ฉ้ข˜ | Multiple Choice",
23
+ "question_formatted": "๐Ÿ’ฌ Your colleague asks to **'touch base'**. What do they mean?",
24
+ "context_formatted": "๐Ÿ“ฑ Slack: \"Hey, can we **touch base** on the Q4 report?\"",
25
+ "options_formatted": [
26
+ "โฌœ A. They want a formal presentation",
27
+ "โฌœ B. They want a brief check-in",
28
+ "โฌœ C. They want to cancel the project",
29
+ "โฌœ D. They want you to write the report"
30
+ ],
31
+ "correct_feedback": "โœ… Correct! **'Touch base'** = quick check-in โšก",
32
+ "wrong_feedback": "โŒ Not quite. **'Touch base'** means a brief, informal chat!",
33
+ "key_phrase": "**touch base**",
34
+ "xp_display": "๐Ÿ’Ž +10 XP"
35
+ }
36
+ },
37
+ {
38
+ "id": 2,
39
+ "type": "chinglish_fix",
40
+ "question": "Identify and fix the Chinglish expression in this email:",
41
+ "context": "\"Hi Team, I want to communicate with you about the project. Let's discuss together tomorrow.\"",
42
+ "correct_answer": "touch base / sync up / check in",
43
+ "explanation": "'Communicate with you' and 'discuss together' are direct translations that sound formal and awkward. Americans would say 'touch base' or 'sync up' instead.",
44
+ "xp_value": 15,
45
+ "display": {
46
+ "type_emoji": "๐Ÿ”ง",
47
+ "type_name": "Chinglish ไฟฎๆญฃ | Fix the Chinglish",
48
+ "question_formatted": "๐Ÿ”ง Find and fix the Chinglish expressions:",
49
+ "email_formatted": "๐Ÿ“ง Original email:\n\"Hi Team, I want to 'communicate with you' about the project. Let's 'discuss together' tomorrow.\"",
50
+ "hint": "๐Ÿ’ก Hint: How would an American say this naturally?",
51
+ "correct_feedback": "โœ… Fixed! **\"Let's touch base\"** or **\"Let's sync up\"** sounds much better! ๐ŸŽ‰",
52
+ "wrong_feedback": "โŒ 'Communicate with you' โ†’ **'touch base'**\nโŒ 'Discuss together' โ†’ **'sync up'**",
53
+ "answer_formatted": "๐Ÿ“ Better: \"Hi Team, can we **touch base** about the project? Let's **sync up** tomorrow.\"",
54
+ "key_phrase": "**touch base / sync up**",
55
+ "xp_display": "๐Ÿ’Ž +15 XP"
56
+ }
57
+ },
58
+ {
59
+ "id": 3,
60
+ "type": "fill_blank",
61
+ "question": "Complete the sentence with the correct expression:",
62
+ "context": "You want to suggest a quick meeting with your manager. You say: 'I wanted to ___ on the project timeline.'",
63
+ "word_bank": ["touch base", "discuss together", "communicate"],
64
+ "correct_answer": "touch base",
65
+ "explanation": "'Touch base' is the natural American expression for suggesting a quick check-in. 'Discuss together' sounds awkward and redundant.",
66
+ "xp_value": 12,
67
+ "display": {
68
+ "type_emoji": "โœ๏ธ",
69
+ "type_name": "ๅกซ็ฉบ้ข˜ | Fill in the Blank",
70
+ "question_formatted": "โœ๏ธ Complete the sentence:",
71
+ "context_formatted": "๐Ÿ’ผ To your manager: \"I wanted to **___** on the project timeline.\"",
72
+ "word_bank_formatted": "๐Ÿ“ฆ Word Bank: [ **touch base** | 'discuss together' โŒ | 'communicate' โŒ ]",
73
+ "correct_feedback": "โœ… Perfect! **'Touch base'** is the way to go! ๐ŸŽฏ",
74
+ "wrong_feedback": "โŒ 'Discuss together' sounds awkward. Try **'touch base'**!",
75
+ "key_phrase": "**touch base**",
76
+ "xp_display": "๐Ÿ’Ž +12 XP"
77
+ }
78
+ }
79
+ ],
80
+ "total_xp": 37,
81
+ "passing_score": 70,
82
+ "display": {
83
+ "header": "๐Ÿ“ ไปŠๆ—ฅๆต‹้ชŒ | Daily Quiz",
84
+ "date": "๐Ÿ“… 2026-02-20",
85
+ "topic": "๐Ÿท๏ธ Topic: **workplace_touch_base**",
86
+ "instructions": "๐ŸŽฏ 3้“ๅฐ้ข˜๏ผŒ็ญ”ๅฏน2้“ๅฐฑ่ฟ‡ๅ…ณ๏ผ3 questions, get 2 right to pass!",
87
+ "progress_bar": "โฌœโฌœโฌœ 0/3 questions",
88
+ "xp_summary": "๐Ÿ’Ž Total XP: 37 | ๐Ÿ† Pass: 2/3 correct",
89
+ "footer": "โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n๐Ÿ’ช Good luck! ๅŠ ๆฒน! ๐Ÿš€"
90
+ },
91
+ "generated": true
92
+ }
@@ -0,0 +1,94 @@
1
+ {
2
+ "_meta": {
3
+ "prompt_version": "quiz_gen_v1.2"
4
+ },
5
+ "quiz_date": "2026-02-25",
6
+ "cefr_level": "B2",
7
+ "keypoint_fingerprint": "workplace_circle_back",
8
+ "questions": [
9
+ {
10
+ "id": 1,
11
+ "type": "multiple_choice",
12
+ "question": "Your meeting is running over time. What's the most natural way to postpone a topic?",
13
+ "context": "You've spent 30 minutes on the budget discussion. There are still 3 agenda items left.",
14
+ "options": [
15
+ "A. Let's discuss again later",
16
+ "B. Let's circle back on this",
17
+ "C. Let's talk more about this",
18
+ "D. We should continue this conversation"
19
+ ],
20
+ "correct_answer": "B",
21
+ "explanation": "'Circle back' is the standard corporate idiom for returning to a topic later. 'Discuss again' sounds mechanical. 'Talk more' and 'continue' don't imply postponement.",
22
+ "xp_value": 10,
23
+ "display": {
24
+ "type_emoji": "๐Ÿ”ค",
25
+ "type_name": "้€‰ๆ‹ฉ้ข˜ | Multiple Choice",
26
+ "question_formatted": "๐Ÿ’ฌ What's the most natural way to **postpone** a topic?",
27
+ "context_formatted": "โฐ Meeting running over. Need to move on.",
28
+ "options_formatted": [
29
+ "โฌœ A. Let's discuss again later",
30
+ "โฌœ B. Let's circle back on this",
31
+ "โฌœ C. Let's talk more about this",
32
+ "โฌœ D. We should continue this conversation"
33
+ ],
34
+ "hint": "๐Ÿ’ก Which sounds most natural in American corporate culture?",
35
+ "correct_feedback": "โœ… Correct! **'Circle back'** is the standard corporate idiom!",
36
+ "wrong_feedback": "โŒ **'Circle back'** is the most natural corporate expression here!",
37
+ "xp_display": "๐Ÿ’Ž +10 XP"
38
+ }
39
+ },
40
+ {
41
+ "id": 2,
42
+ "type": "chinglish_fix",
43
+ "question": "Make this sound more natural in American business:",
44
+ "chinglish_sentence": "We need to discuss this topic again after the meeting.",
45
+ "correct_answer": "Let's circle back on this after the meeting",
46
+ "explanation": "'Discuss this topic again' is grammatically correct but sounds mechanical. 'Circle back' is the idiomatic corporate expression that implies a planned return to the topic.",
47
+ "xp_value": 15,
48
+ "display": {
49
+ "type_emoji": "๐Ÿ”ง",
50
+ "type_name": "Chinglish ไฟฎๆญฃ | Fix the Chinglish",
51
+ "question_formatted": "๐Ÿ”ง Make this sound more corporate:",
52
+ "sentence_formatted": "๐Ÿ“ \"We need to **discuss this topic again** after the meeting.\"",
53
+ "hint": "๐Ÿ’ก Use a spatial metaphor that implies returning",
54
+ "correct_feedback": "โœ… Much better! **'Let's circle back on this'** sounds professional! ๐ŸŽ‰",
55
+ "wrong_feedback": "โŒ Try **'Let's circle back on this'** instead of 'discuss again'",
56
+ "xp_display": "๐Ÿ’Ž +15 XP"
57
+ }
58
+ },
59
+ {
60
+ "id": 3,
61
+ "type": "fill_blank",
62
+ "question": "Complete with the correct corporate idiom:",
63
+ "context": "You want to include your colleague in future emails about a project. You say: 'I'll ___ on the project updates.'",
64
+ "word_bank": ["loop you in", "circle back", "touch base", "reach out"],
65
+ "correct_answer": "loop you in",
66
+ "explanation": "'Loop you in' means to include someone in communication. 'Circle back' is for returning to topics. 'Touch base' is for checking in. 'Reach out' is for initiating contact.",
67
+ "xp_value": 12,
68
+ "display": {
69
+ "type_emoji": "โœ๏ธ",
70
+ "type_name": "ๅกซ็ฉบ้ข˜ | Fill in the Blank",
71
+ "question_formatted": "โœ๏ธ Complete the sentence:",
72
+ "context_formatted": "๐Ÿ“ง \"I'll **___** on the project updates.\"",
73
+ "word_bank_formatted": "๐Ÿ“ฆ Options: [ **loop you in** | circle back | touch base | reach out ]",
74
+ "hint": "๐Ÿ’ก Include someone = ?",
75
+ "correct_feedback": "โœ… Perfect! **'Loop you in'** means include in communication! ๐ŸŽฏ",
76
+ "wrong_feedback": "โŒ **'Loop you in'** is for including someone in future communication!",
77
+ "xp_display": "๐Ÿ’Ž +12 XP"
78
+ }
79
+ }
80
+ ],
81
+ "total_xp": 37,
82
+ "passing_score": 70,
83
+ "display": {
84
+ "header": "๐Ÿ“ ไปŠๆ—ฅๆต‹้ชŒ | Daily Quiz",
85
+ "date": "๐Ÿ“… 2026-02-25",
86
+ "difficulty": "๐Ÿ“Š Level: **B2** (ไธญ้ซ˜็บง)",
87
+ "topic": "๐Ÿท๏ธ Topic: **Circle Back / Loop In**",
88
+ "instructions": "๐ŸŽฏ 3้“ๅฐ้ข˜๏ผŒ็ญ”ๅฏน2้“ๅฐฑ่ฟ‡ๅ…ณ๏ผ3 questions, get 2 right to pass!",
89
+ "progress_bar": "โฌœโฌœโฌœ 0/3 questions",
90
+ "xp_summary": "๐Ÿ’Ž Total XP: 37 | ๐Ÿ† Pass: 2/3 correct",
91
+ "footer": "โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n๐Ÿ’ช Good luck! ๅŠ ๆฒน! ๐Ÿš€"
92
+ },
93
+ "generated": true
94
+ }
@@ -0,0 +1,94 @@
1
+ {
2
+ "_meta": {
3
+ "prompt_version": "quiz_gen_v1.2"
4
+ },
5
+ "quiz_date": "2026-02-25",
6
+ "cefr_level": "C1",
7
+ "keypoint_fingerprint": "workplace_take_offline",
8
+ "questions": [
9
+ {
10
+ "id": 1,
11
+ "type": "multiple_choice",
12
+ "question": "A detailed technical debate is derailing your stakeholder meeting. What's the most diplomatic way to redirect?",
13
+ "context": "Engineers are deep in API latency details while business stakeholders look confused.",
14
+ "options": [
15
+ "A. This is boring, let's stop",
16
+ "B. Let's take this offline with just the engineering team",
17
+ "C. You shouldn't discuss this here",
18
+ "D. We don't have time for this"
19
+ ],
20
+ "correct_answer": "B",
21
+ "explanation": "'Take this offline' is the diplomatic corporate phrase that redirects without dismissing. It implies the discussion is valid, just not in this forum. The other options are too blunt or rude.",
22
+ "xp_value": 10,
23
+ "display": {
24
+ "type_emoji": "๐Ÿ”ค",
25
+ "type_name": "้€‰ๆ‹ฉ้ข˜ | Multiple Choice",
26
+ "question_formatted": "๐Ÿ’ฌ What's the most **diplomatic** way to redirect?",
27
+ "context_formatted": "โš™๏ธ Engineers debating API details. Stakeholders confused.",
28
+ "options_formatted": [
29
+ "โฌœ A. This is boring, let's stop",
30
+ "โฌœ B. Let's take this offline with just the engineering team",
31
+ "โฌœ C. You shouldn't discuss this here",
32
+ "โฌœ D. We don't have time for this"
33
+ ],
34
+ "hint": "๐Ÿ’ก Which redirects politely without dismissing?",
35
+ "correct_feedback": "โœ… Correct! **'Take this offline'** redirects diplomatically!",
36
+ "wrong_feedback": "โŒ **'Take this offline'** is the diplomatic corporate phrase!",
37
+ "xp_display": "๐Ÿ’Ž +10 XP"
38
+ }
39
+ },
40
+ {
41
+ "id": 2,
42
+ "type": "chinglish_fix",
43
+ "question": "A team member raises a sensitive performance issue in a large group meeting. Make your response more professional:",
44
+ "chinglish_sentence": "Let's talk privately about this later.",
45
+ "correct_answer": "Let's take this offline",
46
+ "explanation": "'Talk privately' can sound exclusionary or secretive in a group setting. 'Take offline' is the professional euphemism that sounds efficient rather than secretive. It implies appropriateness, not exclusion.",
47
+ "xp_value": 15,
48
+ "display": {
49
+ "type_emoji": "๐Ÿ”ง",
50
+ "type_name": "Chinglish ไฟฎๆญฃ | Fix the Chinglish",
51
+ "question_formatted": "๐Ÿ”ง Make this sound more corporate:",
52
+ "sentence_formatted": "๐Ÿ“ \"Let's **talk privately** about this later.\" (in a group meeting)",
53
+ "hint": "๐Ÿ’ก What's the professional euphemism?",
54
+ "correct_feedback": "โœ… Much better! **'Take this offline'** sounds professional! ๐ŸŽ‰",
55
+ "wrong_feedback": "โŒ **'Take this offline'** is the professional euphemism!",
56
+ "xp_display": "๐Ÿ’Ž +15 XP"
57
+ }
58
+ },
59
+ {
60
+ "id": 3,
61
+ "type": "fill_blank",
62
+ "question": "Choose the idiom that means 'unproductive discussion':",
63
+ "context": "Your team has been discussing the same problem for 30 minutes with no progress. You say: 'We're ___ here. Let's move on.'",
64
+ "word_bank": ["spinning our wheels", "boiling the ocean", "touching base", "circling back"],
65
+ "correct_answer": "spinning our wheels",
66
+ "explanation": "'Spinning our wheels' comes from car imageryโ€”wheels spinning in mud without moving forward. It describes unproductive discussion. 'Boiling the ocean' is about over-ambitious scope. The others don't fit this context.",
67
+ "xp_value": 12,
68
+ "display": {
69
+ "type_emoji": "โœ๏ธ",
70
+ "type_name": "ๅกซ็ฉบ้ข˜ | Fill in the Blank",
71
+ "question_formatted": "โœ๏ธ Complete with the right idiom:",
72
+ "context_formatted": "๐Ÿ”„ 30 minutes, no progress. \"We're **___** here.\"",
73
+ "word_bank_formatted": "๐Ÿ“ฆ Options: [ **spinning our wheels** | boiling the ocean | touching base | circling back ]",
74
+ "hint": "๐Ÿ’ก Car metaphor = going nowhere",
75
+ "correct_feedback": "โœ… Perfect! **'Spinning our wheels'** = unproductive! ๐ŸŽฏ",
76
+ "wrong_feedback": "โŒ **'Spinning our wheels'** describes unproductive discussion!",
77
+ "xp_display": "๐Ÿ’Ž +12 XP"
78
+ }
79
+ }
80
+ ],
81
+ "total_xp": 37,
82
+ "passing_score": 70,
83
+ "display": {
84
+ "header": "๐Ÿ“ ไปŠๆ—ฅๆต‹้ชŒ | Daily Quiz",
85
+ "date": "๐Ÿ“… 2026-02-25",
86
+ "difficulty": "๐Ÿ“Š Level: **C1** (้ซ˜็บง)",
87
+ "topic": "๐Ÿท๏ธ Topic: **Take Offline / Spinning Wheels**",
88
+ "instructions": "๐ŸŽฏ 3้“ๅฐ้ข˜๏ผŒ็ญ”ๅฏน2้“ๅฐฑ่ฟ‡ๅ…ณ๏ผ3 questions, get 2 right to pass!",
89
+ "progress_bar": "โฌœโฌœโฌœ 0/3 questions",
90
+ "xp_summary": "๐Ÿ’Ž Total XP: 37 | ๐Ÿ† Pass: 2/3 correct",
91
+ "footer": "โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n๐Ÿ’ช Good luck! ๅŠ ๆฒน! ๐Ÿš€"
92
+ },
93
+ "generated": true
94
+ }
@@ -0,0 +1,104 @@
1
+ {
2
+ "_meta": {
3
+ "prompt_version": "quiz_gen_v1.2"
4
+ },
5
+ "quiz_date": "2026-02-25",
6
+ "cefr_level": "C2",
7
+ "keypoint_fingerprint": "workplace_boil_the_ocean",
8
+ "questions": [
9
+ {
10
+ "id": 1,
11
+ "type": "multiple_choice",
12
+ "question": "In an executive meeting, a VP proposes rebuilding the entire platform, adding AI, AND entering 3 new markets in Q1. What's the most strategic response?",
13
+ "context": "You need to push back diplomatically while showing strategic thinking.",
14
+ "options": [
15
+ "A. That's impossible, we can't do it",
16
+ "B. Let's not boil the oceanโ€”what's the minimum viable scope?",
17
+ "C. I think we should do less",
18
+ "D. This is too ambitious"
19
+ ],
20
+ "correct_answer": "B",
21
+ "explanation": "'Boil the ocean' is the C-suite idiom for impossibly ambitious scope. Using it shows strategic thinking. It's visual, slightly humorous, and makes the point diplomatically. The other options are too direct or unsophisticated for executive settings.",
22
+ "xp_value": 10,
23
+ "display": {
24
+ "type_emoji": "๐Ÿ”ค",
25
+ "type_name": "้€‰ๆ‹ฉ้ข˜ | Multiple Choice",
26
+ "question_formatted": "๐Ÿ’ฌ What's the most **strategic** response?",
27
+ "context_formatted": "๐ŸŽฏ VP proposes impossibly ambitious scope in executive meeting.",
28
+ "options_formatted": [
29
+ "โฌœ A. That's impossible, we can't do it",
30
+ "โฌœ B. Let's not boil the oceanโ€”what's the minimum viable scope?",
31
+ "โฌœ C. I think we should do less",
32
+ "โฌœ D. This is too ambitious"
33
+ ],
34
+ "hint": "๐Ÿ’ก Which shows C-suite language mastery?",
35
+ "correct_feedback": "โœ… Excellent! **'Boil the ocean'** is strategic C-suite language!",
36
+ "wrong_feedback": "โŒ **'Boil the ocean'** shows strategic thinking at executive level!",
37
+ "xp_display": "๐Ÿ’Ž +10 XP"
38
+ }
39
+ },
40
+ {
41
+ "id": 2,
42
+ "type": "chinglish_fix",
43
+ "question": "Your CEO wants a complete digital transformation by Q2. Transform this response to sound more executive:",
44
+ "chinglish_sentence": "That's too ambitious. We need to reduce the scope.",
45
+ "correct_answer": "That's boiling the ocean. We need a phased approach.",
46
+ "explanation": "'Too ambitious' and 'reduce scope' sound unsophisticated. 'Boiling the ocean' and 'phased approach' are the idiomatic expressions that signal strategic thinking. The ocean metaphor is powerful and memorable.",
47
+ "xp_value": 15,
48
+ "display": {
49
+ "type_emoji": "๐Ÿ”ง",
50
+ "type_name": "Chinglish ไฟฎๆญฃ | Fix the Chinglish",
51
+ "question_formatted": "๐Ÿ”ง Make this sound more C-suite:",
52
+ "sentence_formatted": "๐Ÿ“ \"That's **too ambitious**. We need to **reduce the scope**.\"",
53
+ "hint": "๐Ÿ’ก Use the ocean metaphor and 'phased'",
54
+ "correct_feedback": "โœ… Perfect! **'Boiling the ocean' + 'phased approach'** = executive language! ๐ŸŽ‰",
55
+ "wrong_feedback": "โŒ Try **'That's boiling the ocean. We need a phased approach.'**",
56
+ "xp_display": "๐Ÿ’Ž +15 XP"
57
+ }
58
+ },
59
+ {
60
+ "id": 3,
61
+ "type": "dialogue_completion",
62
+ "question": "What's the best next step after proposing a major initiative?",
63
+ "context": "You've proposed a new strategy. Before finalizing, you need buy-in from regional teams.",
64
+ "options": [
65
+ "A. Let's implement immediately",
66
+ "B. We need to socialize this with the regional teams first",
67
+ "C. Let's keep it confidential",
68
+ "D. We should decide now"
69
+ ],
70
+ "correct_answer": "B",
71
+ "explanation": "'Socialize this' is uniquely corporate. It means systematically sharing with stakeholders to gather input and build consensus. It's more deliberate than 'discussing'โ€”it's a process. This is standard C-suite decision-making language.",
72
+ "xp_value": 15,
73
+ "display": {
74
+ "type_emoji": "๐Ÿ’ฌ",
75
+ "type_name": "ๅฏน่ฏ่กฅๅ…จ | Dialogue Completion",
76
+ "question_formatted": "๐Ÿ’ฌ What's the best next step?",
77
+ "context_formatted": "๐Ÿ“‹ You've proposed a new strategy. Regional teams need input.",
78
+ "options_formatted": [
79
+ "โฌœ A. Let's implement immediately",
80
+ "โฌœ B. We need to socialize this with the regional teams first",
81
+ "โฌœ C. Let's keep it confidential",
82
+ "โฌœ D. We should decide now"
83
+ ],
84
+ "hint": "๐Ÿ’ก Get stakeholder buy-in before deciding = ?",
85
+ "correct_feedback": "โœ… Perfect! **'Socialize this'** = systematic stakeholder buy-in! ๐ŸŽฏ",
86
+ "wrong_feedback": "โŒ **'Socialize this with stakeholders'** is the C-suite process!",
87
+ "xp_display": "๐Ÿ’Ž +15 XP"
88
+ }
89
+ }
90
+ ],
91
+ "total_xp": 40,
92
+ "passing_score": 70,
93
+ "display": {
94
+ "header": "๐Ÿ“ ไปŠๆ—ฅๆต‹้ชŒ | Daily Quiz",
95
+ "date": "๐Ÿ“… 2026-02-25",
96
+ "difficulty": "๐Ÿ“Š Level: **C2** (็ฒพ้€š็บง)",
97
+ "topic": "๐Ÿท๏ธ Topic: **Boil the Ocean / Socialize**",
98
+ "instructions": "๐ŸŽฏ 3้“ๅฐ้ข˜๏ผŒ็ญ”ๅฏน2้“ๅฐฑ่ฟ‡ๅ…ณ๏ผ3 questions, get 2 right to pass!",
99
+ "progress_bar": "โฌœโฌœโฌœ 0/3 questions",
100
+ "xp_summary": "๐Ÿ’Ž Total XP: 40 | ๐Ÿ† Pass: 2/3 correct",
101
+ "footer": "โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n๐Ÿ’ช Good luck! ๅŠ ๆฒน! ๐Ÿš€"
102
+ },
103
+ "generated": true
104
+ }
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@rookiestar/eng-lang-tutor",
3
+ "version": "1.0.1",
4
+ "description": "ๅœฐ้“็พŽๅผ่‹ฑ่ฏญๅฏผๅธˆ - OpenClaw Skill for learning authentic American English",
5
+ "main": "scripts/cli/cli.py",
6
+ "scripts": {
7
+ "postinstall": "python3 -m pip install -r requirements.txt --quiet"
8
+ },
9
+ "keywords": [
10
+ "english",
11
+ "learning",
12
+ "openclaw",
13
+ "skill",
14
+ "tutor",
15
+ "cefr",
16
+ "american-english",
17
+ "language-learning",
18
+ "gamification"
19
+ ],
20
+ "author": "RookieStar",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/rookiestar/Skills.git",
25
+ "directory": "eng-lang-tutor"
26
+ },
27
+ "bugs": {
28
+ "url": "https://github.com/rookiestar/Skills/issues"
29
+ },
30
+ "homepage": "https://github.com/rookiestar/Skills/tree/main/eng-lang-tutor#readme",
31
+ "files": [
32
+ "**/*",
33
+ "!tests/**",
34
+ "!**/*.pyc",
35
+ "!**/__pycache__/**",
36
+ "!.DS_Store"
37
+ ],
38
+ "engines": {
39
+ "node": ">=14.0.0"
40
+ }
41
+ }