1241 lines
30 KiB
Markdown
1241 lines
30 KiB
Markdown
# Grammar System Guide
|
||
|
||
**Version:** 1.0.0
|
||
**Last Updated:** 2026-01-26
|
||
**Purpose:** Complete guide for managing grammar rules in the SENA Language Learning System
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
1. [Overview](#overview)
|
||
2. [Database Structure](#database-structure)
|
||
3. [API Endpoints](#api-endpoints)
|
||
4. [Grammar Engine Concepts](#grammar-engine-concepts)
|
||
5. [Pattern Logic System](#pattern-logic-system)
|
||
6. [Sentence Generation Algorithm](#sentence-generation-algorithm)
|
||
7. [Use Cases & Examples](#use-cases--examples)
|
||
8. [Database Queries](#database-queries)
|
||
9. [Validation Rules](#validation-rules)
|
||
10. [AI Integration Guide](#ai-integration-guide)
|
||
|
||
---
|
||
|
||
## Overview
|
||
|
||
The Grammar System is the **brain** that controls how vocabulary is mixed into sentences and stories. It provides:
|
||
|
||
- **Sentence Templates**: Define grammatical structures (e.g., "S + V + O")
|
||
- **Pattern Logic**: Smart rules to pick words from Vocabulary table based on roles and semantics
|
||
- **Curriculum Mapping**: Track where each grammar appears in textbooks
|
||
- **Media Stories**: Attach stories/videos that demonstrate the grammar rule
|
||
- **Automatic Sentence Generation**: Generate grammatically correct and semantically meaningful sentences
|
||
|
||
### Key Features
|
||
|
||
✅ **Role-Based Word Selection** - Pick words by syntax role (subject, verb, object, etc.)
|
||
✅ **Semantic Filtering** - Ensure semantic compatibility (e.g., "humans eat food", not "food eats humans")
|
||
✅ **Grammar Agreement** - Auto-select correct be verb (am/is/are) based on subject
|
||
✅ **Article Selection** - Choose a/an based on phonetic sound
|
||
✅ **Form Selection** - Pick correct word form (v1, v_ing, v2, n_singular, etc.)
|
||
✅ **Dependency Management** - Link slots for grammar agreement
|
||
✅ **Optional Slots** - Support sentence variations
|
||
|
||
---
|
||
|
||
## Database Structure
|
||
|
||
### Table: `grammars`
|
||
|
||
Main table storing grammar rule definitions.
|
||
|
||
| Column | Type | Required | Description |
|
||
|--------|------|----------|-------------|
|
||
| `id` | INTEGER | Auto | Primary key |
|
||
| `grammar_code` | STRING(100) | ✓ | Unique identifier (e.g., "gram-001-present-cont") |
|
||
| `title` | STRING(200) | ✓ | Grammar name (e.g., "Present Continuous") |
|
||
| `translation` | STRING(200) | - | Vietnamese translation |
|
||
| `structure` | JSON | ✓ | Formula + pattern_logic (see below) |
|
||
| `instructions` | JSON | - | { vi: string, hint: string } |
|
||
| `difficulty_score` | INTEGER | - | 1-10 (default: 1) |
|
||
| `category` | STRING(100) | - | e.g., "Tenses", "Modal Verbs" |
|
||
| `tags` | JSON | - | Array of tags |
|
||
| `is_active` | BOOLEAN | ✓ | Soft delete flag (default: true) |
|
||
| `createdAt` | TIMESTAMP | Auto | Creation timestamp |
|
||
| `updatedAt` | TIMESTAMP | Auto | Last update timestamp |
|
||
|
||
#### `structure` Field Format
|
||
|
||
```json
|
||
{
|
||
"formula": "S + am/is/are + V-ing + (a/an) + O + Adv",
|
||
"pattern_logic": [
|
||
{
|
||
"slot_id": "S_01",
|
||
"role": "is_subject",
|
||
"semantic_filter": ["human", "animal"]
|
||
},
|
||
{
|
||
"slot_id": "BE_01",
|
||
"role": "is_be",
|
||
"dependency": "S_01"
|
||
},
|
||
{
|
||
"slot_id": "V_01",
|
||
"role": "is_verb",
|
||
"use_form": "v_ing",
|
||
"semantic_filter": ["action"]
|
||
},
|
||
{
|
||
"slot_id": "O_01",
|
||
"role": "is_object",
|
||
"semantic_match": "V_01"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### Table: `grammar_mappings`
|
||
|
||
Curriculum mapping - tracks where grammar appears in textbooks.
|
||
|
||
| Column | Type | Required | Description |
|
||
|--------|------|----------|-------------|
|
||
| `id` | INTEGER | Auto | Primary key |
|
||
| `grammar_id` | INTEGER | ✓ | FK to grammars.id (cascade delete) |
|
||
| `book_id` | STRING(100) | ✓ | Book identifier (e.g., "global-success-2") |
|
||
| `grade` | INTEGER | ✓ | Grade level |
|
||
| `unit` | INTEGER | - | Unit number |
|
||
| `lesson` | INTEGER | - | Lesson number |
|
||
| `context_note` | TEXT | - | Additional context |
|
||
|
||
### Table: `grammar_media_stories`
|
||
|
||
Media content demonstrating the grammar rule.
|
||
|
||
| Column | Type | Required | Description |
|
||
|--------|------|----------|-------------|
|
||
| `id` | INTEGER | Auto | Primary key |
|
||
| `grammar_id` | INTEGER | ✓ | FK to grammars.id (cascade delete) |
|
||
| `story_id` | STRING(100) | ✓ | Unique story identifier |
|
||
| `title` | STRING(200) | ✓ | Story title |
|
||
| `type` | ENUM | ✓ | 'story', 'video', 'animation', 'audio' |
|
||
| `url` | STRING(500) | ✓ | Single URL to complete media file |
|
||
| `thumbnail` | STRING(500) | - | Thumbnail image URL |
|
||
| `description` | TEXT | - | Story description |
|
||
| `duration_seconds` | INTEGER | - | Media duration |
|
||
| `min_grade` | INTEGER | - | Minimum grade level |
|
||
|
||
---
|
||
|
||
## API Endpoints
|
||
|
||
Base URL: `/api/grammar`
|
||
|
||
### 1. Create Grammar Rule
|
||
|
||
**POST** `/api/grammar`
|
||
|
||
**Headers:**
|
||
```
|
||
Authorization: Bearer <token>
|
||
Content-Type: application/json
|
||
```
|
||
|
||
**Request Body:**
|
||
```json
|
||
{
|
||
"grammar_code": "gram-001-present-cont",
|
||
"title": "Present Continuous",
|
||
"translation": "Thì hiện tại tiếp diễn",
|
||
"structure": {
|
||
"formula": "S + am/is/are + V-ing + (a/an) + O + Adv",
|
||
"pattern_logic": [
|
||
{
|
||
"slot_id": "S_01",
|
||
"role": "is_subject",
|
||
"semantic_filter": ["human", "animal"]
|
||
},
|
||
{
|
||
"slot_id": "BE_01",
|
||
"role": "is_be",
|
||
"dependency": "S_01"
|
||
},
|
||
{
|
||
"slot_id": "V_01",
|
||
"role": "is_verb",
|
||
"use_form": "v_ing",
|
||
"semantic_filter": ["action"]
|
||
},
|
||
{
|
||
"slot_id": "O_01",
|
||
"role": "is_object",
|
||
"semantic_match": "V_01"
|
||
}
|
||
]
|
||
},
|
||
"instructions": {
|
||
"vi": "Dùng để nói về hành động đang diễn ra.",
|
||
"hint": "Cấu trúc: Be + V-ing"
|
||
},
|
||
"difficulty_score": 2,
|
||
"category": "Tenses",
|
||
"tags": ["present", "continuous", "action"],
|
||
"mappings": [
|
||
{
|
||
"book_id": "global-success-2",
|
||
"grade": 2,
|
||
"unit": 5,
|
||
"lesson": 1
|
||
}
|
||
],
|
||
"media_stories": [
|
||
{
|
||
"story_id": "st-01",
|
||
"title": "The Greedy Cat",
|
||
"type": "story",
|
||
"url": "https://cdn.sena.tech/stories/the-greedy-cat-full.mp4",
|
||
"thumbnail": "https://cdn.sena.tech/thumbs/greedy-cat.jpg",
|
||
"description": "A story about a cat who loves eating everything.",
|
||
"duration_seconds": 180,
|
||
"min_grade": 2
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**Response (201):**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "Grammar rule created successfully",
|
||
"data": {
|
||
"id": 1,
|
||
"grammar_code": "gram-001-present-cont",
|
||
"title": "Present Continuous",
|
||
"mappings": [...],
|
||
"mediaStories": [...]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. Get All Grammar Rules
|
||
|
||
**GET** `/api/grammar?page=1&limit=20&category=Tenses&grade=2&include_media=true`
|
||
|
||
**Query Parameters:**
|
||
- `page` (integer, default: 1)
|
||
- `limit` (integer, default: 20)
|
||
- `category` (string) - Filter by category
|
||
- `grade` (integer) - Filter by grade level
|
||
- `book_id` (string) - Filter by book ID
|
||
- `difficulty_min` (integer) - Minimum difficulty
|
||
- `difficulty_max` (integer) - Maximum difficulty
|
||
- `search` (string) - Search in title/translation/code
|
||
- `include_media` ('true'/'false', default: 'false')
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": [...],
|
||
"pagination": {
|
||
"total": 50,
|
||
"page": 1,
|
||
"limit": 20,
|
||
"totalPages": 3
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. Get Grammar by ID or Code
|
||
|
||
**GET** `/api/grammar/:id`
|
||
|
||
`:id` can be numeric ID or grammar_code string.
|
||
|
||
**Examples:**
|
||
- `/api/grammar/1` - Get by ID
|
||
- `/api/grammar/gram-001-present-cont` - Get by code
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"id": 1,
|
||
"grammar_code": "gram-001-present-cont",
|
||
"title": "Present Continuous",
|
||
"structure": {...},
|
||
"mappings": [...],
|
||
"mediaStories": [...]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4. Update Grammar Rule
|
||
|
||
**PUT** `/api/grammar/:id`
|
||
|
||
**Request Body:** (partial update)
|
||
```json
|
||
{
|
||
"translation": "Thì hiện tại tiếp diễn (cập nhật)",
|
||
"difficulty_score": 3,
|
||
"tags": ["present", "continuous", "action", "updated"]
|
||
}
|
||
```
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "Grammar rule updated successfully",
|
||
"data": {...}
|
||
}
|
||
```
|
||
|
||
### 5. Delete Grammar Rule
|
||
|
||
**DELETE** `/api/grammar/:id`
|
||
|
||
Performs soft delete (sets `is_active = false`).
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "Grammar rule deleted successfully"
|
||
}
|
||
```
|
||
|
||
### 6. Get Grammars by Curriculum
|
||
|
||
**GET** `/api/grammar/curriculum?book_id=global-success-2&grade=2&unit=5&lesson=1`
|
||
|
||
**Query Parameters:**
|
||
- `book_id` (string, required if grade not provided)
|
||
- `grade` (integer, required if book_id not provided)
|
||
- `unit` (integer, optional)
|
||
- `lesson` (integer, optional)
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": [...],
|
||
"count": 5
|
||
}
|
||
```
|
||
|
||
### 7. Get Grammar Statistics
|
||
|
||
**GET** `/api/grammar/stats`
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"total": 50,
|
||
"by_category": [
|
||
{ "category": "Tenses", "count": 20 },
|
||
{ "category": "Modal Verbs", "count": 10 }
|
||
],
|
||
"by_difficulty": [
|
||
{ "difficulty_score": 1, "count": 15 },
|
||
{ "difficulty_score": 2, "count": 20 }
|
||
],
|
||
"by_grade": [
|
||
{ "grade": 1, "count": 10 },
|
||
{ "grade": 2, "count": 15 }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 8. Get Grammar Guide (for AI)
|
||
|
||
**GET** `/api/grammar/guide`
|
||
|
||
Returns comprehensive guide in JSON format for AI agents to understand how to create grammar rules.
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"guide_version": "1.0.0",
|
||
"data_structure": {...},
|
||
"pattern_logic_roles": {...},
|
||
"semantic_filters": {...},
|
||
"form_keys_reference": {...},
|
||
"rules": {...},
|
||
"examples": {...},
|
||
"validation_checklist": [...],
|
||
"common_mistakes": [...],
|
||
"ai_tips": {...}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Grammar Engine Concepts
|
||
|
||
### 1. Pattern Logic System
|
||
|
||
Pattern logic defines **slots** that pick words from the Vocabulary table based on **roles** and **filters**.
|
||
|
||
#### Slot Properties
|
||
|
||
| Property | Type | Required | Description |
|
||
|----------|------|----------|-------------|
|
||
| `slot_id` | string | ✓ | Unique slot identifier (e.g., "S_01", "V_01") |
|
||
| `role` | string | ✓ | Word role from vocab.syntax (see roles below) |
|
||
| `semantic_filter` | array | - | Filter by semantic types (e.g., ["human", "animal"]) |
|
||
| `use_form` | string | - | Which form to use (v1, v_ing, v2, n_singular, etc.) |
|
||
| `dependency` | string | - | Slot ID this depends on for agreement |
|
||
| `is_optional` | boolean | - | Can be skipped (default: false) |
|
||
| `position` | string | - | Placement hint: 'start', 'middle', 'end' |
|
||
| `semantic_match` | string | - | Match with another slot for compatibility |
|
||
|
||
#### Available Roles
|
||
|
||
Roles query the `vocab.syntax` JSON field:
|
||
|
||
| Role | Description | Example Words |
|
||
|------|-------------|---------------|
|
||
| `is_subject` | Can be sentence subject | I, cat, teacher, apple |
|
||
| `is_verb` | Action or state verb | eat, run, sleep, love |
|
||
| `is_object` | Can be sentence object | apple, book, water |
|
||
| `is_be` | Be verb | am, is, are |
|
||
| `is_adj` | Adjective | happy, big, red |
|
||
| `is_adv` | Adverb | quickly, slowly, happily |
|
||
| `is_article` | Article | a, an |
|
||
| `is_pronoun` | Pronoun | I, you, he, she, it |
|
||
| `is_preposition` | Preposition | in, on, at, under |
|
||
|
||
### 2. Semantic Filters
|
||
|
||
Filter words by semantic types from `vocab.semantics`:
|
||
|
||
**Common Semantic Types:**
|
||
- `human` - People, person, teacher
|
||
- `animal` - Cat, dog, bird
|
||
- `object` - Book, pen, table
|
||
- `food` - Apple, rice, bread
|
||
- `plant` - Tree, flower, grass
|
||
- `place` - School, park, home
|
||
- `abstract` - Love, idea, freedom
|
||
- `emotion` - Happy, sad, angry
|
||
- `action` - Eat, run, jump
|
||
- `state` - Be, have, exist
|
||
|
||
**Example:**
|
||
```json
|
||
{
|
||
"slot_id": "S_01",
|
||
"role": "is_subject",
|
||
"semantic_filter": ["human", "animal"]
|
||
}
|
||
```
|
||
→ Only selects subjects that are humans or animals.
|
||
|
||
### 3. Form Selection
|
||
|
||
Use `use_form` to pick specific word variations from `VocabForm` table:
|
||
|
||
**Verb Forms:**
|
||
- `v1` - Base form (eat, go)
|
||
- `v_s_es` - Third person singular (eats, goes)
|
||
- `v_ing` - Present participle (eating, going)
|
||
- `v2` - Past simple (ate, went)
|
||
- `v3` - Past participle (eaten, gone)
|
||
|
||
**Noun Forms:**
|
||
- `n_singular` - Singular (cat, book)
|
||
- `n_plural` - Plural (cats, books)
|
||
|
||
**Adjective Forms:**
|
||
- `adj_base` - Base (happy, big)
|
||
- `adj_comparative` - Comparative (happier, bigger)
|
||
- `adj_superlative` - Superlative (happiest, biggest)
|
||
|
||
**Adverb Forms:**
|
||
- `adv_manner` - Manner (quickly, slowly)
|
||
- `adv_frequency` - Frequency (always, never)
|
||
- `adv_time` - Time (yesterday, today)
|
||
|
||
**Example:**
|
||
```json
|
||
{
|
||
"slot_id": "V_01",
|
||
"role": "is_verb",
|
||
"use_form": "v_ing"
|
||
}
|
||
```
|
||
→ Picks the V-ing form (e.g., "eating" from "eat").
|
||
|
||
### 4. Dependency Rules
|
||
|
||
Link slots for grammar agreement using `dependency` field.
|
||
|
||
#### Be Verb Agreement
|
||
|
||
```json
|
||
{
|
||
"slot_id": "BE_01",
|
||
"role": "is_be",
|
||
"dependency": "S_01"
|
||
}
|
||
```
|
||
|
||
**Logic:**
|
||
- If `S_01` is "I" → use "am"
|
||
- If `S_01` is singular (he, she, it, cat) → use "is"
|
||
- If `S_01` is plural (we, they, cats) → use "are"
|
||
|
||
#### Article Selection
|
||
|
||
```json
|
||
{
|
||
"slot_id": "ART_01",
|
||
"role": "is_article",
|
||
"dependency": "O_01"
|
||
}
|
||
```
|
||
|
||
**Logic:**
|
||
- Check `O_01` phonetic from VocabForm
|
||
- If starts with vowel sound (/æ/, /e/, /ɪ/, /ɒ/, /ʌ/) → use "an"
|
||
- Otherwise → use "a"
|
||
|
||
**Example:**
|
||
- "an apple" (/ˈæp.əl/ - vowel sound)
|
||
- "a book" (/bʊk/ - consonant sound)
|
||
|
||
#### Semantic Matching
|
||
|
||
```json
|
||
{
|
||
"slot_id": "O_01",
|
||
"role": "is_object",
|
||
"semantic_match": "V_01"
|
||
}
|
||
```
|
||
|
||
**Logic:**
|
||
- Check `V_01.semantics.can_take_object_type`
|
||
- Match with `O_01.semantics.word_type`
|
||
- Only select objects the verb can take
|
||
|
||
**Example:**
|
||
- Verb "eat" can take object types: ["food", "plant"]
|
||
- Object "apple" has word_type: "food"
|
||
- ✅ Valid match: "eat an apple"
|
||
- ❌ Invalid: "eat a table" (table is "object", not "food")
|
||
|
||
---
|
||
|
||
## Sentence Generation Algorithm
|
||
|
||
### Step-by-Step Process
|
||
|
||
1. **Load Grammar Rule**
|
||
```javascript
|
||
const grammar = await Grammar.findOne({
|
||
where: { grammar_code: 'gram-001-present-cont' },
|
||
include: ['mappings', 'mediaStories']
|
||
});
|
||
```
|
||
|
||
2. **Parse Pattern Logic**
|
||
```javascript
|
||
const pattern_logic = grammar.structure.pattern_logic;
|
||
```
|
||
|
||
3. **Loop Through Slots (in order)**
|
||
```javascript
|
||
for (let slot of pattern_logic) {
|
||
// Step 4-8 for each slot
|
||
}
|
||
```
|
||
|
||
4. **Query Vocab by Role**
|
||
```sql
|
||
SELECT * FROM vocab
|
||
WHERE syntax->>'is_verb' = 'true'
|
||
AND is_active = true;
|
||
```
|
||
|
||
5. **Apply Semantic Filter**
|
||
```sql
|
||
WHERE semantics->'can_be_subject_type' @> '["human"]'::jsonb
|
||
```
|
||
|
||
6. **Fetch Specific Form**
|
||
```sql
|
||
SELECT vf.text, vf.phonetic, vf.audio
|
||
FROM vocab_forms vf
|
||
WHERE vf.vocab_id = ? AND vf.form_key = 'v_ing'
|
||
```
|
||
|
||
7. **Apply Dependency Rules**
|
||
- If `dependency` = "S_01", apply be verb agreement
|
||
- If `dependency` = "O_01", apply article selection
|
||
- If `semantic_match` = "V_01", check semantic compatibility
|
||
|
||
8. **Random Selection**
|
||
```javascript
|
||
const randomWord = words[Math.floor(Math.random() * words.length)];
|
||
```
|
||
|
||
9. **Handle Optional Slots**
|
||
```javascript
|
||
if (slot.is_optional && Math.random() > 0.5) {
|
||
continue; // Skip this slot
|
||
}
|
||
```
|
||
|
||
10. **Concatenate Result**
|
||
```javascript
|
||
sentence = selectedWords.map(w => w.text).join(' ');
|
||
// "The cat is eating an apple quickly"
|
||
```
|
||
|
||
### Example Generation
|
||
|
||
**Grammar:** Present Continuous
|
||
**Formula:** `S + am/is/are + V-ing + (a/an) + O + Adv`
|
||
|
||
**Pattern Logic:**
|
||
1. `S_01`: is_subject, semantic_filter: ["animal"] → **"cat"**
|
||
2. `BE_01`: is_be, dependency: S_01 → **"is"** (singular)
|
||
3. `V_01`: is_verb, use_form: v_ing, semantic_filter: ["action"] → **"eating"**
|
||
4. `ART_01`: is_article, dependency: O_01 → **"an"** (apple starts with vowel)
|
||
5. `O_01`: is_object, semantic_match: V_01 → **"apple"** (food)
|
||
6. `ADV_01`: is_adv, is_optional: true → **"quickly"**
|
||
|
||
**Generated Sentence:**
|
||
```
|
||
"The cat is eating an apple quickly."
|
||
```
|
||
|
||
**With Audio:**
|
||
```json
|
||
{
|
||
"text": "The cat is eating an apple quickly.",
|
||
"audio_segments": [
|
||
{ "word": "The", "audio": "https://cdn.sena.tech/audio/the.mp3" },
|
||
{ "word": "cat", "audio": "https://cdn.sena.tech/audio/cat_n_singular.mp3" },
|
||
{ "word": "is", "audio": "https://cdn.sena.tech/audio/is.mp3" },
|
||
{ "word": "eating", "audio": "https://cdn.sena.tech/audio/eating_v_ing.mp3" },
|
||
{ "word": "an", "audio": "https://cdn.sena.tech/audio/an.mp3" },
|
||
{ "word": "apple", "audio": "https://cdn.sena.tech/audio/apple_n_singular.mp3" },
|
||
{ "word": "quickly", "audio": "https://cdn.sena.tech/audio/quickly_adv_manner.mp3" }
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Use Cases & Examples
|
||
|
||
### Use Case 1: Present Continuous Tense
|
||
|
||
**Grammar Rule:**
|
||
```json
|
||
{
|
||
"grammar_code": "gram-001-present-cont",
|
||
"title": "Present Continuous",
|
||
"structure": {
|
||
"formula": "S + am/is/are + V-ing + O",
|
||
"pattern_logic": [
|
||
{ "slot_id": "S_01", "role": "is_subject", "semantic_filter": ["human", "animal"] },
|
||
{ "slot_id": "BE_01", "role": "is_be", "dependency": "S_01" },
|
||
{ "slot_id": "V_01", "role": "is_verb", "use_form": "v_ing" },
|
||
{ "slot_id": "O_01", "role": "is_object", "semantic_match": "V_01" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**Generated Sentences:**
|
||
- "I am eating an apple."
|
||
- "The cat is drinking milk."
|
||
- "They are playing football."
|
||
|
||
### Use Case 2: Yes/No Questions
|
||
|
||
**Grammar Rule:**
|
||
```json
|
||
{
|
||
"grammar_code": "gram-010-yes-no-question",
|
||
"title": "Yes/No Questions with Be",
|
||
"structure": {
|
||
"formula": "Am/Is/Are + S + Adj?",
|
||
"pattern_logic": [
|
||
{ "slot_id": "BE_01", "role": "is_be", "position": "start" },
|
||
{ "slot_id": "S_01", "role": "is_subject" },
|
||
{ "slot_id": "ADJ_01", "role": "is_adj" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**Generated Sentences:**
|
||
- "Is the cat happy?"
|
||
- "Are you hungry?"
|
||
- "Am I late?"
|
||
|
||
### Use Case 3: Modal Verbs (Can)
|
||
|
||
**Grammar Rule:**
|
||
```json
|
||
{
|
||
"grammar_code": "gram-020-modal-can",
|
||
"title": "Modal Verb Can",
|
||
"structure": {
|
||
"formula": "S + can + V1 + O",
|
||
"pattern_logic": [
|
||
{ "slot_id": "S_01", "role": "is_subject", "semantic_filter": ["human"] },
|
||
{ "slot_id": "V_01", "role": "is_verb", "use_form": "v1" },
|
||
{ "slot_id": "O_01", "role": "is_object", "semantic_match": "V_01", "is_optional": true }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**Generated Sentences:**
|
||
- "I can swim."
|
||
- "She can play the piano."
|
||
- "They can speak English."
|
||
|
||
### Use Case 4: Past Simple Tense
|
||
|
||
**Grammar Rule:**
|
||
```json
|
||
{
|
||
"grammar_code": "gram-030-past-simple",
|
||
"title": "Past Simple",
|
||
"structure": {
|
||
"formula": "S + V2 + O + Adv",
|
||
"pattern_logic": [
|
||
{ "slot_id": "S_01", "role": "is_subject" },
|
||
{ "slot_id": "V_01", "role": "is_verb", "use_form": "v2" },
|
||
{ "slot_id": "O_01", "role": "is_object", "semantic_match": "V_01" },
|
||
{ "slot_id": "ADV_01", "role": "is_adv", "is_optional": true }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**Generated Sentences:**
|
||
- "I ate an apple yesterday."
|
||
- "The cat slept all day."
|
||
- "They played football."
|
||
|
||
### Use Case 5: Wh-Questions
|
||
|
||
**Grammar Rule:**
|
||
```json
|
||
{
|
||
"grammar_code": "gram-040-wh-question",
|
||
"title": "Wh-Questions (What)",
|
||
"structure": {
|
||
"formula": "What + am/is/are + S + V-ing?",
|
||
"pattern_logic": [
|
||
{ "slot_id": "BE_01", "role": "is_be" },
|
||
{ "slot_id": "S_01", "role": "is_subject" },
|
||
{ "slot_id": "V_01", "role": "is_verb", "use_form": "v_ing" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**Generated Sentences:**
|
||
- "What are you doing?"
|
||
- "What is the cat eating?"
|
||
- "What am I wearing?"
|
||
|
||
---
|
||
|
||
## Database Queries
|
||
|
||
### Query 1: Find All Grammars for Grade 2
|
||
|
||
```sql
|
||
SELECT g.*
|
||
FROM grammars g
|
||
JOIN grammar_mappings gm ON g.id = gm.grammar_id
|
||
WHERE gm.grade = 2 AND g.is_active = true
|
||
ORDER BY g.difficulty_score ASC;
|
||
```
|
||
|
||
### Query 2: Get Grammars by Category
|
||
|
||
```sql
|
||
SELECT * FROM grammars
|
||
WHERE category = 'Tenses' AND is_active = true
|
||
ORDER BY difficulty_score ASC;
|
||
```
|
||
|
||
### Query 3: Find Grammars Using Specific Role
|
||
|
||
```sql
|
||
SELECT * FROM grammars
|
||
WHERE structure::text LIKE '%"role":"is_verb"%'
|
||
AND is_active = true;
|
||
```
|
||
|
||
### Query 4: Get All Media Stories for a Grammar
|
||
|
||
```sql
|
||
SELECT gms.*
|
||
FROM grammar_media_stories gms
|
||
JOIN grammars g ON gms.grammar_id = g.id
|
||
WHERE g.grammar_code = 'gram-001-present-cont';
|
||
```
|
||
|
||
### Query 5: Count Grammars by Difficulty
|
||
|
||
```sql
|
||
SELECT difficulty_score, COUNT(*) as count
|
||
FROM grammars
|
||
WHERE is_active = true
|
||
GROUP BY difficulty_score
|
||
ORDER BY difficulty_score ASC;
|
||
```
|
||
|
||
### Query 6: Find Grammars with Optional Slots
|
||
|
||
```sql
|
||
SELECT * FROM grammars
|
||
WHERE structure::text LIKE '%"is_optional":true%'
|
||
AND is_active = true;
|
||
```
|
||
|
||
### Query 7: Get Curriculum Coverage
|
||
|
||
```sql
|
||
SELECT gm.book_id, gm.grade, COUNT(DISTINCT g.id) as grammar_count
|
||
FROM grammar_mappings gm
|
||
JOIN grammars g ON gm.grammar_id = g.id
|
||
WHERE g.is_active = true
|
||
GROUP BY gm.book_id, gm.grade
|
||
ORDER BY gm.book_id, gm.grade;
|
||
```
|
||
|
||
---
|
||
|
||
## Validation Rules
|
||
|
||
### 1. Grammar Code Format
|
||
|
||
**Rule:** `gram-{3-digit-sequence}-{kebab-case-identifier}`
|
||
|
||
**Valid:**
|
||
- `gram-001-present-cont`
|
||
- `gram-015-modal-can`
|
||
- `gram-100-passive-voice`
|
||
|
||
**Invalid:**
|
||
- `gram-1-test` (not 3 digits)
|
||
- `GRAM-001-TEST` (uppercase)
|
||
- `present-continuous` (no prefix)
|
||
|
||
### 2. Structure Requirements
|
||
|
||
**Required:**
|
||
- `formula` (string) - Must be present
|
||
- `pattern_logic` (array) - Must have at least 1 slot
|
||
|
||
**Example:**
|
||
```json
|
||
{
|
||
"formula": "S + V + O",
|
||
"pattern_logic": [
|
||
{ "slot_id": "S_01", "role": "is_subject" }
|
||
]
|
||
}
|
||
```
|
||
|
||
### 3. Slot Validation
|
||
|
||
**Required Properties:**
|
||
- `slot_id` - Unique identifier
|
||
- `role` - Must be valid role (see Available Roles)
|
||
|
||
**Optional Properties:**
|
||
- `semantic_filter` - Array of semantic types
|
||
- `use_form` - Must be valid form key
|
||
- `dependency` - Must reference existing slot_id
|
||
- `is_optional` - Boolean
|
||
- `position` - 'start', 'middle', 'end'
|
||
|
||
### 4. Dependency Validation
|
||
|
||
**Rule:** `dependency` must reference a slot_id that appears **before** the current slot.
|
||
|
||
**Valid:**
|
||
```json
|
||
[
|
||
{ "slot_id": "S_01", "role": "is_subject" },
|
||
{ "slot_id": "BE_01", "role": "is_be", "dependency": "S_01" }
|
||
]
|
||
```
|
||
|
||
**Invalid:**
|
||
```json
|
||
[
|
||
{ "slot_id": "BE_01", "role": "is_be", "dependency": "S_01" },
|
||
{ "slot_id": "S_01", "role": "is_subject" }
|
||
]
|
||
```
|
||
|
||
### 5. Form Key Validation
|
||
|
||
**Rule:** `use_form` must match valid form keys:
|
||
|
||
- Verbs: `v1`, `v_s_es`, `v_ing`, `v2`, `v3`
|
||
- Nouns: `n_singular`, `n_plural`
|
||
- Adjectives: `adj_base`, `adj_comparative`, `adj_superlative`
|
||
- Adverbs: `adv_manner`, `adv_frequency`, `adv_time`
|
||
|
||
### 6. Semantic Filter Validation
|
||
|
||
**Rule:** Semantic types must be consistent with vocab semantics.
|
||
|
||
**Common Types:**
|
||
- Subject types: `human`, `animal`, `object`
|
||
- Object types: `food`, `plant`, `tool`, `container`
|
||
- Action types: `action`, `state`, `emotion`
|
||
|
||
### 7. Media Story Validation
|
||
|
||
**Required Properties:**
|
||
- `story_id` - Unique identifier
|
||
- `title` - Story title
|
||
- `type` - Must be 'story', 'video', 'animation', or 'audio'
|
||
- `url` - Valid URL
|
||
|
||
**Optional Properties:**
|
||
- `thumbnail` - Image URL
|
||
- `description` - Text description
|
||
- `duration_seconds` - Integer
|
||
- `min_grade` - Integer
|
||
|
||
---
|
||
|
||
## AI Integration Guide
|
||
|
||
### For AI Agents Creating Grammar Rules
|
||
|
||
#### Step 1: Analyze Curriculum
|
||
|
||
1. Identify grammar topic (e.g., "Present Continuous")
|
||
2. Determine difficulty level (1-10)
|
||
3. Find curriculum mapping (book, grade, unit, lesson)
|
||
|
||
#### Step 2: Define Formula
|
||
|
||
Create human-readable formula:
|
||
```
|
||
S + am/is/are + V-ing + (a/an) + O + Adv
|
||
```
|
||
|
||
**Tips:**
|
||
- Use S for Subject, V for Verb, O for Object
|
||
- Show alternatives with `/` (am/is/are)
|
||
- Mark optional with `()` (Adv)
|
||
|
||
#### Step 3: Design Pattern Logic
|
||
|
||
For each word in formula, create a slot:
|
||
|
||
```json
|
||
{
|
||
"slot_id": "S_01",
|
||
"role": "is_subject",
|
||
"semantic_filter": ["human", "animal"]
|
||
}
|
||
```
|
||
|
||
**Checklist:**
|
||
- ✓ Unique `slot_id` (S_01, V_01, O_01, etc.)
|
||
- ✓ Valid `role` from pattern_logic_roles
|
||
- ✓ Semantic filter matches curriculum level
|
||
- ✓ Specify `use_form` for verbs/nouns
|
||
- ✓ Add `dependency` for grammar agreement
|
||
- ✓ Mark `is_optional` for sentence variations
|
||
|
||
#### Step 4: Add Dependencies
|
||
|
||
Link slots for grammar rules:
|
||
|
||
**Be Verb Agreement:**
|
||
```json
|
||
{
|
||
"slot_id": "BE_01",
|
||
"role": "is_be",
|
||
"dependency": "S_01"
|
||
}
|
||
```
|
||
|
||
**Article Selection:**
|
||
```json
|
||
{
|
||
"slot_id": "ART_01",
|
||
"role": "is_article",
|
||
"dependency": "O_01"
|
||
}
|
||
```
|
||
|
||
**Semantic Matching:**
|
||
```json
|
||
{
|
||
"slot_id": "O_01",
|
||
"role": "is_object",
|
||
"semantic_match": "V_01"
|
||
}
|
||
```
|
||
|
||
#### Step 5: Create Instructions
|
||
|
||
```json
|
||
{
|
||
"vi": "Dùng để nói về hành động đang diễn ra.",
|
||
"hint": "Cấu trúc: Be + V-ing"
|
||
}
|
||
```
|
||
|
||
#### Step 6: Add Mappings
|
||
|
||
```json
|
||
{
|
||
"mappings": [
|
||
{
|
||
"book_id": "global-success-2",
|
||
"grade": 2,
|
||
"unit": 5,
|
||
"lesson": 1
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### Step 7: Attach Media Stories
|
||
|
||
```json
|
||
{
|
||
"media_stories": [
|
||
{
|
||
"story_id": "st-01",
|
||
"title": "The Greedy Cat",
|
||
"type": "story",
|
||
"url": "https://cdn.sena.tech/stories/the-greedy-cat-full.mp4",
|
||
"thumbnail": "https://cdn.sena.tech/thumbs/greedy-cat.jpg",
|
||
"description": "A story about a cat who loves eating everything."
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### Step 8: Validate & Submit
|
||
|
||
**Pre-Submit Checklist:**
|
||
1. ✓ `grammar_code` follows format
|
||
2. ✓ `structure.formula` is clear
|
||
3. ✓ `pattern_logic` has at least 1 slot
|
||
4. ✓ All roles are valid
|
||
5. ✓ `use_form` values are correct
|
||
6. ✓ Dependencies reference valid slots
|
||
7. ✓ Semantic filters match vocab
|
||
8. ✓ Media URLs are accessible
|
||
9. ✓ `difficulty_score` is 1-10
|
||
10. ✓ At least 1 mapping exists
|
||
|
||
**Submit via API:**
|
||
```bash
|
||
POST /api/grammar
|
||
Content-Type: application/json
|
||
Authorization: Bearer <token>
|
||
|
||
{...grammar data...}
|
||
```
|
||
|
||
#### Common Mistakes to Avoid
|
||
|
||
1. **Invalid Role**
|
||
- ❌ `"role": "is_noun"`
|
||
- ✅ `"role": "is_object"`
|
||
|
||
2. **Missing Formula**
|
||
- ❌ `"structure": { "pattern_logic": [...] }`
|
||
- ✅ `"structure": { "formula": "S + V + O", "pattern_logic": [...] }`
|
||
|
||
3. **Invalid Dependency**
|
||
- ❌ `"dependency": "INVALID_SLOT"`
|
||
- ✅ `"dependency": "S_01"`
|
||
|
||
4. **Wrong Form Key**
|
||
- ❌ `{ "role": "is_verb", "use_form": "n_singular" }`
|
||
- ✅ `{ "role": "is_verb", "use_form": "v_ing" }`
|
||
|
||
5. **Semantic Mismatch**
|
||
- ❌ `{ "role": "is_verb", "semantic_filter": ["object"] }`
|
||
- ✅ `{ "role": "is_verb", "semantic_filter": ["action"] }`
|
||
|
||
#### AI Tips
|
||
|
||
- **Efficiency:** Create grammars in order of difficulty (easy → hard)
|
||
- **Accuracy:** Validate pattern_logic against actual vocab entries
|
||
- **Completeness:** Include mappings and media stories
|
||
- **Testing:** Test sentence generation with sample vocab
|
||
- **Documentation:** Use clear formulas and instructions
|
||
|
||
---
|
||
|
||
## API Integration Example (JavaScript)
|
||
|
||
### Create Grammar Rule
|
||
|
||
```javascript
|
||
const axios = require('axios');
|
||
|
||
async function createGrammar(token) {
|
||
try {
|
||
const response = await axios.post('http://localhost:3000/api/grammar', {
|
||
grammar_code: 'gram-001-present-cont',
|
||
title: 'Present Continuous',
|
||
translation: 'Thì hiện tại tiếp diễn',
|
||
structure: {
|
||
formula: 'S + am/is/are + V-ing + (a/an) + O + Adv',
|
||
pattern_logic: [
|
||
{
|
||
slot_id: 'S_01',
|
||
role: 'is_subject',
|
||
semantic_filter: ['human', 'animal']
|
||
},
|
||
{
|
||
slot_id: 'BE_01',
|
||
role: 'is_be',
|
||
dependency: 'S_01'
|
||
},
|
||
{
|
||
slot_id: 'V_01',
|
||
role: 'is_verb',
|
||
use_form: 'v_ing',
|
||
semantic_filter: ['action']
|
||
},
|
||
{
|
||
slot_id: 'ART_01',
|
||
role: 'is_article',
|
||
dependency: 'O_01',
|
||
is_optional: true
|
||
},
|
||
{
|
||
slot_id: 'O_01',
|
||
role: 'is_object',
|
||
semantic_match: 'V_01'
|
||
},
|
||
{
|
||
slot_id: 'ADV_01',
|
||
role: 'is_adv',
|
||
is_optional: true,
|
||
position: 'end'
|
||
}
|
||
]
|
||
},
|
||
instructions: {
|
||
vi: 'Dùng để nói về hành động đang diễn ra.',
|
||
hint: 'Cấu trúc: Be + V-ing'
|
||
},
|
||
difficulty_score: 2,
|
||
category: 'Tenses',
|
||
tags: ['present', 'continuous', 'action'],
|
||
mappings: [
|
||
{
|
||
book_id: 'global-success-2',
|
||
grade: 2,
|
||
unit: 5,
|
||
lesson: 1
|
||
}
|
||
],
|
||
media_stories: [
|
||
{
|
||
story_id: 'st-01',
|
||
title: 'The Greedy Cat',
|
||
type: 'story',
|
||
url: 'https://cdn.sena.tech/stories/the-greedy-cat-full.mp4',
|
||
thumbnail: 'https://cdn.sena.tech/thumbs/greedy-cat.jpg',
|
||
description: 'A story about a cat who loves eating everything.',
|
||
duration_seconds: 180,
|
||
min_grade: 2
|
||
}
|
||
]
|
||
}, {
|
||
headers: {
|
||
'Authorization': `Bearer ${token}`,
|
||
'Content-Type': 'application/json'
|
||
}
|
||
});
|
||
|
||
console.log('✅ Grammar created:', response.data);
|
||
} catch (error) {
|
||
console.error('❌ Error:', error.response?.data || error.message);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Get Grammar Guide
|
||
|
||
```javascript
|
||
async function getGrammarGuide(token) {
|
||
try {
|
||
const response = await axios.get('http://localhost:3000/api/grammar/guide', {
|
||
headers: { 'Authorization': `Bearer ${token}` }
|
||
});
|
||
|
||
const guide = response.data.data;
|
||
console.log('📖 Grammar Guide Version:', guide.guide_version);
|
||
console.log('📊 Pattern Logic Roles:', guide.pattern_logic_roles);
|
||
console.log('✅ Validation Checklist:', guide.validation_checklist);
|
||
} catch (error) {
|
||
console.error('❌ Error:', error.message);
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Summary
|
||
|
||
The Grammar System provides a powerful framework for:
|
||
|
||
1. **Defining Grammar Rules** - Store templates with formula and pattern logic
|
||
2. **Automatic Sentence Generation** - Mix vocabulary intelligently based on roles and semantics
|
||
3. **Curriculum Mapping** - Track where each grammar appears in textbooks
|
||
4. **Media Integration** - Attach stories/videos for engaging learning
|
||
5. **AI-Ready** - Comprehensive guide for automated data entry
|
||
|
||
**Key Benefits:**
|
||
- ✅ Generates grammatically correct sentences
|
||
- ✅ Ensures semantic compatibility
|
||
- ✅ Supports all grammar types (tenses, questions, modals, etc.)
|
||
- ✅ Provides audio for each word
|
||
- ✅ Tracks curriculum coverage
|
||
- ✅ AI-friendly for automated content creation
|
||
|
||
**Next Steps:**
|
||
1. Create vocabulary entries with complete syntax and semantics
|
||
2. Define grammar rules for each textbook lesson
|
||
3. Implement sentence generation service
|
||
4. Integrate with Grammar Engine for real-time sentence creation
|
||
5. Add media stories for engaging content
|
||
|
||
---
|
||
|
||
**For questions or support, contact the SENA development team.**
|