#!/usr/bin/env python # -*- coding: utf-8 -*- """ وحدة المساعدة المركزية للنظام تحتوي على دوال مساعدة مشتركة تستخدم في جميع أنحاء التطبيق """ import os import sys import streamlit as st import pandas as pd import numpy as np import json import re import time import tempfile from datetime import datetime, timedelta import random import secrets import shutil import base64 import logging from pathlib import Path # تكوين التسجيلات logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger("wahbi-ai") def create_directory_if_not_exists(directory_path): """إنشاء مسار إذا لم يكن موجوداً""" try: if not os.path.exists(directory_path): os.makedirs(directory_path) logger.info(f"تم إنشاء المجلد: {directory_path}") return True except Exception as e: logger.error(f"خطأ في إنشاء المجلد {directory_path}: {e}") return False def get_data_folder(): """الحصول على مسار مجلد البيانات الرئيسي""" # مسار بيانات النظام الرئيسي data_folder = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "data") create_directory_if_not_exists(data_folder) return data_folder def load_config(): """تحميل إعدادات التكوين من ملف config.json""" config_path = os.path.join(get_data_folder(), "config.json") # إذا لم يكن ملف التكوين موجوداً، قم بإنشاء ملف افتراضي if not os.path.exists(config_path): default_config = { "system": { "version": "1.0.0", "release_date": "2025-03-30", "company_name": "شركة شبه الجزيرة للمقاولات", "company_logo": "", "language": "ar", "theme": "light", "debug_mode": False }, "ai_models": { "default_model": "claude-3-7-sonnet-20250219", "openai_model": "gpt-4o", "huggingface_model": "mistralai/Mistral-7B-Instruct-v0.2" }, "notifications": { "enable_email": False, "enable_browser": True, "check_interval": 60 } } with open(config_path, 'w', encoding='utf-8') as f: json.dump(default_config, f, ensure_ascii=False, indent=2) return default_config # تحميل ملف التكوين الموجود try: with open(config_path, 'r', encoding='utf-8') as f: return json.load(f) except Exception as e: logger.error(f"خطأ في تحميل ملف التكوين: {e}") return {} def save_config(config): """حفظ إعدادات التكوين إلى ملف config.json""" config_path = os.path.join(get_data_folder(), "config.json") try: with open(config_path, 'w', encoding='utf-8') as f: json.dump(config, f, ensure_ascii=False, indent=2) return True except Exception as e: logger.error(f"خطأ في حفظ ملف التكوين: {e}") return False def format_time(timestamp=None, format_str="%Y-%m-%d %H:%M:%S"): """تنسيق الوقت إلى صيغة معينة""" if timestamp is None: timestamp = datetime.now() elif isinstance(timestamp, (int, float)): timestamp = datetime.fromtimestamp(timestamp) return timestamp.strftime(format_str) def get_user_info(): """الحصول على معلومات المستخدم الحالي""" # في التطبيق الفعلي، يمكن استرداد معلومات المستخدم من قاعدة البيانات أو من حالة الجلسة if "user_info" in st.session_state: return st.session_state.user_info # معلومات افتراضية للتطوير return { "id": 1, "username": "admin", "full_name": "مدير النظام", "email": "admin@example.com", "role": "مدير", "department": "الإدارة", "last_login": format_time() } def get_current_project(): """الحصول على معلومات المشروع الحالي""" if "current_project" in st.session_state: return st.session_state.current_project # في حالة عدم وجود مشروع محدد return None def load_icons(): """تحميل الأيقونات المستخدمة في النظام""" icons_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "assets", "icons") icons = {} # التأكد من وجود مجلد الأيقونات if not os.path.exists(icons_path): create_directory_if_not_exists(icons_path) return icons # تحميل جميع الأيقونات for icon_file in os.listdir(icons_path): if icon_file.endswith(('.png', '.svg', '.jpg')): icon_name = os.path.splitext(icon_file)[0] icon_path = os.path.join(icons_path, icon_file) try: with open(icon_path, "rb") as f: icons[icon_name] = base64.b64encode(f.read()).decode() except Exception as e: logger.error(f"خطأ في تحميل الأيقونة {icon_name}: {e}") return icons def get_random_id(length=8): """إنشاء معرف عشوائي بطول محدد""" return secrets.token_hex(length // 2) def compress_text(text, max_length=10000): """اختصار النص إلى حد أقصى محدد مع الحفاظ على المعنى""" if not text or len(text) <= max_length: return text # تقسيم النص إلى جمل sentences = re.split(r'(?<=[.!?])\s+', text) # حساب متوسط طول الجملة avg_sentence_length = len(text) / len(sentences) # حساب عدد الجمل التي يمكن تضمينها num_sentences_to_keep = int(max_length / avg_sentence_length) # الاحتفاظ بالجمل الأولى والأخيرة للحفاظ على السياق keep_first = num_sentences_to_keep // 2 keep_last = num_sentences_to_keep - keep_first # دمج الجمل المختارة compressed_text = ' '.join(sentences[:keep_first] + sentences[-keep_last:]) # إضافة إشارة إلى أن النص تم اختصاره if len(compressed_text) < len(text): compressed_text += " [...المزيد من النص تم اختصاره...]" return compressed_text def str_to_bool(text): """تحويل النص إلى قيمة منطقية""" return text.lower() in ('yes', 'true', 'y', 't', '1', 'نعم', 'صحيح') def handle_arabic_text(text): """معالجة النص العربي للعرض بشكل صحيح""" if not text: return "" # إضافة علامة RTL لضمان عرض النص العربي بشكل صحيح return f"
{text}
" def render_credits(): """عرض معلومات النظام وحقوق الملكية""" st.markdown("---") config = load_config() system_info = config.get("system", {}) col1, col2, col3 = st.columns([1, 2, 1]) with col2: st.markdown( f"""

{system_info.get('company_name', 'شركة شبه الجزيرة للمقاولات')}

الإصدار: {system_info.get('version', '1.0.0')}

© جميع الحقوق محفوظة 2025

""", unsafe_allow_html=True ) # دالة للحصول على اتصال قاعدة البيانات def get_connection(): """ دالة للحصول على اتصال بقاعدة البيانات ملاحظة: ينبغي أن تكون مستبدلة بالدالة من db_connector.py في البيئة الإنتاجية """ try: # استيراد المستوى الفعلي للاتصال بقاعدة البيانات from database.db_connector import get_connection as get_db_connection return get_db_connection() except ImportError: # إذا كان الاتصال بقاعدة البيانات غير متاح logger.warning("لم يتم العثور على وحدة اتصال قاعدة البيانات. استخدام مخزن بيانات مؤقت.") # إرجاع None للإشارة إلى عدم وجود اتصال return None def load_css(file_name=None): """تحميل ملف CSS مخصص""" try: if file_name: css_file = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "assets", "css", file_name) if os.path.exists(css_file): with open(css_file, "r", encoding="utf-8") as f: css_content = f.read() else: logger.warning(f"ملف CSS غير موجود: {css_file}") return else: # CSS افتراضي css_content = """ .sidebar .sidebar-content { direction: rtl; text-align: right; } div[data-testid="stForm"] { border: 1px solid #ddd; padding: 10px; border-radius: 10px; } .module-title { color: #1E88E5; text-align: center; font-size: 1.8rem; margin-bottom: 1rem; } .instructions { background-color: #f8f9fa; border-right: 3px solid #4CAF50; padding: 10px; margin-bottom: 15px; } .results-container { background-color: #f5f5f5; padding: 15px; border-radius: 5px; margin-top: 20px; } .risk-high { color: #d32f2f; font-weight: bold; } .risk-medium { color: #f57c00; font-weight: bold; } .risk-low { color: #388e3c; font-weight: bold; } .form-container { background-color: #f9f9f9; padding: 20px; border-radius: 10px; margin-bottom: 20px; } .section-header { color: #2196F3; font-size: 1.2rem; font-weight: bold; margin-top: 20px; margin-bottom: 10px; border-bottom: 1px solid #eee; padding-bottom: 5px; } """ st.markdown(f"", unsafe_allow_html=True) except Exception as e: logger.error(f"خطأ في تحميل ملف CSS: {e}")