دراسة هندسية: تحويل ملفات PDF الجامعية غير المهيكلة إلى منظومة PWA مع منتدى وإشعارات فورية
دراسة هندسية: تحويل ملفات PDF الجامعية غير المهيكلة إلى منظومة PWA متكاملة
في بيئة التعليم العالي، غالبًا ما تصطدم التجربة الرقمية للطلاب بالبنية التحتية القديمة. في الكلية العليا للمعلوماتية بجامعة نوفوسيبيرسك الحكومية (VKI NSU)، ظل المصدر الأساسي للجداول الدراسية يُنشر لسنوات بتنسيق ملفات PDF متعددة الصفحات يتم تنسيقها يدويًا وبدون هيكلية برمجية.
يقدم هذا المقال استعراضًا هندسيًا تفصيليًا لتطوير خدمة برمجية متكاملة: من التغلب على عقبات استخراج البيانات (Data Extraction) والهندسة العكسية (Reverse Engineering) إلى تصميم واجهة PWA سريعة الاستجابة، وخلفية برمجية عالية الأداء عبر FastAPI، ومجتمع طلابي متكامل.
1. سياق المشكلة والتحليل المعماري
من منظور هندسة المنتجات، عانى النموذج القديم لتوزيع البيانات من عيوب استخدام جسيمة:
- غياب واجهات برمجة التطبيقات (APIs): عدم توفر أي واجهة REST برمجية مفتوحة من قبل النظام الجامعي.
- احتكاك استخدام مرتفع (High Friction): اضطرار الطلاب يوميًا لتنزيل ملفات PDF وتكبير الشاشة يدويًا للبحث عن رمز مجموعتهم الدراسية بين مئات الخلايا.
- انعدام التفاعل الفوري: عند حدوث أي تعديل طارئ في الجدول (تغيير أستاذ أو نقل قاعة)، كان الطلاب يكتشفون ذلك بعد فوات الأوان.
كان الهدف واضحًا: بناء منصة متكاملة (Fullstack) ذاتية التشغيل وعالية الاعتمادية تحول المستندات الخام تلقائيًا إلى كائنات برمجية مهيكلة مع تسليمها فورًا لجميع الأجهزة.
2. هندسة البيانات: الهندسة العكسية ومسار تحليل PDF المخصص
يمثل استخراج الجداول من ملفات PDF تحديًا هندسيًا معقدًا نظرًا لأن معيار PDF لا يحتوي بطبيعته على مفاهيم “الصفوف” أو “الأعمدة”، بل يعتمد على إحداثيات رسم وتجميع خطوط ونصوص مجردة.
قصور الحلول مفتوحة المصدر السابقة
في المراحل الأولى، تم اختبار حلول مفتوحة المصدر جاهزة، بما في ذلك مشروع VkiHub للمطور DedMaxTech. إلا أن أول تحديث في تنسيق الجداول من قبل إدارة الكلية أدى إلى انهيار كامل لعمليات المعالجة:
- إزاحة الإحداثيات (Bounding Box Shift): أدت الإزاحات الطفيفة في الأعمدة إلى تداخل بيانات المجموعات المتجاورة.
- الخلايا المدمجة الديناميكية (Merged Cells): تسببت الخلايا المدمجة للمجموعات الفرعية والمحاضرات المشتركة في كسر مصفوفات القراءة المحددة مسبقًا.
- تنسيقات نصوص متباينة: اختصارات عشوائية لأسماء الأساتذة ورموز القاعات.
أثبتت التجربة أن الاعتماد على مكتبات خارجية دون تحكم كامل في المنطق الأساسي يؤدي إلى انهيار متسلسل (Cascade Failures) عند أي تعديل في الملفات المصدرية.
بناء محرك التحليل Core من الصفر
في الإصدار المعاد بناؤه من الخلفية البرمجية (services/parser.py)، تم استبدال جميع الاعتماديات الخارجية بمسار خوارزمي مخصص:
[ ملف PDF من الموقع ]
│
▼ (Camelot Lattice/Stream Extraction)
[ مصفوفة الجداول الخام ]
│
▼ (find_header_row & تعابير نمطية)
[ تحديد عناوين المجموعات ديناميكيًا ]
│
▼ (تحليل استدلالي واستخراج الكيانات)
[ كائنات JSON مهيكلة ونظيفة ]
│
▼ (بناء الفهارس المعكوسة)
[ فهارس: المجموعات / الأساتذة / القاعات ]
أبرز القرارات الهندسية في محرك التحليل:
- الكشف الديناميكي عن العناوين (
find_header_row): فحص الصفوف العليا للمصفوفة بتعابير نمطية صارمة (^[А-ЯA-Z]\d{4}[а-яa-z]{1,2}\d$) لتحديد الخط الفاصل بين بيانات الترويسة وبيانات الجدول تلقائيًا. - التفكيك الاستدلالي للخلايا (
parse_cell): تحليل متدرج للنصوص واستخراج دقيق للبيانات:- عزل اسم الأستاذ وتوحيد نمط الاختصارات:
extract_teacher. - استخراج رقم القاعة ومبنى الكلية:
extract_room. - تصنيف نوع الحصة (
isLecture،isPractice،isExam،isConsultation،isCanceled). - إزالة التكرارات اللفظية وتنقية النص (
remove_duplicate_words).
- عزل اسم الأستاذ وتوحيد نمط الاختصارات:
def parse_cell(self, text: str):
if not text or not text.strip():
return None
text = self.clean_text(text)
teacher = self.extract_teacher(text)
classroom = self.extract_room(text)
isLecture = 'лекци' in text.lower() or 'диста' in text.lower()
lesson_text = self.extract_subject(text)
lesson = self.normalize_lesson(self.remove_duplicate_words(lesson_text))
if not lesson:
return None
formatted_lesson = (lesson[0].upper() + lesson[1:]) if lesson.lower() == lesson else lesson
if classroom:
formatted_lesson = formatted_lesson.replace(classroom, '')
isIssusing = ((not teacher or not classroom) and (not isLecture or (isLecture and 'нет' in text.lower()))) or 'выставле' in text.lower()
return {
'line': self.remove_duplicate_words(text) if isIssusing else text,
'lesson': formatted_lesson,
'teacher': teacher,
'classroom': classroom,
'isLecture': isLecture,
'isPractice': 'практик' in text.lower(),
'isExam': 'экзам' in text.lower(),
'isIssusing': isIssusing,
'isConsultation': 'консул' in text.lower(),
'isCanceled': 'отмен' in text.lower()
}
- بناء الفهارس المعكوسة (Inverted Index): توليد فهارس ثانوية فورية في الذاكرة — جدول الأساتذة (
/schedule/teachers) وجدول القاعات (/schedule/classrooms)، مما أتاح الاستعلام عن القاعات الشاغرة في أي فترة زمنية بتعقيد زمني قدره O(1).
3. المعمارية وحزمة التقنيات المستخدمة
تم تصميم بنية النظام وفق مبدأ فصل الاهتمامات والتحسين الشديد لسرعة استجابة الواجهة (Time-to-Interactive).
| طبقة النظام | التقنيات والأدوات | الدور المعماري |
|---|---|---|
| Backend Core | Python 3.12, FastAPI, Tortoise ORM | معالجة غير متزامنة، مهام مجدولة للمزامنة، ضمان تكامل العمليات |
| Database | PostgreSQL | تخزين الحسابات، الجلسات، مواضيع المنتدى، واشتراكات الإشعارات |
| Frontend App | React 19, TypeScript, Vite | واجهة أحادية الصفحة (SPA)، توجيه وتخزين مؤقت على العميل |
| PWA & Offline | Service Workers, Web App Manifest | التخزين المؤقت في الخلفية، التثبيت كتطبيق أصيل، العمل دون إنترنت |
| Styling & UI | Modular SCSS, Custom Design System | نظام تصميم مخصص خفيف الوزن وتفادي حزم واجهات المستخدم الثقيلة |
| Push Gateway | Web Push Protocol, VAPID, pywebpush | إرسال الإشعارات الفورية على مستوى نظام التشغيل |
4. توسيع المنتج: إنشاء منتدى الطلاب
بدأ المشروع كأداة لعرض الجداول، ولكن أثناء العمل المشترك مع مصمم واجهة المستخدم، ظهرت فرصة لتحويل هذا التفاعل اليومي إلى مجتمع طلابي نشط.
تصميم نظام المحتوى المنشأ من قبل المستخدمين (UGC)
صُمم المنتدى لتقليل الاحتكاك وسهولة الاستخدام:
- الأمان وإدارة الجلسات: مصادقة آمنة، إدارة صلاحيات المستخدمين وأدوات الإشراف.
- هيكل المحتوى: تصنيفات مخصصة، وسوم للبحث، شجرة تعليقات متداخلة وتفاعلات فورية.
- تحسين تجربة الهواتف: نوافذ كتابة متجاوبة وتحديثات تفاؤلية (Optimistic UI) للتعليقات.
5. القدرات الأساسية للمنصة اليوم
أصبحت المنصة اليوم بيئة رقمية متكاملة لطلاب وأساتذة الكلية:
-
معرفة القاعات الشاغرة لحظيًا: بفضل الفهرسة المعكوسة للقاعات، يمكن للطلاب بنقرة واحدة إيجاد القاعات الخالية للدراسة الذاتية أو العمل الجماعي.
-
إشعارات فورية مدفوعة بالأحداث: عامل مجدول يفحص موقع الكلية دوريًا، وفور رصد تعديل في جدول أي مجموعة أو أستاذ، يُرسل إشعار Web Push للمشتركين فورًا.
-
معمارية PWA تعمل بلا اتصال: يعمل التطبيق بكفاءة داخل القاعات حتى عند ضعف شبكة الهاتف المحمول بفضل استراتيجيات Service Worker.
-
منتدى طلابي مدمج: مساحة لتبادل الملخصات الدراسية، تشكيل فرق المشاريع، ومناقشة الموضوعات الأكاديمية.
6. الخلاصات والدروس الهندسية
قدمت المنصة دروسًا قيّمة في التطوير والتشغيل:
- مرونة التعامل مع المصدر: تطبيق آليات التخزين الاحتياطي (Fallback Caching) للتعامل مع انقطاعات الموقع الرسمي.
- امتلاك المنطق البرمجي الأساسي: التخلص من الاعتماديات الهشة وبناء محرك تحليل مخصص خفّض معدل أخطاء المعالجة إلى ما يقارب الصفر.
الخاتمة
أثبت هذا المشروع أن الدقة الهندسية والتحكم الكامل في الشيفرة البرمجية والتركيز على حل مشكلات المستخدمين الحقيقية يمكن أن يحول ملف PDF بسيط إلى منتج طلابي عالي الاعتمادية خلال فصل صيف واحد.