Spaces:
Build error
Build error
| """ | |
| وظائف معالجة البيانات (تحليل الملفات التعريفية، إدارة التقدم، إلخ) | |
| """ | |
| import json | |
| from typing import Dict, List, Optional | |
| from datetime import datetime, timedelta | |
| import io | |
| def parse_profile_file(file_content: str, file_type: str = "json") -> Optional[Dict]: | |
| """ | |
| تحليل ملف تعريفي مرفوع | |
| Args: | |
| file_content: محتوى الملف | |
| file_type: نوع الملف (json, txt, markdown) | |
| Returns: | |
| القاموس المُحلل أو None | |
| """ | |
| try: | |
| if file_type == "json": | |
| return json.loads(file_content) | |
| elif file_type in ["txt", "markdown", "md"]: | |
| # تحليل بسيط من نص حر | |
| profile = { | |
| "name": extract_field(file_content, ["name", "الاسم", "اسم"]), | |
| "age": extract_field(file_content, ["age", "العمر", "عمر"]), | |
| "level": extract_field(file_content, ["level", "المستوى", "مستوى"]), | |
| "skills": extract_field(file_content, ["skills", "المهارات", "مهارات"]), | |
| "available_hours": extract_field(file_content, ["hours", "ساعات", "وقت متاح"]), | |
| "learning_style": extract_field(file_content, ["style", "أسلوب", "تفضيلات"]), | |
| "goals": extract_field(file_content, ["goals", "أهداف", "هدف"]), | |
| } | |
| return profile | |
| except Exception as e: | |
| print(f"خطأ في تحليل الملف: {str(e)}") | |
| return None | |
| def extract_field(text: str, keywords: List[str]) -> str: | |
| """استخراج حقل من نص حر بناءً على كلمات مفتاحية""" | |
| text_lower = text.lower() | |
| for keyword in keywords: | |
| if keyword.lower() in text_lower: | |
| # البحث عن السطر الذي يحتوي على الكلمة المفتاحية | |
| for line in text.split('\n'): | |
| if keyword.lower() in line.lower(): | |
| # استخراج القيمة بعد النقطتين أو المساواة | |
| if ':' in line: | |
| return line.split(':', 1)[1].strip() | |
| elif '=' in line: | |
| return line.split('=', 1)[1].strip() | |
| return "" | |
| def create_default_profile() -> Dict: | |
| """إنشاء ملف تعريفي افتراضي""" | |
| return { | |
| "name": "مستخدم جديد", | |
| "age": "", | |
| "level": "مبتدئ", | |
| "skills": [], | |
| "available_hours": 10, | |
| "learning_style": "مختلط (نظري وعملي)", | |
| "goals": "تعلم مهارات جديدة", | |
| "preferences": { | |
| "language": "ar", | |
| "notifications": True, | |
| "theme": "light" | |
| } | |
| } | |
| def validate_profile(profile: Dict) -> tuple[bool, List[str]]: | |
| """ | |
| التحقق من صحة الملف التعريفي | |
| Returns: | |
| (هل صالح, قائمة بالأخطاء) | |
| """ | |
| errors = [] | |
| required_fields = ["name", "level", "available_hours"] | |
| for field in required_fields: | |
| if field not in profile or not profile[field]: | |
| errors.append(f"الحقل '{field}' مطلوب") | |
| if profile.get("available_hours"): | |
| try: | |
| hours = int(profile["available_hours"]) | |
| if hours < 1 or hours > 40: | |
| errors.append("الوقت المتاح يجب أن يكون بين 1 و 40 ساعة أسبوعياً") | |
| except: | |
| errors.append("الوقت المتاح يجب أن يكون رقماً") | |
| return len(errors) == 0, errors | |
| def generate_schedule(curriculum: List[Dict], available_hours: int) -> List[Dict]: | |
| """ | |
| توليد جدول زمني بناءً على المنهج والوقت المتاح | |
| Args: | |
| curriculum: المنهج الدراسي | |
| available_hours: الساعات المتاحة أسبوعياً | |
| Returns: | |
| جدول زمني مفصل | |
| """ | |
| schedule = [] | |
| start_date = datetime.now() | |
| for week_num, unit in enumerate(curriculum, start=1): | |
| week_start = start_date + timedelta(weeks=week_num - 1) | |
| # توزيع الدروس على أيام الأسبوع | |
| lessons = unit.get("lessons", []) | |
| total_mins = sum(lesson.get("duration_mins", 60) for lesson in lessons) | |
| # إضافة وقت التجربة | |
| if unit.get("experiment"): | |
| total_mins += 120 # افتراض ساعتين للتجربة | |
| schedule_entry = { | |
| "week": week_num, | |
| "start_date": week_start.strftime("%Y-%m-%d"), | |
| "unit_title": unit.get("unit_title", f"الوحدة {week_num}"), | |
| "total_hours": round(total_mins / 60, 1), | |
| "daily_breakdown": distribute_to_days(lessons, available_hours), | |
| "experiment": unit.get("experiment"), | |
| "status": "pending" | |
| } | |
| schedule.append(schedule_entry) | |
| return schedule | |
| def distribute_to_days(lessons: List[Dict], hours_per_week: int) -> List[Dict]: | |
| """توزيع الدروس على أيام الأسبوع""" | |
| days = ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس"] | |
| distribution = [] | |
| mins_per_day = (hours_per_week * 60) // len(days) | |
| current_day = 0 | |
| current_day_mins = 0 | |
| current_day_lessons = [] | |
| for lesson in lessons: | |
| lesson_mins = lesson.get("duration_mins", 60) | |
| if current_day_mins + lesson_mins > mins_per_day and current_day_lessons: | |
| # حفظ اليوم الحالي والانتقال للتالي | |
| distribution.append({ | |
| "day": days[current_day % len(days)], | |
| "lessons": current_day_lessons.copy(), | |
| "total_mins": current_day_mins | |
| }) | |
| current_day += 1 | |
| current_day_mins = 0 | |
| current_day_lessons = [] | |
| current_day_lessons.append(lesson) | |
| current_day_mins += lesson_mins | |
| # إضافة آخر يوم | |
| if current_day_lessons: | |
| distribution.append({ | |
| "day": days[current_day % len(days)], | |
| "lessons": current_day_lessons, | |
| "total_mins": current_day_mins | |
| }) | |
| return distribution | |
| def calculate_progress(completed_units: List[int], total_units: int) -> Dict: | |
| """ | |
| حساب التقدم الإجمالي | |
| Returns: | |
| معلومات التقدم | |
| """ | |
| completed = len(completed_units) | |
| percentage = (completed / total_units * 100) if total_units > 0 else 0 | |
| return { | |
| "completed_units": completed, | |
| "total_units": total_units, | |
| "percentage": round(percentage, 1), | |
| "remaining_units": total_units - completed, | |
| "status": get_progress_status(percentage) | |
| } | |
| def get_progress_status(percentage: float) -> str: | |
| """تحديد حالة التقدم""" | |
| if percentage < 25: | |
| return "بداية الرحلة 🌱" | |
| elif percentage < 50: | |
| return "في الطريق 🚀" | |
| elif percentage < 75: | |
| return "تقدم ممتاز 🌟" | |
| elif percentage < 100: | |
| return "قرب الإنجاز 🎯" | |
| else: | |
| return "مكتمل! 🎉" | |
| def export_profile_to_json(profile: Dict) -> str: | |
| """تصدير الملف التعريفي إلى JSON""" | |
| return json.dumps(profile, ensure_ascii=False, indent=2) | |
| def export_progress_to_json(progress_data: Dict) -> str: | |
| """تصدير بيانات التقدم إلى JSON""" | |
| return json.dumps(progress_data, ensure_ascii=False, indent=2) | |
| def load_local_data(filename: str) -> Optional[Dict]: | |
| """تحميل بيانات من ملف JSON محلي""" | |
| try: | |
| with open(f"data/{filename}", "r", encoding="utf-8") as f: | |
| return json.load(f) | |
| except: | |
| return None | |
| def save_local_data(filename: str, data: Dict) -> bool: | |
| """حفظ بيانات في ملف JSON محلي""" | |
| try: | |
| with open(f"data/{filename}", "w", encoding="utf-8") as f: | |
| json.dump(data, f, ensure_ascii=False, indent=2) | |
| return True | |
| except: | |
| return False | |
| def get_completion_stats(completed_lessons: List[str], curriculum: List[Dict]) -> Dict: | |
| """حساب إحصائيات الإنجاز المفصلة""" | |
| total_lessons = sum(len(unit.get("lessons", [])) for unit in curriculum) | |
| completed = len(completed_lessons) | |
| total_experiments = len([u for u in curriculum if u.get("experiment")]) | |
| completed_experiments = 0 # يمكن تتبعها بشكل منفصل | |
| return { | |
| "lessons": { | |
| "completed": completed, | |
| "total": total_lessons, | |
| "percentage": round(completed / total_lessons * 100, 1) if total_lessons > 0 else 0 | |
| }, | |
| "experiments": { | |
| "completed": completed_experiments, | |
| "total": total_experiments, | |
| "percentage": round(completed_experiments / total_experiments * 100, 1) if total_experiments > 0 else 0 | |
| }, | |
| "overall_percentage": round((completed + completed_experiments) / (total_lessons + total_experiments) * 100, 1) | |
| } | |