# 05 — بازی‌ها، موتور بازی و پداگوژی

## 1. مدل تسلط ۵ سطحی

قلب سیستم آموزشی. هر تعامل کودک فقط روی «سطح تسلط یک حرف» اثر می‌گذارد.

| سطح | نام | معیار ارتقای داخلی | بازی‌های مرتبط |
|---|---|---|---|
| **L0 آشنایی** | حرف دیده/شنیده شده | تماشای معرفی حرف (۱ بار) | معرفی + Safari |
| **L1 تشخیص با راهنمایی** | انتخاب درست از ۲ گزینه | ۲ پاسخ درست متوالی | Letter-Pop (آسان) |
| **L2 تشخیص مستقل** | انتخاب از ۴+ گزینه | ≥ 80٪ در ۱۰ تلاش اخیر | Letter-Pop، Catch، Memory |
| **L3 یادآوری** | شنیدن صدا → یافتن حرف | ≥ 80٪ تلاش‌های sound→letter | Sound-Hunt، Odd-One-Out |
| **L4 تولید** | تتبع حرف / ساخت کلمه | Trace با ≥70٪ پوشش مسیر ×2 یا ۳ کلمه | Trace، Word-Builder |

**تنزل سطح وجود ندارد** — خطا فقط «مرگفته» می‌کند ( Leitner box پایین می‌آید → مرور زودتر)، سطح تسلط همیشه صعودی است. این تصمیم برای سلامت روان کودک و انگیزه‌ی او حیاتی است.

## 2. تکرار فاصله‌دار (SRS) کودکانه — Leitner ۵ جعبه‌ای

```
پاسخ درست:  box → box+1        فاصله مرور: [همان جلسه] → [۱ روز] → [۲] → [۴] → [۷ روز]
پاسخ غلط:   box → box 0        حرف دوباره در همان جلسه به چرخه برمی‌گردد
```

- هر جلسه با «مرور گرم‌کردنی» شروع می‌شود: حروفِ سرِرسید (dueAt ≤ now).
- حروف خطاخیز (confusables) با نرخ تزریق ۲۰٪ وارد دورها می‌شوند تا تبعیض تقویت شود.

### الگوریتم انتخاب حرفِ هر دور (Letter Selector)

```js
// وزن‌دهی: فوریت SRS + ضعف نسبی + توالی درسی + تنوع
score(letter) =
    w1 * urgency(dueAt)            // 0..1  — هرچه سرِرسیدتر، فوری‌تر
  + w2 * weakness(wrong/(ok+wrong)) // 0..1
  + w3 * curriculumGap(order)       // حروف ابتدای مسیر که هنوز شروع نشده‌اند
  + w4 * variety(recencyPenalty)    // جریمه‌ی تکرار حرفِ دور قبلی
// w = [0.35, 0.25, 0.25, 0.15] — قابل تنظیم در pack.config
// خروجی: وزن‌دار-تصادفی از بین ۶ حرف؛ ۲۰٪ احتمال تزریق confusableِ حرف ضعیف
```

## 3. قرارداد GameModule — هر بازی یک ماژول مستقل

```js
// js/games/letterPop.js
export default {
  id: 'letter-pop',
  titleKey: 'games.letterPop.title',       // کلید i18n؛ متن هرگز hard-code نمی‌شود
  skill: 'recognition',                    // recognition | recall | discrimination | production
  requiredLevel: 1,                        // حداقل تسلط لازم برای ورود به این بازی
  supportsPacks: '*',                      // یا ['fa'] اگر بازی به خاصیت زبان وابسته باشد

  init({ pack, letters, difficulty }) { /* آماده‌سازی دورها از روی داده */ },
  mount(container, ctx)  { /* DOM + GSAP intro + اتصال ورودی لمسی */ },
  evaluate(answer)       { /* → { ok, letterId } و emit روی EventBus */ },
  destroy()              { /* حذف listeners و timelineها */ }
};
```

**GameRegistry** بازی‌ها را با `id` ثبت می‌کند؛ صفحه‌ی نقشه‌ی ماجراجویی فقط بازی‌هایی را باز می‌کند که `requiredLevel` حروف فعال را داشته باشند.

## 4. فهرست ۸ بازی

| # | id | نام | مهارت / هدف آموزشی | مکانیک | منطق اصلی |
|---|---|---|---|---|---|
| 1 | `letter-pop` | 🎈 حباب حروف | تشخیص شکل (L1→L2) | صدای/تصویر هدف اعلام می‌شود؛ کودک حبابِ حرف درست را می‌ترکاند | گزینه‌ها از Selector؛ راهنمایی = حباب هدف با pulse نشان می‌شود |
| 2 | `memory-match` | 🃏 جفت گنج | ارتباط حرف↔تصویر/صدا (L2) | کارت‌های رو شده؛ جفت کردن حرف با کلمه‌ی نمونه‌اش | فلِش کارت‌ها با GSAP `flip`; جفت درست = جشن، جفت غلط = چرخش برگشت |
| 3 | `sound-hunt` | 🔊 شکار صدا | یادآوری صدا→حرف (L3) | صدا پخش می‌شود؛ انتخاب حرف درست از بین کارت‌ها | از AudioEngine (فایل → TTS); دکمه‌ی «دوباره بشنو» همیشه موجود |
| 4 | `trace-letter` | ✏️ خط خطی کردن | تولید/نوشتن (L4) | تتبع مسیر حرف روی canvas با انگشت؛ نقطه‌های راهنما | مسیر از `letter.stroke` (SVG path → نمونه‌گیری نقاط)؛ پوشش ≥70٪ = موفق |
| 5 | `catch-basket` | 🧺 سبد میوه | تشخیص با سرعت (L2) | حروف از بالا می‌ریزند؛ حرکت سبد برای گرفتنِ هدف | سرعت سقوط = AdaptiveDifficulty (میانگین زمان پاسخ اخیر) |
| 6 | `word-builder` | 🧱 بچین و بخوان | ترکیب/Blending (L4) | حروف کلمه‌ی نمونه مخلوط می‌شوند؛ چیدن ترتیب درست | `word.letters` — پشتیبانی RTL/LTR خودکار از `pack.dir` |
| 7 | `odd-one-out` | 🤔 کدام متفاوت است؟ | تبعیض (L3) | از میان ۴ حرف، آن‌که «مخالف صدا» را دارد پیدا کن | گزینه‌ها از `letter.confusables` — مستقیم روی حروف خطاخیز |
| 8 | `alphabet-safari` | 🦁 سافاری الفبا | آشنایی/بازی آزاد (L0) | نقشه‌ی آزاد؛ ضربه‌زدن به هر حرف → صدای حرف + کلمه + انیمیشن حیوان | بدون امتیاز؛ فقط exposure و کشف |

## 5. سختی تطبیقی (Adaptive Difficulty)

- **ورودی:** میانگین زمان پاسخ و نرخ موفقیتِ ۲۰ تلاش اخیر (پنجره‌ی لغزان).
- **خروجی:** تعداد گزینه‌ها (۲→۴→۶)، سرعت عناصر، و از بین رفتن راهنمایی.
- **قانون طلایی:** نرخ موفقیت هدف ۷۰–۸۵٪ — ناحیه‌ی «جریان». اگر > ۹۰٪ → سخت‌تر؛ اگر < ۶۰٪ → ساده‌تر + راهنمایی بیشتر (هرگز پیام منفی).

## 6. گیمیفیکیشن

| عنصر | طراحی |
|---|---|
| ⭐ ستاره | ۱–۳ ستاره در پایان هر بازی بر اساس دقت (نه سرعت) |
| 🏅 نشان (Badge) | تعریف‌شده در پک: «۵ حرف استادشدم»، «۷ روز پیوسته»، «پادشاه ب/پ» |
| 🦊 ماسکات | شخصیت راهنما (روباه!) — دستورالعمل‌ها را می‌گوید، جشن می‌گیرد، در خطا دلداری می‌دهد |
| 🗺️ نقشه ماجراجویی | مسیر بصری پیشرفت؛ هر حرف یک ایستگاه؛ ایستگاه قفل = پاداش کنجکاوی |
| 🎁 مراسم پاداش | پایان هر بازی: انفجار کاغذرنگی + ستاره‌ها یک‌به‌یک — GSAP `star-reveal` |

## 7. طراحی جلسه (Session) — ۸ تا ۱۲ دقیقه

```
[مرور گرم‌کننده]   ۲–۳ دقیقه   حروف سرِرسید SRS — بازی آشنا
[معرفی]           ۱–۲ دقیقه   حرف جدید با ماسکات (ببین + بشنو)
[تمرین]           ۳–۴ دقیقه   بازی هدفمندِ سطح فعلی حرف
[چالش]            ۲ دقیقه     Odd-One-Out / Word-Builder (اگر آماده بود)
[مراسم]           ۳۰ ثانیه    ستاره‌ها + نشان‌ها + «فردا باز بیا!» ماسکات
```

- پس از ۱۵ دقیقه، ماسکات با ملایمتر حالت «خستگی» پیشنهاد توقف می‌دهد (قابل تنظیم توسط والد).
- یک جلسه = دقیقاً یک session در `session_events` (برای گزارش والدین).

## 8. جریان رویدادهای موتور بازی (EventBus)

```
game:start ─► audio:intro · ui:showHUD
game:attempt {ok:false} ─► anim:gentle-shake · audio:retry-hint · srs:demote
game:attempt {ok:true}  ─► anim:success-pop · audio:praise · scoring:add · srs:promote
game:complete ─► anim:reward-ceremony · scoring:finalize · progress:persist · sync:enqueue
letter:mastered ─► ui:unlockStation · badges:check
```

هر شنونده مستقل تست می‌شود — تست واحد SRS و Scoring بدون مرورگر (Jest) ممکن است.
