# 02 — معماری سیستم

## 1. نمای کلی

```
┌────────────────────────────────────────────────────────────────┐
│                      کلاینت (مرورگر — SPA)                      │
│                                                                │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │ UI Layer                                                  │  │
│  │  Screens (Home, LoginChild, Map, Game, Report)            │  │
│  │  Components (LetterCard, StarBar, Mascot, RewardModal)    │  │
│  │  Bootstrap 5 + CSS Variables + GSAP Timelines             │  │
│  ├──────────────────────────────────────────────────────────┤  │
│  │ Game Engine (مستقل از زبان)                               │  │
│  │  GameModules (8 بازی) · Scoring · AdaptiveDifficulty      │  │
│  │  MasteryTracker · SRS Scheduler (Leitner)                 │  │
│  ├──────────────────────────────────────────────────────────┤  │
│  │ Core                                                     │  │
│  │  EventBus (pub/sub) · HashRouter · Store (observable)     │  │
│  │  AudioEngine (File→TTS fallback) · i18n · PackLoader      │  │
│  ├──────────────────────────────────────────────────────────┤  │
│  │ Data Layer                                                │  │
│  │  Repository Pattern:                                     │  │
│  │   LocalRepo (localStorage) ⇄ SyncQueue ⇄ RestRepo (AJAX)  │  │
│  └──────────────────────────────────────────────────────────┘  │
│                                                                │
│        Service Worker (App Shell Cache + Media Cache)          │
└───────────────┬──────────────────────────────┬─────────────────┘
                │ HTTPS · REST / JSON          │ static assets
                ▼                              ▼
┌───────────────────────────────┐   ┌──────────────────────────┐
│      API Server (Express)     │   │   Static / CDN           │
│  middleware: auth · validate  │   │  /packs/*.json           │
│  routes → services → repos    │   │  /audio/**.mp3|.ogg      │
│         ↓                     │   │  /img/**.svg|.webp       │
│  SQLite (dev) → PostgreSQL    │   └──────────────────────────┘
└───────────────────────────────┘
```

**اصل حاکم:** منطقِ آموزش و بازی فقط با «داده‌ی پکیج زبانی» کار می‌کند و هرگز با محتوای یک زبان خاص hard-code نمی‌شود.

## 2. استک فناوری و دلیل انتخاب

| لایه | فناوری | چرا |
|---|---|---|
| UI | Bootstrap 5 (SASS سفارشی‌سازی‌شده) | گرید ریسپانسیو، کامپوننت لمسی، بدون وابستگی به jQuery |
| انیمیشن | GSAP 3 (+ Draggable برای بازی‌های کشیدنی) | تایم‌لاین مرکزی، کنترل دقیق، عملکرد بالا روی موبایل |
| منطق | Vanilla JS (ES Modules) | بدون فریمورک → باندل کم، کنترل کامل، مناسب سطح‌بندی یادگیری تیم |
| ارتباط | AJAX با `fetch` + پوشش retry/timeout | لایه‌ی `RestRepo` تمام شبکه را کپسوله می‌کند |
| بک‌اند | Node.js + Express | هم‌زبانه با فرانت (JS)، JSON-محور، سبک |
| دیتابیس | SQLite (dev) / PostgreSQL (prod) | شروع سریع بدون سرور DB؛ مهاجرت ساده با ORM (Knex/Prisma) |
| آفلاین | Service Worker + Cache API | اجرای بی‌شبکه + کش پکیج زبانی |
| کیفیت | Jest · Supertest · Playwright | تست واحد SRS/امتیازدهی، تست API، تست E2E |

## 3. تصمیمات کلیدی معماری (ADR خلاصه)

### ADR-01: SPA بدون فریمورک (Vanilla ES Modules)
- **تصمیم:** به‌جای React/Vue، معماری ماژولار با `EventBus` و `Store` سبک (الگوی Observable).
- **دلیل:** حجم اولیه‌ی کم (شرط KPI: اولین بازی < ۵ ثانیه)، عدم نیاز به build پیچیده، مالکیت کامل بر DOM برای انیمیشن‌های GSAP.
- **پیامد:** نظم کد باید با قرارداد ساختار پوشه (سند 06) تضمین شود.

### ADR-02: پکیج زبانی Data-Driven
- **تصمیم:** تمام محتوای آموزشی در JSON (سند 03)؛ کد فقط رابط عمومی `pack.letters[]`، `pack.words[]` و متادیتا (`dir`, `lang`, `forms`) را می‌شناسد.
- **دلیل:** افزودن زبان = افزودن فایل؛ RTL/LTR و اشکال متصل فارسی به‌جای if/else در کد، از متادیتای پک می‌آیند.

### ADR-03: Repository Pattern + Sync Queue (Offline-First)
- **تصمیم:** کلاینت فقط با `LocalRepo` می‌نویسد/می‌خواند؛ `SyncQueue` تغییرات را ورودی‌شده-اول-خروجی‌آخر (FIFO) به `POST /progress:batch` می‌فرستد.
- **دلیل:** بازخورد آنی برای کودک (بدون انتظار شبکه)، تاب‌آوری در قطع شبکه، حل تعارض با استراتژی «آخرین برد-برنده سمت سرور + merge بر اساس max(updated_at)».

### ADR-04: EventBus به‌عنوان ستون فقرات
- **تصمیم:** همه‌ی ماژول‌ها فقط از طریق رویدادها با هم حرف می‌زنند: `game:success`, `audio:play`, `progress:update`…
- **دلیل:** جداسازی کامل Game Engine از UI و Audio؛ هر شنونده بدون دانستن فرستنده کار می‌کند → تست‌پذیری.

### ADR-05: احراز هویت دومرحله‌ای (والد/کودک)
- **تصمیم:** والد: ایمیل/رمز → JWT. کودک: آواتار+رنگ → session token وصل به دستگاه.
- **دلیل:** کودک نمی‌تواند رمز مدیریت کند؛ داده‌ی حساس فقط زیر حساب والد.

### ADR-06: بدون build الزامی (Optionally Buildable)
- **تصمیم:** کد با ES Modules مستقیم در مرورگر اجرا می‌شود؛ Vite صرفاً اختیاری برای minify در production.
- **دلیل:** سادگی استقرار (هر هاست استاتیکی) + امکان بهینه‌سازی تدریجی.

## 4. جریان داده‌ی نمونه — «یک تلاش درست در بازی»

```
کودک روی حباب «ب» ضربه می‌زند
   │
   ▼
GameModule.evaluate() ──► EventBus.emit('game:attempt', {letter:'fa_be', ok:true})
   │                              │                    │                 │
   ▼                              ▼                    ▼                 ▼
UI: AnimationService       AudioEngine: پخش        Scoring: +10       MasteryTracker:
'success-pop' timeline     صدای تشویق + تلفظ       (کمبو ×2…)         ارتقای L2→L3؟
                                                   │                  │
                                                   ▼                  ▼
                                             Store.update()     LocalRepo.save()
                                                                        │
                                                                        ▼
                                                                SyncQueue.enqueue()
                                                                        │ (آنلاین؟)
                                                                        ▼
                                                        POST /api/v1/children/:id/progress:batch
                                                                        │
                                                                        ▼
                                                    Server: اعتبارسنجی → Upsert → رویداد در
                                                    session_events (برای گزارش والدین)
```

## 5. مدیریت خطا و تاب‌آوری

| حالت | رفتار سیستم |
|---|---|
| قطع شبکه هنگام بازی | بازی ادامه دارد (همه‌چیز local)؛ SyncQueue خودکار retry با backoff نمایی |
| خطای بارگذاری فایل صوتی | fallback خودکار به TTS (سند 07) |
| پک زبانی ناقص/خراب | اعتبارسنجی schema هنگام بارگذاری + پیام خطای «والد را صدا کن» |
| کرش ماژول بازی در وسط جلسه | هر بازی در `try/catch` سندباکس‌شده؛ بازگشت امن به نقشه‌ی ماجراجویی با حفظ پیشرفت |
| خطای سرور در سینک | صف باقی می‌ماند؛ حداکثر ۵۰۰ رویداد در صف (LRU) |

## 6. استقرار (Deployment)

```
Static Host (CDN)  ←  client/ + packs + audio + sw.js
Node Process       ←  server/  (Docker یا PaaS مثل Railway/Render)
PostgreSQL         ←  سرویس مدیریت‌شده (مثل Neon/Supabase)
CI                 ←  GitHub Actions: lint → test → build → deploy
```
