Update Saqel Platform: 2026-09-12 16:23:39
This commit is contained in:
@@ -586,7 +586,7 @@ const LabIdentity kFinanceBudgetToolIdentity = LabIdentity(
|
||||
|
||||
const LabIdentity kHistoryJordanChronologyToolIdentity = LabIdentity(
|
||||
toolKey: 'history_jordan_chronology',
|
||||
subjectAr: 'تاريخ الأردن',
|
||||
subjectAr: 'التاريخ',
|
||||
lessonAr: 'التسلسل الزمني التفاعلي',
|
||||
);
|
||||
|
||||
|
||||
@@ -339,8 +339,12 @@ class Grade10LabsRegistry {
|
||||
if (s.contains('وطنية') || s.contains('مدنية') || s.contains('civics')) {
|
||||
return 'التربية الوطنية والمدنية';
|
||||
}
|
||||
if (s.contains('أردن') || s.contains('اردن')) return 'تاريخ الأردن';
|
||||
if (s.contains('تاريخ') || s.contains('history')) return 'التاريخ';
|
||||
if (s.contains('تاريخ') ||
|
||||
s.contains('أردن') ||
|
||||
s.contains('اردن') ||
|
||||
s.contains('history')) {
|
||||
return 'التاريخ';
|
||||
}
|
||||
if (s.contains('رقمية') || s.contains('حاسوب') || s.contains('digital')) {
|
||||
return 'المهارات الرقمية';
|
||||
}
|
||||
@@ -353,7 +357,11 @@ class Grade10LabsRegistry {
|
||||
final direct = bySubject(norm);
|
||||
if (direct.isNotEmpty) return direct;
|
||||
return all
|
||||
.where((e) => e.subjectAr.contains(norm) || norm.contains(e.subjectAr))
|
||||
.where((e) =>
|
||||
e.subjectAr == norm ||
|
||||
(norm == 'التاريخ' && (e.subjectAr == 'التاريخ' || e.subjectAr == 'تاريخ الأردن')) ||
|
||||
e.subjectAr.contains(norm) ||
|
||||
norm.contains(e.subjectAr))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -361,9 +369,14 @@ class Grade10LabsRegistry {
|
||||
/// Defaults to true in development so that the reviewer/teacher can immediately test the labs.
|
||||
static bool previewModeEnabled = true;
|
||||
|
||||
/// Exact identity lookup.
|
||||
/// Exact identity lookup strictly isolated per subject.
|
||||
/// When [previewModeEnabled] is active or [allowPreview] is true, returns the lab for testing.
|
||||
/// When false (strict production gate), returns ONLY when released & carrying a published bundle.
|
||||
///
|
||||
/// CRITICAL INTEGRITY RULE:
|
||||
/// Never leak labs across subjects. A Physics lab must NEVER appear under History, Geography,
|
||||
/// Digital Skills, Civics, or any other subject. If a subject has no matching candidate lab,
|
||||
/// this method returns null immediately.
|
||||
static Grade10LabEntry? findForLesson({
|
||||
required String subjectTitle,
|
||||
required String lessonTitle,
|
||||
@@ -372,42 +385,55 @@ class Grade10LabsRegistry {
|
||||
bool? allowPreview,
|
||||
}) {
|
||||
final usePreview = allowPreview ?? previewModeEnabled;
|
||||
final candidates = bySubjectNormalized(subjectTitle);
|
||||
|
||||
// Subject Isolation Gate: If no candidate labs exist for this subject, return null immediately.
|
||||
if (candidates.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (usePreview) {
|
||||
// 1. Exact match on curriculumLessonId within candidate subject labs
|
||||
if (curriculumLessonId != null && curriculumLessonId.isNotEmpty) {
|
||||
final exact = entryForCurriculumLessonId(curriculumLessonId);
|
||||
if (exact != null) return exact;
|
||||
}
|
||||
if (lessonId != null && lessonId.isNotEmpty) {
|
||||
for (final e in all) {
|
||||
if (e.identity.curriculumLessonId.contains(lessonId) ||
|
||||
e.identity.toolKey == lessonId ||
|
||||
e.identity.sourceMarkdown.contains(lessonId)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
final candidates = bySubjectNormalized(subjectTitle);
|
||||
if (candidates.isNotEmpty) {
|
||||
final t = lessonTitle.toLowerCase();
|
||||
for (final c in candidates) {
|
||||
if (t.contains(c.lessonAr.toLowerCase()) ||
|
||||
c.lessonAr.toLowerCase().contains(t)) {
|
||||
if (c.identity.curriculumLessonId == curriculumLessonId) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
if (lessonId != null && lessonId.isNotEmpty) {
|
||||
for (final c in candidates) {
|
||||
if (c.identity.lessonKey == lessonId ||
|
||||
c.identity.curriculumLessonId.endsWith(lessonId)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Lesson Title fuzzy matching strictly within candidate subject labs
|
||||
final t = lessonTitle.toLowerCase().trim();
|
||||
for (final c in candidates) {
|
||||
final ct = c.lessonAr.toLowerCase().trim();
|
||||
if (t == ct || (ct.length > 4 && (t.contains(ct) || ct.contains(t)))) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Lesson Key / Tool Key match strictly within candidate subject labs
|
||||
if (lessonId != null && lessonId.isNotEmpty) {
|
||||
for (final c in candidates) {
|
||||
if (c.identity.lessonKey == lessonId ||
|
||||
c.identity.toolKey == lessonId ||
|
||||
c.identity.curriculumLessonId.endsWith(lessonId) ||
|
||||
c.identity.sourceMarkdown.contains(lessonId)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return publishedEntryForCurriculumLessonId(curriculumLessonId ?? '');
|
||||
if (curriculumLessonId != null && curriculumLessonId.isNotEmpty) {
|
||||
for (final c in candidates) {
|
||||
if (c.identity.curriculumLessonId == curriculumLessonId && c.identity.isPublished) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Grade10LabEntry? entryForCurriculumLessonId(
|
||||
|
||||
Reference in New Issue
Block a user