@studyjoyful/shared 1.0.9 → 1.0.12
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.
- package/package.json +1 -1
- package/src/i18n/locales/en/chat.json +2 -1
- package/src/i18n/locales/en/home.json +148 -0
- package/src/i18n/locales/en/index.ts +2 -0
- package/src/i18n/locales/en/sidebar.json +2 -0
- package/src/index.ts +25 -0
- package/src/topics/english-topics.ts +120 -0
- package/src/topics/index.ts +139 -0
- package/src/topics/math-topics.ts +172 -0
- package/src/topics/types.ts +143 -0
package/package.json
CHANGED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scan": {
|
|
3
|
+
"title": "Scan Homework",
|
|
4
|
+
"subtitle": "Take a photo and generate practice instantly",
|
|
5
|
+
"cta": "Scan Now"
|
|
6
|
+
},
|
|
7
|
+
"quickStart": {
|
|
8
|
+
"title": "Quick Start",
|
|
9
|
+
"math": {
|
|
10
|
+
"title": "Math Practice",
|
|
11
|
+
"subtitle": "{{grade}} Topics",
|
|
12
|
+
"subtitleNoGrade": "Select topics"
|
|
13
|
+
},
|
|
14
|
+
"english": {
|
|
15
|
+
"title": "English Practice",
|
|
16
|
+
"subtitle": "{{grade}} Topics",
|
|
17
|
+
"subtitleNoGrade": "Select topics"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"chat": {
|
|
21
|
+
"sectionTitle": "Or describe what you need",
|
|
22
|
+
"title": "Chat with AI",
|
|
23
|
+
"placeholder": "\"Create practice for 2-digit subtraction\""
|
|
24
|
+
},
|
|
25
|
+
"recentTasks": {
|
|
26
|
+
"title": "Recent Tasks",
|
|
27
|
+
"viewAll": "View All",
|
|
28
|
+
"questions": "questions",
|
|
29
|
+
"empty": "No tasks yet",
|
|
30
|
+
"notStarted": "Not started"
|
|
31
|
+
},
|
|
32
|
+
"time": {
|
|
33
|
+
"justNow": "Just now",
|
|
34
|
+
"minutesAgo": "{{count}} min ago",
|
|
35
|
+
"hoursAgo": "{{count}}h ago",
|
|
36
|
+
"daysAgo": "{{count}}d ago"
|
|
37
|
+
},
|
|
38
|
+
"topics": {
|
|
39
|
+
"title": "Select Topic",
|
|
40
|
+
"popular": "Popular",
|
|
41
|
+
"all": "All Topics",
|
|
42
|
+
"math": {
|
|
43
|
+
"addition": {
|
|
44
|
+
"label": "Addition",
|
|
45
|
+
"description": "With & without carrying"
|
|
46
|
+
},
|
|
47
|
+
"subtraction": {
|
|
48
|
+
"label": "Subtraction",
|
|
49
|
+
"description": "With & without borrowing"
|
|
50
|
+
},
|
|
51
|
+
"multiplication": {
|
|
52
|
+
"label": "Multiplication",
|
|
53
|
+
"description": "Times tables & word problems"
|
|
54
|
+
},
|
|
55
|
+
"division": {
|
|
56
|
+
"label": "Division",
|
|
57
|
+
"description": "Basic division concepts"
|
|
58
|
+
},
|
|
59
|
+
"fractions": {
|
|
60
|
+
"label": "Fractions",
|
|
61
|
+
"description": "Halves, quarters, thirds"
|
|
62
|
+
},
|
|
63
|
+
"shapes": {
|
|
64
|
+
"label": "Shapes",
|
|
65
|
+
"description": "2D and 3D shapes"
|
|
66
|
+
},
|
|
67
|
+
"time": {
|
|
68
|
+
"label": "Time",
|
|
69
|
+
"description": "Telling time, duration"
|
|
70
|
+
},
|
|
71
|
+
"money": {
|
|
72
|
+
"label": "Money",
|
|
73
|
+
"description": "Counting, adding money"
|
|
74
|
+
},
|
|
75
|
+
"measurement": {
|
|
76
|
+
"label": "Measurement",
|
|
77
|
+
"description": "Length, mass, volume"
|
|
78
|
+
},
|
|
79
|
+
"wordProblems": {
|
|
80
|
+
"label": "Word Problems",
|
|
81
|
+
"description": "Mixed operations"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"english": {
|
|
85
|
+
"spelling": {
|
|
86
|
+
"label": "Spelling",
|
|
87
|
+
"description": "Common words & patterns"
|
|
88
|
+
},
|
|
89
|
+
"vocabulary": {
|
|
90
|
+
"label": "Vocabulary",
|
|
91
|
+
"description": "Word meanings & usage"
|
|
92
|
+
},
|
|
93
|
+
"grammar": {
|
|
94
|
+
"label": "Grammar",
|
|
95
|
+
"description": "Sentence structure"
|
|
96
|
+
},
|
|
97
|
+
"reading": {
|
|
98
|
+
"label": "Reading",
|
|
99
|
+
"description": "Comprehension practice"
|
|
100
|
+
},
|
|
101
|
+
"phonics": {
|
|
102
|
+
"label": "Phonics",
|
|
103
|
+
"description": "Sound-letter relationships"
|
|
104
|
+
},
|
|
105
|
+
"punctuation": {
|
|
106
|
+
"label": "Punctuation",
|
|
107
|
+
"description": "Periods, commas, capitals"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"confirm": {
|
|
112
|
+
"title": "Confirm Practice",
|
|
113
|
+
"settings": "Settings",
|
|
114
|
+
"questions": "Questions",
|
|
115
|
+
"difficulty": "Difficulty",
|
|
116
|
+
"easier": "Easier",
|
|
117
|
+
"balanced": "Balanced",
|
|
118
|
+
"harder": "Harder",
|
|
119
|
+
"generate": "Generate Practice",
|
|
120
|
+
"customizeWithAI": "Customize with AI"
|
|
121
|
+
},
|
|
122
|
+
"scanPage": {
|
|
123
|
+
"title": "Scan Homework",
|
|
124
|
+
"tips": "Tips",
|
|
125
|
+
"tip1": "Make sure text is clear and in focus",
|
|
126
|
+
"tip2": "Good lighting helps accuracy",
|
|
127
|
+
"tip3": "Include the full question",
|
|
128
|
+
"takePhoto": "Take Photo",
|
|
129
|
+
"choosePhoto": "Choose from Gallery",
|
|
130
|
+
"analyzing": "Analyzing...",
|
|
131
|
+
"detected": "Detected",
|
|
132
|
+
"inScope": "Ready to practice",
|
|
133
|
+
"outOfScope": "Out of scope",
|
|
134
|
+
"confidence": {
|
|
135
|
+
"high": "High confidence",
|
|
136
|
+
"medium": "Please verify",
|
|
137
|
+
"low": "Needs clarification"
|
|
138
|
+
},
|
|
139
|
+
"notRecognized": "Could not recognize learning content",
|
|
140
|
+
"tryAgain": "Try Again",
|
|
141
|
+
"switchToChat": "Describe Instead",
|
|
142
|
+
"advancedSettings": "Advanced Settings",
|
|
143
|
+
"generatePractice": "Generate Practice",
|
|
144
|
+
"browseTopics": "Browse Topics",
|
|
145
|
+
"tryInstead": "Try these topics instead:"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import common from './common.json';
|
|
6
6
|
import auth from './auth.json';
|
|
7
7
|
import chat from './chat.json';
|
|
8
|
+
import home from './home.json';
|
|
8
9
|
import tasks from './tasks.json';
|
|
9
10
|
import learning from './learning.json';
|
|
10
11
|
import profile from './profile.json';
|
|
@@ -15,6 +16,7 @@ export const en = {
|
|
|
15
16
|
common,
|
|
16
17
|
auth,
|
|
17
18
|
chat,
|
|
19
|
+
home,
|
|
18
20
|
tasks,
|
|
19
21
|
learning,
|
|
20
22
|
profile,
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* - i18n: Internationalization (translations, resources)
|
|
8
8
|
* - constants: Shared constants (examples, etc.)
|
|
9
9
|
* - types: Common type definitions
|
|
10
|
+
* - topics: Topic definitions with AI context
|
|
10
11
|
* - utils: Utility functions
|
|
11
12
|
*/
|
|
12
13
|
|
|
@@ -41,5 +42,29 @@ export {
|
|
|
41
42
|
type PaginationMeta,
|
|
42
43
|
} from './types';
|
|
43
44
|
|
|
45
|
+
// Topics exports
|
|
46
|
+
export {
|
|
47
|
+
// Types
|
|
48
|
+
type TopicDefinition,
|
|
49
|
+
type TopicCategory,
|
|
50
|
+
type TopicIconName,
|
|
51
|
+
// Constants
|
|
52
|
+
ALL_TOPICS,
|
|
53
|
+
MATH_TOPICS,
|
|
54
|
+
ENGLISH_TOPICS,
|
|
55
|
+
ICON_MAP,
|
|
56
|
+
// Functions
|
|
57
|
+
getAllTopics,
|
|
58
|
+
getTopicById,
|
|
59
|
+
getTopicsBySubject,
|
|
60
|
+
getTopicsBySubjectAndGrade,
|
|
61
|
+
getPopularTopicsBySubject,
|
|
62
|
+
getPopularTopicsBySubjectAndGrade,
|
|
63
|
+
getTopicAIContext,
|
|
64
|
+
findTopicsByKeyword,
|
|
65
|
+
getSuggestedAlternatives,
|
|
66
|
+
getIconForPlatform,
|
|
67
|
+
} from './topics';
|
|
68
|
+
|
|
44
69
|
// Utils exports
|
|
45
70
|
export { randomSelect, shuffle } from './utils';
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* English Topics
|
|
3
|
+
*
|
|
4
|
+
* English topics for P1-P3 based on Singapore MOE syllabus.
|
|
5
|
+
* aiContext provides concise topic description for AI generation.
|
|
6
|
+
* Grade-specific adaptation is handled by the API prompt.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { TopicDefinition } from './types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* All English topics
|
|
13
|
+
*/
|
|
14
|
+
export const ENGLISH_TOPICS: TopicDefinition[] = [
|
|
15
|
+
// ============================================
|
|
16
|
+
// Phonics & Sounds
|
|
17
|
+
// ============================================
|
|
18
|
+
{
|
|
19
|
+
id: 'english-phonics',
|
|
20
|
+
subject: 'English',
|
|
21
|
+
label: 'Phonics',
|
|
22
|
+
description: 'Letter sounds & blending',
|
|
23
|
+
aiContext: `Phonics practice focusing on letter-sound relationships, blending sounds to read words, and segmenting words for spelling.
|
|
24
|
+
Question types: Match sounds to letters, blend sounds to read words, identify vowel sounds, rhyming words.`,
|
|
25
|
+
keywords: ['phonics', 'sounds', 'letters', 'blend', 'vowels', 'consonants', 'CVC', 'rhyme'],
|
|
26
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
27
|
+
category: 'phonics',
|
|
28
|
+
iconName: 'music',
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
// ============================================
|
|
32
|
+
// Vocabulary
|
|
33
|
+
// ============================================
|
|
34
|
+
{
|
|
35
|
+
id: 'english-spelling',
|
|
36
|
+
subject: 'English',
|
|
37
|
+
label: 'Spelling',
|
|
38
|
+
description: 'Common words & patterns',
|
|
39
|
+
aiContext: `Spelling practice focusing on sight words, spelling patterns, and word families.
|
|
40
|
+
Question types: Complete the spelling, correct misspelled words, fill in missing letters, word family exercises.`,
|
|
41
|
+
keywords: ['spelling', 'spell', 'words', 'sight words', 'patterns', 'letters'],
|
|
42
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
43
|
+
category: 'vocabulary',
|
|
44
|
+
isPopular: true,
|
|
45
|
+
iconName: 'text',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'english-vocabulary',
|
|
49
|
+
subject: 'English',
|
|
50
|
+
label: 'Vocabulary',
|
|
51
|
+
description: 'Word meanings & usage',
|
|
52
|
+
aiContext: `Vocabulary practice focusing on word meanings, usage in sentences, and categorizing words.
|
|
53
|
+
Question types: Match word to meaning, use word in sentence, find synonyms/antonyms, complete sentences with correct word.`,
|
|
54
|
+
keywords: ['vocabulary', 'words', 'meanings', 'synonyms', 'antonyms', 'definition'],
|
|
55
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
56
|
+
category: 'vocabulary',
|
|
57
|
+
isPopular: true,
|
|
58
|
+
iconName: 'book',
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
// ============================================
|
|
62
|
+
// Grammar
|
|
63
|
+
// ============================================
|
|
64
|
+
{
|
|
65
|
+
id: 'english-grammar',
|
|
66
|
+
subject: 'English',
|
|
67
|
+
label: 'Grammar',
|
|
68
|
+
description: 'Sentence structure & rules',
|
|
69
|
+
aiContext: `Grammar practice focusing on parts of speech (nouns, verbs, adjectives), sentence structure, and correct usage.
|
|
70
|
+
Question types: Identify parts of speech, fill in correct word form, correct the sentence, complete sentences.`,
|
|
71
|
+
keywords: ['grammar', 'nouns', 'verbs', 'adjectives', 'sentences', 'tenses', 'pronouns'],
|
|
72
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
73
|
+
category: 'grammar',
|
|
74
|
+
isPopular: true,
|
|
75
|
+
iconName: 'list',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: 'english-punctuation',
|
|
79
|
+
subject: 'English',
|
|
80
|
+
label: 'Punctuation',
|
|
81
|
+
description: 'Periods, commas & capitals',
|
|
82
|
+
aiContext: `Punctuation practice focusing on end punctuation, capital letters, and basic comma usage.
|
|
83
|
+
Question types: Add correct punctuation, correct the punctuation, identify punctuation marks, rewrite with correct punctuation.`,
|
|
84
|
+
keywords: ['punctuation', 'period', 'comma', 'capital', 'question mark', 'apostrophe', 'exclamation'],
|
|
85
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
86
|
+
category: 'punctuation',
|
|
87
|
+
iconName: 'code',
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
// ============================================
|
|
91
|
+
// Reading
|
|
92
|
+
// ============================================
|
|
93
|
+
{
|
|
94
|
+
id: 'english-reading',
|
|
95
|
+
subject: 'English',
|
|
96
|
+
label: 'Reading Comprehension',
|
|
97
|
+
description: 'Understanding texts',
|
|
98
|
+
aiContext: `Reading comprehension practice with age-appropriate passages about school, family, animals, and everyday life.
|
|
99
|
+
Question types: Multiple choice comprehension, true/false, short answer questions, sequencing events.
|
|
100
|
+
Focus: Understanding main idea, finding information, making connections.`,
|
|
101
|
+
keywords: ['reading', 'comprehension', 'passage', 'understand', 'main idea', 'inference'],
|
|
102
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
103
|
+
category: 'reading',
|
|
104
|
+
iconName: 'book',
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get English topics filtered by grade
|
|
110
|
+
*/
|
|
111
|
+
export function getEnglishTopicsByGrade(grade: 'P1' | 'P2' | 'P3'): TopicDefinition[] {
|
|
112
|
+
return ENGLISH_TOPICS.filter((topic) => topic.gradeRange.includes(grade));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Get popular English topics
|
|
117
|
+
*/
|
|
118
|
+
export function getPopularEnglishTopics(): TopicDefinition[] {
|
|
119
|
+
return ENGLISH_TOPICS.filter((topic) => topic.isPopular);
|
|
120
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Topics Module
|
|
3
|
+
*
|
|
4
|
+
* Unified topic definitions for StudyJoyful.
|
|
5
|
+
* Based on Singapore MOE (Ministry of Education) syllabus for P1-P3.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { getAllTopics, getTopicById, getTopicsBySubject } from '@studyjoyful/shared';
|
|
10
|
+
*
|
|
11
|
+
* // Get all topics
|
|
12
|
+
* const topics = getAllTopics();
|
|
13
|
+
*
|
|
14
|
+
* // Get topics by subject
|
|
15
|
+
* const mathTopics = getTopicsBySubject('Math');
|
|
16
|
+
*
|
|
17
|
+
* // Get topic by ID
|
|
18
|
+
* const addition = getTopicById('math-addition');
|
|
19
|
+
*
|
|
20
|
+
* // Get AI context for a topic
|
|
21
|
+
* const context = getTopicAIContext('math-addition');
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import type { ChildGrade, Subject } from '../types/child';
|
|
26
|
+
import { ENGLISH_TOPICS, getEnglishTopicsByGrade, getPopularEnglishTopics } from './english-topics';
|
|
27
|
+
import { MATH_TOPICS, getMathTopicsByGrade, getPopularMathTopics } from './math-topics';
|
|
28
|
+
import type { TopicCategory, TopicDefinition, TopicIconName } from './types';
|
|
29
|
+
import { getIconForPlatform, ICON_MAP } from './types';
|
|
30
|
+
|
|
31
|
+
// Re-export types
|
|
32
|
+
export type { TopicCategory, TopicDefinition, TopicIconName };
|
|
33
|
+
export { ICON_MAP, getIconForPlatform };
|
|
34
|
+
|
|
35
|
+
// Re-export topic arrays
|
|
36
|
+
export { ENGLISH_TOPICS, MATH_TOPICS };
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* All topics combined
|
|
40
|
+
*/
|
|
41
|
+
export const ALL_TOPICS: TopicDefinition[] = [...MATH_TOPICS, ...ENGLISH_TOPICS];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get all topics
|
|
45
|
+
*/
|
|
46
|
+
export function getAllTopics(): TopicDefinition[] {
|
|
47
|
+
return ALL_TOPICS;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get topic by ID
|
|
52
|
+
*/
|
|
53
|
+
export function getTopicById(id: string): TopicDefinition | undefined {
|
|
54
|
+
return ALL_TOPICS.find((topic) => topic.id === id);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get topics by subject
|
|
59
|
+
*/
|
|
60
|
+
export function getTopicsBySubject(subject: Subject): TopicDefinition[] {
|
|
61
|
+
return subject === 'Math' ? MATH_TOPICS : ENGLISH_TOPICS;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get topics by subject and grade
|
|
66
|
+
*/
|
|
67
|
+
export function getTopicsBySubjectAndGrade(subject: Subject, grade: ChildGrade): TopicDefinition[] {
|
|
68
|
+
return subject === 'Math' ? getMathTopicsByGrade(grade) : getEnglishTopicsByGrade(grade);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get popular topics by subject
|
|
73
|
+
*/
|
|
74
|
+
export function getPopularTopicsBySubject(subject: Subject): TopicDefinition[] {
|
|
75
|
+
return subject === 'Math' ? getPopularMathTopics() : getPopularEnglishTopics();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get popular topics by subject and grade
|
|
80
|
+
*/
|
|
81
|
+
export function getPopularTopicsBySubjectAndGrade(subject: Subject, grade: ChildGrade): TopicDefinition[] {
|
|
82
|
+
const topics = getTopicsBySubjectAndGrade(subject, grade);
|
|
83
|
+
return topics.filter((topic) => topic.isPopular);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get AI context for a topic
|
|
88
|
+
*
|
|
89
|
+
* @param topicId - Topic ID or label
|
|
90
|
+
* @returns Formatted context string for AI (grade adaptation handled by API prompt)
|
|
91
|
+
*/
|
|
92
|
+
export function getTopicAIContext(topicId: string): string {
|
|
93
|
+
// Try to find by ID first
|
|
94
|
+
let topic = getTopicById(topicId);
|
|
95
|
+
|
|
96
|
+
// If not found, try to match by label (case-insensitive)
|
|
97
|
+
if (!topic) {
|
|
98
|
+
const lowerTopicId = topicId.toLowerCase();
|
|
99
|
+
topic = ALL_TOPICS.find(
|
|
100
|
+
(t) =>
|
|
101
|
+
t.label.toLowerCase() === lowerTopicId ||
|
|
102
|
+
t.id.toLowerCase().includes(lowerTopicId) ||
|
|
103
|
+
t.keywords.some((k) => k.toLowerCase() === lowerTopicId)
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!topic) {
|
|
108
|
+
return `Topic: ${topicId}`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return `Topic: ${topic.label}
|
|
112
|
+
Subject: ${topic.subject}
|
|
113
|
+
${topic.aiContext}`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Find topics matching keywords
|
|
118
|
+
*/
|
|
119
|
+
export function findTopicsByKeyword(keyword: string, subject?: Subject): TopicDefinition[] {
|
|
120
|
+
const lowerKeyword = keyword.toLowerCase();
|
|
121
|
+
const topics = subject ? getTopicsBySubject(subject) : ALL_TOPICS;
|
|
122
|
+
|
|
123
|
+
return topics.filter(
|
|
124
|
+
(topic) =>
|
|
125
|
+
topic.label.toLowerCase().includes(lowerKeyword) ||
|
|
126
|
+
topic.description.toLowerCase().includes(lowerKeyword) ||
|
|
127
|
+
topic.keywords.some((k) => k.toLowerCase().includes(lowerKeyword))
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Get suggested topics for out-of-scope content
|
|
133
|
+
*/
|
|
134
|
+
export function getSuggestedAlternatives(subject: Subject, grade: ChildGrade, count: number = 3): string[] {
|
|
135
|
+
const popularTopics = getPopularTopicsBySubjectAndGrade(subject, grade);
|
|
136
|
+
const topics = popularTopics.length > 0 ? popularTopics : getTopicsBySubjectAndGrade(subject, grade);
|
|
137
|
+
return topics.slice(0, count).map((t) => t.label);
|
|
138
|
+
}
|
|
139
|
+
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Math Topics
|
|
3
|
+
*
|
|
4
|
+
* Math topics for P1-P3 based on Singapore MOE syllabus.
|
|
5
|
+
* aiContext provides concise topic description for AI generation.
|
|
6
|
+
* Grade-specific adaptation is handled by the API prompt.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { TopicDefinition } from './types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* All Math topics
|
|
13
|
+
*/
|
|
14
|
+
export const MATH_TOPICS: TopicDefinition[] = [
|
|
15
|
+
// ============================================
|
|
16
|
+
// Arithmetic
|
|
17
|
+
// ============================================
|
|
18
|
+
{
|
|
19
|
+
id: 'math-addition',
|
|
20
|
+
subject: 'Math',
|
|
21
|
+
label: 'Addition',
|
|
22
|
+
description: 'With & without carrying',
|
|
23
|
+
aiContext: `Addition practice focusing on number bonds, place value, and step-by-step regrouping (carrying).
|
|
24
|
+
Question types: Fill in blanks, find the sum, word problems with "altogether", "total", "in all".`,
|
|
25
|
+
keywords: ['add', 'plus', 'sum', 'total', 'altogether', 'carrying', 'regrouping', 'number bonds'],
|
|
26
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
27
|
+
category: 'arithmetic',
|
|
28
|
+
isPopular: true,
|
|
29
|
+
iconName: 'add',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'math-subtraction',
|
|
33
|
+
subject: 'Math',
|
|
34
|
+
label: 'Subtraction',
|
|
35
|
+
description: 'With & without borrowing',
|
|
36
|
+
aiContext: `Subtraction practice focusing on relationship with addition, place value, and step-by-step borrowing (regrouping).
|
|
37
|
+
Question types: Find the difference, how many more/fewer, word problems with "left", "remaining", "gave away".`,
|
|
38
|
+
keywords: ['subtract', 'minus', 'difference', 'left', 'remaining', 'borrowing', 'regrouping', 'take away'],
|
|
39
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
40
|
+
category: 'arithmetic',
|
|
41
|
+
isPopular: true,
|
|
42
|
+
iconName: 'subtract',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: 'math-multiplication',
|
|
46
|
+
subject: 'Math',
|
|
47
|
+
label: 'Multiplication',
|
|
48
|
+
description: 'Times tables & word problems',
|
|
49
|
+
aiContext: `Multiplication practice focusing on equal groups, arrays, times tables, and relationship with repeated addition.
|
|
50
|
+
Question types: Times tables practice, array problems, "groups of", word problems with equal sharing/grouping.`,
|
|
51
|
+
keywords: ['multiply', 'times', 'product', 'groups of', 'times tables', 'arrays', 'repeated addition'],
|
|
52
|
+
gradeRange: ['P2', 'P3'],
|
|
53
|
+
category: 'arithmetic',
|
|
54
|
+
isPopular: true,
|
|
55
|
+
iconName: 'multiply',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'math-division',
|
|
59
|
+
subject: 'Math',
|
|
60
|
+
label: 'Division',
|
|
61
|
+
description: 'Equal sharing & grouping',
|
|
62
|
+
aiContext: `Division practice focusing on equal sharing, grouping, and inverse relationship with multiplication.
|
|
63
|
+
Question types: Share equally, how many groups, word problems with "each", "equally divided".`,
|
|
64
|
+
keywords: ['divide', 'share', 'equally', 'groups', 'quotient', 'remainder', 'each'],
|
|
65
|
+
gradeRange: ['P2', 'P3'],
|
|
66
|
+
category: 'arithmetic',
|
|
67
|
+
iconName: 'divide',
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
// ============================================
|
|
71
|
+
// Fractions
|
|
72
|
+
// ============================================
|
|
73
|
+
{
|
|
74
|
+
id: 'math-fractions',
|
|
75
|
+
subject: 'Math',
|
|
76
|
+
label: 'Fractions',
|
|
77
|
+
description: 'Halves, quarters, thirds',
|
|
78
|
+
aiContext: `Fractions practice focusing on equal parts, visual models (circles, rectangles), and relating to everyday objects.
|
|
79
|
+
Question types: Shade fractions, identify fractions, compare fractions, word problems with sharing.`,
|
|
80
|
+
keywords: ['fraction', 'half', 'quarter', 'third', 'parts', 'whole', 'numerator', 'denominator'],
|
|
81
|
+
gradeRange: ['P2', 'P3'],
|
|
82
|
+
category: 'fractions',
|
|
83
|
+
iconName: 'fraction',
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
// ============================================
|
|
87
|
+
// Geometry
|
|
88
|
+
// ============================================
|
|
89
|
+
{
|
|
90
|
+
id: 'math-shapes',
|
|
91
|
+
subject: 'Math',
|
|
92
|
+
label: 'Shapes',
|
|
93
|
+
description: '2D and 3D shapes',
|
|
94
|
+
aiContext: `Shapes practice focusing on 2D shapes (circle, triangle, square, rectangle) and 3D shapes (cube, cuboid, cone, cylinder).
|
|
95
|
+
Question types: Identify shapes, count sides/corners, match shapes to objects, spot shapes in pictures.`,
|
|
96
|
+
keywords: ['shapes', 'circle', 'triangle', 'square', 'rectangle', 'sides', 'corners', '3D', 'cube'],
|
|
97
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
98
|
+
category: 'geometry',
|
|
99
|
+
iconName: 'shapes',
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
// ============================================
|
|
103
|
+
// Measurement
|
|
104
|
+
// ============================================
|
|
105
|
+
{
|
|
106
|
+
id: 'math-time',
|
|
107
|
+
subject: 'Math',
|
|
108
|
+
label: 'Time',
|
|
109
|
+
description: 'Telling time & duration',
|
|
110
|
+
aiContext: `Time practice focusing on analog clock reading, digital time, duration, and connecting to daily routines.
|
|
111
|
+
Question types: What time is it?, Draw hands on clock, calculate duration, sequence events.`,
|
|
112
|
+
keywords: ['time', 'clock', "o'clock", 'half past', 'quarter', 'minutes', 'hours', 'duration'],
|
|
113
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
114
|
+
category: 'measurement',
|
|
115
|
+
iconName: 'time',
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: 'math-money',
|
|
119
|
+
subject: 'Math',
|
|
120
|
+
label: 'Money',
|
|
121
|
+
description: 'Counting & calculating',
|
|
122
|
+
aiContext: `Money practice using Singapore currency (dollars and cents), focusing on counting, adding, and making change.
|
|
123
|
+
Question types: Count the money, find total cost, calculate change, shopping word problems.`,
|
|
124
|
+
keywords: ['money', 'cents', 'dollars', 'coins', 'change', 'cost', 'price', 'buy', 'pay'],
|
|
125
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
126
|
+
category: 'measurement',
|
|
127
|
+
iconName: 'money',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id: 'math-measurement',
|
|
131
|
+
subject: 'Math',
|
|
132
|
+
label: 'Measurement',
|
|
133
|
+
description: 'Length, mass, volume',
|
|
134
|
+
aiContext: `Measurement practice focusing on length (cm, m), mass (g, kg), volume (ml, L), estimation, and appropriate units.
|
|
135
|
+
Question types: Compare lengths, measure and record, convert units, word problems with measurement.`,
|
|
136
|
+
keywords: ['length', 'mass', 'volume', 'centimeter', 'meter', 'kilogram', 'gram', 'liter', 'measure'],
|
|
137
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
138
|
+
category: 'measurement',
|
|
139
|
+
iconName: 'ruler',
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
// ============================================
|
|
143
|
+
// Problem Solving
|
|
144
|
+
// ============================================
|
|
145
|
+
{
|
|
146
|
+
id: 'math-word-problems',
|
|
147
|
+
subject: 'Math',
|
|
148
|
+
label: 'Word Problems',
|
|
149
|
+
description: 'Mixed operations & reasoning',
|
|
150
|
+
aiContext: `Word problems practice using Singapore Math bar model / model drawing method for visualization.
|
|
151
|
+
Question types: One-step, two-step, comparison ("more than", "fewer than"), part-whole problems.
|
|
152
|
+
Focus: Understanding the question, identifying operation, showing working, checking answer.`,
|
|
153
|
+
keywords: ['word problem', 'story problem', 'solve', 'altogether', 'remaining', 'how many', 'model drawing'],
|
|
154
|
+
gradeRange: ['P1', 'P2', 'P3'],
|
|
155
|
+
category: 'problem-solving',
|
|
156
|
+
iconName: 'document',
|
|
157
|
+
},
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Get Math topics filtered by grade
|
|
162
|
+
*/
|
|
163
|
+
export function getMathTopicsByGrade(grade: 'P1' | 'P2' | 'P3'): TopicDefinition[] {
|
|
164
|
+
return MATH_TOPICS.filter((topic) => topic.gradeRange.includes(grade));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Get popular Math topics
|
|
169
|
+
*/
|
|
170
|
+
export function getPopularMathTopics(): TopicDefinition[] {
|
|
171
|
+
return MATH_TOPICS.filter((topic) => topic.isPopular);
|
|
172
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Topics Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for topic data used across Web and App.
|
|
5
|
+
* Topics are based on Singapore MOE (Ministry of Education) syllabus.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ChildGrade, Subject } from '../types/child';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Topic definition with rich context for AI
|
|
12
|
+
*/
|
|
13
|
+
export interface TopicDefinition {
|
|
14
|
+
/** Unique identifier: 'math-addition', 'english-spelling' */
|
|
15
|
+
id: string;
|
|
16
|
+
|
|
17
|
+
/** Subject: Math or English */
|
|
18
|
+
subject: Subject;
|
|
19
|
+
|
|
20
|
+
/** Display label: 'Addition' */
|
|
21
|
+
label: string;
|
|
22
|
+
|
|
23
|
+
/** Short description for UI: 'With & without carrying' */
|
|
24
|
+
description: string;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Rich context for AI generation
|
|
28
|
+
* Should include:
|
|
29
|
+
* - What the topic covers
|
|
30
|
+
* - Grade-specific variations
|
|
31
|
+
* - Common question types
|
|
32
|
+
*/
|
|
33
|
+
aiContext: string;
|
|
34
|
+
|
|
35
|
+
/** Related keywords for matching */
|
|
36
|
+
keywords: string[];
|
|
37
|
+
|
|
38
|
+
/** Applicable grades */
|
|
39
|
+
gradeRange: ChildGrade[];
|
|
40
|
+
|
|
41
|
+
/** Topic category for grouping */
|
|
42
|
+
category: TopicCategory;
|
|
43
|
+
|
|
44
|
+
/** Whether this is a popular/recommended topic */
|
|
45
|
+
isPopular?: boolean;
|
|
46
|
+
|
|
47
|
+
/** Icon name (platform-agnostic) */
|
|
48
|
+
iconName: TopicIconName;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Topic categories
|
|
53
|
+
*/
|
|
54
|
+
export type TopicCategory =
|
|
55
|
+
// Math categories
|
|
56
|
+
| 'arithmetic' // +, -, ×, ÷
|
|
57
|
+
| 'numbers' // Number sense, place value
|
|
58
|
+
| 'fractions' // Fractions, decimals
|
|
59
|
+
| 'geometry' // Shapes, angles
|
|
60
|
+
| 'measurement' // Length, mass, volume, time
|
|
61
|
+
| 'data' // Graphs, charts
|
|
62
|
+
| 'problem-solving' // Word problems
|
|
63
|
+
// English categories
|
|
64
|
+
| 'phonics' // Letter sounds, blending
|
|
65
|
+
| 'vocabulary' // Words, meanings
|
|
66
|
+
| 'grammar' // Parts of speech, sentences
|
|
67
|
+
| 'reading' // Comprehension
|
|
68
|
+
| 'writing' // Composition, sentences
|
|
69
|
+
| 'punctuation'; // Punctuation marks
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Platform-agnostic icon names
|
|
73
|
+
* Maps to:
|
|
74
|
+
* - Ionicons (App): add-outline, remove-outline, etc.
|
|
75
|
+
* - Lucide (Web): Plus, Minus, etc.
|
|
76
|
+
*/
|
|
77
|
+
export type TopicIconName =
|
|
78
|
+
| 'add'
|
|
79
|
+
| 'subtract'
|
|
80
|
+
| 'multiply'
|
|
81
|
+
| 'divide'
|
|
82
|
+
| 'fraction'
|
|
83
|
+
| 'shapes'
|
|
84
|
+
| 'time'
|
|
85
|
+
| 'money'
|
|
86
|
+
| 'ruler'
|
|
87
|
+
| 'document'
|
|
88
|
+
| 'text'
|
|
89
|
+
| 'book'
|
|
90
|
+
| 'list'
|
|
91
|
+
| 'music'
|
|
92
|
+
| 'code';
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Icon mappings for different platforms
|
|
96
|
+
*/
|
|
97
|
+
export const ICON_MAP = {
|
|
98
|
+
ionicons: {
|
|
99
|
+
add: 'add-outline',
|
|
100
|
+
subtract: 'remove-outline',
|
|
101
|
+
multiply: 'close-outline',
|
|
102
|
+
divide: 'git-compare-outline',
|
|
103
|
+
fraction: 'pie-chart-outline',
|
|
104
|
+
shapes: 'shapes-outline',
|
|
105
|
+
time: 'time-outline',
|
|
106
|
+
money: 'cash-outline',
|
|
107
|
+
ruler: 'resize-outline',
|
|
108
|
+
document: 'document-text-outline',
|
|
109
|
+
text: 'text-outline',
|
|
110
|
+
book: 'book-outline',
|
|
111
|
+
list: 'list-outline',
|
|
112
|
+
music: 'musical-notes-outline',
|
|
113
|
+
code: 'code-outline',
|
|
114
|
+
},
|
|
115
|
+
lucide: {
|
|
116
|
+
add: 'Plus',
|
|
117
|
+
subtract: 'Minus',
|
|
118
|
+
multiply: 'X',
|
|
119
|
+
divide: 'Divide',
|
|
120
|
+
fraction: 'PieChart',
|
|
121
|
+
shapes: 'Shapes',
|
|
122
|
+
time: 'Clock',
|
|
123
|
+
money: 'Coins',
|
|
124
|
+
ruler: 'Ruler',
|
|
125
|
+
document: 'FileText',
|
|
126
|
+
text: 'Type',
|
|
127
|
+
book: 'BookOpen',
|
|
128
|
+
list: 'List',
|
|
129
|
+
music: 'Music',
|
|
130
|
+
code: 'Code',
|
|
131
|
+
},
|
|
132
|
+
} as const;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get icon name for a specific platform
|
|
136
|
+
*/
|
|
137
|
+
export function getIconForPlatform(
|
|
138
|
+
iconName: TopicIconName,
|
|
139
|
+
platform: 'ionicons' | 'lucide'
|
|
140
|
+
): string {
|
|
141
|
+
return ICON_MAP[platform][iconName];
|
|
142
|
+
}
|
|
143
|
+
|