تسليم المهام
تختار خدمة تسليم المهام (WP-DTE-BE، modules/delivery) عنصرًا مخزّنًا وجاهزًا للعرض من بنك الأسئلة وتقدّمه كما هو بدون أي تعديل. لا تؤلِّف المنصة محتوًى في وقت التشغيل ولا تعتمد على قوالب أو نماذج توليدية.
نموذج الاقتصار على بنك الأسئلة
يُؤلَّف كل سؤال ويُدقَّق خارج المنصة، ثم يُستورَد إلى بنك الأسئلة عبر قناة استيراد تُجري في وقت الاستيراد: فحوص المطابقة النحوية بالعربية (جنسًا وعددًا وإعرابًا)، والتحقق من البيانات الوصفية، ومراجعة سلامة اللغة، وحساب معامل الصعوبة (delta_prior). بحلول اللحظة التي يدخل فيها السؤال إلى البنك يكون جاهزًا للتقديم دون أي معالجة إضافية.
عند تشغيل خدمة التسليم تؤدي ثلاثة أشياء فقط: تصفية ثم تقديم ثم تسجيل. لا يُجمَّع محتوى، ولا يُستدعى نموذج لغوي، ولا تُملأ قوالب.
مرشحات الاختيار
يحدّد كل طلب تقديم سياقًا مستهدفًا. يطبّق المحرك المرشحات التالية مجتمعةً:
| المرشح | الوصف |
|---|---|
subSkillId | يجب أن يطابق المهارة الفرعية المستهدفة بالتدريب أو التقييم |
taskMode | practice أو quick_check أو progress_monitoring_probe؛ لكل منها قواعد تجربة مستخدم خاصة |
scaffoldTier | Level_1_Foundation أو Level_2_Targeted أو Level_3_Independence (progress_monitoring_probe تتجاهل مستوى السقالة) |
difficultyBand | شريحة الصعوبة المرتبطة بـ delta_prior |
dialect | MSA أو LEV؛ العناصر التي لا تحمل وسوم اللهجة تُعامَل باعتبارها متوافقة مع أي لهجة |
| العناصر المقدَّمة مؤخرًا | تُستثنى العناصر التي قُدِّمت للطالب نفسه ضمن نافذة الاستثناء الأخيرة |
حين يجتاز أكثر من سؤال جميع المرشحات يطبّق المحرك ترتيبًا حتميًا بالكامل: أقرب شريحة صعوبة أولًا، ثم delta_prior تصاعديًا، ثم itemBankId أبجديًا. يكون الاختيار متطابقًا بالبايت مع مدخلات متطابقة؛ وهذا يلبّي قاعدة الحتمية V-6.
تحديد مستوى السقالة
مستوى السقالة خاص بكل (طالب × مهارة × حزمة × نوع مهمة) ولا يمثّل سمة عامة على مستوى الطالب. بالنسبة لأوضاع المهام المعتمدة على السقالة (تدريب أو quick_check ضمن حزمة نشطة) تبحث خدمة التسليم عن سجل student_scaffold_assignment الخاص بالطالب. إن لم يوجد سجل يُعاد no_eligible_item؛ لا يُطبَّق مستوى سقالة عشوائي بديل.
أما المجسّات (quick_check التشخيصي خارج حزمة) فتختار بصرف النظر عن مستوى السقالة.
نتائج التقديم
كل استجابة تقديم هي HTTP 200. حين لا يُقدَّم أي سؤال يكون served قيمته null ويحمل reason أحد رموز النتيجة غير الناجحة. المُستدعي هو المسؤول عن اختيار تجربة المستخدم المناسبة لكل حالة.
| النتيجة | served | المعنى | ما يجب فعله |
|---|---|---|---|
ok | حمولة السؤال | تم اختيار سؤال واجتاز جميع الفحوص | عرض السؤال |
no_eligible_item | null | لم يجتز أي سؤال مزيج المرشحات | عرض تجربة مستخدم الفجوة؛ النتيجة تكتب سجلًا في قائمة انتظار الفجوات |
blocked_by_visibility_rule | null | تم اختيار سؤال لكنه فشل في غلاف رؤية الطالب عند التقديم | تعامَل معه كخطأ في قناة المحتوى؛ اعرض تجربة المستخدم نفسها كـ no_eligible_item |
failed | null | فشل داخلي غير متوقع | أعِد المحاولة مرة واحدة؛ إذا استمر الخطأ فصعِّده |
no_eligible_item
يكتب كل نتيجة no_eligible_item سجلًا في قائمة انتظار الفجوات. تُجمِّع نقطة نهاية ملخّص الفجوات للمدير هذه السجلات حسب (مهارة فرعية × مستوى سقالة × وضع) حتى تعرف فرق تأليف المحتوى خارج المنصة التوليفات التي تحتاج إلى أسئلة جديدة.
no_eligible_item ليس خطأ، بل إشارة فجوة. لا تعامله كـ 4xx أو 5xx. أرسله إلى قناة المحتوى حتى تُسدَّد الفجوة خارج المنصة.
blocked_by_visibility_rule
يُشغِّل غلاف الرؤية فحصًا نهائيًا على حمولة محتوى السؤال المختار مباشرةً قبل كتابة التقديم. إذا وجد الفحص تصنيفًا داخليًا يجب ألّا يصل إلى الطالب يُلغى التقديم ويُسجَّل كـ blocked_by_visibility_rule. صُمِّمت بوابة الاستيراد لمنع وصول مثل هذه الأسئلة إلى الحالة التشغيلية، لذا تُشير هذه النتيجة إلى فجوة في قناة المحتوى تستوجب التحقيق.
من منظور المُستدعي، يجب التعامل مع blocked_by_visibility_rule كما يُتعامَل مع no_eligible_item: served قيمته null، ويجب أن تعكس تجربة المستخدم غياب السؤال، ويظهر الحادث في ملخّص الفجوات حتى تتمكّن فريق المحتوى من التحقيق.
سجل نسخة المهمة المقدَّمة
يكتب كل تقديم ناجح سجل served_task_instance بمفتاح أساسي UUID. هذا UUID هو رمز الربط لأوراق العمل المطبوعة التي تحمل رمز QR (تدفق إنشاء الجلسة ومسح الأوراق). أرقام UUID غير قابلة للتعداد وفريدة عالميًا، وآمنة للتضمين في الورق المادي، خلافًا للأعداد الصحيحة ذات الزيادة التلقائية.
يثبّت سجل التدقيق ما يلي لضمان إعادة الإنتاج الدائمة:
- إصدار لقطة بنك الأسئلة وإصدار سياسة الاختيار
- مستوى السقالة وإصدار القواعد المستخدم
- نافذة استثناء العناصر المقدَّمة مؤخرًا
- سياق الطلب (مهارة فرعية، وضع، شريحة، لهجة)
إعادة التشغيل الجاف: التحقق من V-6
POST /api/admin/delivery/dry-run-replay يعيد تشغيل اختيار السؤال مقابل الإصدارات المثبّتة نفسها. لا يكتب شيئًا. يُبيّن الردّ ما إذا كان كل طلب مُعاد يُعيد العنصر المتطابق بالبايت. تعني نتيجة false تراجعًا في الحتمية.
مرجع API
| الأسلوب | المسار | الإذن | ملاحظات |
|---|---|---|---|
POST | /api/delivery/task | VIEW_OWN_CLASSES أو RUN_BACKOFFICE | تقديم سؤال واحد؛ served:null هو 200 |
GET | /api/delivery/log/{taskInstanceId} | RUN_BACKOFFICE | سجل تدقيق كامل لنسخة واحدة |
GET | /api/admin/delivery/gap-summary | RUN_BACKOFFICE | أعداد الفجوات حسب (مهارة فرعية × مستوى سقالة × وضع) |
POST | /api/admin/delivery/dry-run-replay | RUN_BACKOFFICE | تحقق حتمية V-6؛ قراءة فقط |
لا توجد نقطة نهاية تقديم مهام موجَّهة للطالب. تتطلب جميع مسارات التسليم إذن معلّم أو مسؤول. لا يُجري الطلاب مطلقًا طلبات مباشرة إلى هذه الخدمة (B.17).
ما لا تفعله خدمة التسليم
- لا تولّد محتوى ولا تؤلّفه في وقت التشغيل.
- لا تستدعي نموذجًا لغويًا في أي مرحلة.
- لا تلجأ إلى سؤال بديل حين لا يوجد تطابق للمستوى المطلوب.
- لا تتحقق من المطابقة النحوية العربية وقت التقديم؛ ذلك الفحص يجري عند الاستيراد.
- لا تعرض نقطة نهاية موجَّهة للطالب.
ذو صلة
- تصنيف المهارات: معرّفات المهارة الفرعية المستخدمة كمفاتيح اختيار
- ملفات الطلاب: مصدر مستوى السقالة
- حزم التدخل: سياق الحزمة الذي يحكم اختيار المستوى
- سلامة اللغة: فحص المطابقة العربية وبوابة السلامة وقت الاستيراد