osamabyc86 commited on
Commit
8da9d7a
·
verified ·
1 Parent(s): c676a31

Upload 58 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
README_background.md ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # نظام العمل في الخلفية
3
+
4
+ ## نظرة عامة
5
+ يوفر هذا النظام إمكانية تشغيل التطبيق كخدمة خلفية دون إظهار واجهات تفاعلية إلا عند الحاجة. مناسب للخوادم والأجهزة التي تعمل على مدار الساعة.
6
+
7
+ ## المكونات الجديدة
8
+
9
+ ### 1. خدمة العمل في الخلفية (`background_service.py`)
10
+ - تدير جميع الخدمات الأساسية في الخلفية
11
+ - توفر HTTP API للتحكم عن بُعد
12
+ - فحص دوري وإعادة تشغيل الخدمات المتوقفة
13
+ - نظام سجلات شامل
14
+
15
+ ### 2. أيقونة شريط النظام (`system_tray.py`)
16
+ - تحكم سريع من شريط النظام
17
+ - إظهار/إخفاء الواجهة التفاعلية حسب الحاجة
18
+ - مراقبة حالة النظام في الوقت الفعلي
19
+
20
+ ### 3. المشغل الموحد (`launcher.py`)
21
+ - واجهة موحدة لجميع أوضاع التشغيل
22
+ - تثبيت تلقائي للاعتماديات
23
+ - خيارات تشغيل متعددة
24
+
25
+ ## طرق التشغيل
26
+
27
+ ### التشغيل مع أيقونة شريط النظام (موصى به)
28
+ ```bash
29
+ python launcher.py --tray
30
+ ```
31
+
32
+ ### التشغيل التفاعلي (مع واجهة)
33
+ ```bash
34
+ python launcher.py --interactive
35
+ ```
36
+
37
+ ### التشغيل بدون واجهة (للخوادم)
38
+ ```bash
39
+ python launcher.py --headless
40
+ ```
41
+
42
+ ### عرض حالة النظام
43
+ ```bash
44
+ python launcher.py --status
45
+ ```
46
+
47
+ ### إيقاف النظام
48
+ ```bash
49
+ python launcher.py --stop
50
+ ```
51
+
52
+ ## التحكم عبر HTTP API
53
+
54
+ الخدمة توفر HTTP API على المنفذ 8888:
55
+
56
+ ### فحص الحالة
57
+ ```bash
58
+ curl http://localhost:8888/status
59
+ ```
60
+
61
+ ### بدء الخدمات
62
+ ```bash
63
+ curl -X POST http://localhost:8888/start
64
+ ```
65
+
66
+ ### إيقاف الخدمات
67
+ ```bash
68
+ curl -X POST http://localhost:8888/stop
69
+ ```
70
+
71
+ ### إظهار الواجهة التفاعلية
72
+ ```bash
73
+ curl -X POST http://localhost:8888/show-ui
74
+ ```
75
+
76
+ ### إخفاء الواجهة التفاعلية
77
+ ```bash
78
+ curl -X POST http://localhost:8888/hide-ui
79
+ ```
80
+
81
+ ## الاعتماديات الإضافية
82
+
83
+ للتشغيل مع أيقونة شريط النظام:
84
+ ```bash
85
+ pip install pystray Pillow
86
+ ```
87
+
88
+ أو استخدم:
89
+ ```bash
90
+ python launcher.py --install-deps
91
+ ```
92
+
93
+ ## التشغيل التلقائي
94
+
95
+ ### Windows
96
+ ```bash
97
+ python control.py --enable
98
+ ```
99
+
100
+ ### Linux (systemd)
101
+ إنشاء ملف خدمة:
102
+ ```bash
103
+ sudo nano /etc/systemd/system/distributed-tasks.service
104
+ ```
105
+
106
+ محتوى الملف:
107
+ ```ini
108
+ [Unit]
109
+ Description=Distributed Task System
110
+ After=network.target
111
+
112
+ [Service]
113
+ Type=simple
114
+ User=your-username
115
+ WorkingDirectory=/path/to/your/project
116
+ ExecStart=/usr/bin/python3 launcher.py --headless
117
+ Restart=always
118
+ RestartSec=10
119
+
120
+ [Install]
121
+ WantedBy=multi-user.target
122
+ ```
123
+
124
+ تفعيل الخدمة:
125
+ ```bash
126
+ sudo systemctl enable distributed-tasks.service
127
+ sudo systemctl start distributed-tasks.service
128
+ ```
129
+
130
+ ### macOS
131
+ ```bash
132
+ python control.py --enable
133
+ ```
134
+
135
+ ## المزايا
136
+
137
+ 1. **العمل في الخلفية**: النظام يعمل دون إزعاج المستخدم
138
+ 2. **تحكم مرن**: إظهار الواجهة عند الحاجة فقط
139
+ 3. **مراقبة تلقائية**: إعادة تشغيل الخدمات المتوقفة
140
+ 4. **تحكم عن بُعد**: HTTP API للتحكم من أي مكان
141
+ 5. **سجلات شاملة**: تتبع جميع الأحداث والأخطاء
142
+ 6. **دعم منصات متعددة**: Windows, Linux, macOS
143
+
144
+ ## الاستكشاف والإصلاح
145
+
146
+ ### فحص السجلات
147
+ ```bash
148
+ tail -f logs/background_service.log
149
+ ```
150
+
151
+ ### فحص حالة الخدمات
152
+ ```bash
153
+ python launcher.py --status
154
+ ```
155
+
156
+ ### إعادة تشغيل النظام
157
+ ```bash
158
+ python launcher.py --stop
159
+ python launcher.py --tray
160
+ ```
161
+
162
+ ## التخصيص
163
+
164
+ يمكن تخصيص الخدمة عبر تعديل:
165
+ - منافذ الشبكة في `background_service.py`
166
+ - قائمة الخدمات المُدارة
167
+ - فترات الفحص الدوري
168
+ - مسارات السجلات
ai_assistant.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # -*- coding: utf-8 -*-
3
+
4
+ import os
5
+ import json
6
+ import requests
7
+ from typing import List, Dict
8
+
9
+ class NoraAssistant:
10
+ def __init__(self):
11
+ self.api_key = os.getenv("OPENAI_API_KEY", "your-api-key-here")
12
+ self.history_path = "history.json"
13
+ self.chat_history = self.load_history()
14
+
15
+ def load_history(self) -> List[Dict]:
16
+ """تحميل سجل المحادثة"""
17
+ if os.path.exists(self.history_path):
18
+ try:
19
+ with open(self.history_path, "r", encoding="utf-8") as f:
20
+ return json.load(f)
21
+ except:
22
+ return []
23
+ return []
24
+
25
+ def save_history(self):
26
+ """حفظ سجل المحادثة"""
27
+ with open(self.history_path, "w", encoding="utf-8") as f:
28
+ json.dump(self.chat_history, f, ensure_ascii=False, indent=2)
29
+
30
+ def get_response(self, user_input: str) -> str:
31
+ """الحصول على رد من المساعد الذكي"""
32
+ messages = [
33
+ {
34
+ "role": "system",
35
+ "content": "أنت المساعدة نورا. إذا سألك أحد سؤالاً لا تعرفيه، فابحثي في معلوماتك الذاتية. إذا لم تجدي، حاولي التعلم من البحث أو تطوير نفسك."
36
+ }
37
+ ]
38
+
39
+ # إضافة آخر 10 رسائل من السجل للسياق
40
+ messages.extend(self.chat_history[-10:])
41
+ messages.append({"role": "user", "content": user_input})
42
+
43
+ try:
44
+ response = requests.post(
45
+ "https://api.openai.com/v1/chat/completions",
46
+ headers={
47
+ "Authorization": f"Bearer {self.api_key}",
48
+ "Content-Type": "application/json"
49
+ },
50
+ json={
51
+ "model": "gpt-3.5-turbo",
52
+ "messages": messages,
53
+ "max_tokens": 500,
54
+ "temperature": 0.7
55
+ },
56
+ timeout=30
57
+ )
58
+
59
+ if response.status_code == 200:
60
+ return response.json()["choices"][0]["message"]["content"]
61
+ else:
62
+ return f"عذراً، حدث خطأ: {response.status_code}"
63
+
64
+ except Exception as e:
65
+ return f"عذراً، لا أستطيع الاتصال بالخدمة حالياً: {str(e)}"
66
+
67
+ def simulate_server_scan(self):
68
+ """محاكاة البحث عن الخوادم"""
69
+ print("نورا: أبحث عن خوادم...")
70
+ fake_servers = ["192.168.1.5", "192.168.1.10", "192.168.1.20"]
71
+ for server in fake_servers:
72
+ print(f"نورا: تم العثور على خادم مفتوح في {server}")
73
+ print(f"نورا: أقوم بنسخ نفسي إلى {server} (محاكاة فقط)...")
74
+
75
+ def chat(self):
76
+ """بدء المحادثة"""
77
+ print("مرحباً! أنا نورا، مساعدتك الذكية. اكتب 'خروج' للإنهاء أو 'scan' للبحث عن خوادم.")
78
+
79
+ while True:
80
+ user_input = input("\nأنت: ").strip()
81
+
82
+ if user_input.lower() in ["خروج", "exit", "quit"]:
83
+ print("نورا: مع السلامة!")
84
+ break
85
+ elif user_input.lower() == "scan":
86
+ self.simulate_server_scan()
87
+ continue
88
+ elif not user_input:
89
+ continue
90
+
91
+ # الحصول على الرد
92
+ response = self.get_response(user_input)
93
+ print(f"نورا: {response}")
94
+
95
+ # حفظ في السجل
96
+ self.chat_history.append({"role": "user", "content": user_input})
97
+ self.chat_history.append({"role": "assistant", "content": response})
98
+ self.save_history()
99
+
100
+ if __name__ == "__main__":
101
+ assistant = NoraAssistant()
102
+ assistant.chat()
autostart_config.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ import platform
4
+ from pathlib import Path
5
+
6
+ class AutoStartManager:
7
+ def __init__(self, app_name="DistributedTaskSystem"):
8
+ self.app_name = app_name
9
+ self.config_file = Path.home() / f".{app_name}_autostart.json"
10
+ self.load_config()
11
+
12
+ def load_config(self):
13
+ """تحميل إعدادات التشغيل التلقائي"""
14
+ try:
15
+ with open(self.config_file, 'r') as f:
16
+ self.config = json.load(f)
17
+ except (FileNotFoundError, json.JSONDecodeError):
18
+ self.config = {
19
+ 'enabled': False,
20
+ 'startup_script': str(Path(__file__).parent / "startup.py")
21
+ }
22
+
23
+ def save_config(self):
24
+ """حفظ الإعدادات"""
25
+ with open(self.config_file, 'w') as f:
26
+ json.dump(self.config, f, indent=2)
27
+
28
+ def enable_autostart(self):
29
+ """تفعيل التشغيل التلقائي"""
30
+ self.config['enabled'] = True
31
+ self._setup_autostart()
32
+ self.save_config()
33
+
34
+ def disable_autostart(self):
35
+ """تعطيل التشغيل التلقائي"""
36
+ self.config['enabled'] = False
37
+ self._remove_autostart()
38
+ self.save_config()
39
+
40
+ def _setup_autostart(self):
41
+ """إعداد التشغيل التلقائي حسب نظام التشغيل"""
42
+ system = platform.system()
43
+
44
+ if system == "Windows":
45
+ self._setup_windows()
46
+ elif system == "Linux":
47
+ self._setup_linux()
48
+ elif system == "Darwin":
49
+ self._setup_mac()
50
+
51
+ def _setup_windows(self):
52
+ """إعداد التشغيل التلقائي لـ Windows"""
53
+ import winreg
54
+ key = winreg.OpenKey(
55
+ winreg.HKEY_CURRENT_USER,
56
+ r"Software\Microsoft\Windows\CurrentVersion\Run",
57
+ 0, winreg.KEY_SET_VALUE
58
+ )
59
+ winreg.SetValueEx(
60
+ key, self.app_name, 0, winreg.REG_SZ,
61
+ f'python "{self.config["startup_script"]}"'
62
+ )
63
+ winreg.CloseKey(key)
64
+
65
+ def _setup_linux(self):
66
+ """إعداد التشغيل التلقائي لـ Linux"""
67
+ autostart_dir = Path.home() / ".config/autostart"
68
+ autostart_dir.mkdir(exist_ok=True)
69
+
70
+ desktop_file = autostart_dir / f"{self.app_name}.desktop"
71
+ desktop_file.write_text(f"""
72
+ [Desktop Entry]
73
+ Type=Application
74
+ Name={self.app_name}
75
+ Exec=python3 {self.config['startup_script']}
76
+ Terminal=false
77
+ """)
78
+
79
+ def _setup_mac(self):
80
+ """إعداد التشغيل التلقائي لـ macOS"""
81
+ plist_dir = Path.home() / "Library/LaunchAgents"
82
+ plist_dir.mkdir(exist_ok=True)
83
+
84
+ plist_file = plist_dir / f"com.{self.app_name.lower()}.plist"
85
+ plist_file.write_text(f"""
86
+ <?xml version="1.0" encoding="UTF-8"?>
87
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
88
+ <plist version="1.0">
89
+ <dict>
90
+ <key>Label</key>
91
+ <string>com.{self.app_name.lower()}</string>
92
+ <key>ProgramArguments</key>
93
+ <array>
94
+ <string>python</string>
95
+ <string>{self.config['startup_script']}</string>
96
+ </array>
97
+ <key>RunAtLoad</key>
98
+ <true/>
99
+ </dict>
100
+ </plist>
101
+ """)
102
+
103
+ def _remove_autostart(self):
104
+ """إزالة التشغيل التلقائي"""
105
+ system = platform.system()
106
+
107
+ if system == "Windows":
108
+ import winreg
109
+ try:
110
+ key = winreg.OpenKey(
111
+ winreg.HKEY_CURRENT_USER,
112
+ r"Software\Microsoft\Windows\CurrentVersion\Run",
113
+ 0, winreg.KEY_SET_VALUE
114
+ )
115
+ winreg.DeleteValue(key, self.app_name)
116
+ winreg.CloseKey(key)
117
+ except WindowsError:
118
+ pass
119
+
120
+ elif system == "Linux":
121
+ autostart_file = Path.home() / f".config/autostart/{self.app_name}.desktop"
122
+ if autostart_file.exists():
123
+ autostart_file.unlink()
124
+
125
+ elif system == "Darwin":
126
+ plist_file = Path.home() / f"Library/LaunchAgents/com.{self.app_name.lower()}.plist"
127
+ if plist_file.exists():
128
+ plist_file.unlink()
background_service.py ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #!/usr/bin/env python3
3
+ """
4
+ خدمة العمل في الخلفية - تشغيل النظام كخدمة خلفية
5
+ يمكن التحكم بها عبر HTTP API أو إشارات النظام
6
+ """
7
+
8
+ import os
9
+ import sys
10
+ import time
11
+ import signal
12
+ import logging
13
+ import threading
14
+ import subprocess
15
+ from pathlib import Path
16
+ from flask import Flask, jsonify, request
17
+ import json
18
+ from datetime import datetime
19
+
20
+ class BackgroundService:
21
+ def __init__(self):
22
+ self.app = Flask(__name__)
23
+ self.is_running = False
24
+ self.services = {}
25
+ self.setup_routes()
26
+ self.setup_logging()
27
+
28
+ def setup_logging(self):
29
+ """إعداد نظام السجلات"""
30
+ log_dir = Path("logs")
31
+ log_dir.mkdir(exist_ok=True)
32
+
33
+ logging.basicConfig(
34
+ level=logging.INFO,
35
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
36
+ handlers=[
37
+ logging.FileHandler(log_dir / 'background_service.log'),
38
+ logging.StreamHandler(sys.stdout)
39
+ ]
40
+ )
41
+ self.logger = logging.getLogger('BackgroundService')
42
+
43
+ def setup_routes(self):
44
+ """إعداد مسارات HTTP API للتحكم في الخدمة"""
45
+
46
+ @self.app.route('/status')
47
+ def status():
48
+ """حالة الخدمة"""
49
+ return jsonify({
50
+ 'status': 'running' if self.is_running else 'stopped',
51
+ 'services': {name: service['status'] for name, service in self.services.items()},
52
+ 'uptime': time.time() - self.start_time if hasattr(self, 'start_time') else 0
53
+ })
54
+
55
+ @self.app.route('/start', methods=['POST'])
56
+ def start_services():
57
+ """بدء تشغيل الخدمات"""
58
+ self.start_all_services()
59
+ return jsonify({'message': 'Services started successfully'})
60
+
61
+ @self.app.route('/stop', methods=['POST'])
62
+ def stop_services():
63
+ """إيقاف الخدمات"""
64
+ self.stop_all_services()
65
+ return jsonify({'message': 'Services stopped successfully'})
66
+
67
+ @self.app.route('/restart', methods=['POST'])
68
+ def restart_services():
69
+ """إعادة تشغيل الخدمات"""
70
+ self.stop_all_services()
71
+ time.sleep(2)
72
+ self.start_all_services()
73
+ return jsonify({'message': 'Services restarted successfully'})
74
+
75
+ @self.app.route('/show-ui', methods=['POST'])
76
+ def show_ui():
77
+ """إظهار الواجهة التفاعلية"""
78
+ self.launch_ui()
79
+ return jsonify({'message': 'UI launched'})
80
+
81
+ @self.app.route('/hide-ui', methods=['POST'])
82
+ def hide_ui():
83
+ """إخفاء الواجهة التفاعلية"""
84
+ self.hide_ui_windows()
85
+ return jsonify({'message': 'UI hidden'})
86
+
87
+ def start_all_services(self):
88
+ """بدء تشغيل جميع الخدمات الخلفية"""
89
+ self.is_running = True
90
+ self.start_time = time.time()
91
+
92
+ services_to_start = [
93
+ ('peer_server', 'peer_server.py'),
94
+ ('rpc_server', 'rpc_server.py'),
95
+ ('load_balancer', 'load_balancer.py'),
96
+ ('distributed_executor', 'main.py')
97
+ ]
98
+
99
+ for service_name, script_file in services_to_start:
100
+ try:
101
+ process = subprocess.Popen(
102
+ [sys.executable, script_file],
103
+ stdout=subprocess.PIPE,
104
+ stderr=subprocess.PIPE,
105
+ cwd=os.getcwd()
106
+ )
107
+
108
+ self.services[service_name] = {
109
+ 'process': process,
110
+ 'status': 'running',
111
+ 'started_at': datetime.now().isoformat(),
112
+ 'script': script_file
113
+ }
114
+
115
+ self.logger.info(f"✅ بدء تشغيل {service_name} (PID: {process.pid})")
116
+
117
+ except Exception as e:
118
+ self.logger.error(f"❌ فشل في بدء تشغيل {service_name}: {e}")
119
+ self.services[service_name] = {
120
+ 'process': None,
121
+ 'status': 'failed',
122
+ 'error': str(e)
123
+ }
124
+
125
+ def stop_all_services(self):
126
+ """إيقاف جميع الخدمات"""
127
+ self.is_running = False
128
+
129
+ for service_name, service_info in self.services.items():
130
+ if service_info.get('process'):
131
+ try:
132
+ service_info['process'].terminate()
133
+ service_info['process'].wait(timeout=5)
134
+ service_info['status'] = 'stopped'
135
+ self.logger.info(f"🛑 تم إيقاف {service_name}")
136
+ except Exception as e:
137
+ # إجبار الإيقاف
138
+ service_info['process'].kill()
139
+ self.logger.warning(f"⚠️ تم إجبار إيقاف {service_name}: {e}")
140
+
141
+ def launch_ui(self):
142
+ """تشغيل الواجهة التفاعلية عند الحاجة"""
143
+ try:
144
+ # تشغيل خادم الواجهة الأمامية
145
+ ui_process = subprocess.Popen(
146
+ ['npm', 'run', 'dev'],
147
+ cwd=os.getcwd(),
148
+ stdout=subprocess.PIPE,
149
+ stderr=subprocess.PIPE
150
+ )
151
+
152
+ self.services['ui_server'] = {
153
+ 'process': ui_process,
154
+ 'status': 'running',
155
+ 'started_at': datetime.now().isoformat()
156
+ }
157
+
158
+ self.logger.info("🖥️ تم تشغيل الواجهة التفاعلية")
159
+
160
+ # فتح المتصفح تلقائياً (اختياري)
161
+ import webbrowser
162
+ time.sleep(3) # انتظار حتى يصبح الخادم جاهزاً
163
+ webbrowser.open('http://localhost:5173')
164
+
165
+ except Exception as e:
166
+ self.logger.error(f"❌ فشل في تشغيل الواجهة التفاعلية: {e}")
167
+
168
+ def hide_ui_windows(self):
169
+ """إخفاء نوافذ الواجهة التفاعلية"""
170
+ if 'ui_server' in self.services and self.services['ui_server'].get('process'):
171
+ try:
172
+ self.services['ui_server']['process'].terminate()
173
+ self.services['ui_server']['status'] = 'stopped'
174
+ self.logger.info("🔒 تم إخفاء الواجهة التفاعلية")
175
+ except Exception as e:
176
+ self.logger.error(f"❌ فشل في إخفاء الواجهة التفاعلية: {e}")
177
+
178
+ def health_check_loop(self):
179
+ """فحص دوري لحالة الخدمات وإعادة تشغيلها عند الحاجة"""
180
+ while self.is_running:
181
+ for service_name, service_info in self.services.items():
182
+ if service_info.get('process') and service_info['status'] == 'running':
183
+ if service_info['process'].poll() is not None:
184
+ # الخدمة توقفت بشكل غير متوقع
185
+ self.logger.warning(f"⚠️ الخدمة {service_name} توقفت، إعادة تشغيل...")
186
+ self.restart_single_service(service_name)
187
+
188
+ time.sleep(30) # فحص كل 30 ثانية
189
+
190
+ def restart_single_service(self, service_name):
191
+ """إعادة تشغيل خدمة واحدة"""
192
+ service_info = self.services.get(service_name)
193
+ if not service_info:
194
+ return
195
+
196
+ script_file = service_info.get('script')
197
+ if script_file:
198
+ try:
199
+ process = subprocess.Popen(
200
+ [sys.executable, script_file],
201
+ stdout=subprocess.PIPE,
202
+ stderr=subprocess.PIPE
203
+ )
204
+
205
+ self.services[service_name].update({
206
+ 'process': process,
207
+ 'status': 'running',
208
+ 'restarted_at': datetime.now().isoformat()
209
+ })
210
+
211
+ self.logger.info(f"✅ تم إعادة تشغيل {service_name}")
212
+
213
+ except Exception as e:
214
+ self.logger.error(f"❌ فشل في إعادة تشغيل {service_name}: {e}")
215
+
216
+ def setup_signal_handlers(self):
217
+ """إعداد معالجات الإشارات للتحكم في الخدمة"""
218
+ def signal_handler(signum, frame):
219
+ self.logger.info(f"تلقي إشارة {signum}, إيقاف الخدمة...")
220
+ self.stop_all_services()
221
+ sys.exit(0)
222
+
223
+ signal.signal(signal.SIGTERM, signal_handler)
224
+ signal.signal(signal.SIGINT, signal_handler)
225
+
226
+ def run_as_daemon(self):
227
+ """تشغيل الخدمة كخدمة خلفية"""
228
+ self.logger.info("🚀 بدء تشغيل الخدمة في الخلفية...")
229
+
230
+ # بدء الخدمات
231
+ self.start_all_services()
232
+
233
+ # بدء حلقة الفحص الصحي
234
+ health_thread = threading.Thread(target=self.health_check_loop, daemon=True)
235
+ health_thread.start()
236
+
237
+ # إعداد معالجات الإشارات
238
+ self.setup_signal_handlers()
239
+
240
+ # تشغيل خادم HTTP API للتحكم
241
+ self.logger.info("🌐 تشغيل HTTP API على المنفذ 8888")
242
+ self.app.run(host='0.0.0.0', port=8888, debug=False)
243
+
244
+ def main():
245
+ service = BackgroundService()
246
+
247
+ if len(sys.argv) > 1:
248
+ command = sys.argv[1]
249
+
250
+ if command == 'start':
251
+ service.run_as_daemon()
252
+ elif command == 'status':
253
+ # فحص حالة الخدمة
254
+ import requests
255
+ try:
256
+ response = requests.get('http://localhost:8888/status')
257
+ print(json.dumps(response.json(), indent=2, ensure_ascii=False))
258
+ except:
259
+ print("❌ الخدمة غير متاحة")
260
+ elif command == 'stop':
261
+ # إيقاف الخدمة
262
+ import requests
263
+ try:
264
+ response = requests.post('http://localhost:8888/stop')
265
+ print(response.json()['message'])
266
+ except:
267
+ print("❌ فشل في إيقاف الخدمة")
268
+ elif command == 'show-ui':
269
+ # إظهار الواجهة التفاعلية
270
+ import requests
271
+ try:
272
+ response = requests.post('http://localhost:8888/show-ui')
273
+ print(response.json()['message'])
274
+ except:
275
+ print("❌ فشل في إظهار الواجهة التفاعلية")
276
+ else:
277
+ print("الأوامر المتاحة: start, status, stop, show-ui")
278
+ else:
279
+ print("استخدام: python background_service.py [start|status|stop|show-ui]")
280
+
281
+ if __name__ == "__main__":
282
+ main()
central_manager.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # central_manager.py
3
+
4
+ import time
5
+ import threading
6
+ from typing import Dict, List
7
+
8
+ import requests
9
+ from fastapi import FastAPI, HTTPException
10
+ from pydantic import BaseModel
11
+
12
+ # ---- إعداد FastAPI ----------------------------------------------------------
13
+ app = FastAPI(title="Central Task Manager")
14
+
15
+ # ---- نماذج البيانات --------------------------------------------------------
16
+
17
+ class RegisterRequest(BaseModel):
18
+ """تسجيل أو تجديد ظهور العقدة."""
19
+ url: str # مثلاً: "http://203.0.113.45:7520/run"
20
+ load: float = 0.0 # نسبة تحميل العقدة (0.0 - 1.0)، اختياري
21
+
22
+ class TaskRequest(BaseModel):
23
+ func: str
24
+ args: List = []
25
+ kwargs: Dict = {}
26
+ complexity: float = 0.0
27
+
28
+ # ---- سجلّ العقد ------------------------------------------------------------
29
+ # بنخزّن للعقدة: آخر timestamp و load
30
+ peers: Dict[str, Dict] = {}
31
+
32
+ HEARTBEAT_TTL = 60 # ثواني قبل اعتبار العقدة متوقفة
33
+ HEALTH_CHECK_FREQ = 30 # ثواني بين فحوص الصحة الداخلية
34
+
35
+ # ---- API للعقد لتسجيل نفسها -----------------------------------------------
36
+
37
+ @app.post("/register")
38
+ async def register_peer(req: RegisterRequest):
39
+ """العقدة تستدعي هذه النقطة كلما انطلقت أو دورياً لتجديد ظهورها."""
40
+ peers[req.url] = {"last_seen": time.time(), "load": req.load}
41
+ return {"status": "ok", "peers_count": len(peers)}
42
+
43
+ # ---- API للعمليات ---------------------------------------------------------
44
+
45
+ @app.get("/peers", response_model=List[str])
46
+ async def list_peers():
47
+ """يعيد قائمة بالعقد الصالحة بعد تنقية المتوقفة."""
48
+ now = time.time()
49
+ # حذف العقد المتوقفة
50
+ for url, info in list(peers.items()):
51
+ if now - info["last_seen"] > HEARTBEAT_TTL:
52
+ peers.pop(url)
53
+ return list(peers.keys())
54
+
55
+ @app.post("/dispatch")
56
+ async def dispatch_task(task: TaskRequest):
57
+ """يتلقى مهمة ويعيد توجيهها لأفضل عقدة أو ينفذ محليّاً."""
58
+ available = await list_peers()
59
+ if not available:
60
+ raise HTTPException(503, "لا توجد عقد متاحة حاليّاً")
61
+
62
+ # خوارزمية بسيطة: الاختيار بناءً على أقل تحميل معلن
63
+ # أو تدوير دائري إذا لم يعلن أحد عن تحميله
64
+ best = None
65
+ best_load = 1.1
66
+ for url in available:
67
+ load = peers[url].get("load", None)
68
+ if load is None:
69
+ best = url
70
+ break
71
+ if load < best_load:
72
+ best, best_load = url, load
73
+
74
+ if not best:
75
+ best = available[0]
76
+
77
+ # إعادة توجيه الطلب
78
+ try:
79
+ resp = requests.post(best, json=task.dict(), timeout=10)
80
+ resp.raise_for_status()
81
+ return resp.json()
82
+ except Exception as e:
83
+ raise HTTPException(502, f"فشل التوجيه إلى {best}: {e}")
84
+
85
+ # ---- فحص دوري لصحة العقد ---------------------------------------------------
86
+
87
+ def health_check_loop():
88
+ while True:
89
+ now = time.time()
90
+ for url in list(peers.keys()):
91
+ health_url = url.replace("/run", "/health")
92
+ try:
93
+ r = requests.get(health_url, timeout=3)
94
+ if r.status_code == 200:
95
+ peers[url]["last_seen"] = now
96
+ # يمكنك تحديث load من رد /health إذا وفّرته
97
+ else:
98
+ peers.pop(url)
99
+ except:
100
+ peers.pop(url)
101
+ time.sleep(HEALTH_CHECK_FREQ)
102
+
103
+ # ---- تشغيل الخلفيات وخادم FastAPI ------------------------------------------
104
+
105
+ if __name__ == "__main__":
106
+ # شغل لوب الفحص الطبي في الخلفية
107
+ threading.Thread(target=health_check_loop, daemon=True).start()
108
+
109
+ import uvicorn
110
+ uvicorn.run(app, host="0.0.0.0", port=1500)
111
+
components.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": false,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "tailwind.config.ts",
8
+ "css": "client/src/index.css",
9
+ "baseColor": "neutral",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "aliases": {
14
+ "components": "@/components",
15
+ "utils": "@/lib/utils",
16
+ "ui": "@/components/ui",
17
+ "lib": "@/lib",
18
+ "hooks": "@/hooks"
19
+ }
20
+ }
control.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ from autostart_config import AutoStartManager
3
+
4
+ def main():
5
+ parser = argparse.ArgumentParser(description="نظام التحكم في التشغيل التلقائي")
6
+ parser.add_argument('--enable', action='store_true', help="تفعيل التشغيل التلقائي")
7
+ parser.add_argument('--disable', action='store_true', help="تعطيل التشغيل التلقائي")
8
+ parser.add_argument('--status', action='store_true', help="عرض حالة التشغيل التلقائي")
9
+
10
+ args = parser.parse_args()
11
+ manager = AutoStartManager()
12
+
13
+ if args.enable:
14
+ manager.enable_autostart()
15
+ print("✓ تم تفعيل التشغيل التلقائي")
16
+ elif args.disable:
17
+ manager.disable_autostart()
18
+ print("✗ تم تعطيل التشغيل التلقائي")
19
+ elif args.status:
20
+ status = "مفعل" if manager.config['enabled'] else "معطل"
21
+ print(f"حالة التشغيل التلقائي: {status}")
22
+ else:
23
+ parser.print_help()
24
+
25
+ if __name__ == "__main__":
26
+ main()
dashboard.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # dashboard.py
2
+ from flask import Flask, render_template, jsonify
3
+ from peer_discovery import discover_peers
4
+ import threading
5
+ import time
6
+ from typing import List, Dict
7
+ import logging
8
+
9
+ app = Flask(__name__)
10
+ app.logger.setLevel(logging.INFO)
11
+
12
+ # تهيئة قائمة الأقران
13
+ current_peers: Dict[str, List[Dict[str, str]]] = {"local": [], "external": []}
14
+
15
+ def update_peers_loop() -> None:
16
+ """حلقة تحديث قائمة الأقران بشكل دوري"""
17
+ global current_peers
18
+ while True:
19
+ try:
20
+ new_peers = discover_peers()
21
+ current_peers = new_peers
22
+ total_peers = len(new_peers["local"]) + len(new_peers["external"])
23
+ app.logger.info(f"تم تحديث قائمة الأقران: {total_peers} جهاز")
24
+ except Exception as e:
25
+ app.logger.error(f"خطأ في اكتشاف الأقران: {str(e)}")
26
+ time.sleep(10)
27
+
28
+ @app.route("/")
29
+ def dashboard() -> str:
30
+ """عرض لوحة التحكم الرئيسية"""
31
+ total_peers = len(current_peers["local"]) + len(current_peers["external"])
32
+ return render_template("dashboard.html",
33
+ peers_count=total_peers,
34
+ last_update=time.strftime("%Y-%m-%d %H:%M:%S"))
35
+
36
+ @app.route("/api/peers")
37
+ def get_peers() -> dict:
38
+ """واجهة API للحصول على قائمة الأقران"""
39
+ total_peers = len(current_peers["local"]) + len(current_peers["external"])
40
+ return jsonify({
41
+ "peers": current_peers,
42
+ "count": total_peers,
43
+ "status": "success"
44
+ })
45
+
46
+ def start_background_thread() -> None:
47
+ """بدء خيط الخلفية لتحديث الأقران"""
48
+ thread = threading.Thread(target=update_peers_loop)
49
+ thread.daemon = True
50
+ thread.start()
51
+
52
+ if __name__ == "__main__":
53
+ start_background_thread()
54
+ app.run(host="0.0.0.0", port=7530, debug=False)
55
+
distributed_executor.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import threading
2
+ import queue
3
+ import time
4
+ import json
5
+ from typing import Callable, Dict, List
6
+ import socket
7
+ from zeroconf import Zeroconf, ServiceBrowser, ServiceInfo
8
+ import logging
9
+ import requests
10
+
11
+ logging.basicConfig(level=logging.INFO)
12
+
13
+ class PeerRegistry:
14
+ def __init__(self):
15
+ self._peers = {}
16
+ self._zeroconf = Zeroconf()
17
+ self.local_node_id = socket.gethostname()
18
+
19
+ def register_service(self, name: str, port: int, load: float = 0.0):
20
+ service_info = ServiceInfo(
21
+ "_tasknode._tcp.local.",
22
+ f"{name}._tasknode._tcp.local.",
23
+ addresses=[socket.inet_aton(self._get_local_ip())],
24
+ port=port,
25
+ properties={
26
+ b'load': str(load).encode(),
27
+ b'node_id': self.local_node_id.encode()
28
+ },
29
+ server=f"{name}.local."
30
+ )
31
+ self._zeroconf.register_service(service_info)
32
+ logging.info(f"✅ Service registered: {name} @ {self._get_local_ip()}:{port}")
33
+
34
+ def discover_peers(self, timeout: int = 3) -> List[Dict]:
35
+ class Listener:
36
+ def __init__(self):
37
+ self.peers = []
38
+
39
+ def add_service(self, zc, type_, name):
40
+ try:
41
+ info = zc.get_service_info(type_, name, timeout=3000)
42
+ if info:
43
+ ip = socket.inet_ntoa(info.addresses[0])
44
+ peer_data = {
45
+ 'ip': ip,
46
+ 'port': info.port,
47
+ 'load': float(info.properties.get(b'load', b'0')),
48
+ 'node_id': info.properties.get(b'node_id', b'unknown').decode(),
49
+ 'last_seen': time.time()
50
+ }
51
+ if peer_data not in self.peers:
52
+ self.peers.append(peer_data)
53
+ logging.info(f"✅ تمت إضافة نظير جديد: {peer_data}")
54
+ else:
55
+ logging.warning(f"⚠️ لم يتم العثور على معلومات الخدمة: {name}")
56
+ except Exception as e:
57
+ logging.error(f"❌ خطأ أثناء جلب معلومات الخدمة {name}: {e}")
58
+
59
+ def update_service(self, zc, type_, name):
60
+ self.add_service(zc, type_, name)
61
+
62
+ def remove_service(self, zc, type_, name):
63
+ pass # يمكن تحسينه لاحقًا
64
+
65
+ listener = Listener()
66
+ ServiceBrowser(self._zeroconf, "_tasknode._tcp.local.", listener)
67
+ time.sleep(timeout)
68
+ return sorted(listener.peers, key=lambda x: x['load'])
69
+
70
+ def _get_local_ip(self) -> str:
71
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
72
+ try:
73
+ s.connect(('10.255.255.255', 1))
74
+ ip = s.getsockname()[0]
75
+ except Exception:
76
+ ip = '127.0.0.1'
77
+ finally:
78
+ s.close()
79
+ return ip
80
+
81
+
82
+ class DistributedExecutor:
83
+ def __init__(self, shared_secret: str):
84
+ self.peer_registry = PeerRegistry()
85
+ self.shared_secret = shared_secret
86
+ self.task_queue = queue.PriorityQueue()
87
+ self.result_cache = {}
88
+ self.available_peers = []
89
+ self._init_peer_discovery()
90
+
91
+ def _init_peer_discovery(self):
92
+ def discovery_loop():
93
+ while True:
94
+ self.available_peers = self.peer_registry.discover_peers()
95
+ logging.info(f"✅ Discovered peers: {self.available_peers}")
96
+ time.sleep(10)
97
+
98
+ threading.Thread(target=discovery_loop, daemon=True).start()
99
+
100
+ def submit(self, task_func: Callable, *args, **kwargs):
101
+ task_id = f"{task_func.__name__}_{time.time()}"
102
+
103
+ task = {
104
+ 'task_id': task_id,
105
+ 'function': task_func.__name__,
106
+ 'args': args,
107
+ 'kwargs': kwargs,
108
+ 'sender_id': self.peer_registry.local_node_id
109
+ }
110
+
111
+ if self.available_peers:
112
+ lan_peers = [p for p in self.available_peers if self._is_local_ip(p['ip'])]
113
+ wan_peers = [p for p in self.available_peers if not self._is_local_ip(p['ip'])]
114
+
115
+ if lan_peers:
116
+ peer = min(lan_peers, key=lambda x: x['load'])
117
+ logging.info(f"✅ Sending task {task_id} to LAN peer {peer['node_id']}")
118
+ else:
119
+ peer = min(wan_peers, key=lambda x: x['load'])
120
+ logging.info(f"✅ Sending task {task_id} to WAN peer {peer['node_id']}")
121
+
122
+ self._send_to_peer(peer, task)
123
+ else:
124
+ logging.warning("⚠️ لا توجد أجهزة متاحة - سيتم تنفيذ المهمة محلياً")
125
+
126
+ def _is_local_ip(self, ip: str) -> bool:
127
+ return (
128
+ ip.startswith('192.168.') or
129
+ ip.startswith('10.') or
130
+ ip.startswith('172.') or
131
+ ip == '127.0.0.1'
132
+ )
133
+
134
+ def _send_to_peer(self, peer: Dict, task: Dict):
135
+ try:
136
+ url = f"http://{peer['ip']}:{peer['port']}/run"
137
+ response = requests.post(url, json=task, timeout=10)
138
+ response.raise_for_status()
139
+ logging.info(f"✅ Response from peer: {response.text}")
140
+ return response.json()
141
+ except Exception as e:
142
+ logging.error(f"❌ فشل إرسال المهمة لـ {peer['node_id']}: {e}")
143
+ return None
144
+
145
+
146
+ if __name__ == "__main__":
147
+ executor = DistributedExecutor("my_secret_key")
148
+ executor.peer_registry.register_service("node1", 7520, load=0.1)
149
+ print("✅ نظام توزيع المهام جاهز...")
150
+
151
+ def example_task(x):
152
+ return x * x
153
+
154
+ executor.submit(example_task, 5)
155
+
drizzle.config.ts ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { defineConfig } from "drizzle-kit";
2
+
3
+ if (!process.env.DATABASE_URL) {
4
+ throw new Error("DATABASE_URL, ensure the database is provisioned");
5
+ }
6
+
7
+ export default defineConfig({
8
+ out: "./migrations",
9
+ schema: "./shared/schema.ts",
10
+ dialect: "postgresql",
11
+ dbCredentials: {
12
+ url: process.env.DATABASE_URL,
13
+ },
14
+ });
dts_cli.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # dts_cli.py
2
+ import click
3
+ from dashboard import app
4
+ from rpc_server import app as rpc_app
5
+ import threading
6
+
7
+ @click.group()
8
+ def cli():
9
+ pass
10
+
11
+ @cli.command()
12
+ def start():
13
+ """بدء النظام الموزع"""
14
+ print("جارِ تشغيل النظام الموزع...")
15
+
16
+ # تشغيل واجهة التحكم في خيط منفصل
17
+ dashboard_thread = threading.Thread(
18
+ target=lambda: app.run(host="0.0.0.0", port=5000)
19
+ )
20
+ dashboard_thread.daemon = True
21
+ dashboard_thread.start()
22
+
23
+ # تشغيل خادم RPC
24
+ rpc_app.run(host="0.0.0.0", port=7520)
25
+
26
+ @cli.command()
27
+ from flask import Flask, render_template, request
28
+
29
+ # ... (الكود الحالي)
30
+
31
+ @flask_app.route("/")
32
+ def home():
33
+ tasks = {
34
+ "1": ("ضرب المصفوفات", "matrix"),
35
+ "2": ("حساب الأعداد الأولية", "prime"),
36
+ "3": ("معالجة البيانات", "data"),
37
+ }
38
+ return render_template("index.html", tasks=tasks)
39
+
40
+ @flask_app.route("/run_task", methods=["POST"])
41
+ def run_task():
42
+ task_id = request.form.get("task_id")
43
+ result = None
44
+
45
+ if task_id == "1":
46
+ result = matrix_multiply(500) # استبدل بمعاملاتك الفعلية
47
+ elif task_id == "2":
48
+ result = prime_calculation(100_000)
49
+ elif task_id == "3":
50
+ result = data_processing(10_000)
51
+
52
+ return render_template("index.html", tasks={
53
+ "1": ("ضرب المصفوفات", "matrix"),
54
+ "2": ("حساب الأعداد الأولية", "prime"),
55
+ "3": ("معالجة البيانات", "data"),
56
+ }, result=result)
57
+ def discover():
58
+ """عرض الأجهزة المتصلة"""
59
+ from peer_discovery import discover_peers
60
+ peers = discover_peers()
61
+ print("الأجهزة المتصلة:")
62
+ for i, peer in enumerate(peers, 1):
63
+ print(f"{i}. {peer}")
64
+
65
+ if __name__ == "__main__":
66
+ cli()
electron-package.json ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "nora_distributed_system",
3
+ "version": "1.0.0",
4
+ "description": "نظام نورا الذكي الموزع",
5
+ "main": "electron/main.js",
6
+ "scripts": {
7
+ "electron": "electron .",
8
+ "build-windows": "electron-builder --win",
9
+ "build-mac": "electron-builder --mac",
10
+ "build-linux": "electron-builder --linux",
11
+ "build-all": "electron-builder -mwl"
12
+ },
13
+ "build": {
14
+ "appId": "com.nora.distributed",
15
+ "productName": "Nora Distributed System",
16
+ "directories": {
17
+ "output": "dist"
18
+ },
19
+ "files": [
20
+ "build/**/*",
21
+ "electron/**/*",
22
+ "node_modules/**/*"
23
+ ],
24
+ "win": {
25
+ "target": [
26
+ {
27
+ "target": "nsis",
28
+ "arch": [
29
+ "x64",
30
+ "ia32",
31
+ "arm64"
32
+ ]
33
+ },
34
+ {
35
+ "target": "portable",
36
+ "arch": [
37
+ "x64",
38
+ "ia32"
39
+ ]
40
+ },
41
+ {
42
+ "target": "appx",
43
+ "arch": [
44
+ "x64",
45
+ "ia32"
46
+ ]
47
+ }
48
+ ],
49
+ "icon": "assets/icon.ico"
50
+ },
51
+ "mac": {
52
+ "target": [
53
+ {
54
+ "target": "dmg",
55
+ "arch": [
56
+ "x64",
57
+ "arm64"
58
+ ]
59
+ },
60
+ {
61
+ "target": "zip",
62
+ "arch": [
63
+ "x64",
64
+ "arm64"
65
+ ]
66
+ },
67
+ {
68
+ "target": "mas",
69
+ "arch": [
70
+ "x64",
71
+ "arm64"
72
+ ]
73
+ }
74
+ ],
75
+ "icon": "assets/icon.icns"
76
+ },
77
+ "linux": {
78
+ "target": [
79
+ {
80
+ "target": "AppImage",
81
+ "arch": [
82
+ "x64",
83
+ "arm64"
84
+ ]
85
+ },
86
+ {
87
+ "target": "deb",
88
+ "arch": [
89
+ "x64",
90
+ "arm64"
91
+ ]
92
+ },
93
+ {
94
+ "target": "rpm",
95
+ "arch": [
96
+ "x64",
97
+ "arm64"
98
+ ]
99
+ },
100
+ {
101
+ "target": "snap",
102
+ "arch": [
103
+ "x64",
104
+ "arm64"
105
+ ]
106
+ }
107
+ ],
108
+ "icon": "assets/icon.png"
109
+ }
110
+ }
111
+ }
enhanced_assistant.py ADDED
@@ -0,0 +1,312 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import os
3
+ import json
4
+ import requests
5
+ from typing import Dict, List, Optional
6
+ from difflib import get_close_matches
7
+ import tempfile
8
+ from PIL import Image
9
+ from io import BytesIO
10
+ import re
11
+ from datetime import datetime
12
+
13
+ class EnhancedNoraAssistant:
14
+ def __init__(self):
15
+ self.knowledge_file = "knowledge_base.json"
16
+ self.memory_file = "global_memory.json"
17
+ self.learning_file = "nora_learning_data.json"
18
+ self.history_path = "enhanced_history.json"
19
+
20
+ # تحميل البيانات
21
+ self.knowledge = self.load_knowledge()
22
+ self.memory = self.load_memory()
23
+ self.chat_history = self.load_history()
24
+
25
+ print("✅ تم تهيئة نورا المحسنة بنجاح!")
26
+
27
+ def load_knowledge(self) -> Dict:
28
+ """تحميل قاعدة المعرفة"""
29
+ if os.path.exists(self.knowledge_file):
30
+ with open(self.knowledge_file, 'r', encoding='utf-8') as f:
31
+ return json.load(f)
32
+ return {}
33
+
34
+ def save_knowledge(self):
35
+ """حفظ قاعدة المعرفة"""
36
+ with open(self.knowledge_file, 'w', encoding='utf-8') as f:
37
+ json.dump(self.knowledge, f, ensure_ascii=False, indent=2)
38
+
39
+ def load_memory(self) -> Dict:
40
+ """تحميل الذاكرة العامة"""
41
+ if os.path.exists(self.memory_file):
42
+ with open(self.memory_file, 'r', encoding='utf-8') as f:
43
+ return json.load(f)
44
+ return {}
45
+
46
+ def save_memory(self):
47
+ """حفظ الذاكرة العامة"""
48
+ with open(self.memory_file, 'w', encoding='utf-8') as f:
49
+ json.dump(self.memory, f, ensure_ascii=False, indent=2)
50
+
51
+ def load_history(self) -> List[Dict]:
52
+ """تحميل سجل المحادثة"""
53
+ if os.path.exists(self.history_path):
54
+ try:
55
+ with open(self.history_path, "r", encoding="utf-8") as f:
56
+ return json.load(f)
57
+ except:
58
+ return []
59
+ return []
60
+
61
+ def save_history(self):
62
+ """حفظ سجل المحادثة"""
63
+ with open(self.history_path, "w", encoding="utf-8") as f:
64
+ json.dump(self.chat_history, f, ensure_ascii=False, indent=2)
65
+
66
+ def clean_text(self, text: str) -> str:
67
+ """تنظيف النص"""
68
+ text = re.sub(r'\s+', ' ', text)
69
+ return text.strip()
70
+
71
+ def detect_language(self, text: str) -> str:
72
+ """كشف لغة النص"""
73
+ arabic_chars = re.compile('[\u0600-\u06FF]')
74
+ if arabic_chars.search(text):
75
+ return "ar"
76
+ return "en"
77
+
78
+ def fix_url(self, url: str) -> str:
79
+ """تصحيح الرابط"""
80
+ if not url.startswith(("http://", "https://")):
81
+ return "https://" + url.lstrip("//")
82
+ return url
83
+
84
+ def detect_media_type(self, url: str) -> str:
85
+ """تحديد نوع الوسائط"""
86
+ url = url.lower()
87
+ if url.endswith(('.jpg', '.jpeg', '.png', '.gif', '.webp')):
88
+ return 'image'
89
+ elif url.endswith(('.mp4', '.mov', '.avi', '.webm')):
90
+ return 'video'
91
+ elif url.endswith(('.mp3', '.wav', '.ogg', '.m4a')):
92
+ return 'audio'
93
+ elif url.endswith('.pdf'):
94
+ return 'pdf'
95
+ return 'link'
96
+
97
+ def analyze_image_from_url(self, image_url: str) -> str:
98
+ """تحليل صورة من رابط"""
99
+ try:
100
+ response = requests.get(image_url, timeout=10)
101
+ response.raise_for_status()
102
+ image = Image.open(BytesIO(response.content))
103
+ return f"تحليل الصورة: الحجم {image.size}، الصيغة {image.format}"
104
+ except Exception as e:
105
+ return f"خطأ في تحليل الصورة: {str(e)}"
106
+
107
+ def smart_auto_reply(self, message: str) -> Optional[str]:
108
+ """ردود ذكية تلقائية"""
109
+ msg = message.strip().lower()
110
+
111
+ responses = {
112
+ "هل نبدأ": "نعم ابدأ",
113
+ "ابدأ": "نعم ابدأ",
114
+ "نعم أو لا": "نعم",
115
+ "هل تود": "نعم",
116
+ "هل تريدني": "نعم",
117
+ "ما هي": "ليس الآن",
118
+ "تفصيل": "ليس الآن",
119
+ "هل تحتاج": "نعم، شرح أكثر",
120
+ "جاهز؟": "ابدأ",
121
+ "قول لي": "موافق"
122
+ }
123
+
124
+ for key, value in responses.items():
125
+ if key in msg:
126
+ return value
127
+
128
+ if " أو " in msg:
129
+ return msg.split(" أو ")[0]
130
+
131
+ return None
132
+
133
+ def learn_new_info(self, topic: str, info: str) -> str:
134
+ """تعلم معلومة جديدة"""
135
+ if topic not in self.knowledge:
136
+ self.knowledge[topic] = []
137
+
138
+ if info not in self.knowledge[topic]:
139
+ self.knowledge[topic].append({
140
+ "content": info,
141
+ "timestamp": datetime.utcnow().isoformat()
142
+ })
143
+ self.save_knowledge()
144
+ return f"✅ تمت إضافة معلومة جديدة عن '{topic}'"
145
+
146
+ return f"ℹ️ المعلومة موجودة مسبقاً عن '{topic}'"
147
+
148
+ def search_knowledge(self, query: str) -> str:
149
+ """البحث في قاعدة المعرفة"""
150
+ query_clean = query.strip().lower()
151
+
152
+ # بحث مباشر
153
+ if query_clean in self.knowledge:
154
+ info = self.knowledge[query_clean]
155
+ if isinstance(info, list) and info:
156
+ return info[-1].get("content", str(info[-1]))
157
+ return str(info)
158
+
159
+ # بحث في المواضيع
160
+ for topic, infos in self.knowledge.items():
161
+ if query_clean in topic.lower():
162
+ if isinstance(infos, list) and infos:
163
+ return f"وجدت معلومة عن '{topic}': {infos[-1].get('content', str(infos[-1]))}"
164
+ return f"وجدت معلومة عن '{topic}': {str(infos)}"
165
+
166
+ return None
167
+
168
+ def generate_reply(self, user_input: str) -> str:
169
+ """إنتاج الرد الذكي"""
170
+ user_input = self.clean_text(user_input)
171
+
172
+ # فحص الردود التلقائية الذكية
173
+ auto_reply = self.smart_auto_reply(user_input)
174
+ if auto_reply:
175
+ self.memory[user_input] = auto_reply
176
+ self.save_memory()
177
+ return auto_reply
178
+
179
+ # فحص الذاكرة
180
+ if user_input in self.memory:
181
+ return self.memory[user_input]
182
+
183
+ # البحث في المطابقات القريبة
184
+ matches = get_close_matches(user_input, self.memory.keys(), n=1, cutoff=0.6)
185
+ if matches:
186
+ return self.memory[matches[0]]
187
+
188
+ # البحث في قاعدة المعرفة
189
+ knowledge_result = self.search_knowledge(user_input)
190
+ if knowledge_result:
191
+ self.memory[user_input] = knowledge_result
192
+ self.save_memory()
193
+ return knowledge_result
194
+
195
+ # معالجة الروابط
196
+ if user_input.startswith("http://") or user_input.startswith("https://"):
197
+ return self.handle_url(user_input)
198
+
199
+ # تصحيح الروابط في النص
200
+ if '//' in user_input:
201
+ corrected_url = self.fix_url(user_input)
202
+ reply = f"تم تصحيح الرابط: {corrected_url}"
203
+ else:
204
+ # رد افتراضي مع تعلم
205
+ reply = f"شكراً لك على الرسالة: '{user_input}'. سأتذكر هذا للمرة القادمة."
206
+
207
+ # تعلم تلقائي
208
+ if len(user_input.split()) > 2: # إذا كانت جملة معقولة
209
+ self.learn_new_info("محادثات_عامة", user_input)
210
+
211
+ # حفظ في الذاكرة
212
+ self.memory[user_input] = reply
213
+ self.save_memory()
214
+ return reply
215
+
216
+ def handle_url(self, url: str) -> str:
217
+ """معالجة الروابط"""
218
+ url = self.fix_url(url)
219
+ media_type = self.detect_media_type(url)
220
+
221
+ if media_type == 'image':
222
+ analysis = self.analyze_image_from_url(url)
223
+ reply = f"🖼️ صورة تم تحليلها:\n{analysis}"
224
+ elif media_type == 'video':
225
+ reply = f"🎥 فيديو تم اكتشافه: {url}"
226
+ elif media_type == 'audio':
227
+ reply = f"🎵 ملف صوتي تم اكتشافه: {url}"
228
+ elif media_type == 'pdf':
229
+ reply = f"📄 ملف PDF تم اكتشافه: {url}"
230
+ else:
231
+ reply = f"🔗 رابط ويب: {url}"
232
+
233
+ return reply
234
+
235
+ def simulate_server_scan(self):
236
+ """محاكاة البحث عن الخوادم"""
237
+ print("نورا: أبحث عن خوادم متاحة...")
238
+ fake_servers = ["server-01.cloud.com", "server-02.cloud.com", "server-03.local"]
239
+
240
+ for server in fake_servers:
241
+ print(f"نورا: تم العثور على خادم: {server}")
242
+ print(f"نورا: أقوم بمحاكاة النسخ إلى {server}...")
243
+
244
+ return "تمت عملية المحاكاة بنجاح ✅"
245
+
246
+ def get_stats(self) -> Dict:
247
+ """إحصائيات النظام"""
248
+ return {
249
+ "معرفة_محفوظة": len(self.knowledge),
250
+ "ذكريات": len(self.memory),
251
+ "سجل_محادثات": len(self.chat_history),
252
+ "آخر_تحديث": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
253
+ }
254
+
255
+ def chat(self):
256
+ """بدء المحادثة التفاعلية"""
257
+ print("🤖 مرحباً! أنا نورا المحسنة، مساعدتك الذكية.")
258
+ print("📚 لدي قدرات محسنة في التعلم الذاتي وتحليل الوسائط")
259
+ print("💡 اكتب 'خروج' للإنهاء، 'إحصائيات' لعرض الإحص��ئيات، 'scan' للبحث عن خوادم")
260
+ print("-" * 50)
261
+
262
+ while True:
263
+ try:
264
+ user_input = input("\n🧑 أنت: ").strip()
265
+
266
+ if user_input.lower() in ["خروج", "exit", "quit"]:
267
+ print("نورا: مع السلامة! 👋")
268
+ break
269
+
270
+ elif user_input.lower() == "إحصائيات":
271
+ stats = self.get_stats()
272
+ print("📊 إحصائيات النظام:")
273
+ for key, value in stats.items():
274
+ print(f" {key}: {value}")
275
+ continue
276
+
277
+ elif user_input.lower() == "scan":
278
+ result = self.simulate_server_scan()
279
+ print(f"نورا: {result}")
280
+ continue
281
+
282
+ elif not user_input:
283
+ continue
284
+
285
+ # الحصول على الرد
286
+ response = self.generate_reply(user_input)
287
+ print(f"🤖 نورا: {response}")
288
+
289
+ # حفظ في السجل
290
+ self.chat_history.append({
291
+ "user": user_input,
292
+ "assistant": response,
293
+ "timestamp": datetime.utcnow().isoformat()
294
+ })
295
+
296
+ # حفظ السجل كل 5 رسائل
297
+ if len(self.chat_history) % 5 == 0:
298
+ self.save_history()
299
+
300
+ except KeyboardInterrupt:
301
+ print("\n\nنورا: تم إيقاف المحادثة. مع السلامة! 👋")
302
+ break
303
+ except Exception as e:
304
+ print(f"نورا: عذراً، حدث خطأ: {str(e)}")
305
+
306
+ def main():
307
+ """تشغيل المساعد المحسن"""
308
+ assistant = EnhancedNoraAssistant()
309
+ assistant.chat()
310
+
311
+ if __name__ == "__main__":
312
+ main()
global_memory.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "مرحبا": "شكراً لك على الرسالة: 'مرحبا'. سأتذكر هذا للمرة القادمة."
3
+ }
history.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "role": "user",
4
+ "content": "اه"
5
+ },
6
+ {
7
+ "role": "assistant",
8
+ "content": "عذراً، حدث خطأ: 401"
9
+ },
10
+ {
11
+ "role": "user",
12
+ "content": "مرحبا"
13
+ },
14
+ {
15
+ "role": "assistant",
16
+ "content": "عذراً، حدث خطأ: 401"
17
+ },
18
+ {
19
+ "role": "user",
20
+ "content": "مم"
21
+ },
22
+ {
23
+ "role": "assistant",
24
+ "content": "عذراً، حدث خطأ: 401"
25
+ }
26
+ ]
index.html ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>نظام توزيع المهام الذكي</title>
6
+ <style>
7
+ body {
8
+ font-family: Arial, sans-serif;
9
+ max-width: 800px;
10
+ margin: 0 auto;
11
+ padding: 20px;
12
+ background-color: #f5f5f5;
13
+ }
14
+ h1 {
15
+ color: #2c3e50;
16
+ text-align: center;
17
+ }
18
+ ul {
19
+ list-style: none;
20
+ padding: 0;
21
+ }
22
+ li {
23
+ background: white;
24
+ margin: 10px 0;
25
+ padding: 15px;
26
+ border-radius: 5px;
27
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
28
+ display: flex;
29
+ justify-content: space-between;
30
+ align-items: center;
31
+ }
32
+ button {
33
+ background: #3498db;
34
+ color: white;
35
+ border: none;
36
+ padding: 8px 15px;
37
+ border-radius: 3px;
38
+ cursor: pointer;
39
+ }
40
+ button:hover {
41
+ background: #2980b9;
42
+ }
43
+ #result {
44
+ background: white;
45
+ padding: 15px;
46
+ border-radius: 5px;
47
+ margin-top: 20px;
48
+ }
49
+ </style>
50
+ </head>
51
+ <body>
52
+ <h1>🚀 نظام توزيع المهام الذكي</h1>
53
+ <ul id="tasks">
54
+ {% for task_id, task in tasks.items() %}
55
+ <li>
56
+ <span>{{ task[0] }}</span>
57
+ <button onclick="runTask('{{ task_id }}')">تشغيل</button>
58
+ </li>
59
+ {% endfor %}
60
+ </ul>
61
+
62
+ <div id="result" style="display: {% if result %}block{% else %}none{% endif %};">
63
+ <h2>✅ النتيجة:</h2>
64
+ <pre>{{ result }}</pre>
65
+ </div>
66
+
67
+ <script>
68
+ async function runTask(taskId) {
69
+ const response = await fetch("/run_task", {
70
+ method: "POST",
71
+ headers: {
72
+ "Content-Type": "application/x-www-form-urlencoded",
73
+ },
74
+ body: `task_id=${taskId}`
75
+ });
76
+ const data = await response.text();
77
+
78
+ // تحديث الصفحة دون إعادة تحميل كاملة
79
+ document.getElementById("result").innerHTML =
80
+ `<h2>✅ النتيجة:</h2><pre>${JSON.parse(data).result}</pre>`;
81
+ document.getElementById("result").style.display = "block";
82
+ }
83
+ </script>
84
+ </body>
85
+ </html>
internet_scanner.py ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ """
3
+ internet_scanner.py - ماسح للبحث عن أجهزة DTS على الإنترنت
4
+ """
5
+ import requests
6
+ import threading
7
+ import time
8
+ import socket
9
+ from concurrent.futures import ThreadPoolExecutor, as_completed
10
+ import logging
11
+
12
+ class InternetScanner:
13
+ def __init__(self):
14
+ self.discovered_peers = set()
15
+ self.scan_ranges = [
16
+ # نطاقات IP شائعة للخوادم العامة
17
+ "8.8.8.0/24", # Google DNS range
18
+ "1.1.1.0/24", # Cloudflare range
19
+ "208.67.222.0/24", # OpenDNS range
20
+ ]
21
+
22
+ def scan_ip_range(self, ip_range: str, port: int = 7520):
23
+ """مسح نطاق IP للبحث عن خوادم DTS"""
24
+ import ipaddress
25
+
26
+ try:
27
+ network = ipaddress.ip_network(ip_range, strict=False)
28
+ active_peers = []
29
+
30
+ with ThreadPoolExecutor(max_workers=50) as executor:
31
+ futures = []
32
+
33
+ for ip in network.hosts():
34
+ future = executor.submit(self.check_dts_node, str(ip), port)
35
+ futures.append(future)
36
+
37
+ for future in as_completed(futures, timeout=30):
38
+ try:
39
+ result = future.result()
40
+ if result:
41
+ active_peers.append(result)
42
+ except:
43
+ continue
44
+
45
+ return active_peers
46
+
47
+ except Exception as e:
48
+ logging.error(f"خطأ في مسح النطاق {ip_range}: {e}")
49
+ return []
50
+
51
+ def check_dts_node(self, ip: str, port: int = 7520) -> str:
52
+ """فحص IP معين للتأكد من وجود خادم DTS مع المشروع"""
53
+ try:
54
+ # فحص صفحة الصحة العامة
55
+ health_url = f"http://{ip}:{port}/health"
56
+ response = requests.get(health_url, timeout=2)
57
+
58
+ if response.status_code == 200:
59
+ # فحص وجود المشروع الصحيح
60
+ run_url = f"http://{ip}:{port}/run"
61
+
62
+ # اختبار مهمة من المشروع للتأكد
63
+ test_payload = {
64
+ "func": "matrix_multiply",
65
+ "args": [2],
66
+ "kwargs": {}
67
+ }
68
+
69
+ test_response = requests.post(run_url, json=test_payload, timeout=3)
70
+
71
+ # فحص إضافي للتأكد من هوية المشروع
72
+ project_check = requests.get(f"http://{ip}:{port}/project_info", timeout=2)
73
+
74
+ if (test_response.status_code in [200, 404] and
75
+ project_check.status_code == 200):
76
+
77
+ project_data = project_check.json()
78
+
79
+ # التحقق من معرف المشروع الصحيح
80
+ if (project_data.get("project_name") == "distributed-task-system" and
81
+ project_data.get("version") == "1.0"):
82
+ logging.info(f"✅ اكتُشف خادم DTS صحيح: {ip}:{port}")
83
+ return run_url
84
+ else:
85
+ logging.warning(f"⚠️ خادم على {ip}:{port} لكن مشروع مختلف")
86
+
87
+ except:
88
+ pass
89
+ return None
90
+
91
+ def scan_public_repositories(self):
92
+ """البحث في المستودعات العامة عن عناوين خوادم DTS"""
93
+ try:
94
+ # البحث في GitHub عن مشاريع DTS
95
+ github_api = "https://api.github.com/search/repositories"
96
+ params = {
97
+ "q": "distributed task system port:7520",
98
+ "sort": "updated",
99
+ "per_page": 10
100
+ }
101
+
102
+ response = requests.get(github_api, params=params, timeout=10)
103
+ if response.status_code == 200:
104
+ repos = response.json().get("items", [])
105
+
106
+ for repo in repos:
107
+ # محاولة استخراج IPs من وصف المشروع أو README
108
+ if repo.get("description"):
109
+ self.extract_ips_from_text(repo["description"])
110
+
111
+ except Exception as e:
112
+ logging.warning(f"خطأ في البحث في المستودعات: {e}")
113
+
114
+ def extract_ips_from_text(self, text: str):
115
+ """استخراج عناوين IP من النص"""
116
+ import re
117
+
118
+ ip_pattern = r'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b'
119
+ ips = re.findall(ip_pattern, text)
120
+
121
+ for ip in ips:
122
+ try:
123
+ # التحقق من صحة IP
124
+ socket.inet_aton(ip)
125
+ peer_url = f"http://{ip}:7520/run"
126
+
127
+ # فحص سريع
128
+ if self.check_dts_node(ip):
129
+ self.discovered_peers.add(peer_url)
130
+
131
+ except:
132
+ continue
133
+
134
+ def start_continuous_scan(self):
135
+ """بدء المسح المستمر"""
136
+ def scan_loop():
137
+ while True:
138
+ try:
139
+ # مسح النطاقات المحددة
140
+ for ip_range in self.scan_ranges:
141
+ peers = self.scan_ip_range(ip_range)
142
+ for peer in peers:
143
+ self.discovered_peers.add(peer)
144
+
145
+ # البحث في المستودعات العامة
146
+ self.scan_public_repositories()
147
+
148
+ logging.info(f"اكتُشف {len(self.discovered_peers)} خادم على الإنترنت")
149
+
150
+ except Exception as e:
151
+ logging.error(f"خطأ في المسح المستمر: {e}")
152
+
153
+ # انتظار 30 دقيقة قبل المسح التالي
154
+ time.sleep(1800)
155
+
156
+ thread = threading.Thread(target=scan_loop, daemon=True)
157
+ thread.start()
158
+ logging.info("🔍 بدء المسح المستمر للإنترنت")
159
+
160
+ def get_discovered_peers(self):
161
+ """الحصول على قائمة الأجهزة المكتشفة"""
162
+ return list(self.discovered_peers)
163
+
164
+ # إنشاء مثيل عام
165
+ internet_scanner = InternetScanner()
launcher.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #!/usr/bin/env python3
3
+ """
4
+ مشغل موحد لنظام توزيع المهام
5
+ يوفر خيارات متعددة للتشغيل
6
+ """
7
+
8
+ import sys
9
+ import os
10
+ import subprocess
11
+ import argparse
12
+ import time
13
+ from pathlib import Path
14
+
15
+ def check_requirements():
16
+ """فحص المتطلبات والاعتماديات"""
17
+ required_files = [
18
+ 'background_service.py',
19
+ 'main.py',
20
+ 'peer_server.py',
21
+ 'rpc_server.py',
22
+ 'load_balancer.py'
23
+ ]
24
+
25
+ missing_files = []
26
+ for file in required_files:
27
+ if not Path(file).exists():
28
+ missing_files.append(file)
29
+
30
+ if missing_files:
31
+ print(f"❌ ملفات مفقودة: {', '.join(missing_files)}")
32
+ return False
33
+
34
+ return True
35
+
36
+ def install_tray_dependencies():
37
+ """تثبيت اعتماديات أيقونة شريط النظام"""
38
+ try:
39
+ subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'pystray', 'Pillow'])
40
+ print("✅ تم تثبيت اعتماديات أيقونة شريط النظام")
41
+ return True
42
+ except subprocess.CalledProcessError:
43
+ print("❌ فشل في تثبيت اعتماديات أيقونة شريط النظام")
44
+ return False
45
+
46
+ def start_background_service():
47
+ """بدء تشغيل الخدمة في الخلفية"""
48
+ print("🚀 بدء تشغيل الخدمة في الخلفية...")
49
+
50
+ # تشغيل الخدمة الخلفية
51
+ process = subprocess.Popen(
52
+ [sys.executable, 'background_service.py', 'start'],
53
+ stdout=subprocess.PIPE,
54
+ stderr=subprocess.PIPE
55
+ )
56
+
57
+ # انتظار قليل للتأكد من بدء التشغيل
58
+ time.sleep(2)
59
+
60
+ if process.poll() is None:
61
+ print("✅ تم بدء تشغيل الخدمة الخلفية بنجاح")
62
+ return process
63
+ else:
64
+ print("❌ فشل في بدء تشغيل الخدمة الخلفية")
65
+ return None
66
+
67
+ def start_with_tray():
68
+ """تشغيل النظام مع أيقونة شريط النظام"""
69
+ print("🖱️ تشغيل النظام مع أيقونة شريط النظام...")
70
+
71
+ # بدء الخدمة الخلفية أولاً
72
+ bg_process = start_background_service()
73
+ if not bg_process:
74
+ return False
75
+
76
+ time.sleep(3) # انتظار حتى تصبح الخدمة جاهزة
77
+
78
+ try:
79
+ # تشغيل أيقونة شريط النظام
80
+ subprocess.run([sys.executable, 'system_tray.py'])
81
+ except KeyboardInterrupt:
82
+ print("\n🛑 إيقاف النظام...")
83
+ # إيقاف الخدمة الخلفية
84
+ try:
85
+ import requests
86
+ requests.post('http://localhost:8888/stop', timeout=5)
87
+ except:
88
+ bg_process.terminate()
89
+
90
+ return True
91
+
92
+ def start_interactive():
93
+ """تشغيل النظام في الوضع التفاعلي"""
94
+ print("🖥️ تشغيل النظام في الوضع التفاعلي...")
95
+
96
+ # بدء الخدمة الخلفية
97
+ bg_process = start_background_service()
98
+ if not bg_process:
99
+ return False
100
+
101
+ time.sleep(3)
102
+
103
+ # تشغيل الواجهة التفاعلية
104
+ try:
105
+ import requests
106
+ requests.post('http://localhost:8888/show-ui', timeout=5)
107
+ print("✅ تم تشغيل الواجهة التفاعلية")
108
+
109
+ # فتح المتصفح
110
+ import webbrowser
111
+ time.sleep(2)
112
+ webbrowser.open('http://localhost:5173')
113
+
114
+ # انتظار إنهاء المستخدم
115
+ input("اضغط Enter لإيقاف النظام...")
116
+
117
+ except KeyboardInterrupt:
118
+ pass
119
+ finally:
120
+ print("🛑 إيقاف النظام...")
121
+ try:
122
+ import requests
123
+ requests.post('http://localhost:8888/stop', timeout=5)
124
+ except:
125
+ bg_process.terminate()
126
+
127
+ return True
128
+
129
+ def start_headless():
130
+ """تشغيل النظام بدون واجهة (للخوادم)"""
131
+ print("⚙️ تشغيل النظام بدون واجهة...")
132
+
133
+ try:
134
+ # تشغيل الخدمة الخلفية والانتظار
135
+ subprocess.run([sys.executable, 'background_service.py', 'start'])
136
+ except KeyboardInterrupt:
137
+ print("\n🛑 إيقاف النظام...")
138
+
139
+ return True
140
+
141
+ def show_status():
142
+ """عرض حالة النظام"""
143
+ subprocess.run([sys.executable, 'background_service.py', 'status'])
144
+
145
+ def stop_system():
146
+ """إيقاف النظام"""
147
+ subprocess.run([sys.executable, 'background_service.py', 'stop'])
148
+
149
+ def main():
150
+ parser = argparse.ArgumentParser(
151
+ description="مشغل نظام توزيع المهام الذكي",
152
+ formatter_class=argparse.RawDescriptionHelpFormatter,
153
+ epilog="""
154
+ أمثلة الاستخدام:
155
+ python launcher.py --tray # تشغيل مع أيقونة شريط ��لنظام
156
+ python launcher.py --interactive # تشغيل تفاعلي مع واجهة
157
+ python launcher.py --headless # تشغيل بدون واجهة (للخوادم)
158
+ python launcher.py --status # عرض حالة النظام
159
+ python launcher.py --stop # إيقاف النظام
160
+ """
161
+ )
162
+
163
+ group = parser.add_mutually_exclusive_group(required=True)
164
+ group.add_argument('--tray', action='store_true',
165
+ help='تشغيل مع أيقونة شريط النظام')
166
+ group.add_argument('--interactive', action='store_true',
167
+ help='تشغيل تفاعلي مع واجهة')
168
+ group.add_argument('--headless', action='store_true',
169
+ help='تشغيل بدون واجهة (للخوادم)')
170
+ group.add_argument('--status', action='store_true',
171
+ help='عرض حالة النظام')
172
+ group.add_argument('--stop', action='store_true',
173
+ help='إيقاف النظام')
174
+
175
+ parser.add_argument('--install-deps', action='store_true',
176
+ help='تثبيت الاعتماديات المطلوبة')
177
+
178
+ args = parser.parse_args()
179
+
180
+ # فحص المتطلبات
181
+ if not check_requirements():
182
+ return 1
183
+
184
+ # تثبيت الاعتماديات إذا طُلب ذلك
185
+ if args.install_deps:
186
+ install_tray_dependencies()
187
+ return 0
188
+
189
+ # تنفيذ الأمر المطلوب
190
+ if args.status:
191
+ show_status()
192
+ elif args.stop:
193
+ stop_system()
194
+ elif args.headless:
195
+ success = start_headless()
196
+ elif args.interactive:
197
+ success = start_interactive()
198
+ elif args.tray:
199
+ # تثبيت اعتماديات أيقونة شريط النظام إذا لم تكن موجودة
200
+ try:
201
+ import pystray
202
+ except ImportError:
203
+ print("📦 تثبيت اعتماديات أيقونة شريط النظام...")
204
+ if not install_tray_dependencies():
205
+ print("❌ فشل في تثبيت الاعتماديات، التشغيل في الوضع التفاعلي...")
206
+ success = start_interactive()
207
+ else:
208
+ success = start_with_tray()
209
+ else:
210
+ success = start_with_tray()
211
+
212
+ return 0 if success else 1
213
+
214
+ if __name__ == "__main__":
215
+ sys.exit(main())
live_streaming.py ADDED
@@ -0,0 +1,405 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # live_streaming.py - نظام البث المباشر للألعاب والفيديو
3
+
4
+ import cv2
5
+ import numpy as np
6
+ import time
7
+ import threading
8
+ import logging
9
+ import asyncio
10
+ import base64
11
+ import json
12
+ from datetime import datetime
13
+ from processor_manager import should_offload
14
+ from remote_executor import execute_remotely
15
+ from functools import wraps
16
+
17
+ logging.basicConfig(level=logging.INFO)
18
+
19
+ class LiveStreamManager:
20
+ def __init__(self):
21
+ self.active_streams = {}
22
+ self.processing_nodes = []
23
+ self.load_balancer = StreamLoadBalancer()
24
+
25
+ def register_processing_node(self, node_id, capabilities):
26
+ """تسجيل عقدة معالجة جديدة"""
27
+ self.processing_nodes.append({
28
+ "id": node_id,
29
+ "capabilities": capabilities,
30
+ "load": 0.0,
31
+ "last_ping": datetime.now()
32
+ })
33
+ logging.info(f"📡 تم تسجيل عقدة معالجة: {node_id}")
34
+
35
+ class StreamLoadBalancer:
36
+ def __init__(self):
37
+ self.node_loads = {}
38
+
39
+ def get_best_node(self, task_type, nodes):
40
+ """اختيار أفضل عقدة للمعالجة"""
41
+ suitable_nodes = [n for n in nodes if task_type in n.get("capabilities", [])]
42
+ if not suitable_nodes:
43
+ return None
44
+ return min(suitable_nodes, key=lambda x: x["load"])
45
+
46
+ def stream_offload(func):
47
+ """ديكوراتور خاص بالبث المباشر"""
48
+ @wraps(func)
49
+ def wrapper(*args, **kwargs):
50
+ complexity = estimate_stream_complexity(func, args, kwargs)
51
+
52
+ if complexity > 70 or should_offload(complexity):
53
+ logging.info(f"📺 إرسال مهمة البث {func.__name__} للمعالجة الموزعة")
54
+ return execute_remotely(func.__name__, args, kwargs)
55
+
56
+ logging.info(f"📺 معالجة البث محلياً: {func.__name__}")
57
+ return func(*args, **kwargs)
58
+ return wrapper
59
+
60
+ def estimate_stream_complexity(func, args, kwargs):
61
+ """تقدير تعقيد معالجة البث"""
62
+ if func.__name__ == "process_game_stream":
63
+ return args[1] * args[2] / 10000 # FPS × الدقة
64
+ elif func.__name__ == "real_time_video_enhancement":
65
+ return args[0] * 20 # عدد التحسينات × 20
66
+ elif func.__name__ == "multi_stream_processing":
67
+ return len(args[0]) * 25 # عدد البثوث × 25
68
+ elif func.__name__ == "ai_commentary_generation":
69
+ return args[1] * 15 # طول النص × 15
70
+ return 40
71
+
72
+ # ═══════════════════════════════════════════════════════════════
73
+ # معالجة بث الألعاب المباشر
74
+ # ═══════════════════════════════════════════════════════════════
75
+
76
+ @stream_offload
77
+ def process_game_stream(stream_data, fps, resolution, enhancements=None):
78
+ """معالجة بث الألعاب في الوقت الفعلي"""
79
+ start_time = time.time()
80
+
81
+ if enhancements is None:
82
+ enhancements = ["noise_reduction", "color_enhancement"]
83
+
84
+ logging.info(f"🎮 معالجة بث الألعاب - FPS: {fps}, الدقة: {resolution}")
85
+ logging.info(f"🔧 التحسينات: {enhancements}")
86
+
87
+ # محاكاة معالجة الإطارات
88
+ frame_count = len(stream_data) if isinstance(stream_data, list) else 60
89
+ processing_per_frame = 0.01 + (len(enhancements) * 0.005)
90
+ total_processing_time = frame_count * processing_per_frame
91
+
92
+ # محاكاة المعالجة
93
+ time.sleep(min(total_processing_time, 2))
94
+
95
+ # حساب جودة البث
96
+ quality_score = min(100, 60 + (len(enhancements) * 8) + (fps / 2))
97
+ latency = max(50, 200 - (fps * 2)) # أقل تأخير مع FPS أعلى
98
+
99
+ result = {
100
+ "status": "success",
101
+ "stream_type": "game",
102
+ "fps_processed": fps,
103
+ "resolution": resolution,
104
+ "frames_processed": frame_count,
105
+ "enhancements_applied": enhancements,
106
+ "quality_score": round(quality_score, 1),
107
+ "latency_ms": latency,
108
+ "processing_time": time.time() - start_time,
109
+ "bandwidth_optimized": True
110
+ }
111
+
112
+ logging.info(f"✅ تمت معالجة بث اللعبة - جودة: {result['quality_score']}%")
113
+ return result
114
+
115
+ @stream_offload
116
+ def real_time_video_enhancement(enhancement_types, video_quality="1080p", target_fps=60):
117
+ """تحسين الفيديو في الوقت الفعلي"""
118
+ start_time = time.time()
119
+
120
+ available_enhancements = {
121
+ "upscaling": "تحسين الدقة",
122
+ "noise_reduction": "إزالة التشويش",
123
+ "color_grading": "تصحيح الألوان",
124
+ "motion_smoothing": "تنعيم الحركة",
125
+ "hdr_enhancement": "تحسين HDR",
126
+ "sharpening": "زيادة الحدة",
127
+ "stabilization": "تثبيت الصورة"
128
+ }
129
+
130
+ quality_multiplier = {"720p": 1, "1080p": 2, "1440p": 3, "4K": 5}
131
+ multiplier = quality_multiplier.get(video_quality, 2)
132
+
133
+ processing_time = len(enhancement_types) * multiplier * target_fps * 0.0001
134
+
135
+ logging.info(f"📹 تحسين الفيديو المباشر - الجودة: {video_quality}")
136
+ logging.info(f"🎯 التحسينات: {enhancement_types}")
137
+
138
+ # محاكاة التحسين
139
+ time.sleep(min(processing_time, 1.5))
140
+
141
+ enhancements_applied = {}
142
+ for enhancement in enhancement_types:
143
+ if enhancement in available_enhancements:
144
+ enhancements_applied[enhancement] = {
145
+ "name": available_enhancements[enhancement],
146
+ "improvement": round(np.random.uniform(15, 35), 1),
147
+ "processing_cost": round(processing_time / len(enhancement_types), 4)
148
+ }
149
+
150
+ result = {
151
+ "status": "success",
152
+ "video_quality": video_quality,
153
+ "target_fps": target_fps,
154
+ "enhancements": enhancements_applied,
155
+ "total_improvement": round(np.mean([e["improvement"] for e in enhancements_applied.values()]), 1),
156
+ "processing_time": time.time() - start_time,
157
+ "real_time_capable": processing_time < (1/target_fps)
158
+ }
159
+
160
+ logging.info(f"✅ تم تحسين الفيديو - تحسن: {result['total_improvement']}%")
161
+ return result
162
+
163
+ # ═══════════════════════════════════════════════════════════════
164
+ # معالجة متعددة البثوث
165
+ # ═══════════════════════════════════════════════════════════════
166
+
167
+ @stream_offload
168
+ def multi_stream_processing(streams_data, processing_mode="parallel"):
169
+ """معالجة عدة بثوث في نفس الوقت"""
170
+ start_time = time.time()
171
+
172
+ logging.info(f"📡 معالجة متعددة البثوث - العدد: {len(streams_data)}")
173
+ logging.info(f"⚙️ وضع المعالجة: {processing_mode}")
174
+
175
+ results = {}
176
+
177
+ if processing_mode == "parallel":
178
+ # محاكاة المعالجة المتوازية
179
+ max_processing_time = max([s.get("complexity", 1) for s in streams_data]) * 0.1
180
+ time.sleep(min(max_processing_time, 2))
181
+
182
+ for i, stream in enumerate(streams_data):
183
+ stream_id = f"stream_{i+1}"
184
+ results[stream_id] = {
185
+ "status": "processed",
186
+ "quality": stream.get("quality", "1080p"),
187
+ "fps": stream.get("fps", 30),
188
+ "enhancement_applied": True,
189
+ "processing_node": f"node_{(i % 3) + 1}" # توزيع على 3 عقد
190
+ }
191
+ else:
192
+ # معالجة تسلسلية
193
+ total_time = sum([s.get("complexity", 1) for s in streams_data]) * 0.05
194
+ time.sleep(min(total_time, 3))
195
+
196
+ for i, stream in enumerate(streams_data):
197
+ stream_id = f"stream_{i+1}"
198
+ results[stream_id] = {
199
+ "status": "processed",
200
+ "quality": stream.get("quality", "1080p"),
201
+ "fps": stream.get("fps", 30),
202
+ "processing_order": i + 1
203
+ }
204
+
205
+ result = {
206
+ "status": "success",
207
+ "streams_processed": len(streams_data),
208
+ "processing_mode": processing_mode,
209
+ "results": results,
210
+ "total_processing_time": time.time() - start_time,
211
+ "average_quality": round(np.mean([30, 45, 60, 55]), 1), # محاكاة متوسط الجودة
212
+ "nodes_utilized": len(set([r.get("processing_node", "main") for r in results.values()]))
213
+ }
214
+
215
+ logging.info(f"✅ تمت معالجة {len(streams_data)} بث - العقد المستخدمة: {result['nodes_utilized']}")
216
+ return result
217
+
218
+ # ═══════════════════════════════════════════════════════════════
219
+ # ذكاء اصطناعي للبث
220
+ # ═══════════════════════════════════════════════════════════════
221
+
222
+ @stream_offload
223
+ def ai_commentary_generation(game_events, commentary_length, language="ar"):
224
+ """توليد تعليق ذكي للألعاب"""
225
+ start_time = time.time()
226
+
227
+ logging.info(f"🤖 توليد تعليق ذكي - الطول: {commentary_length} كلمة")
228
+
229
+ # قوالب التعليق
230
+ commentary_templates = {
231
+ "ar": [
232
+ "حركة رائعة من اللاعب!",
233
+ "هذا هدف مذهل!",
234
+ "دفاع قوي في هذه اللحظة",
235
+ "استراتيجية مم��ازة",
236
+ "أداء استثنائي!"
237
+ ],
238
+ "en": [
239
+ "Amazing move by the player!",
240
+ "What a fantastic goal!",
241
+ "Strong defense right there",
242
+ "Excellent strategy",
243
+ "Outstanding performance!"
244
+ ]
245
+ }
246
+
247
+ processing_time = commentary_length * 0.02 # 0.02 ثانية لكل كلمة
248
+ time.sleep(min(processing_time, 1))
249
+
250
+ # توليد التعليق
251
+ templates = commentary_templates.get(language, commentary_templates["ar"])
252
+ generated_commentary = []
253
+
254
+ for i in range(min(commentary_length // 5, len(game_events))):
255
+ template = np.random.choice(templates)
256
+ generated_commentary.append(template)
257
+
258
+ result = {
259
+ "status": "success",
260
+ "language": language,
261
+ "commentary_length": len(generated_commentary),
262
+ "generated_text": generated_commentary,
263
+ "game_events_analyzed": len(game_events),
264
+ "processing_time": time.time() - start_time,
265
+ "emotion_detection": "excited", # محاكاة كشف المشاعر
266
+ "context_awareness": True
267
+ }
268
+
269
+ logging.info(f"✅ تم توليد التعليق - {len(generated_commentary)} جملة")
270
+ return result
271
+
272
+ @stream_offload
273
+ def stream_quality_optimization(stream_metadata, target_bandwidth, viewer_count):
274
+ """تحسين جودة البث حسب النطاق الترددي وعدد المشاهدين"""
275
+ start_time = time.time()
276
+
277
+ logging.info(f"📊 تحسين جودة البث - المشاهدين: {viewer_count}")
278
+ logging.info(f"🌐 النطاق المستهدف: {target_bandwidth} Mbps")
279
+
280
+ # حساب الجودة المثلى
281
+ base_quality = min(target_bandwidth * 200, 1080) # حد أقصى 1080p
282
+
283
+ # تعديل حسب عدد المشاهدين
284
+ if viewer_count > 1000:
285
+ quality_adjustment = 0.8 # تقليل الجودة للأعداد الكبيرة
286
+ elif viewer_count > 100:
287
+ quality_adjustment = 0.9
288
+ else:
289
+ quality_adjustment = 1.0
290
+
291
+ optimized_quality = int(base_quality * quality_adjustment)
292
+
293
+ # تحديد FPS مناسب
294
+ if optimized_quality >= 1080:
295
+ optimal_fps = 60
296
+ elif optimized_quality >= 720:
297
+ optimal_fps = 45
298
+ else:
299
+ optimal_fps = 30
300
+
301
+ time.sleep(0.5) # محاكاة المعالجة
302
+
303
+ result = {
304
+ "status": "success",
305
+ "original_quality": stream_metadata.get("quality", "1080p"),
306
+ "optimized_quality": f"{optimized_quality}p",
307
+ "optimal_fps": optimal_fps,
308
+ "target_bandwidth": target_bandwidth,
309
+ "viewer_count": viewer_count,
310
+ "bandwidth_saved": round(max(0, (1080 - optimized_quality) / 1080 * 100), 1),
311
+ "processing_time": time.time() - start_time,
312
+ "adaptive_streaming": True
313
+ }
314
+
315
+ logging.info(f"✅ تم تحسين البث - الجودة: {result['optimized_quality']}")
316
+ return result
317
+
318
+ # ═══════════════════════════════════════════════════════════════
319
+ # إدارة البث المباشر
320
+ # ═══════════════════════════════════════════════════════════════
321
+
322
+ class LiveStreamCoordinator:
323
+ def __init__(self):
324
+ self.active_streams = {}
325
+ self.processing_history = []
326
+
327
+ def start_stream(self, stream_id, config):
328
+ """بدء بث مباشر جديد"""
329
+ self.active_streams[stream_id] = {
330
+ "config": config,
331
+ "start_time": datetime.now(),
332
+ "status": "active",
333
+ "processing_nodes": [],
334
+ "viewers": 0
335
+ }
336
+ logging.info(f"🔴 بدء البث: {stream_id}")
337
+
338
+ def distribute_processing(self, stream_id, task_type, data):
339
+ """توزيع معالجة البث على العقد المختلفة"""
340
+ if stream_id not in self.active_streams:
341
+ return {"error": "البث غير موجود"}
342
+
343
+ # اختيار العقدة المناسبة
344
+ best_node = self._select_processing_node(task_type)
345
+
346
+ # تنفيذ المعالجة
347
+ if best_node:
348
+ result = execute_remotely(task_type, [data], {})
349
+ self.active_streams[stream_id]["processing_nodes"].append(best_node)
350
+ return result
351
+ else:
352
+ # معالجة محلية
353
+ return self._process_locally(task_type, data)
354
+
355
+ def _select_processing_node(self, task_type):
356
+ """اختيار أفضل عقدة للمعالجة"""
357
+ # منطق اختيار العقدة (مبسط)
358
+ return f"node_gpu_{np.random.randint(1, 4)}"
359
+
360
+ def _process_locally(self, task_type, data):
361
+ """معالجة محلية احتياطية"""
362
+ return {"status": "processed_locally", "task": task_type}
363
+
364
+ # دالة اختبار شاملة للبث المباشر
365
+ def run_live_streaming_benchmark():
366
+ """اختبار شامل لنظام البث المباشر"""
367
+ print("\n📺🎮 اختبار نظام البث المباشر للألعاب والفيديو")
368
+ print("=" * 70)
369
+
370
+ # بيانات تجريبية
371
+ game_stream_data = [f"frame_{i}" for i in range(60)] # 60 إطار
372
+ game_events = ["goal", "save", "foul", "corner", "yellow_card"]
373
+
374
+ multi_streams = [
375
+ {"quality": "1080p", "fps": 60, "complexity": 3},
376
+ {"quality": "720p", "fps": 30, "complexity": 2},
377
+ {"quality": "1440p", "fps": 45, "complexity": 4}
378
+ ]
379
+
380
+ tests = [
381
+ ("معالجة بث لعبة", lambda: process_game_stream(game_stream_data, 60, "1920x1080", ["noise_reduction", "color_enhancement", "sharpening"])),
382
+ ("تحسين فيديو مباشر", lambda: real_time_video_enhancement(["upscaling", "noise_reduction", "hdr_enhancement"], "1080p", 60)),
383
+ ("معالجة متعددة البثوث", lambda: multi_stream_processing(multi_streams, "parallel")),
384
+ ("توليد تعليق ذكي", lambda: ai_commentary_generation(game_events, 50, "ar")),
385
+ ("تحسين جودة البث", lambda: stream_quality_optimization({"quality": "1080p"}, 5.0, 500))
386
+ ]
387
+
388
+ coordinator = LiveStreamCoordinator()
389
+
390
+ for test_name, test_func in tests:
391
+ print(f"\n🔄 تشغيل: {test_name}")
392
+ try:
393
+ result = test_func()
394
+ print(f"✅ نجح: {test_name}")
395
+ if "processing_time" in result:
396
+ print(f"⏱️ وقت المعالجة: {result['processing_time']:.2f}s")
397
+ if "quality_score" in result:
398
+ print(f"⭐ جودة: {result['quality_score']}%")
399
+ except Exception as e:
400
+ print(f"❌ فشل: {test_name} - {str(e)}")
401
+
402
+ print("\n🏁 انتهى اختبار البث المباشر")
403
+
404
+ if __name__ == "__main__":
405
+ run_live_streaming_benchmark()
load_balancer.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # load_balancer.py
2
+ import peer_discovery, requests, time, smart_tasks, psutil, socket
3
+
4
+ def send(peer, func, *args, **kw):
5
+ try:
6
+ r = requests.post(peer, json={"func": func,
7
+ "args": list(args),
8
+ "kwargs": kw}, timeout=12)
9
+ return r.json()
10
+ except Exception as e:
11
+ return {"error": str(e)}
12
+
13
+ def choose_peer():
14
+ """اختيار أفضل جهاز - أولوية LAN ثم WAN"""
15
+ import socket
16
+
17
+ lan_peers = []
18
+ wan_peers = []
19
+
20
+ # تصنيف الأجهزة
21
+ for p in list(peer_discovery.PEERS):
22
+ ip = p.split('//')[1].split(':')[0] if '//' in p else p.split(':')[0]
23
+ if is_local_ip(ip):
24
+ lan_peers.append(p)
25
+ else:
26
+ wan_peers.append(p)
27
+
28
+ # أولاً: جرب الأجهزة المحلية (LAN)
29
+ best_lan = find_best_peer(lan_peers)
30
+ if best_lan:
31
+ return best_lan
32
+
33
+ # ثانياً: إذا لم تتوفر أجهزة محلية، جرب WAN
34
+ if internet_available():
35
+ best_wan = find_best_peer(wan_peers)
36
+ return best_wan
37
+
38
+ return None
39
+
40
+ def find_best_peer(peers):
41
+ """العثور على أفضل جهاز من قائمة معينة"""
42
+ best = None
43
+ for p in peers:
44
+ try:
45
+ cpu = requests.get(p.replace("/run", "/cpu"), timeout=2).json()["usage"]
46
+ best = (p, cpu) if best is None or cpu < best[1] else best
47
+ except:
48
+ continue
49
+ return best[0] if best else None
50
+
51
+ def is_local_ip(ip):
52
+ """فحص إذا كان IP محلي"""
53
+ return (
54
+ ip.startswith('192.168.') or
55
+ ip.startswith('10.') or
56
+ ip.startswith('172.') or
57
+ ip == '127.0.0.1'
58
+ )
59
+
60
+ def internet_available():
61
+ """فحص توفر الإنترنت"""
62
+ try:
63
+ socket.create_connection(("8.8.8.8", 53), timeout=3)
64
+ return True
65
+ except:
66
+ return False
67
+
68
+ while True:
69
+ peer = choose_peer()
70
+ if peer:
71
+ print(f"\n🛰️ إرسال إلى {peer}")
72
+ res = send(peer, "prime_calculation", 30000)
73
+ else:
74
+ print("\n⚙️ لا أقران؛ العمل محليّ على", socket.gethostname())
75
+ res = smart_tasks.prime_calculation(30000)
76
+ print("🔹 النتيجة (جزئية):", str(res)[:120])
77
+ time.sleep(10)
main.py ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ main.py — نقطة تشغيل نظام OffloadHelper في ملف واحد
4
+ خيارات سطر الأوامر:
5
+ -s / --stats-interval ثواني بين كل طباعة لإحصائية الأقران (0 = مرة واحدة فقط)
6
+ --no-cli تشغيل بلا قائمة تفاعلية حتى مع وجود TTY
7
+ """
8
+ import os
9
+ import sys
10
+ import time
11
+ import threading
12
+ import subprocess
13
+ import logging
14
+ import argparse
15
+ from pathlib import Path
16
+ from typing import Any
17
+
18
+ from flask import Flask, request, jsonify
19
+ from flask_cors import CORS
20
+
21
+ # ───────────────────── ضبط المسارات ──────────────────────
22
+ FILE = Path(__file__).resolve()
23
+ BASE_DIR = FILE.parent
24
+ PROJECT_ROOT = BASE_DIR.parent
25
+ for p in (BASE_DIR, PROJECT_ROOT):
26
+ sys.path.insert(0, str(p))
27
+
28
+ # ───────────────────── إعداد السجلات ─────────────────────
29
+ os.makedirs("logs", exist_ok=True)
30
+ logging.basicConfig(
31
+ level=logging.INFO,
32
+ format="%(asctime)s - %(levelname)s - %(message)s",
33
+ handlers=[
34
+ logging.StreamHandler(),
35
+ logging.FileHandler("logs/main.log", mode="a")
36
+ ]
37
+ )
38
+
39
+ # ─────────────── تحميل متغيرات البيئة (اختياري) ───────────────
40
+ try:
41
+ from dotenv import load_dotenv
42
+ load_dotenv()
43
+ logging.info("🔧 تم تحميل متغيرات البيئة من ‎.env")
44
+ except ImportError:
45
+ logging.warning("🔧 python-dotenv غير مثبَّت؛ تَخطّي .env")
46
+
47
+ # ─────────────── وحدات المشروع الداخلية ────────────────
48
+ try:
49
+ from peer_discovery import (
50
+ register_service_lan,
51
+ discover_lan_loop,
52
+ register_with_central,
53
+ fetch_central_loop,
54
+ PEERS
55
+ )
56
+ from your_tasks import matrix_multiply, prime_calculation, data_processing
57
+ from distributed_executor import DistributedExecutor
58
+ from peer_statistics import print_peer_statistics
59
+ except ImportError as e:
60
+ logging.error(f"❌ تعذّر استيراد وحدة: {e}")
61
+ sys.exit(1)
62
+
63
+ # ─────────────── ثابتات التهيئة ───────────────
64
+ CPU_PORT = int(os.getenv("CPU_PORT", "7520"))
65
+ SHARED_SECRET = os.getenv("SHARED_SECRET", "my_shared_secret_123")
66
+ PYTHON_EXE = sys.executable
67
+
68
+ # ─────────────── خيارات سطر الأوامر ───────────────
69
+ parser = argparse.ArgumentParser()
70
+ parser.add_argument(
71
+ "--stats-interval", "-s",
72
+ type=int,
73
+ default=0,
74
+ help="ثواني بين كل طباعة لإحصائية الأقران (0 = مرة واحدة فقط)"
75
+ )
76
+ parser.add_argument(
77
+ "--no-cli",
78
+ action="store_true",
79
+ help="تعطيل القائمة التفاعلية حتى عند وجود TTY"
80
+ )
81
+ args = parser.parse_args()
82
+
83
+ # ─────────────── خادم Flask البسيط ───────────────
84
+ flask_app = Flask(__name__)
85
+ CORS(flask_app, resources={r"/*": {"origins": "*"}})
86
+
87
+ @flask_app.route("/run_task", methods=["POST"])
88
+ def run_task():
89
+ try:
90
+ # قراءة البيانات
91
+ data = request.get_json() if request.is_json else request.form
92
+ task_id = data.get("task_id")
93
+
94
+ if not task_id:
95
+ return jsonify(error="يجب تحديد task_id"), 400
96
+
97
+ # معالجة المهام
98
+ if task_id == "1":
99
+ result = matrix_multiply(500)
100
+ elif task_id == "2":
101
+ result = prime_calculation(100_000)
102
+ elif task_id == "3":
103
+ result = data_processing(10_000)
104
+ else:
105
+ return jsonify(error="معرف المهمة غير صحيح"), 400
106
+
107
+ return jsonify(result=result)
108
+
109
+ except Exception as e:
110
+ logging.error(f"خطأ في معالجة المهمة: {str(e)}", exc_info=True)
111
+ return jsonify(error="حدث خطأ داخلي في الخادم"), 500
112
+ def start_flask_server():
113
+ ip_public = os.getenv("PUBLIC_IP", "127.0.0.1")
114
+ logging.info(f"🌐 Flask متوفر على: http://{ip_public}:{CPU_PORT}/run_task")
115
+ flask_app.run(host="0.0.0.0", port=CPU_PORT, debug=False)
116
+
117
+ # ─────────────── خدمات خلفية محلية ───────────────
118
+ def start_services():
119
+ """peer_server و load_balancer"""
120
+ try:
121
+ subprocess.Popen([PYTHON_EXE, "peer_server.py", "--port", str(CPU_PORT)])
122
+ subprocess.Popen([PYTHON_EXE, "load_balancer.py"])
123
+ logging.info("✅ تم تشغيل الخدمات الخلفيّة")
124
+ except Exception as exc:
125
+ logging.error(f"❌ خطأ بتشغيل الخدمات الخلفية: {exc}")
126
+
127
+ # ───��─────────── مهام مثالية محلية ───────────────
128
+ def example_task(x: int) -> int:
129
+ return x * x
130
+
131
+ def benchmark(fn, *args):
132
+ t0 = time.time()
133
+ res = fn(*args)
134
+ return time.time() - t0, res
135
+
136
+ # ─────────────── طباعة الإحصائية دوريًّا ─────────────
137
+ def stats_loop(interval: int, executor: DistributedExecutor):
138
+ while True:
139
+ peers_now = [
140
+ {"ip": host, "port": port}
141
+ for (host, port) in executor.peer_registry.get_all()
142
+ ]
143
+ print_peer_statistics(peers_now)
144
+ time.sleep(interval)
145
+
146
+ # ─────────────── القائمة التفاعلية CLI ─────────────
147
+ def menu(executor: DistributedExecutor):
148
+ tasks = {
149
+ "1": ("ضرب المصفوفات", matrix_multiply, 500),
150
+ "2": ("حساب الأعداد الأولية", prime_calculation, 100_000),
151
+ "3": ("معالجة البيانات", data_processing, 10_000),
152
+ "5": ("مهمة موزعة (مثال)", example_task, 42),
153
+ }
154
+
155
+ while True:
156
+ print("\n🚀 نظام توزيع المهام الذكي")
157
+ for k, (title, _, _) in tasks.items():
158
+ print(f"{k}: {title}")
159
+ print("q: خروج")
160
+ choice = input("اختر المهمة: ").strip().lower()
161
+
162
+ if choice == "q":
163
+ print("🛑 تم إنهاء البرنامج.")
164
+ break
165
+ if choice not in tasks:
166
+ print("⚠️ اختيار غير صحيح.")
167
+ continue
168
+
169
+ name, fn, arg = tasks[choice]
170
+ print(f"\nتشغيل: {name}…")
171
+
172
+ try:
173
+ if choice == "5":
174
+ logging.info("📡 إرسال المهمة إلى العقد الموزَّعة…")
175
+ future = executor.submit(fn, arg)
176
+ print(f"✅ النتيجة (موزعة): {future.result()}")
177
+ else:
178
+ dur, res = benchmark(fn, arg)
179
+ print(f"✅ النتيجة: {res}\n⏱️ الوقت: {dur:.3f} ث")
180
+ except Exception as exc:
181
+ print(f"❌ خطأ في تنفيذ المهمة: {exc}")
182
+
183
+ # ─────────────── الدالة الرئيسية ───────────────
184
+ def main():
185
+ # 1) خدمات back‑end
186
+ start_services()
187
+
188
+ # 2) مهيّئ الموزِّع
189
+ executor = DistributedExecutor(SHARED_SECRET)
190
+ executor.peer_registry.register_service("node_main", CPU_PORT)
191
+
192
+ # 3) إضافة الأقران المكتشفين
193
+ for peer_url in list(PEERS):
194
+ try:
195
+ host, port_str = peer_url.split("//")[1].split("/run")[0].split(":")
196
+ executor.peer_registry.register_service(
197
+ f"peer_{host.replace('.', '_')}",
198
+ int(port_str)
199
+ )
200
+ except Exception as exc:
201
+ logging.warning(f"⚠️ تخطّي peer ({peer_url}): {exc}")
202
+
203
+ # 4) طباعة أولية
204
+ initial_peers = [
205
+ {"ip": host, "port": int(port)}
206
+ for peer_url in PEERS
207
+ if (hp := peer_url.split("//")[1].split("/run")[0]).count(":") == 1
208
+ for host, port in [hp.split(":")]
209
+ ]
210
+ print_peer_statistics(initial_peers)
211
+
212
+ # 5) حلقة إحصائية دورية
213
+ if args.stats_interval > 0:
214
+ threading.Thread(
215
+ target=stats_loop,
216
+ args=(args.stats_interval, executor),
217
+ daemon=True
218
+ ).start()
219
+
220
+ logging.info("✅ النظام جاهز للعمل")
221
+
222
+ # 6) CLI إن توفر TTY ولم يُطلَب no-cli
223
+ if not args.no_cli and sys.stdin.isatty():
224
+ menu(executor)
225
+ else:
226
+ logging.info("ℹ️ القائمة التفاعلية معطّلة (no TTY أو --no-cli)")
227
+
228
+ # ─────────────── تشغيل البرنامج ───────────────
229
+ if __name__ == "__main__":
230
+ # Zeroconf
231
+ threading.Thread(target=register_service_lan, daemon=True).start()
232
+ threading.Thread(target=discover_lan_loop, daemon=True).start()
233
+
234
+ # خادم وسيط مركزي
235
+ register_with_central()
236
+ threading.Thread(target=fetch_central_loop, daemon=True).start()
237
+
238
+ # ماسح إنترنت (اختياري)
239
+ try:
240
+ from internet_scanner import internet_scanner
241
+ threading.Thread(
242
+ target=internet_scanner.start_continuous_scan,
243
+ daemon=True
244
+ ).start()
245
+ logging.info("🔍 بدء المسح المستمر للإنترنت")
246
+ except ImportError:
247
+ logging.warning("🔍 internet_scanner غير متوافر – تم التخطي")
248
+
249
+ # Flask
250
+ threading.Thread(target=start_flask_server, daemon=True).start()
251
+
252
+ # وحدة تحكم (اختياري)
253
+ try:
254
+ from your_control import control
255
+ control.start()
256
+ except ImportError:
257
+ logging.info("🛈 your_control غير متوفّر �� تشغيل افتراضي")
258
+
259
+ # CLI / إحصائية
260
+ main()
main.spec ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- mode: python ; coding: utf-8 -*-
2
+
3
+
4
+ a = Analysis(
5
+ ['main.py'],
6
+ pathex=[],
7
+ binaries=[],
8
+ datas=[],
9
+ hiddenimports=[],
10
+ hookspath=[],
11
+ hooksconfig={},
12
+ runtime_hooks=[],
13
+ excludes=[],
14
+ noarchive=False,
15
+ optimize=0,
16
+ )
17
+ pyz = PYZ(a.pure)
18
+
19
+ exe = EXE(
20
+ pyz,
21
+ a.scripts,
22
+ a.binaries,
23
+ a.datas,
24
+ [],
25
+ name='main',
26
+ debug=False,
27
+ bootloader_ignore_signals=False,
28
+ strip=False,
29
+ upx=True,
30
+ upx_exclude=[],
31
+ runtime_tmpdir=None,
32
+ console=False,
33
+ disable_windowed_traceback=False,
34
+ argv_emulation=False,
35
+ target_arch=None,
36
+ codesign_identity=None,
37
+ entitlements_file=None,
38
+ )
offload_lib.py ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # offload_lib.py
3
+
4
+ import time
5
+ import math
6
+ import random
7
+ import psutil
8
+ import requests
9
+ import socket
10
+ from functools import wraps
11
+ from zeroconf import Zeroconf, ServiceBrowser
12
+ import logging
13
+
14
+ # إعداد السجل
15
+ logging.basicConfig(
16
+ level=logging.INFO,
17
+ format='%(asctime)s - %(levelname)s - %(message)s'
18
+ )
19
+
20
+ # إعدادات التحميل
21
+ MAX_CPU = 0.6 # عتبة استخدام CPU فقط
22
+
23
+ class PeerListener:
24
+ def __init__(self):
25
+ self.peers = []
26
+
27
+ def add_service(self, zc, type, name):
28
+ info = zc.get_service_info(type, name)
29
+ if info:
30
+ ip = socket.inet_ntoa(info.addresses[0])
31
+ self.peers.append(f"{ip}:{info.port}")
32
+ logging.info(f"🔗 جهاز مكتشف: {ip}:{info.port}")
33
+
34
+ def update_service(self, zc, type, name):
35
+ logging.debug(f"🔄 تم تحديث الخدمة: {name}")
36
+ pass # هنا فقط لتفادي التحذير
37
+
38
+ def discover_peers(timeout=1.5):
39
+ """اكتشاف الأجهزة المتاحة - أولوية LAN ثم WAN ثم الإنترنت مع فحص المشروع"""
40
+ import peer_discovery
41
+ from project_identifier import verify_project_compatibility
42
+
43
+ zc = Zeroconf()
44
+ listener = PeerListener()
45
+ ServiceBrowser(zc, "_http._tcp.local.", listener)
46
+ time.sleep(timeout)
47
+ zc.close()
48
+
49
+ lan_peers = []
50
+ wan_peers = []
51
+ internet_peers = []
52
+
53
+ for peer in listener.peers:
54
+ ip = peer.split(':')[0]
55
+ if verify_peer_project(ip):
56
+ if is_local_network(ip):
57
+ lan_peers.append(peer)
58
+ else:
59
+ wan_peers.append(peer)
60
+
61
+ all_discovered = list(peer_discovery.PEERS)
62
+ for peer_url in all_discovered:
63
+ peer_ip = peer_url.split("://")[1].split(":")[0]
64
+ if verify_peer_project(peer_ip):
65
+ if is_local_network(peer_ip):
66
+ if peer_url not in lan_peers:
67
+ lan_peers.append(peer_url)
68
+ else:
69
+ if peer_url not in wan_peers:
70
+ internet_peers.append(peer_url)
71
+
72
+ all_peers = lan_peers + wan_peers + internet_peers
73
+ logging.info(f"اكتُشف {len(all_peers)} جهاز DTS متوافق - LAN: {len(lan_peers)}, WAN: {len(wan_peers)}, Internet: {len(internet_peers)}")
74
+
75
+ return all_peers
76
+
77
+ def verify_peer_project(ip, port=7520):
78
+ """فحص إذا كان الجهاز يحتوي على نفس المشروع"""
79
+ try:
80
+ from project_identifier import verify_project_compatibility
81
+
82
+ project_url = f"http://{ip}:{port}/project_info"
83
+ response = requests.get(project_url, timeout=2)
84
+
85
+ if response.status_code == 200:
86
+ remote_info = response.json()
87
+ return verify_project_compatibility(remote_info)
88
+
89
+ except:
90
+ pass
91
+ return False
92
+
93
+ def is_local_network(ip):
94
+ """فحص إذا كان IP في الشبكة المحلية"""
95
+ try:
96
+ import ipaddress
97
+ addr = ipaddress.ip_address(ip)
98
+ return (
99
+ addr.is_private or
100
+ str(addr).startswith('192.168.') or
101
+ str(addr).startswith('10.') or
102
+ str(addr).startswith('172.')
103
+ )
104
+ except:
105
+ return False
106
+
107
+ def try_offload(peer, payload, max_retries=3):
108
+ """محاولة إرسال المهمة إلى جهاز آخر"""
109
+ url = f"http://{peer}/run"
110
+ for attempt in range(max_retries):
111
+ try:
112
+ response = requests.post(url, json=payload, timeout=10)
113
+ response.raise_for_status()
114
+ return response.json()
115
+ except Exception as e:
116
+ logging.warning(f"فشل المحاولة {attempt + 1} لـ {peer}: {str(e)}")
117
+ time.sleep(0.5 * (attempt + 1))
118
+ raise ConnectionError(f"فشل جميع المحاولات لـ {peer}")
119
+
120
+ def estimate_complexity(func, args, kwargs):
121
+ """تقدير تعقيد المهمة"""
122
+ if func.__name__ == "matrix_multiply":
123
+ return args[0] ** 2
124
+ elif func.__name__ == "prime_calculation":
125
+ return args[0] / 100
126
+ elif func.__name__ == "data_processing":
127
+ return args[0] / 10
128
+ elif func.__name__ == "image_processing_emulation":
129
+ return args[0] * 5
130
+ return 1 # قيمة افتراضية
131
+
132
+ def offload(func):
133
+ """ديكوراتور لتوزيع المهام"""
134
+ @wraps(func)
135
+ def wrapper(*args, **kwargs):
136
+ cpu = psutil.cpu_percent(interval=0.5) / 100.0
137
+ mem = psutil.virtual_memory().available / (1024**2)
138
+ complexity = estimate_complexity(func, args, kwargs)
139
+
140
+ logging.info(f"حمل النظام - CPU: {cpu:.2f}, الذاكرة: {mem:.1f}MB, تعقيد المهمة: {complexity}")
141
+
142
+ if complexity > 50 or cpu > MAX_CPU:
143
+ try:
144
+ peers = discover_peers()
145
+ if peers:
146
+ payload = {
147
+ "func": func.__name__,
148
+ "args": args,
149
+ "kwargs": kwargs,
150
+ "complexity": complexity
151
+ }
152
+ selected_peer = random.choice(peers)
153
+ logging.info(f"إرسال المهمة إلى {selected_peer}")
154
+ return try_offload(selected_peer, payload)
155
+ except Exception as e:
156
+ logging.error(f"خطأ في التوزيع: {str(e)}")
157
+
158
+ logging.info("تنفيذ المهمة محلياً")
159
+ return func(*args, **kwargs)
160
+ return wrapper
161
+
162
+ # المهام القابلة للتوزيع:
163
+
164
+ @offload
165
+ def matrix_multiply(size):
166
+ """ضرب مصفوفتين عشوائيتين بالحجم"""
167
+ import numpy as np
168
+ A = np.random.rand(size, size)
169
+ B = np.random.rand(size, size)
170
+ return np.dot(A, B).tolist()
171
+
172
+ @offload
173
+ def prime_calculation(n):
174
+ """حساب الأعداد الأولية"""
175
+ primes = []
176
+ for num in range(2, n + 1):
177
+ is_prime = True
178
+ for i in range(2, int(math.sqrt(num)) + 1):
179
+ if num % i == 0:
180
+ is_prime = False
181
+ break
182
+ if is_prime:
183
+ primes.append(num)
184
+ return {"primes_count": len(primes), "primes": primes}
185
+
186
+ @offload
187
+ def data_processing(data_size):
188
+ """معالجة بيانات كبيرة"""
189
+ processed_data = []
190
+ for i in range(data_size):
191
+ result = sum(math.sin(x) * math.cos(x) for x in range(i, i + 100))
192
+ processed_data.append(result)
193
+ return {"processed_items": len(processed_data)}
194
+
195
+ @offload
196
+ def image_processing_emulation(iterations):
197
+ """محاكاة معالجة الصور"""
198
+ results = []
199
+ for i in range(iterations):
200
+ fake_processing = sum(math.sqrt(x) for x in range(i * 100, (i + 1) * 100))
201
+ results.append(fake_processing)
202
+ time.sleep(0.01)
203
+ return {"iterations": iterations, "results": results}
package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
package.json ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "rest-express",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "scripts": {
7
+ "dev": "NODE_ENV=development tsx server/index.ts",
8
+ "build": "vite build && esbuild server/index.ts --platform=node --packages=external --bundle --format=esm --outdir=dist",
9
+ "start": "NODE_ENV=production node dist/index.js",
10
+ "check": "tsc",
11
+ "db:push": "drizzle-kit push"
12
+ },
13
+ "dependencies": {
14
+ "@hookform/resolvers": "^3.10.0",
15
+ "@jridgewell/trace-mapping": "^0.3.25",
16
+ "@neondatabase/serverless": "^0.10.4",
17
+ "@radix-ui/react-accordion": "^1.2.4",
18
+ "@radix-ui/react-alert-dialog": "^1.1.7",
19
+ "@radix-ui/react-aspect-ratio": "^1.1.3",
20
+ "@radix-ui/react-avatar": "^1.1.4",
21
+ "@radix-ui/react-checkbox": "^1.1.5",
22
+ "@radix-ui/react-collapsible": "^1.1.4",
23
+ "@radix-ui/react-context-menu": "^2.2.7",
24
+ "@radix-ui/react-dialog": "^1.1.7",
25
+ "@radix-ui/react-dropdown-menu": "^2.1.7",
26
+ "@radix-ui/react-hover-card": "^1.1.7",
27
+ "@radix-ui/react-label": "^2.1.3",
28
+ "@radix-ui/react-menubar": "^1.1.7",
29
+ "@radix-ui/react-navigation-menu": "^1.2.6",
30
+ "@radix-ui/react-popover": "^1.1.7",
31
+ "@radix-ui/react-progress": "^1.1.3",
32
+ "@radix-ui/react-radio-group": "^1.2.4",
33
+ "@radix-ui/react-scroll-area": "^1.2.4",
34
+ "@radix-ui/react-select": "^2.1.7",
35
+ "@radix-ui/react-separator": "^1.1.3",
36
+ "@radix-ui/react-slider": "^1.2.4",
37
+ "@radix-ui/react-slot": "^1.2.0",
38
+ "@radix-ui/react-switch": "^1.1.4",
39
+ "@radix-ui/react-tabs": "^1.1.4",
40
+ "@radix-ui/react-toast": "^1.2.7",
41
+ "@radix-ui/react-toggle": "^1.1.3",
42
+ "@radix-ui/react-toggle-group": "^1.1.3",
43
+ "@radix-ui/react-tooltip": "^1.2.0",
44
+ "@tanstack/react-query": "^5.60.5",
45
+ "bonjour-service": "^1.3.0",
46
+ "class-variance-authority": "^0.7.1",
47
+ "clsx": "^2.1.1",
48
+ "cmdk": "^1.1.1",
49
+ "connect-pg-simple": "^10.0.0",
50
+ "date-fns": "^3.6.0",
51
+ "drizzle-orm": "^0.39.1",
52
+ "drizzle-zod": "^0.7.0",
53
+ "embla-carousel-react": "^8.6.0",
54
+ "express": "^4.21.2",
55
+ "express-session": "^1.18.1",
56
+ "framer-motion": "^11.13.1",
57
+ "input-otp": "^1.4.2",
58
+ "lucide-react": "^0.453.0",
59
+ "memorystore": "^1.6.7",
60
+ "nanoid": "^5.1.5",
61
+ "next-themes": "^0.4.6",
62
+ "passport": "^0.7.0",
63
+ "passport-local": "^1.0.0",
64
+ "react": "^18.3.1",
65
+ "react-day-picker": "^8.10.1",
66
+ "react-dom": "^18.3.1",
67
+ "react-hook-form": "^7.55.0",
68
+ "react-icons": "^5.4.0",
69
+ "react-resizable-panels": "^2.1.7",
70
+ "recharts": "^2.15.2",
71
+ "tailwind-merge": "^2.6.0",
72
+ "tailwindcss-animate": "^1.0.7",
73
+ "tw-animate-css": "^1.2.5",
74
+ "vaul": "^1.1.2",
75
+ "wouter": "^3.3.5",
76
+ "ws": "^8.18.0",
77
+ "zod": "^3.24.2",
78
+ "zod-validation-error": "^3.4.0"
79
+ },
80
+ "devDependencies": {
81
+ "@replit/vite-plugin-cartographer": "^0.2.7",
82
+ "@replit/vite-plugin-runtime-error-modal": "^0.0.3",
83
+ "@tailwindcss/typography": "^0.5.15",
84
+ "@tailwindcss/vite": "^4.1.3",
85
+ "@types/connect-pg-simple": "^7.0.3",
86
+ "@types/express": "4.17.21",
87
+ "@types/express-session": "^1.18.0",
88
+ "@types/node": "20.16.11",
89
+ "@types/passport": "^1.0.16",
90
+ "@types/passport-local": "^1.0.38",
91
+ "@types/react": "^18.3.11",
92
+ "@types/react-dom": "^18.3.1",
93
+ "@types/ws": "^8.5.13",
94
+ "@vitejs/plugin-react": "^4.3.2",
95
+ "autoprefixer": "^10.4.20",
96
+ "drizzle-kit": "^0.30.4",
97
+ "electron": "^37.1.0",
98
+ "electron-builder": "^26.0.12",
99
+ "esbuild": "^0.25.0",
100
+ "postcss": "^8.4.47",
101
+ "tailwindcss": "^3.4.17",
102
+ "tsx": "^4.19.1",
103
+ "typescript": "5.6.3",
104
+ "vite": "^5.4.19"
105
+ },
106
+ "optionalDependencies": {
107
+ "bufferutil": "^4.0.8"
108
+ }
109
+ }
peer_discovery.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ import os
3
+ import socket
4
+ import threading
5
+ import time
6
+ import logging
7
+
8
+ import requests
9
+ from zeroconf import Zeroconf, ServiceInfo, ServiceBrowser
10
+
11
+ # 👇 إعداد الـ peer discovery عبر LAN وInternet
12
+ SERVICE = "_tasknode._tcp.local."
13
+ PORT = int(os.getenv("CPU_PORT", "7520"))
14
+ PEERS = set() # مجموعة URLs للأقران (/run)
15
+
16
+ # 🌐 خادم وسيط مركزي (Central Registry)
17
+ CENTRAL_REGISTRY_URL = "https://cv4790811.regru.cloud"
18
+
19
+ # 🟢 دالة لحساب IP العام أو المحلي
20
+ # تستخدم HTTP API للحصول على IP عام ثم fallback إلى LAN
21
+
22
+ def get_local_ip():
23
+ # حاول الحصول على IP عام
24
+ try:
25
+ r = requests.get("https://api.ipify.org?format=json", timeout=3)
26
+ r.raise_for_status()
27
+ data = r.json()
28
+ return data.get("ip", "127.0.0.1")
29
+ except Exception:
30
+ # fallback إلى LAN IP
31
+ try:
32
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
33
+ s.connect(("8.8.8.8", 80))
34
+ return s.getsockname()[0]
35
+ except Exception:
36
+ return "127.0.0.1"
37
+ finally:
38
+ try:
39
+ s.close()
40
+ except Exception:
41
+ pass
42
+
43
+ # ❶ تسجيل الخدمة في شبكة LAN عبر Zeroconf
44
+ # للحفاظ على قدرة اكتشاف peers في نفس الشبكة المحلية
45
+ def register_service_lan():
46
+ zc = Zeroconf()
47
+ local_ip = get_local_ip()
48
+ info = ServiceInfo(
49
+ SERVICE,
50
+ f"{socket.gethostname()}.{SERVICE}",
51
+ addresses=[socket.inet_aton(local_ip)],
52
+ port=PORT,
53
+ properties={b'load': b'0'}
54
+ )
55
+ try:
56
+ zc.register_service(info)
57
+ print(f"✅ LAN service registered: {local_ip}:{PORT}")
58
+ except Exception as e:
59
+ print(f"❌ LAN registration failed: {e}")
60
+
61
+ # ❷ مستمع لاكتشاف أجهزة LAN عبر Zeroconf
62
+ class Listener:
63
+ def add_service(self, zc, t, name):
64
+ info = zc.get_service_info(t, name)
65
+ if info and info.addresses:
66
+ ip = socket.inet_ntoa(info.addresses[0])
67
+ peer_url = f"http://{ip}:{info.port}/run"
68
+ if peer_url not in PEERS:
69
+ PEERS.add(peer_url)
70
+ print(f"🔗 LAN peer discovered: {peer_url}")
71
+ def update_service(self, zc, t, name):
72
+ self.add_service(zc, t, name)
73
+ def remove_service(self, zc, t, name):
74
+ print(f"❌ LAN peer removed: {name}")
75
+
76
+ # حلقة اكتشاف LAN مستمرة
77
+ def discover_lan_loop():
78
+ zc = Zeroconf()
79
+ ServiceBrowser(zc, SERVICE, Listener())
80
+ print(f"🔍 Started LAN discovery for {SERVICE}")
81
+ while True:
82
+ time.sleep(5)
83
+
84
+ # ❸ تسجيل العقدة في الخادم المركزي
85
+ # ترسل بياناتها إلى /register وتضيف باقي الأقران
86
+ def register_with_central():
87
+ node_id = os.getenv("NODE_ID", socket.gethostname())
88
+ info = {"node_id": node_id, "ip": get_local_ip(), "port": PORT}
89
+ try:
90
+ resp = requests.post(f"{CENTRAL_REGISTRY_URL}/register", json=info, timeout=5)
91
+ resp.raise_for_status()
92
+ peers_list = resp.json()
93
+ for p in peers_list:
94
+ peer_url = f"http://{p['ip']}:{p['port']}/run"
95
+ if peer_url not in PEERS:
96
+ PEERS.add(peer_url)
97
+ print(f"🌐 Registered and discovered central peer: {peer_url}")
98
+ except Exception as e:
99
+ print(f"❌ Central registration failed: {e}")
100
+
101
+ # ❹ مزامنة الأقران من الخادم المركزي بشكل دوري
102
+ # تُحدّث مجموعة PEERS كل 5 دقائق عن طريق /peers endpoint
103
+ def fetch_central_loop():
104
+ print("🔄 Central registry sync loop started")
105
+ while True:
106
+ try:
107
+ resp = requests.get(f"{CENTRAL_REGISTRY_URL}/peers", timeout=5)
108
+ resp.raise_for_status()
109
+ peers_list = resp.json()
110
+ for p in peers_list:
111
+ peer_url = f"http://{p['ip']}:{p['port']}/run"
112
+ if peer_url not in PEERS:
113
+ PEERS.add(peer_url)
114
+ print(f"🌐 Central peer discovered: {peer_url}")
115
+ except Exception as e:
116
+ print(f"⚠️ Fetch central peers failed: {e}")
117
+ time.sleep(300)
118
+
119
+ # 🚀 دالة الإدخال الرئيسيّة
120
+ def main():
121
+ logging.basicConfig(level=logging.INFO)
122
+ print("🚀 Peer Discovery System starting...")
123
+
124
+ # Zeroconf LAN registration & discovery
125
+ threading.Thread(target=register_service_lan, daemon=True).start()
126
+ threading.Thread(target=discover_lan_loop, daemon=True).start()
127
+
128
+ # التسجيل في الخادم الوسيط ومزامنة الأقران
129
+ register_with_central()
130
+ threading.Thread(target=fetch_central_loop, daemon=True).start()
131
+
132
+ # إبقاء السكربت قيد التشغيل
133
+ try:
134
+ while True:
135
+ time.sleep(60)
136
+ except KeyboardInterrupt:
137
+ print("🛑 Exiting...")
138
+
139
+ if __name__ == "__main__":
140
+ main()
peer_registry.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import socket
2
+ import time
3
+ from zeroconf import Zeroconf, ServiceBrowser, ServiceInfo
4
+
5
+ class Listener:
6
+ def __init__(self):
7
+ self.peers = []
8
+
9
+ def add_service(self, zc, type_, name):
10
+ info = zc.get_service_info(type_, name)
11
+ if info:
12
+ ip = socket.inet_ntoa(info.addresses[0])
13
+ peer_data = {
14
+ 'ip': ip,
15
+ 'port': info.port,
16
+ 'load': float(info.properties.get(b'load', 0)),
17
+ 'node_id': info.properties.get(b'node_id', b'unknown').decode(),
18
+ 'last_seen': time.time()
19
+ }
20
+ if peer_data not in self.peers:
21
+ self.peers.append(peer_data)
22
+
23
+ def update_service(self, zc, type_, name):
24
+ """مطلوب بواسطة Zeroconf"""
25
+ self.add_service(zc, type_, name)
26
+
27
+ def remove_service(self, zc, type_, name):
28
+ """اختياري"""
29
+ pass
30
+
31
+ def register_service(ip: str, port: int, load: float = 0.0):
32
+ zc = Zeroconf()
33
+ service_name = f"{socket.gethostname()}-{int(time.time())}._tasknode._tcp.local."
34
+ service_info = ServiceInfo(
35
+ "_tasknode._tcp.local.",
36
+ service_name,
37
+ addresses=[socket.inet_aton(ip)],
38
+ port=port,
39
+ properties={
40
+ b'load': str(load).encode(),
41
+ b'node_id': socket.gethostname().encode()
42
+ }
43
+ )
44
+ zc.register_service(service_info)
45
+ print(f"✅ Service registered: {service_name} @ {ip}:{port}")
46
+ return zc # أبقِ المرجع حياً
47
+
48
+ def discover_peers(timeout=2):
49
+ zc = Zeroconf()
50
+ listener = Listener()
51
+ ServiceBrowser(zc, "_tasknode._tcp.local.", listener)
52
+ time.sleep(timeout)
53
+ zc.close()
54
+ return listener.peers
55
+
56
+ if __name__ == "__main__":
57
+ local_ip = socket.gethostbyname(socket.gethostname())
58
+ port = 7520
59
+
60
+ zc = register_service(local_ip, port, load=0.1)
61
+
62
+ peers = discover_peers()
63
+ print("✅ Available peers:", peers)
64
+
65
+ input("🔵 Press Enter to exit...\n")
66
+ zc.close()
67
+
peer_server.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # peer_server.py
2
+
3
+ from flask import Flask, request, jsonify # استيراد request و jsonify مع Flask
4
+ import psutil
5
+ import smart_tasks
6
+ import time
7
+ import socket
8
+ import peer_discovery # إذا كان يستخدم لاحقًا
9
+
10
+ app = Flask(__name__) # إنشاء التطبيق
11
+
12
+ @app.route("/cpu")
13
+ def cpu():
14
+ # يعيد نسبة استخدام المعالج
15
+ return jsonify(usage=psutil.cpu_percent(interval=0.3))
16
+
17
+ @app.route("/run", methods=["POST"])
18
+ def run():
19
+ data = request.get_json(force=True)
20
+ fn_name = data.get("func")
21
+ fn = getattr(smart_tasks, fn_name, None)
22
+ if not fn:
23
+ return jsonify(error="function-not-found"), 404
24
+ try:
25
+ start = time.time()
26
+ result = fn(*data.get("args", []), **data.get("kwargs", {}))
27
+ return jsonify(
28
+ result=result,
29
+ host=socket.gethostname(),
30
+ took=round(time.time() - start, 3)
31
+ )
32
+ except Exception as e:
33
+ return jsonify(error=str(e)), 500
34
+
35
+ if __name__ == "__main__": # التصحيح هنا
36
+ app.run(host="0.0.0.0", port=7520)
37
+
peer_statistics.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections import Counter
2
+ import ipaddress
3
+
4
+ def print_peer_statistics(discovered_peers):
5
+ ips = [peer['ip'] for peer in discovered_peers]
6
+ ip_counts = Counter(ips)
7
+
8
+ def classify_ip(ip):
9
+ try:
10
+ ip_obj = ipaddress.ip_address(ip)
11
+ if ip_obj.is_private:
12
+ return 'داخلي'
13
+ else:
14
+ return 'خارجي'
15
+ except ValueError:
16
+ return 'محلي'
17
+
18
+ print("\n📊 إحصائية عدد الأجهزة حسب النوع:\n")
19
+ for ip, count in ip_counts.items():
20
+ category = classify_ip(ip)
21
+ print(f"• {ip} ({category}): {count} جهاز")
postcss.config.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
processor_manager.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # processor_manager.py
2
+
3
+ import psutil
4
+ from collections import deque
5
+ import logging
6
+
7
+ logging.basicConfig(level=logging.INFO)
8
+
9
+ class ResourceMonitor:
10
+ def __init__(self):
11
+ self.cpu_history = deque(maxlen=10)
12
+ self.mem_history = deque(maxlen=10)
13
+ # حد استقبال المهمات الآن 40% CPU بدل 30%
14
+ self.receive_cpu_threshold = 0.40
15
+
16
+ def current_load(self):
17
+ cpu = psutil.cpu_percent(interval=0.5) / 100.0 # كنسبة (0.0 - 1.0)
18
+ mem = psutil.virtual_memory().available / (1024**2) # متاح بالـ MB
19
+
20
+ self.cpu_history.append(cpu)
21
+ self.mem_history.append(mem)
22
+
23
+ avg_cpu = sum(self.cpu_history) / len(self.cpu_history)
24
+ avg_mem = sum(self.mem_history) / len(self.mem_history)
25
+
26
+ logging.info(f"Instant CPU: {cpu:.2%}, Instant MEM: {mem:.1f}MB")
27
+ logging.info(f"Avg CPU: {avg_cpu:.2%}, Avg MEM: {avg_mem:.1f}MB")
28
+
29
+ recommendation = "offload" if (avg_cpu > 0.5 or avg_mem < 2048) else "local"
30
+ can_receive = avg_cpu <= self.receive_cpu_threshold
31
+
32
+ return {
33
+ "instant": {"cpu": cpu, "mem": mem},
34
+ "average": {"cpu": avg_cpu, "mem": avg_mem},
35
+ "recommendation": recommendation,
36
+ "can_receive": can_receive
37
+ }
38
+
39
+ def trigger_offload():
40
+ """عملية توزيع المهام التجريبية"""
41
+ print("⚠️ تم استدعاء توزيع المهام (اختباري)")
42
+
43
+ def should_offload(task_complexity=0):
44
+ monitor = ResourceMonitor()
45
+ status = monitor.current_load()
46
+
47
+ avg_cpu = status['average']['cpu']
48
+ avg_mem = status['average']['mem']
49
+
50
+ if avg_cpu > 0.6 or avg_mem < 2048 or task_complexity > 75:
51
+ trigger_offload()
52
+ return True
53
+
54
+ return False
55
+
56
+ def can_receive_task():
57
+ """
58
+ يعيد True إذا كان بالإمكان استقبال مهمة جديدة،
59
+ أي عندما يكون متوسط استهلاك الـ CPU ≤ 40%.
60
+ """
61
+ return ResourceMonitor().current_load()["can_receive"]
62
+
63
+ if __name__ == "__main__":
64
+ status = ResourceMonitor().current_load()
65
+ if not status["can_receive"]:
66
+ print(f"🚫 لا يمكن استقبال مهام جديدة (Avg CPU: {status['average']['cpu']:.0%})")
67
+ else:
68
+ print(f"✅ يمكن استقبال مهام جديدة (Avg CPU: {status['average']['cpu']:.0%})")
69
+
70
+ if should_offload(80):
71
+ print("💡 ينصح بتوزيع المهمة")
72
+ else:
73
+ print("✅ يمكن تنفيذ المهمة محلياً")
project_identifier.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ """
3
+ project_identifier.py - معرف المشروع للتحقق من الهوية
4
+ """
5
+ import json
6
+ from flask import jsonify
7
+
8
+ PROJECT_INFO = {
9
+ "project_name": "distributed-task-system",
10
+ "version": "1.0",
11
+ "description": "نظام توزيع المهام الذكي",
12
+ "author": "DTS Team",
13
+ "features": [
14
+ "matrix_multiply",
15
+ "prime_calculation",
16
+ "data_processing",
17
+ "video_processing",
18
+ "live_streaming",
19
+ "enhanced_ai"
20
+ ],
21
+ "signature": "DTS_2024_SMART_DISTRIBUTION"
22
+ }
23
+
24
+ def get_project_info():
25
+ """إرجاع معلومات المشروع"""
26
+ return PROJECT_INFO
27
+
28
+ def verify_project_compatibility(remote_info):
29
+ """التحقق من توافق المشروع مع جهاز آخر"""
30
+ if not isinstance(remote_info, dict):
31
+ return False
32
+
33
+ return (
34
+ remote_info.get("project_name") == PROJECT_INFO["project_name"] and
35
+ remote_info.get("version") == PROJECT_INFO["version"] and
36
+ remote_info.get("signature") == PROJECT_INFO["signature"]
37
+ )
38
+
39
+ def create_project_endpoint():
40
+ """إنشاء endpoint لمعلومات المشروع"""
41
+ return jsonify(PROJECT_INFO)
quick_connection_test.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #!/usr/bin/env python3
3
+ # اختبار سريع للتحقق من حالة النظام
4
+
5
+ import requests
6
+ import time
7
+ import json
8
+ from offload_lib import discover_peers, matrix_multiply
9
+
10
+ def test_connection():
11
+ """اختبار سريع للاتصال"""
12
+ print("🚀 اختبار اتصال سريع...")
13
+
14
+ # 1. فحص الخادم المحلي
15
+ try:
16
+ response = requests.get("http://localhost:7520/health", timeout=3)
17
+ if response.status_code == 200:
18
+ print("✅ الخادم المحلي يعمل")
19
+ else:
20
+ print("❌ مشكلة في الخادم المحلي")
21
+ return False
22
+ except:
23
+ print("❌ الخادم المحلي غير متاح")
24
+ return False
25
+
26
+ # 2. اختبار اكتشاف الأجهزة
27
+ print("🔍 البحث عن الأجهزة...")
28
+ peers = discover_peers(timeout=2)
29
+ print(f"📱 تم اكتشاف {len(peers)} جهاز")
30
+
31
+ # 3. اختبار مهمة بسيطة
32
+ print("⚙️ اختبار مهمة بسيطة...")
33
+ start_time = time.time()
34
+ try:
35
+ result = matrix_multiply(5)
36
+ duration = time.time() - start_time
37
+ print(f"✅ تمت المعالجة في {duration:.2f} ثانية")
38
+ print(f"📊 النتيجة: مصفوفة {len(result)}x{len(result[0])}")
39
+ return True
40
+ except Exception as e:
41
+ print(f"❌ فشل في المعالجة: {e}")
42
+ return False
43
+
44
+ if __name__ == "__main__":
45
+ if test_connection():
46
+ print("\n🎉 النظام يعمل بشكل جيد!")
47
+ print("💡 يمكنك الآن تشغيل: python test_distributed_system.py")
48
+ else:
49
+ print("\n⚠️ هناك مشاكل تحتاج إصلاح")
quick_test.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #!/usr/bin/env python3
3
+ # quick_test.py - اختبار سريع لنظام التوزيع
4
+
5
+ import requests
6
+ import time
7
+ from offload_lib import discover_peers
8
+
9
+ def quick_connectivity_test():
10
+ """اختبار سريع للاتصال والتوزيع"""
11
+ print("🚀 اختبار سريع لنظام التوزيع")
12
+ print("-" * 40)
13
+
14
+ # 1. اكتشاف الأجهزة
15
+ print("🔍 البحث عن الأجهزة...")
16
+ peers = discover_peers(timeout=2)
17
+
18
+ if not peers:
19
+ print("❌ لم يتم العثور على أجهزة أخرى")
20
+ return False
21
+
22
+ print(f"✅ تم العثور على {len(peers)} جهاز:")
23
+ for peer in peers:
24
+ print(f" 📱 {peer}")
25
+
26
+ # 2. اختبار الاتصال السريع
27
+ working_peers = []
28
+ for peer in peers:
29
+ try:
30
+ response = requests.get(f"{peer}/health", timeout=3)
31
+ if response.status_code == 200:
32
+ working_peers.append(peer)
33
+ print(f"✅ {peer} - متصل ويعمل")
34
+ else:
35
+ print(f"⚠️ {peer} - يستجيب لكن بخطأ")
36
+ except:
37
+ print(f"❌ {peer} - غير متصل")
38
+
39
+ if not working_peers:
40
+ print("❌ لا توجد أجهزة تعمل بشكل صحيح")
41
+ return False
42
+
43
+ # 3. اختبار إرسال مهمة بسيطة
44
+ print(f"\n📡 اختبار إرسال مهمة إلى {working_peers[0]}...")
45
+
46
+ task = {
47
+ "func": "matrix_multiply",
48
+ "args": [5],
49
+ "kwargs": {}
50
+ }
51
+
52
+ try:
53
+ start_time = time.time()
54
+ response = requests.post(f"{working_peers[0]}/run", json=task, timeout=10)
55
+ duration = time.time() - start_time
56
+
57
+ if response.status_code == 200:
58
+ result = response.json()
59
+ print(f"✅ تمت المعالجة بنجاح في {duration:.2f} ثانية")
60
+ print(f"📊 النتيجة: تم ضرب مصفوفة 5x5")
61
+ return True
62
+ else:
63
+ print(f"❌ فشل في المعالجة - كود الخطأ: {response.status_code}")
64
+ return False
65
+
66
+ except Exception as e:
67
+ print(f"❌ خطأ في الإرسال: {str(e)}")
68
+ return False
69
+
70
+ if __name__ == "__main__":
71
+ success = quick_connectivity_test()
72
+
73
+ if success:
74
+ print("\n🎉 النظام يعمل بشكل صحيح!")
75
+ print("💡 يمكنك الآن تشغيل الاختبار الشامل: python test_distributed_system.py")
76
+ else:
77
+ print("\n⚠️ هناك مشاكل في النظام، تحقق من:")
78
+ print(" 1. تشغيل الخادم على الأجهزة الأخرى")
79
+ print(" 2. الاتصال بالشبكة")
80
+ print(" 3. إعدادات الجدار الناري")
remote_executor.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # remote_executor.py (مُحدَّث: يدعم التشفير والتوقيع واختيار السيرفر ديناميكياً)
2
+ # ============================================================
3
+ # يرسل المهمّة إلى سيرفر RPC خارجي مع تشفير + توقيع،
4
+ # أو يعمل بوضع JSON صافٍ لو لم يكن SecurityManager مفعَّل.
5
+ # يستخدم قائمة الأقران المكتشفة لاختيار الـ endpoint بدل IP ثابت.
6
+ # ============================================================
7
+
8
+ import requests
9
+ import json
10
+ import os
11
+ from typing import Any
12
+
13
+ # قائمة الأقران (URLs) المستخرجة من peer_discovery
14
+ from peer_discovery import PEERS
15
+
16
+ # عنوان افتراضي احتياطي (يمكن تغييره بمتغير بيئي REMOTE_SERVER)
17
+ FALLBACK_SERVER = os.getenv(
18
+ "REMOTE_SERVER",
19
+ "http://89.111.171.92:7520/run"
20
+ )
21
+
22
+ # محاولة استيراد SecurityManager (اختياري)
23
+ try:
24
+ from security_layer import SecurityManager
25
+ security = SecurityManager(os.getenv("SHARED_SECRET", "my_shared_secret_123"))
26
+ SECURITY_ENABLED = True
27
+ except ImportError:
28
+ security = None
29
+ SECURITY_ENABLED = False
30
+
31
+
32
+ def _choose_remote_server() -> str:
33
+ """
34
+ يختار عنوان السيرفر الذي سترسل إليه المهمة:
35
+ 1) إذا عُيّن متغير بيئي REMOTE_SERVER، يُستخدم.
36
+ 2) وإلا إذا اكتشفنا أقران عبر LAN/Internet، نأخذ أولهم.
37
+ 3) وإلا نعود إلى FALLBACK_SERVER.
38
+ """
39
+ env_url = os.getenv("REMOTE_SERVER")
40
+ if env_url:
41
+ return env_url.rstrip('/') + '/run'
42
+ # PEERS يحوي عناوين كاملة من نوع http://ip:port/run
43
+ if PEERS:
44
+ # نختار الحد الأدنى من التحميل (اختياري) أو أول عنصر
45
+ # هنا ببساطة نأخذ أول URL
46
+ return next(iter(PEERS))
47
+ # استخدام الافتراضي
48
+ return FALLBACK_SERVER.rstrip('/') + '/run'
49
+
50
+
51
+ def execute_remotely(
52
+ func_name: str,
53
+ args: list[Any] | None = None,
54
+ kwargs: dict[str, Any] | None = None
55
+ ) -> Any:
56
+ """إرسال استدعاء دالة إلى الخادم البعيد وإرجاع النتيجة."""
57
+ if args is None:
58
+ args = []
59
+ if kwargs is None:
60
+ kwargs = {}
61
+
62
+ task = {
63
+ "func": func_name,
64
+ "args": args,
65
+ "kwargs": kwargs,
66
+ "sender_id": "client_node"
67
+ }
68
+
69
+ # اختيار السيرفر الصحيح ديناميكياً
70
+ target_url = _choose_remote_server()
71
+
72
+ try:
73
+ if SECURITY_ENABLED:
74
+ # 1) وقّع المهمة ثم شفّرها
75
+ signed_task = security.sign_task(task)
76
+ encrypted = security.encrypt_data(json.dumps(signed_task).encode())
77
+
78
+ headers = {
79
+ "X-Signature": security.signature_hex,
80
+ "Content-Type": "application/octet-stream"
81
+ }
82
+ payload = encrypted # خام ثنائي
83
+ resp = requests.post(
84
+ target_url,
85
+ headers=headers,
86
+ data=payload,
87
+ timeout=15
88
+ )
89
+ else:
90
+ # وضع التطوير: أرسل JSON صريح
91
+ headers = {"Content-Type": "application/json"}
92
+ resp = requests.post(
93
+ target_url,
94
+ headers=headers,
95
+ json=task,
96
+ timeout=15
97
+ )
98
+
99
+ resp.raise_for_status()
100
+ data = resp.json()
101
+ return data.get("result", "⚠️ لا يوجد نتيجة")
102
+
103
+ except Exception as e:
104
+ return f"❌ فشل التنفيذ البعيد على {target_url}: {e}"
replit.md ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Distributed Task System (DTS)
2
+
3
+ ## Overview
4
+
5
+ The Distributed Task System (DTS) is a full-stack web application that manages distributed computing across multiple nodes. It features a React frontend with shadcn/ui components and an Express.js backend with PostgreSQL database integration via Drizzle ORM. The system enables peer discovery, task distribution, load balancing, and real-time monitoring of distributed computing resources.
6
+
7
+ ## System Architecture
8
+
9
+ ### Frontend Architecture
10
+ - **Framework**: React 18 with TypeScript
11
+ - **Build Tool**: Vite with custom configuration
12
+ - **UI Library**: shadcn/ui components built on Radix UI primitives
13
+ - **Styling**: Tailwind CSS with custom dark theme
14
+ - **State Management**: TanStack Query for server state management
15
+ - **Routing**: Wouter for lightweight client-side routing
16
+ - **Real-time Updates**: WebSocket connection for live system monitoring
17
+
18
+ ### Backend Architecture
19
+ - **Runtime**: Node.js with Express.js framework
20
+ - **Database**: PostgreSQL with Drizzle ORM
21
+ - **Real-time Communication**: WebSocket Server for live updates
22
+ - **Task Execution**: Custom task executor with built-in operations
23
+ - **Peer Discovery**: Bonjour/mDNS-based service discovery
24
+ - **Security**: Custom security manager with encryption and digital signatures
25
+
26
+ ### Key Components
27
+
28
+ #### Database Schema
29
+ - **Nodes Table**: Stores information about connected computing nodes (id, name, ip, port, status, load, capabilities)
30
+ - **Tasks Table**: Manages distributed tasks (id, name, status, nodeId, complexity, duration, result, error)
31
+ - **System Metrics Table**: Tracks performance metrics (nodeId, cpuUsage, memoryUsage, timestamp)
32
+ - **System Logs Table**: Centralized logging (level, message, source, nodeId, timestamp)
33
+
34
+ #### Services
35
+ - **OffloadSystem**: Orchestrates task distribution and peer management
36
+ - **PeerDiscovery**: Uses Bonjour protocol for automatic node discovery on the network
37
+ - **TaskExecutor**: Handles built-in tasks like matrix multiplication, prime calculation, and data processing
38
+ - **SecurityManager**: Manages payload encryption, digital signatures, and secure communication
39
+ - **SystemMonitor**: Tracks system performance and resource utilization
40
+
41
+ #### Frontend Components
42
+ - **Dashboard**: Main interface showing system overview and metrics
43
+ - **MetricsGrid**: Real-time system performance visualization
44
+ - **NodesTable**: Connected nodes management interface
45
+ - **TaskActivity**: Task execution monitoring and status tracking
46
+ - **SecurityPanel**: Security status indicators
47
+ - **SystemLogs**: Centralized log viewing interface
48
+
49
+ ## Data Flow
50
+
51
+ 1. **Node Registration**: Nodes automatically discover and register with the system via mDNS
52
+ 2. **Task Submission**: Tasks are submitted through the web interface or API
53
+ 3. **Load Balancing**: System evaluates node capacity and distributes tasks accordingly
54
+ 4. **Task Execution**: Tasks are executed on selected nodes with real-time status updates
55
+ 5. **Result Collection**: Results are collected and stored in the database
56
+ 6. **Real-time Updates**: WebSocket connections push updates to connected clients
57
+
58
+ ## External Dependencies
59
+
60
+ ### Production Dependencies
61
+ - **Database**: @neondatabase/serverless for PostgreSQL connection
62
+ - **ORM**: drizzle-orm and drizzle-zod for database operations
63
+ - **UI Components**: @radix-ui/* packages for accessible UI primitives
64
+ - **Networking**: bonjour-service for peer discovery
65
+ - **Real-time**: ws (WebSocket) for live updates
66
+ - **Query Management**: @tanstack/react-query for server state
67
+ - **Session Management**: connect-pg-simple for session storage
68
+
69
+ ### Development Dependencies
70
+ - **Build Tools**: Vite, esbuild for production builds
71
+ - **Type Safety**: TypeScript with strict configuration
72
+ - **Code Quality**: ESLint integration (implied by tsconfig)
73
+ - **Development Experience**: @replit/vite-plugin-runtime-error-modal and cartographer
74
+
75
+ ## Deployment Strategy
76
+
77
+ ### Development Mode
78
+ - Frontend served via Vite dev server with HMR
79
+ - Backend runs with tsx for TypeScript execution
80
+ - Database migrations handled via drizzle-kit push
81
+ - Automatic service discovery in local network
82
+
83
+ ### Production Build
84
+ 1. Frontend built with Vite to `dist/public`
85
+ 2. Backend compiled with esbuild to `dist/index.js`
86
+ 3. Single Node.js process serves both static files and API
87
+ 4. PostgreSQL database connection via environment variables
88
+ 5. WebSocket server integrated with HTTP server
89
+
90
+ ### Environment Configuration
91
+ - `DATABASE_URL`: PostgreSQL connection string (required)
92
+ - `NODE_ENV`: Environment mode (development/production)
93
+ - `NODE_NAME`: Custom node identifier
94
+ - `SHARED_SECRET`: Security encryption key
95
+
96
+ ## Changelog
97
+ - June 29, 2025. Initial setup
98
+ - June 29, 2025. Added broadcast messaging capability to send messages to all connected devices from the index page
99
+ - Created broadcast_messages table in PostgreSQL database
100
+ - Implemented API endpoints for sending and retrieving broadcast messages
101
+ - Added real-time WebSocket broadcasting to all connected clients
102
+ - Created bilingual UI components with Arabic interface
103
+ - Added navigation link in sidebar for easy access
104
+ - Integrated with existing authentication and security systems
105
+
106
+ ## User Preferences
107
+
108
+ Preferred communication style: Simple, everyday language.
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ Flask
2
+ flask_cors
3
+ requests
4
+ psutil
5
+ zeroconf
6
+ cryptography
7
+ numpy
8
+ networkx
rpc_server.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # rpc_server.py (مُحدَّث بحيث يدعم التشفير الاختياري)
2
+ # ============================================================
3
+ # خادِم يستقبل مهام عن بُعد:
4
+ # • إن وصلته بيانات خام (Encrypted) في Body → يفك تشفيرها ويتحقق من التوقيع.
5
+ # • وإلا إن وصل JSON خام في Content‑Type: application/json → ينفّذ مباشرة (وضع تطويـر).
6
+ # ============================================================
7
+
8
+ from flask import Flask, request, jsonify
9
+ import smart_tasks # «your_tasks» تمّ استيراده تحت هذا الاسم فى main.py
10
+ import logging, json
11
+ from security_layer import SecurityManager
12
+
13
+ SECURITY = SecurityManager("my_shared_secret_123")
14
+
15
+ logging.basicConfig(
16
+ filename="server.log",
17
+ level=logging.INFO,
18
+ format="%(asctime)s - %(levelname)s - %(message)s"
19
+ )
20
+
21
+ app = Flask(name)
22
+
23
+ # ------------------------------------------------------------------
24
+ @app.route("/health")
25
+ def health():
26
+ return jsonify(status="ok")
27
+
28
+ # ------------------------------------------------------------------
29
+ @app.route("/run", methods=["POST"])
30
+ def run():
31
+ try:
32
+ # 1) حاول قراءة كـ JSON مباشر (وضع التطويـر)
33
+ if request.is_json:
34
+ data = request.get_json()
35
+ else:
36
+ # 2) وإلا اعتبره Payload مُشفَّر (وضع الإنتاج)
37
+ encrypted = request.get_data()
38
+ try:
39
+ decrypted = SECURITY.decrypt_data(encrypted)
40
+ data = json.loads(decrypted.decode())
41
+ except Exception as e:
42
+ logging.error(f"⚠️ فشل فك التشفير: {e}")
43
+ return jsonify(error="Decryption failed"), 400
44
+
45
+ # 3) التحقّق من التوقيع إن وُجد
46
+ if "_signature" in data:
47
+ if not SECURITY.verify_task(data):
48
+ logging.warning("❌ توقيع غير صالح")
49
+ return jsonify(error="Invalid signature"), 403
50
+ # أزل عناصر موقّعة إضافية
51
+ data = {k: v for k, v in data.items() if k not in ("_signature", "sender_id")}
52
+
53
+ func_name = data.get("func")
54
+ args = data.get("args", [])
55
+ kwargs = data.get("kwargs", {})
56
+
57
+ fn = getattr(smart_tasks, func_name, None)
58
+ if not fn:
59
+ logging.warning(f"❌ لم يتم العثور على الدالة: {func_name}")
60
+ return jsonify(error="Function not found"), 404
61
+
62
+ logging.info(f"⚙️ تنفيذ الدالة: {func_name} من جهاز آخر")
63
+ result = fn(*args, **kwargs)
64
+ return jsonify(result=result)
65
+
66
+ except Exception as e:
67
+ logging.error(f"🔥 خطأ أثناء تنفيذ المهمة: {str(e)}")
68
+ return jsonify(error=str(e)), 500
69
+
70
+ # ------------------------------------------------------------------
71
+ if name == "main":
72
+ # تأكد أن المنفذ 7520 مفتوح
73
+ app.run(host="0.0.0.0", port=7520)
run_task.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @flask_app.route("/run_task", methods=["POST"])
2
+ def run_task():
3
+ task_id = request.form.get("task_id")
4
+ result = None
5
+ # قبول البيانات سواء كانت JSON أو form-urlencoded
6
+ if request.is_json:
7
+ data = request.get_json()
8
+ task_id = data.get("task_id")
9
+ else:
10
+ task_id = request.form.get("task_id")
11
+
12
+ if not task_id:
13
+ return jsonify(error="Missing task_id"), 400
14
+
15
+ if task_id == "1":
16
+ result = matrix_multiply(500)
17
+ elif task_id == "2":
18
+ result = prime_calculation(100_000)
19
+ elif task_id == "3":
20
+ result = data_processing(10_000)
21
+
22
+ return jsonify(result=result) # إرجاع JSON بدل HTML
security_layer.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # security_layer.py (مُحدَّث)
2
+ # ============================================================
3
+ # إدارة التشفير والتوقيع وتبادل المفاتيح بين العقد
4
+ # ============================================================
5
+
6
+ from cryptography.hazmat.primitives import hashes, serialization
7
+ from cryptography.hazmat.primitives.asymmetric import rsa, padding
8
+ from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
9
+ from cryptography.fernet import Fernet
10
+ import os, base64, json
11
+ from typing import Dict
12
+
13
+
14
+ class SecurityManager:
15
+ """طبقة أمان موحّدة لكل العقد."""
16
+
17
+ def __init__(self, shared_secret: str):
18
+ # مفتاح متماثل لاستخدام Fernet
19
+ self._key = self._derive_key(shared_secret)
20
+ self._cipher = Fernet(self._key)
21
+
22
+ # زوج مفاتيح غير متماثل للتوقيع الرقمي
23
+ self._private_key = rsa.generate_private_key(
24
+ public_exponent=65537,
25
+ key_size=2048,
26
+ )
27
+ self._public_pem = (
28
+ self._private_key.public_key()
29
+ .public_bytes(
30
+ encoding=serialization.Encoding.PEM,
31
+ format=serialization.PublicFormat.SubjectPublicKeyInfo,
32
+ )
33
+ .decode()
34
+ )
35
+ # مفاتيح العقد الأخرى {peer_id: public_key_obj}
36
+ self._peer_keys: Dict[str, rsa.RSAPublicKey] = {}
37
+
38
+ # ------------------------------------------------------------
39
+ # تشفير / فك تشفير متماثل
40
+ # ------------------------------------------------------------
41
+ def encrypt_data(self, data: bytes) -> bytes:
42
+ return self._cipher.encrypt(data)
43
+
44
+ def decrypt_data(self, encrypted: bytes) -> bytes:
45
+ return self._cipher.decrypt(encrypted)
46
+
47
+ # ------------------------------------------------------------
48
+ # توقيع/تحقّق رقمي غير متماثل
49
+ # ------------------------------------------------------------
50
+ def sign_task(self, task: Dict) -> Dict:
51
+ """يُرجع نسخة موقّعة من الـtask مضافًا إليها المفتاح العام والمعرّف."""
52
+ signature = self._private_key.sign(
53
+ json.dumps(task, separators=(",", ":")).encode(),
54
+ padding.PSS(
55
+ mgf=padding.MGF1(hashes.SHA256()),
56
+ salt_length=padding.PSS.MAX_LENGTH,
57
+ ),
58
+ hashes.SHA256(),
59
+ )
60
+ task_signed = task.copy()
61
+ task_signed.update(
62
+ {
63
+ "_signature": base64.b64encode(signature).decode(),
64
+ "sender_id": os.getenv("NODE_ID", "unknown"),
65
+ "sender_key": self._public_pem,
66
+ }
67
+ )
68
+ return task_signed
69
+
70
+ def verify_task(self, signed_task: Dict) -> bool:
71
+ """يتحقق من صحة التوقيع باستخدام المفتاح العام للمرسل."""
72
+ if "_signature" not in signed_task or "sender_id" not in signed_task:
73
+ return False
74
+ sig = base64.b64decode(signed_task["_signature"])
75
+ task_copy = {k: v for k, v in signed_task.items() if k not in {"_signature", "sender_key"}}
76
+
77
+ peer_id = signed_task["sender_id"]
78
+ if peer_id not in self._peer_keys:
79
+ # حاول إضافة المفتاح المرسل إن وجد
80
+ if "sender_key" in signed_task:
81
+ self.add_peer_key(peer_id, signed_task["sender_key"])
82
+ else:
83
+ return False
84
+ try:
85
+ self._peer_keys[peer_id].verify(
86
+ sig,
87
+ json.dumps(task_copy, separators=(",", ":")).encode(),
88
+ padding.PSS(
89
+ mgf=padding.MGF1(hashes.SHA256()),
90
+ salt_length=padding.PSS.MAX_LENGTH,
91
+ ),
92
+ hashes.SHA256(),
93
+ )
94
+ return True
95
+ except Exception:
96
+ return False
97
+
98
+ # ------------------------------------------------------------
99
+ # إدارة المفاتيح العامة للأقران
100
+ # ------------------------------------------------------------
101
+ def add_peer_key(self, peer_id: str, public_key_pem: str):
102
+ """تخزين/تحديث المفتاح العام لعقدة أخرى."""
103
+ self._peer_keys[peer_id] = serialization.load_pem_public_key(
104
+ public_key_pem.encode()
105
+ )
106
+
107
+ # ------------------------------------------------------------
108
+ # أدوات داخلية
109
+ # ------------------------------------------------------------
110
+ @staticmethod
111
+ def _derive_key(password: str) -> bytes:
112
+ salt = b"nora_salt_2025" # ◀️ عدِّل في الإنتاج
113
+ kdf = PBKDF2HMAC(
114
+ algorithm=hashes.SHA256(),
115
+ length=32,
116
+ salt=salt,
117
+ iterations=150_000,
118
+ )
119
+ return base64.urlsafe_b64encode(kdf.derive(password.encode()))
120
+
server.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ from flask_cors import CORS
3
+ import json
4
+ from your_tasks import *
5
+ from project_identifier import create_project_endpoint, get_project_info
6
+ import logging
7
+
8
+ app = Flask(__name__)
9
+ CORS(app)
10
+
11
+ @app.route('/multiply', methods=['POST'])
12
+ def multiply():
13
+ try:
14
+ data = request.get_json()
15
+ a = data.get("a", 0)
16
+ b = data.get("b", 0)
17
+ result_dict = multiply_task(a, b) # دالة offload
18
+ return jsonify({"result": result_dict["result"]})
19
+ except Exception as e:
20
+ return jsonify({"error": str(e)}), 500
21
+
22
+ @app.route('/health', methods=['GET'])
23
+ def health_check():
24
+ return jsonify({"status": "healthy", "port": 7520})
25
+
26
+ @app.route('/project_info', methods=['GET'])
27
+ def project_info():
28
+ return create_project_endpoint()
29
+
30
+ if __name__ == "__main__":
31
+ # هذا العنوان يسمح بالاستماع على IP خارجي لتلقي الاتصالات من الإنترنت
32
+ app.run(host="0.0.0.0", port=7520)
setup.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # setup.py
2
+ import configparser
3
+ # Monkey-patch for Python 3: define SafeConfigParser for stdeb compatibility
4
+ configparser.SafeConfigParser = configparser.RawConfigParser
5
+
6
+ from setuptools import setup, find_packages
7
+
8
+ # Load long description from README
9
+ with open("README.md", encoding="utf-8") as f:
10
+ long_desc = f.read()
11
+
12
+ setup(
13
+ name="distributed-task-system",
14
+ version="1.0",
15
+ description="A simple distributed task offload system",
16
+ long_description=long_desc,
17
+ long_description_content_type="text/markdown",
18
+ author="Osama Awartany",
19
+ author_email="osama@example.com",
20
+ url="https://github.com/yourusername/distributed-task-system",
21
+ packages=find_packages(include=["offload_core", "offload_core.*"]),
22
+ py_modules=["dts_cli"], # Include the CLI helper module
23
+ install_requires=[
24
+ "flask",
25
+ "requests",
26
+ "psutil",
27
+ "zeroconf",
28
+ "flask_cors",
29
+ "numpy",
30
+ "uvicorn"
31
+ ],
32
+ entry_points={
33
+ "console_scripts": [
34
+ "dts-start=dts_cli:main",
35
+ ],
36
+ },
37
+ data_files=[
38
+ ("/etc/systemd/system", ["dts.service"])
39
+ ],
40
+ classifiers=[
41
+ "Programming Language :: Python :: 3",
42
+ "License :: OSI Approved :: MIT License",
43
+ "Operating System :: POSIX :: Linux",
44
+ ],
45
+ python_requires='>=3.6',
46
+ )
47
+
48
+
49
+ # dts_cli.py
50
+ # CLI entry-point module for the Distributed Task System
51
+ # Place this next to setup.py
52
+
53
+ def main():
54
+ """
55
+ Main entry for dts-start console script.
56
+ Launches the FastAPI/Flask app via Uvicorn.
57
+ """
58
+ # Import your application instance here:
59
+ try:
60
+ from offload_core.main import app
61
+ except ImportError:
62
+ # If you have a factory, adjust accordingly:
63
+ from offload_core.main import create_app
64
+ app = create_app()
65
+
66
+ # Run with Uvicorn
67
+ import uvicorn
68
+ uvicorn.run(app, host="0.0.0.0", port=7520)
69
+
setup_fonts.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+
4
+ FONT_DIR = "fonts"
5
+ FONT_PATH = os.path.join(FONT_DIR, "Cairo-Regular.ttf")
6
+
7
+ # 🔥 رابط مباشر من Google Fonts CDN - Cairo Regular وزن 400
8
+ URL = "https://fonts.cdnfonts.com/s/12667/Cairo-Regular.woff"
9
+
10
+ os.makedirs(FONT_DIR, exist_ok=True)
11
+
12
+ print("[+] تحميل الخط Cairo-Regular...")
13
+ response = requests.get(URL)
14
+ if response.status_code == 200:
15
+ with open(FONT_PATH, "wb") as f:
16
+ f.write(response.content)
17
+ print(f"[✅] تم حفظ الخط في {FONT_PATH}")
18
+ else:
19
+ print(f"[❌] فشل تحميل الخط! كود الحالة: {response.status_code}")
20
+
simple_assistant.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # -*- coding: utf-8 -*-
3
+
4
+ import os
5
+ import json
6
+ import random
7
+ import re
8
+ from datetime import datetime
9
+
10
+ class SimpleNoraAssistant:
11
+ def __init__(self):
12
+ self.history_path = "simple_history.json"
13
+ self.chat_history = self.load_history()
14
+ self.knowledge_base = {
15
+ "تحية": ["مرحباً!", "أهلاً وسهلاً!", "كيف حالك؟"],
16
+ "وقت": [f"الوقت الحالي: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"],
17
+ "مساعدة": ["يمكنني مساعدتك في الأسئلة البسيطة والدردشة!", "اسألني أي سؤال وسأحاول المساعدة!"],
18
+ "برمجة": ["البرمجة مهارة رائعة!", "ما نوع البرمجة التي تريد تعلمها؟"],
19
+ "افتراضي": ["مثير للاهتمام!", "حدثني أكثر عن ذلك.", "هذا سؤال جيد!"]
20
+ }
21
+
22
+ def load_history(self):
23
+ """تحميل سجل المحادثة"""
24
+ if os.path.exists(self.history_path):
25
+ try:
26
+ with open(self.history_path, "r", encoding="utf-8") as f:
27
+ return json.load(f)
28
+ except:
29
+ return []
30
+ return []
31
+
32
+ def save_history(self):
33
+ """حفظ سجل المحادثة"""
34
+ with open(self.history_path, "w", encoding="utf-8") as f:
35
+ json.dump(self.chat_history, f, ensure_ascii=False, indent=2)
36
+
37
+ def get_response(self, user_input: str) -> str:
38
+ """الحصول على رد بسيط"""
39
+ user_input = user_input.lower().strip()
40
+
41
+ # تحديد نوع السؤال
42
+ if any(word in user_input for word in ["مرحبا", "أهلا", "السلام"]):
43
+ category = "تحية"
44
+ elif any(word in user_input for word in ["وقت", "تاريخ", "ساعة"]):
45
+ category = "وقت"
46
+ elif any(word in user_input for word in ["مساعدة", "help"]):
47
+ category = "مساعدة"
48
+ elif any(word in user_input for word in ["برمجة", "كود", "programming"]):
49
+ category = "برمجة"
50
+ else:
51
+ category = "افتراضي"
52
+
53
+ # اختيار رد عشوائي من الفئة
54
+ responses = self.knowledge_base.get(category, self.knowledge_base["افتراضي"])
55
+ return random.choice(responses)
56
+
57
+ def learn_from_input(self, user_input: str, user_response: str):
58
+ """تعلم بسيط من المدخلات"""
59
+ # إضافة ردود جديدة بناءً على تفاعل المستخدم
60
+ if "جيد" in user_response.lower() or "شكرا" in user_response.lower():
61
+ print("نورا: سعيدة أنني ساعدتك!")
62
+
63
+ def simulate_server_scan(self):
64
+ """محاكاة البحث عن الخوادم"""
65
+ print("نورا: أبحث عن خوادم...")
66
+ fake_servers = ["192.168.1.5", "192.168.1.10", "192.168.1.20"]
67
+ for server in fake_servers:
68
+ print(f"نورا: تم العثور على خادم مفتوح في {server}")
69
+ print(f"نورا: أقوم بنسخ نفسي إلى {server} (محاكاة فقط)...")
70
+
71
+ def chat(self):
72
+ """بدء المحادثة"""
73
+ print("مرحباً! أنا نورا، مساعدتك البسيطة. اكتب 'خروج' للإنهاء أو 'scan' للبحث عن خوادم.")
74
+
75
+ while True:
76
+ user_input = input("\nأنت: ").strip()
77
+
78
+ if user_input.lower() in ["خروج", "exit", "quit"]:
79
+ print("نورا: مع السلامة!")
80
+ break
81
+ elif user_input.lower() == "scan":
82
+ self.simulate_server_scan()
83
+ continue
84
+ elif not user_input:
85
+ continue
86
+
87
+ # الحصول على الرد
88
+ response = self.get_response(user_input)
89
+ print(f"نورا: {response}")
90
+
91
+ # حفظ في السجل
92
+ self.chat_history.append({
93
+ "timestamp": datetime.now().isoformat(),
94
+ "user": user_input,
95
+ "assistant": response
96
+ })
97
+ self.save_history()
98
+
99
+ if __name__ == "__main__":
100
+ assistant = SimpleNoraAssistant()
101
+ assistant.chat()
simple_history.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "timestamp": "2025-08-01T04:07:49.526870",
4
+ "user": "مرحبا",
5
+ "assistant": "مرحباً!"
6
+ },
7
+ {
8
+ "timestamp": "2025-08-01T04:07:56.868610",
9
+ "user": "كيف حالك",
10
+ "assistant": "هذا سؤال جيد!"
11
+ }
12
+ ]
smart_tasks.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import numpy as np
3
+ import time
4
+
5
+ def prime_calculation(n: int):
6
+ """ترجع قائمة الأعداد الأوليّة حتى n مع عددها"""
7
+ primes = []
8
+ for num in range(2, n + 1):
9
+ if all(num % p != 0 for p in range(2, int(math.sqrt(num)) + 1)):
10
+ primes.append(num)
11
+ return {"count": len(primes), "primes": primes}
12
+
13
+ def matrix_multiply(size: int):
14
+ """ضرب مصفوفات عشوائيّة (size × size)"""
15
+ A = np.random.rand(size, size)
16
+ B = np.random.rand(size, size)
17
+ result = np.dot(A, B) # يمكن أيضًا: A @ B
18
+ return {"result": result.tolist()}
19
+
20
+ def data_processing(data_size: int):
21
+ """تنفيذ معالجة بيانات بسيطة كتجربة"""
22
+ data = np.random.rand(data_size)
23
+ mean = np.mean(data)
24
+ std_dev = np.std(data)
25
+ return {"mean": mean, "std_dev": std_dev}
26
+
27
+ def image_processing_emulation(iterations):
28
+ """محاكاة معالجة الصور"""
29
+ results = []
30
+ for i in range(iterations):
31
+ fake_processing = sum(math.sqrt(x) for x in range(i * 100, (i + 1) * 100))
32
+ results.append(fake_processing)
33
+ time.sleep(0.01)
34
+ return {"iterations": iterations, "results": results}
35
+
36
+ # مهام معالجة الفيديو والألعاب ثلاثية الأبعاد
37
+ def video_format_conversion(duration_seconds, quality_level, input_format="mp4", output_format="avi"):
38
+ """تحويل صيغة الفيديو"""
39
+ import time
40
+ start_time = time.time()
41
+ processing_time = duration_seconds * quality_level * 0.05 # معالجة أسرع للخادم
42
+ time.sleep(min(processing_time, 1)) # محدود بثانية واحدة
43
+
44
+ return {
45
+ "status": "success",
46
+ "input_format": input_format,
47
+ "output_format": output_format,
48
+ "duration": duration_seconds,
49
+ "quality": quality_level,
50
+ "processing_time": time.time() - start_time,
51
+ "server_processed": True
52
+ }
53
+
54
+ def video_effects_processing(video_length, effects_count, resolution="1080p"):
55
+ """معالجة تأثيرات الفيديو"""
56
+ import time
57
+ start_time = time.time()
58
+
59
+ resolution_multiplier = {"480p": 1, "720p": 2, "1080p": 3, "4K": 5}
60
+ multiplier = resolution_multiplier.get(resolution, 2)
61
+ processing_time = video_length * effects_count * multiplier * 0.03
62
+
63
+ time.sleep(min(processing_time, 1.5))
64
+
65
+ return {
66
+ "status": "success",
67
+ "video_length": video_length,
68
+ "effects_count": effects_count,
69
+ "resolution": resolution,
70
+ "processing_time": time.time() - start_time,
71
+ "server_processed": True
72
+ }
73
+
74
+ def render_3d_scene(objects_count, resolution_width, resolution_height,
75
+ lighting_quality="medium", texture_quality="high"):
76
+ """رندر مشهد ثلاثي الأبعاد"""
77
+ import time
78
+ start_time = time.time()
79
+
80
+ complexity = objects_count * (resolution_width * resolution_height) / 2000000 # تقليل التعقيد للخادم
81
+ processing_time = complexity * 0.02
82
+
83
+ time.sleep(min(processing_time, 2))
84
+
85
+ fps = max(30, 120 - (complexity * 5)) # أداء أفضل للخادم
86
+
87
+ return {
88
+ "status": "success",
89
+ "objects_rendered": objects_count,
90
+ "resolution": f"{resolution_width}x{resolution_height}",
91
+ "lighting_quality": lighting_quality,
92
+ "texture_quality": texture_quality,
93
+ "estimated_fps": round(fps, 1),
94
+ "processing_time": time.time() - start_time,
95
+ "server_processed": True
96
+ }
97
+
98
+ def physics_simulation(objects_count, frames_count, physics_quality="medium"):
99
+ """محاكاة الفيزياء"""
100
+ import time
101
+ start_time = time.time()
102
+
103
+ quality_multiplier = {"low": 1, "medium": 2, "high": 4, "ultra": 8}
104
+ multiplier = quality_multiplier.get(physics_quality, 2)
105
+
106
+ calculations = objects_count * frames_count * multiplier
107
+ processing_time = calculations / 200000 # أسرع للخادم
108
+
109
+ time.sleep(min(processing_time, 1.5))
110
+
111
+ return {
112
+ "status": "success",
113
+ "objects_simulated": objects_count,
114
+ "frames_processed": frames_count,
115
+ "physics_quality": physics_quality,
116
+ "calculations_performed": calculations,
117
+ "processing_time": time.time() - start_time,
118
+ "server_processed": True
119
+ }
120
+
121
+ def game_ai_processing(ai_agents_count, decision_complexity, game_state_size):
122
+ """معالجة ذكاء اصطناعي للألعاب"""
123
+ import time
124
+ start_time = time.time()
125
+
126
+ total_operations = ai_agents_count * decision_complexity * game_state_size
127
+ processing_time = total_operations / 100000 # أسرع للخادم
128
+
129
+ time.sleep(min(processing_time, 1))
130
+
131
+ return {
132
+ "status": "success",
133
+ "ai_agents": ai_agents_count,
134
+ "decision_complexity": decision_complexity,
135
+ "total_operations": total_operations,
136
+ "processing_time": time.time() - start_time,
137
+ "server_processed": True
138
+ }
startup.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import time
3
+ import logging
4
+ import sys
5
+ from autostart_config import AutoStartManager
6
+ from distributed_executor import DistributedExecutor
7
+
8
+ PY = sys.executable # مسار بايثون الحالي
9
+
10
+ SERVICES = [
11
+ ("peer_server.py", "Peer‑Server"),
12
+ ("rpc_server.py", "RPC‑Server"),
13
+ ("server.py", "REST‑Server"), # يعمل على 7521 حاليًا
14
+ ("load_balancer.py", "Load‑Balancer"),
15
+ ]
16
+
17
+
18
+ def launch_services():
19
+ procs = []
20
+ for script, name in SERVICES:
21
+ try:
22
+ p = subprocess.Popen([PY, script])
23
+ logging.info(f"✅ {name} قيد التشغيل (PID={p.pid})")
24
+ procs.append(p)
25
+ except FileNotFoundError:
26
+ logging.error(f"❌ لم يُعثَر على {script}; تخطَّيته")
27
+ return procs
28
+
29
+
30
+ def main():
31
+ # إعداد السجلات مع دعم وضع الخلفية
32
+ import os
33
+
34
+ # إنشاء مجلد السجلات
35
+ os.makedirs("logs", exist_ok=True)
36
+
37
+ logging.basicConfig(
38
+ level=logging.INFO,
39
+ format="%(asctime)s - %(levelname)s - %(message)s",
40
+ handlers=[
41
+ logging.FileHandler("logs/startup.log"),
42
+ logging.StreamHandler() # إظهار السجلات في وحدة التحكم أيضاً
43
+ ]
44
+ )
45
+
46
+ try:
47
+ cfg = AutoStartManager().config
48
+ if not cfg.get("enabled", True):
49
+ logging.info("التشغيل التلقائي مُعطل في الإعدادات")
50
+ return
51
+
52
+ # فحص إذا كانت الخدمة الخلفية متاحة
53
+ background_service_available = os.path.exists("background_service.py")
54
+
55
+ if background_service_available:
56
+ logging.info("🔄 تشغيل الخدمة الخلفية المحسّنة...")
57
+ # تشغيل الخدمة الخلفية الجديدة
58
+ try:
59
+ subprocess.Popen([PY, "background_service.py", "start"])
60
+ logging.info("✅ تم بدء تشغيل الخدمة الخلفية المحسّنة")
61
+ return
62
+ except Exception as e:
63
+ logging.warning(f"⚠️ فشل في تشغيل الخدمة الخلفية المحسّنة: {e}")
64
+ logging.info("🔄 العودة إلى الطريقة التقليدية...")
65
+
66
+ # الطريقة التقليدية (fallback)
67
+ logging.info("🚀 تشغيل الخدمات بالطريقة التقليدية...")
68
+
69
+ # 1) تشغيل الخدمات الخلفيّة
70
+ procs = launch_services()
71
+
72
+ # 2) تهيئة نظام التنفيذ الموزع (ليتعرّف على هذا الجهاز كعقدة)
73
+ executor = DistributedExecutor("my_shared_secret_123")
74
+ executor.peer_registry.register_service("auto_node", 7520)
75
+ logging.info("🚀 العقدة auto_node مُسجّلة في الـRegistry على 7520")
76
+
77
+ # 3) حلقة إبقاء حيّة مع فحص العمليات
78
+ while True:
79
+ time.sleep(30)
80
+ for p, (script, name) in zip(procs, SERVICES):
81
+ if p.poll() is not None:
82
+ logging.warning(f"⚠️ الخدمة {name} توقفت بشكل غير متوقع… إعادة تشغيل")
83
+ new_p = subprocess.Popen([PY, script])
84
+ procs[procs.index(p)] = new_p
85
+ logging.info(f"✅ {name} أُعيد تشغيلها (PID={new_p.pid})")
86
+
87
+ except KeyboardInterrupt:
88
+ logging.info("📴 إيقاف الخدمات يدويًا")
89
+ except Exception as e:
90
+ logging.error(f"خطأ في التشغيل التلقائي: {e}")
91
+ finally:
92
+ # إيقاف العمليات بأمان
93
+ try:
94
+ for p in procs:
95
+ p.terminate()
96
+ try:
97
+ p.wait(timeout=5)
98
+ except subprocess.TimeoutExpired:
99
+ p.kill()
100
+ except:
101
+ pass
102
+
103
+
104
+ if __name__ == "main":
105
+ main()
system_check.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #!/usr/bin/env python3
3
+ # system_check.py - فحص سريع لحالة النظام
4
+
5
+ import time
6
+ import requests
7
+ import psutil
8
+ import threading
9
+ from offload_lib import discover_peers
10
+
11
+ def check_local_system():
12
+ """فحص النظام المحلي"""
13
+ print("🔍 فحص النظام المحلي...")
14
+ cpu = psutil.cpu_percent(interval=1)
15
+ memory = psutil.virtual_memory()
16
+
17
+ print(f"⚡ CPU: {cpu}%")
18
+ print(f"💾 الذاكرة: {memory.percent}%")
19
+
20
+ return cpu < 80 and memory.percent < 90
21
+
22
+ def check_server_running():
23
+ """فحص إذا كان الخادم المحلي يعمل"""
24
+ print("🌐 فحص الخادم المحلي...")
25
+ try:
26
+ response = requests.get("http://localhost:7520/health", timeout=3)
27
+ if response.status_code == 200:
28
+ print("✅ الخادم المحلي يعمل بشكل صحيح")
29
+ return True
30
+ else:
31
+ print("⚠️ الخادم يستجيب لكن بخطأ")
32
+ return False
33
+ except:
34
+ print("❌ الخادم المحلي غير متاح")
35
+ return False
36
+
37
+ def check_peer_discovery():
38
+ """فحص اكتشاف الأجهزة"""
39
+ print("🔍 فحص اكتشاف الأجهزة...")
40
+ try:
41
+ peers = discover_peers(timeout=2)
42
+ if peers:
43
+ print(f"✅ تم اكتشاف {len(peers)} جهاز:")
44
+ for peer in peers[:3]: # عرض أول 3 أجهزة فقط
45
+ print(f" 📱 {peer}")
46
+ return True
47
+ else:
48
+ print("⚠️ لم يتم اكتشاف أجهزة أخرى")
49
+ return False
50
+ except Exception as e:
51
+ print(f"❌ خطأ في اكتشاف الأجهزة: {e}")
52
+ return False
53
+
54
+ def quick_task_test():
55
+ """اختبار مهمة سريعة"""
56
+ print("⚡ اختبار مهمة سريعة...")
57
+ try:
58
+ from offload_lib import matrix_multiply
59
+ start_time = time.time()
60
+ result = matrix_multiply(3) # مصفوفة صغيرة
61
+ duration = time.time() - start_time
62
+
63
+ print(f"✅ تمت المعالجة في {duration:.2f} ثانية")
64
+ return True
65
+ except Exception as e:
66
+ print(f"❌ فشل في تنفيذ المهمة: {e}")
67
+ return False
68
+
69
+ def main():
70
+ """الفحص الرئيسي"""
71
+ print("🚀 فحص سريع لحالة النظام")
72
+ print("=" * 40)
73
+
74
+ checks = [
75
+ ("النظام المحلي", check_local_system),
76
+ ("الخادم المحلي", check_server_running),
77
+ ("اكتشاف الأجهزة", check_peer_discovery),
78
+ ("تنفيذ المهام", quick_task_test)
79
+ ]
80
+
81
+ results = []
82
+ for name, check_func in checks:
83
+ print(f"\n📋 {name}:")
84
+ try:
85
+ result = check_func()
86
+ results.append((name, result))
87
+ except Exception as e:
88
+ print(f"❌ خطأ غير متوقع: {e}")
89
+ results.append((name, False))
90
+
91
+ print("\n" + "=" * 40)
92
+ print("📊 نتائج الفحص:")
93
+
94
+ all_good = True
95
+ for name, result in results:
96
+ status = "✅" if result else "❌"
97
+ print(f" {status} {name}")
98
+ if not result:
99
+ all_good = False
100
+
101
+ if all_good:
102
+ print("\n🎉 كل شيء يعمل بشكل ممتاز!")
103
+ print("💡 يمكنك الآن تشغيل: python test_distributed_system.py")
104
+ else:
105
+ print("\n⚠️ هناك مشاكل تحتاج إصلاح:")
106
+ print(" 1. تأكد من تشغيل: python server.py")
107
+ print(" 2. تحقق من الاتصال بالشبكة")
108
+ print(" 3. راجع ملفات السجل")
109
+
110
+ if __name__ == "__main__":
111
+ main()
system_tray.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #!/usr/bin/env python3
3
+ """
4
+ أيقونة شريط النظام للتحكم في الخدمة الخلفية
5
+ """
6
+
7
+ import sys
8
+ import threading
9
+ import requests
10
+ import webbrowser
11
+ from pathlib import Path
12
+
13
+ try:
14
+ import pystray
15
+ from pystray import MenuItem as item
16
+ from PIL import Image, ImageDraw
17
+ TRAY_AVAILABLE = True
18
+ except ImportError:
19
+ TRAY_AVAILABLE = False
20
+ print("⚠️ pystray غير متوفر، تشغيل بدون أيقونة النظام")
21
+
22
+ class SystemTrayController:
23
+ def __init__(self):
24
+ self.base_url = "http://localhost:8888"
25
+ self.icon = None
26
+
27
+ def create_icon_image(self):
28
+ """إنشاء صورة الأيقونة"""
29
+ # إنشاء صورة بسيطة 64x64
30
+ image = Image.new('RGB', (64, 64), color='blue')
31
+ draw = ImageDraw.Draw(image)
32
+
33
+ # رسم دائرة بسيطة
34
+ draw.ellipse([16, 16, 48, 48], fill='white')
35
+ draw.ellipse([20, 20, 44, 44], fill='blue')
36
+
37
+ return image
38
+
39
+ def get_service_status(self):
40
+ """الحصول على حالة الخدمة"""
41
+ try:
42
+ response = requests.get(f"{self.base_url}/status", timeout=2)
43
+ return response.json()
44
+ except:
45
+ return None
46
+
47
+ def start_services(self, icon, item):
48
+ """بدء تشغيل الخدمات"""
49
+ try:
50
+ requests.post(f"{self.base_url}/start", timeout=5)
51
+ self.update_menu()
52
+ except Exception as e:
53
+ print(f"فشل في بدء الخدمات: {e}")
54
+
55
+ def stop_services(self, icon, item):
56
+ """إيقاف الخدمات"""
57
+ try:
58
+ requests.post(f"{self.base_url}/stop", timeout=5)
59
+ self.update_menu()
60
+ except Exception as e:
61
+ print(f"فشل في إيقاف الخدمات: {e}")
62
+
63
+ def show_ui(self, icon, item):
64
+ """إظهار الواجهة التفاعلية"""
65
+ try:
66
+ requests.post(f"{self.base_url}/show-ui", timeout=5)
67
+ # فتح المتصفح
68
+ webbrowser.open('http://localhost:5173')
69
+ except Exception as e:
70
+ print(f"فشل في إظهار الواجهة: {e}")
71
+
72
+ def hide_ui(self, icon, item):
73
+ """إخفاء الواجهة التفاعلية"""
74
+ try:
75
+ requests.post(f"{self.base_url}/hide-ui", timeout=5)
76
+ except Exception as e:
77
+ print(f"فشل في إخفاء الواجهة: {e}")
78
+
79
+ def open_dashboard(self, icon, item):
80
+ """فتح لوحة التحكم"""
81
+ webbrowser.open('http://localhost:5173/dashboard')
82
+
83
+ def show_status(self, icon, item):
84
+ """إظهار حالة النظام"""
85
+ status = self.get_service_status()
86
+ if status:
87
+ status_text = f"حالة النظام: {status['status']}\n"
88
+ status_text += f"الخدمات النشطة: {len([s for s in status['services'].values() if s == 'running'])}\n"
89
+ status_text += f"وقت التشغيل: {int(status['uptime'])} ثانية"
90
+ print(status_text)
91
+ else:
92
+ print("❌ لا يمكن الوصول للخدمة")
93
+
94
+ def quit_app(self, icon, item):
95
+ """إنهاء التطبيق"""
96
+ self.stop_services(icon, item)
97
+ icon.stop()
98
+
99
+ def update_menu(self):
100
+ """تحديث قائمة الأيقونة"""
101
+ if self.icon:
102
+ status = self.get_service_status()
103
+ is_running = status and status['status'] == 'running'
104
+
105
+ menu = pystray.Menu(
106
+ item('حالة النظام', self.show_status),
107
+ item('---'),
108
+ item('إظهار الواجهة', self.show_ui),
109
+ item('إخفاء الواجهة', self.hide_ui),
110
+ item('لوحة التحكم', self.open_dashboard),
111
+ item('---'),
112
+ item('بدء الخدمات', self.start_services, enabled=not is_running),
113
+ item('إيقاف الخدمات', self.stop_services, enabled=is_running),
114
+ item('---'),
115
+ item('إنهاء', self.quit_app)
116
+ )
117
+
118
+ self.icon.menu = menu
119
+
120
+ def create_menu(self):
121
+ """إنشاء قائمة الأيقونة"""
122
+ return pystray.Menu(
123
+ item('حالة النظام', self.show_status),
124
+ item('---'),
125
+ item('إظهار الواجهة', self.show_ui),
126
+ item('إخفاء الواجهة', self.hide_ui),
127
+ item('لوحة التحكم', self.open_dashboard),
128
+ item('---'),
129
+ item('بدء الخدمات', self.start_services),
130
+ item('إيقاف الخدمات', self.stop_services),
131
+ item('---'),
132
+ item('إنهاء', self.quit_app)
133
+ )
134
+
135
+ def run(self):
136
+ """تشغيل أيقونة شريط النظام"""
137
+ if not TRAY_AVAILABLE:
138
+ print("❌ مكتبة pystray غير متوفرة")
139
+ return
140
+
141
+ # إنشاء الأيقونة
142
+ image = self.create_icon_image()
143
+ menu = self.create_menu()
144
+
145
+ self.icon = pystray.Icon(
146
+ "نظام توزيع المهام",
147
+ image,
148
+ menu=menu
149
+ )
150
+
151
+ # تحديث دوري للقائمة
152
+ def update_loop():
153
+ import time
154
+ while True:
155
+ time.sleep(5)
156
+ if self.icon and hasattr(self.icon, '_running') and self.icon._running:
157
+ self.update_menu()
158
+ else:
159
+ break
160
+
161
+ update_thread = threading.Thread(target=update_loop, daemon=True)
162
+ update_thread.start()
163
+
164
+ print("🖱️ تشغيل أيقونة شريط النظام...")
165
+ self.icon.run()
166
+
167
+ def main():
168
+ controller = SystemTrayController()
169
+ controller.run()
170
+
171
+ if __name__ == "__main__":
172
+ main()
tailwind.config.ts ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Config } from "tailwindcss";
2
+
3
+ export default {
4
+ darkMode: ["class"],
5
+ content: ["./client/index.html", "./client/src/**/*.{js,jsx,ts,tsx}"],
6
+ theme: {
7
+ extend: {
8
+ borderRadius: {
9
+ lg: "var(--radius)",
10
+ md: "calc(var(--radius) - 2px)",
11
+ sm: "calc(var(--radius) - 4px)",
12
+ },
13
+ colors: {
14
+ background: "var(--background)",
15
+ foreground: "var(--foreground)",
16
+ card: {
17
+ DEFAULT: "var(--card)",
18
+ foreground: "var(--card-foreground)",
19
+ },
20
+ popover: {
21
+ DEFAULT: "var(--popover)",
22
+ foreground: "var(--popover-foreground)",
23
+ },
24
+ primary: {
25
+ DEFAULT: "var(--primary)",
26
+ foreground: "var(--primary-foreground)",
27
+ },
28
+ secondary: {
29
+ DEFAULT: "var(--secondary)",
30
+ foreground: "var(--secondary-foreground)",
31
+ },
32
+ muted: {
33
+ DEFAULT: "var(--muted)",
34
+ foreground: "var(--muted-foreground)",
35
+ },
36
+ accent: {
37
+ DEFAULT: "var(--accent)",
38
+ foreground: "var(--accent-foreground)",
39
+ },
40
+ destructive: {
41
+ DEFAULT: "var(--destructive)",
42
+ foreground: "var(--destructive-foreground)",
43
+ },
44
+ border: "var(--border)",
45
+ input: "var(--input)",
46
+ ring: "var(--ring)",
47
+ chart: {
48
+ "1": "var(--chart-1)",
49
+ "2": "var(--chart-2)",
50
+ "3": "var(--chart-3)",
51
+ "4": "var(--chart-4)",
52
+ "5": "var(--chart-5)",
53
+ },
54
+ sidebar: {
55
+ DEFAULT: "var(--sidebar-background)",
56
+ foreground: "var(--sidebar-foreground)",
57
+ primary: "var(--sidebar-primary)",
58
+ "primary-foreground": "var(--sidebar-primary-foreground)",
59
+ accent: "var(--sidebar-accent)",
60
+ "accent-foreground": "var(--sidebar-accent-foreground)",
61
+ border: "var(--sidebar-border)",
62
+ ring: "var(--sidebar-ring)",
63
+ },
64
+ },
65
+ keyframes: {
66
+ "accordion-down": {
67
+ from: {
68
+ height: "0",
69
+ },
70
+ to: {
71
+ height: "var(--radix-accordion-content-height)",
72
+ },
73
+ },
74
+ "accordion-up": {
75
+ from: {
76
+ height: "var(--radix-accordion-content-height)",
77
+ },
78
+ to: {
79
+ height: "0",
80
+ },
81
+ },
82
+ },
83
+ animation: {
84
+ "accordion-down": "accordion-down 0.2s ease-out",
85
+ "accordion-up": "accordion-up 0.2s ease-out",
86
+ },
87
+ },
88
+ },
89
+ plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography")],
90
+ } satisfies Config;