# فاز ۱۱ — داستان‌های کوتاه حرف‌محور: خواندن جمله بعد از تسلط حروف

**نسخه: 1.7.0** · تاریخ: 1404/07/03 (2026-09-25)
درخواست کاربر: «داستان‌های کوتاه حرف‌محور — بعد از تسلط روی حروف، خواندن جمله»

---

## ۱. مفهوم آموزشی

پله‌ی بعدی هرمسیر سوادآموزی: حرف ← واژه ← **جمله**. داستان‌ها فقط از حروفی ساخته شده‌اند که
کودک تا آن نقطه «دیده» و حروف کانونی‌اش را «مسلط» شده — یعنی متن، قابل‌خواندنِ واقعی است
(decodable text)، نه متن دلخواه.

## ۲. قاعده‌ی گشایش (قلب طراحی)

```
داستان.باز  ⟺  حروفِ کانونی mastery ≥ 2 (تشخیص مستقل)
           ∧  همه‌ی حروفِ استفاده‌شده در جمله‌ها order ≤ unlockedCount
```

- `focusLetters`: حروف موضوع داستان (مثل «م» برای «موز ماما») — باید **مسلط** باشند
- سایر حروف جمله‌ها: کافی است **باز** شده باشند (کودک دیده، سطح L1+)
- داستان‌ها بر اساس `maxOrderUsed` (بیشینه‌ی ترتیب حروف) از آسان به سخت مرتب می‌شوند
- کارت قفل: دقیقاً می‌گوید چه چیزی لازم است — «🔒 اول این حرف‌ها را یاد بگیر: ب ت»

## ۳. داده — `client/data/stories/{packId}.json` (جدید، SW-cacheable)

| پک | داستان‌ها | نمونه |
|---|---|---|
| fa | ۳ | «تابِ بابا» (ب/ت، حروف ≤۱۵) · «سیبِ شیر» (ش/س) · «موزِ ماما» (م) |
| en | ۲ | "Sam sees an apple" (S) · "The cat with a cap" (C) |
| nl | ۲ | "Muis eet kaas" (M) · "De vis zwemt" (V/Z) |
| ar | ۲ | «مَوز ماما» (م) · «السَمَك الصَغير» (س/ش) |
| tr | ۲ | "Kedi süt içer" (M) · "Elifin kalemi" (K) |

ساختار هر داستان: `id` (`{pack}_st_*`)، `title`، `emoji`، `focusLetters[]`،
`requiredMastery` (پیش‌فرض ۲)، `sentences[2..6]` ({text, emoji})، و `question`
اختیاری درک مطلب ({text, options[emoji], answer}).

**راستی‌آزمایی داده (`Stories.validate`)**: هر واژه‌ی هر جمله باید با حروف همان پک
تجزیه شود (پارسر فاز ۱۰ با `min:1` برای واژه‌های تک‌حرفی مثل «و») — تست‌شده برای هر ۵ پک.

## ۴. ماژول‌های جدید/تغییر‌یافته

| فایل | نقش |
|---|---|
| `client/js/core/stories.js` | **جدید**: load/validate/lettersUsed/maxOrderUsed/sorted/status — خالص و تست‌شده |
| `client/data/stories/*.json` | **جدید**: ۱۱ داستان در ۵ زبان |
| `client/js/ui/screens/storyScreen.js` | **جدید**: لیست + خواننده + سؤال + مراسم |
| `client/js/core/wordText.js` | `tokenizeSentence` (نقطه‌گذاری فارسی/عربی/لاتین دو سر واژه پاک می‌شود؛ خط تیره‌ی داخل واژه می‌ماند) + `parseWordText({min,max})` |
| `client/js/engine/masteryTracker.js` | `storyReads[]` + `recordStoryRead()` (یکتا) + مهاجرت بی‌دردسر داده‌ی قدیمی |
| `client/js/engine/scoring.js` | نوع نشان `stories_read` |
| هر ۵ پک JSON | نشان «📖 قصه‌خوان» (`{pack}_story_5` — آستانه ۵ داستان) |
| i18n ×۵ | ۱۱ کلید `stories.*` + برچسب نشان |
| `main.js`/`mapScreen.js`/CSS | مسیر `#/stories` + کارت «📖 داستان‌ها» در نقشه + استایل‌ها |

## ۵. تجربه‌ی خواندن (storyScreen)

1. **لیست**: کارت هر داستان با حروف کانونی (چیپ) + وضعیت (باز/قفل با دلیل/✓ خوانده‌شده)
2. **خواننده**: هر جمله یک‌جا، **هر واژه یک دکمه‌ی لمسی** (TTS تک‌واژه، آرام‌تر) +
   🔊 کل جمله (rate 0.75) + ایموجی جمله + ناوبری ◀▶ + نقاط پیشرفت + خوانش خودکار
3. **سؤال درک مطلب**: ۲–۴ گزینه‌ی تصویری؛ غلط = لرزش ملایم + «دوباره!»، درست = جشن
4. **پایان**: +۱ ستاره (فقط بار اول) · ثبت `storyReads` · بررسی نشان قصه‌خوان ·
   رویداد `story_complete` در صف سینک (گزارش سرور) · مراسم «همه‌ی داستان را خواندی!»

سختیِ تطبیقی از فاز ۱۰ دست‌نخورده — داستان خودش سکوی بعد از تسلط است.

## ۶. باگ‌های واقعی که تست‌های این فاز شکار و رفع شدند

1. **مودال تغییر رمز ادمین، کل جلسه را می‌کشت**: رمز فعلی غلط → 401 → `api()` لگات
   logout! حالا سرور `400 BAD_CURRENT_PASSWORD` می‌دهد و کلاینت فقط برای
   `401 UNAUTHORIZED` (توکن مرده) خروج می‌کند. — شکار‌شده توسط e2e-admin فاز ۱۰
2. **seed تست واژه‌سنجی (فاز ۱۰) شکل رکورد tracker را ناقص داشت** (`history:[]` و
   `box/streak` نبود) → `history.push` روی undefined — شکل کامل شد.
3. **ترتیب الفبایی select پک‌ها در پنل ادمین**: «ar» اول است و e2e بی‌انتخاب، واژه‌ی
   فارسی را در پک عربی می‌ساخت (حروف مشترک!) — تست حالا صریحاً پک را انتخاب می‌کند.

## ۷. تست‌ها — همه سبز

| مجموعه | نتیجه |
|---|---|
| واحد (۱۰ فایل) | **۱۶۶/۱۶۶** (`tests/story.test.js` جدید: ۱۴ تست) |
| E2E اپ | **20/20** (+۱: گشایش داستان → ۳ جمله → سؤال → ستاره → ✓ خوانده‌شده) |
| E2E پک‌ها | 6/6 |
| E2E ادمین | **11/11** (استپ‌های فاز ۱۰ که در فاز قبل نیمه‌کاره ماند، سبز کامل) |

تست‌های واحد داستان: اعتبارسنجی ۵ پک، قاعده‌ی گشایش در سه حالت، یکتایی storyReads،
مهاجرت داده‌ی قدیمی، نشان قصه‌خوان (اعطا + عدم‌تکرار)، ترتیب سختی، tokenizeSentence.

## ۸. نکته‌ی استقرار

سرور پیش‌نمایش با `ADMIN_AUTH_MAX=200` بالا آمده تا اجراهای مکرر E2E (لاگین‌های عمدی)
به سقف ضد brute-force نخورند؛ پیش‌فرض production (۱۰ در ۱۵ دقیقه) در کد محفوظ است و
`tests/admin.test.js` همچنان با سقف واقعی روی سرور ایزوله‌ی خودش تست می‌کند.

## ۹. معیارهای باز (فازهای بعد)
- داستان‌های بیشتر در هر پک (الان ۲–۳؛ ساختار داده آماده‌ی هر تعداد)
- نشان‌دادن تعداد داستان‌های خوانده‌شده در اتاق جوایز
- Lighthouse در CI و تست UX با کودکان واقعی (از سند ۱۴)
