EGYADMIN commited on
Commit
49acda5
·
verified ·
1 Parent(s): ed26df4

Update modules/requirement_analyzer.py

Browse files
Files changed (1) hide show
  1. modules/requirement_analyzer.py +56 -491
modules/requirement_analyzer.py CHANGED
@@ -2,43 +2,38 @@ import re
2
  import os
3
  import json
4
  import numpy as np
5
- from typing import Dict, List, Any, Union, Tuple, Optional
6
  from datetime import datetime
7
 
8
  # استيراد نماذج الذكاء الاصطناعي
9
  from modules.ai_models import LLMProcessor
10
 
 
11
  class RequirementAnalyzer:
12
  """
13
  فئة لتحليل متطلبات المناقصة وتقييمها
14
  """
15
-
16
  def __init__(self, use_ai: bool = True):
17
  """
18
  تهيئة محلل المتطلبات
19
-
20
- المعاملات:
21
- ----------
22
- use_ai : bool, optional
23
- استخدام الذكاء الاصطناعي للتحليل المتقدم (افتراضي: True)
24
  """
25
  self.use_ai = use_ai
26
-
27
  # تحميل قاعدة بيانات المتطلبات القياسية
28
  self.standard_requirements = self._load_standard_requirements()
29
-
30
  # تحميل معايير التقييم
31
  self.evaluation_criteria = self._load_evaluation_criteria()
32
-
33
- # إنشاء معالج نماذج اللغة الكبيرة إذا تم تفعيل استخدام الذكاء الاصطناعي
34
  if self.use_ai:
35
  self.llm_processor = LLMProcessor()
36
-
37
  def _load_standard_requirements(self) -> Dict[str, List[Dict[str, Any]]]:
38
  """
39
  تحميل قاعدة بيانات المتطلبات القياسية
40
  """
41
- # في التطبيق الفعلي، قد تُحمل هذه البيانات من ملف أو قاعدة بيانات
42
  return {
43
  "عام": [
44
  {
@@ -55,46 +50,13 @@ class RequirementAnalyzer:
55
  "importance": "عالية",
56
  "category": "فنية"
57
  }
58
- ],
59
- "إنشاءات": [
60
- {
61
- "id": "C001",
62
- "title": "تصنيف المقاولين",
63
- "description": "يجب أن يكون المقاول مصنف لدى وزارة الشؤون البلدية والقروية والإسكان في المجال والدرجة المطلوبة",
64
- "importance": "عالية",
65
- "category": "إدارية"
66
- },
67
- {
68
- "id": "C002",
69
- "title": "جودة المواد",
70
- "description": "يجب أن تكون جميع المواد المستخدمة مطابقة للمواصفات القياسية السعودية",
71
- "importance": "عالية",
72
- "category": "فنية"
73
- }
74
- ],
75
- "تقنية معلومات": [
76
- {
77
- "id": "IT001",
78
- "title": "شهادة NITCS",
79
- "description": "يجب أن يكون المورد حاصل على شهادة المركز الوطني للتصديق الرقمي",
80
- "importance": "عالية",
81
- "category": "إدارية"
82
- },
83
- {
84
- "id": "IT002",
85
- "title": "متطلبات الأمن السيبراني",
86
- "description": "يجب الالتزام بمتطلبات الأمن السيبراني وفق ضوابط الهيئة الوطنية للأمن السيبراني",
87
- "importance": "عالية",
88
- "category": "فنية"
89
- }
90
  ]
91
  }
92
-
93
  def _load_evaluation_criteria(self) -> Dict[str, Dict[str, Any]]:
94
  """
95
  تحميل معايير التقييم للمتطلبات
96
  """
97
- # في التطبيق الفعلي، قد تُحمل هذه البيانات من ملف أو قاعدة بيانات
98
  return {
99
  "فنية": {
100
  "weight": 0.6,
@@ -112,29 +74,12 @@ class RequirementAnalyzer:
112
  "تفاصيل التكاليف": 0.2,
113
  "شروط الدفع": 0.1
114
  }
115
- },
116
- "المحتوى المحلي": {
117
- "weight": 0.1,
118
- "subcriteria": {
119
- "نسبة المحتوى المحلي": 0.7,
120
- "توظيف الكوادر السعودية": 0.3
121
- }
122
  }
123
  }
124
-
125
  def analyze(self, extracted_data: Dict[str, Any]) -> Dict[str, Any]:
126
  """
127
  تحليل البيانات المستخرجة وتقييم المتطلبات
128
-
129
- المعاملات:
130
- ----------
131
- extracted_data : Dict[str, Any]
132
- البيانات المستخرجة من المستند
133
-
134
- المخرجات:
135
- --------
136
- Dict[str, Any]
137
- نتائج تحليل المتطلبات
138
  """
139
  analysis_results = {
140
  "requirements": [],
@@ -144,488 +89,108 @@ class RequirementAnalyzer:
144
  "recommendations": [],
145
  "evaluation": {}
146
  }
147
-
148
  # استخراج المتطلبات من البيانات المستخرجة
149
- if "requirements" in extracted_data:
150
- requirements = extracted_data["requirements"]
151
- else:
152
- requirements = []
153
-
154
- # تصنيف وتنظيم المتطلبات
155
- categorized_reqs = self._categorize_requirements(requirements)
156
- analysis_results["categorized_requirements"] = categorized_reqs
157
-
158
  # تحليل الامتثال للمتطلبات القياسية
159
  compliance_results = self._analyze_compliance(requirements)
160
  analysis_results["compliance"] = compliance_results
161
-
162
  # تحديد الفجوات في المتطلبات
163
  gaps = self._identify_gaps(requirements, extracted_data)
164
  analysis_results["gaps"] = gaps
165
-
166
  # تحليل المخاطر المتعلقة بالمتطلبات
167
  risks = self._analyze_risks(requirements, extracted_data)
168
  analysis_results["risks"] = risks
169
-
170
  # إعداد التوصيات
171
- recommendations = self._generate_recommendations(
172
- requirements, compliance_results, gaps, risks, extracted_data
173
- )
174
  analysis_results["recommendations"] = recommendations
175
-
176
- # إعداد تقييم المتطلبات
177
- if "project_type" in extracted_data:
178
- project_type = extracted_data["project_type"]
179
- else:
180
- project_type = "عام"
181
-
182
- evaluation = self._evaluate_requirements(requirements, project_type)
183
- analysis_results["evaluation"] = evaluation
184
-
185
- # استخدام الذكاء الاصطناعي للتحليل المتقدم إذا كان مفعلاً
186
- if self.use_ai and requirements:
187
- ai_analysis = self._analyze_with_ai(requirements, extracted_data)
188
- analysis_results["ai_analysis"] = ai_analysis
189
-
190
- # تضمين المتطلبات الكاملة في النتيجة
191
- analysis_results["requirements"] = requirements
192
-
193
  return analysis_results
194
-
195
- def _categorize_requirements(self, requirements: List[Dict[str, Any]]) -> Dict[str, List[Dict[str, Any]]]:
196
- """
197
- تصنيف المتطلبات حسب الفئات
198
- """
199
- categorized = {}
200
-
201
- # تصنيف المتطلبات حسب الفئة
202
- for req in requirements:
203
- category = req.get("category", "عامة")
204
-
205
- if category not in categorized:
206
- categorized[category] = []
207
-
208
- categorized[category].append(req)
209
-
210
- # تصنيف ثانوي حسب الأهمية
211
- for category in categorized:
212
- categorized[category] = sorted(
213
- categorized[category],
214
- key=lambda x: 0 if x.get("importance", "عادية") == "عالية" else 1
215
- )
216
-
217
- return categorized
218
-
219
  def _analyze_compliance(self, requirements: List[Dict[str, Any]]) -> Dict[str, Any]:
220
  """
221
  تحليل امتثال المتطلبات للمعايير القياسية
222
  """
223
  compliance_results = {
224
  "compliant": [],
225
- "non_compliant": [],
226
  "missing": [],
227
  "compliance_rate": 0.0
228
  }
229
-
230
- # قائمة بالمتطلبات القياسية المهمة للمقارنة
231
- standard_reqs_flat = []
232
- for category, reqs in self.standard_requirements.items():
233
- for req in reqs:
234
- if req.get("importance", "") == "عالية":
235
- standard_reqs_flat.append(req)
236
-
237
- # تحليل المتطلبات المستخرجة
238
- for std_req in standard_reqs_flat:
239
- found = False
240
-
241
- for req in requirements:
242
- # البحث عن تطابق في العنوان أو الوصف
243
- title_match = std_req["title"].lower() in req.get("title", "").lower()
244
- desc_match = std_req["description"].lower() in req.get("description", "").lower()
245
-
246
- if title_match or desc_match:
247
- found = True
248
- compliance_results["compliant"].append({
249
- "standard_requirement": std_req,
250
- "found_requirement": req
251
- })
252
- break
253
-
254
- if not found:
255
  compliance_results["missing"].append(std_req)
256
-
257
- # حساب نسبة الامتثال
258
- total_std_reqs = len(standard_reqs_flat)
259
  if total_std_reqs > 0:
260
- compliance_rate = len(compliance_results["compliant"]) / total_std_reqs
261
- compliance_results["compliance_rate"] = round(compliance_rate * 100, 2)
262
-
 
263
  return compliance_results
264
-
265
  def _identify_gaps(self, requirements: List[Dict[str, Any]], extracted_data: Dict[str, Any]) -> List[Dict[str, Any]]:
266
  """
267
  تحديد الفجوات في المتطلبات
268
  """
269
  gaps = []
270
-
271
- # تحديد الفجوات بناءً على المتطلبات القياسية المفقودة
272
  for missing_req in self.standard_requirements.get("عام", []):
273
- found = False
274
-
275
- for req in requirements:
276
- if missing_req["title"].lower() in req.get("title", "").lower():
277
- found = True
278
- break
279
-
280
- if not found:
281
  gaps.append({
282
  "type": "متطلب قياسي مفقود",
283
  "requirement": missing_req,
284
- "severity": "عالية" if missing_req.get("importance", "") == "عالية" else "متوسطة",
285
- "recommendation": f"إضافة متطلب: {missing_req['title']}"
286
  })
287
-
288
- # تحديد الفجوات في المحتوى المحلي
289
- if "local_content" in extracted_data:
290
- local_content = extracted_data["local_content"]
291
-
292
- # التحقق من وجود متطلبات المحتوى المحلي
293
- local_content_req_found = False
294
-
295
- for req in requirements:
296
- if "محتوى محلي" in req.get("title", "").lower() or "محتوى محلي" in req.get("description", "").lower():
297
- local_content_req_found = True
298
- break
299
-
300
- if not local_content_req_found:
301
- gaps.append({
302
- "type": "متطلب محتوى محلي مفقود",
303
- "severity": "عالية",
304
- "recommendation": "إضافة متطلبات محددة للمحتوى المحلي ونسبة التوطين المطلوبة"
305
- })
306
-
307
- # تحديد الفجوات في تحديد المسؤوليات
308
- responsibilities_found = False
309
- for req in requirements:
310
- if "مسؤولية" in req.get("title", "").lower() or "مسؤولية" in req.get("description", "").lower():
311
- responsibilities_found = True
312
- break
313
-
314
- if not responsibilities_found:
315
- gaps.append({
316
- "type": "تحديد المسؤوليات",
317
- "severity": "متوسطة",
318
- "recommendation": "إضافة قسم يحدد مسؤوليات الأطراف بوضوح"
319
- })
320
-
321
- # تحديد الفجوات في آلية فض النزاعات
322
- dispute_resolution_found = False
323
- for req in requirements:
324
- if "نزاع" in req.get("title", "").lower() or "نزاع" in req.get("description", "").lower():
325
- dispute_resolution_found = True
326
- break
327
-
328
- if not dispute_resolution_found:
329
- gaps.append({
330
- "type": "آلية فض النزاعات",
331
- "severity": "متوسطة",
332
- "recommendation": "إضافة قسم يوضح آلية فض النزاعات بين الأطراف"
333
- })
334
-
335
  return gaps
336
-
337
- def _analyze_risks(self, requirements: List[Dict[str, Any]], extracted_data: Dict[str, Any]) -> List[Dict[str, Any]]:
338
  """
339
  تحليل المخاطر المتعلقة بالمتطلبات
340
  """
341
  risks = []
342
-
343
- # تحليل مخاطر الامتثال للمتطلبات
344
- vague_requirements = []
345
- for req in requirements:
346
- # تحديد المتطلبات الغامضة
347
- if len(req.get("description", "")) < 30:
348
- vague_requirements.append(req)
349
-
350
  if vague_requirements:
351
  risks.append({
352
- "title": "متطلبات غامضة",
353
- "description": f"تم العثور على {len(vague_requirements)} متطلبات غير محددة بوضوح",
354
  "severity": "عالية",
355
- "probability": "عالية",
356
- "impact": "قد يؤدي إلى نزاعات وتأخير في تنفيذ المشروع",
357
- "mitigation": "توضيح المتطلبات الغامضة وتحديدها بشكل أكثر دقة"
358
  })
359
-
360
- # تحليل مخاطر المحتوى المحلي
361
- if "local_content" in extracted_data:
362
- local_content = extracted_data["local_content"]
363
-
364
- # التحقق من وجود نسب محددة للمحتوى المحلي
365
- local_content_percentage_found = False
366
- for percentage in local_content.get("percentages", []):
367
- local_content_percentage_found = True
368
- break
369
-
370
- if not local_content_percentage_found:
371
- risks.append({
372
- "title": "عدم تحديد نسبة المحتوى المحلي",
373
- "description": "لم يتم تحديد نسبة واضحة للمحتوى المحلي المطلوب",
374
- "severity": "متوسطة",
375
- "probability": "عالية",
376
- "impact": "قد يؤدي إلى عدم الامتثال لمتطلبات المحتوى المحلي والتعرض للغرامات",
377
- "mitigation": "تحديد نسبة المحتوى المحلي المطلوبة بوضوح وآلية التحقق منها"
378
- })
379
-
380
- # تحليل مخاطر الجدول الزمني
381
- if "dates" in extracted_data:
382
- dates = extracted_data["dates"]
383
-
384
- if len(dates) < 2:
385
- risks.append({
386
- "title": "عدم وضوح الجدول الزمني",
387
- "description": "لم يتم تحديد جدول زمني واضح للمشروع",
388
- "severity": "عالية",
389
- "probability": "متوسطة",
390
- "impact": "تأخير في تنفيذ المشروع وصعوبة في متابعة التقدم",
391
- "mitigation": "تحديد جدول زمني تفصيلي مع مراحل ومعالم واضحة"
392
- })
393
-
394
- # تحليل مخاطر سلسلة الإمداد
395
- if "supply_chain" in extracted_data:
396
- supply_chain = extracted_data["supply_chain"]
397
-
398
- if len(supply_chain.get("suppliers", [])) < 2:
399
- risks.append({
400
- "title": "مخاطر سلسلة الإمداد",
401
- "description": "لم يتم تحديد موردين بدلاء أو خطة لإدارة مخاطر سلسلة الإمداد",
402
- "severity": "عالية",
403
- "probability": "متوسطة",
404
- "impact": "تأخير في توريد المواد والمعدات المطلوبة",
405
- "mitigation": "تحديد موردين بدلاء وخطة لإدارة مخاطر سلسلة الإمداد"
406
- })
407
-
408
  return risks
409
-
410
- def _generate_recommendations(self, requirements: List[Dict[str, Any]], compliance_results: Dict[str, Any],
411
- gaps: List[Dict[str, Any]], risks: List[Dict[str, Any]],
412
- extracted_data: Dict[str, Any]) -> List[Dict[str, Any]]:
413
  """
414
  إعداد توصيات لتحسين المتطلبات
415
  """
416
  recommendations = []
417
-
418
  # توصيات لسد الفجوات
419
  for gap in gaps:
420
  recommendations.append({
421
  "title": f"معالجة فجوة: {gap['type']}",
422
- "description": gap.get("recommendation", ""),
423
- "priority": "عالية" if gap.get("severity", "") == "عالية" else "متوسطة",
424
- "benefits": "تحسين جودة المتطلبات وتقليل مخاطر النزاعات"
425
  })
426
-
427
- # توصيات للتخفيف من المخاطر
428
  for risk in risks:
429
  recommendations.append({
430
  "title": f"معالجة خطر: {risk['title']}",
431
- "description": risk.get("mitigation", ""),
432
- "priority": "عالية" if risk.get("severity", "") == "عالية" else "متوسطة",
433
- "benefits": "تقليل المخاطر وتحسين فرص نجاح المشروع"
434
  })
435
-
436
- # توصيات لتحسين المحتوى المحلي
437
- local_content_recommendation = {
438
- "title": "تحسين متطلبات المحتوى المحلي",
439
- "description": "تحديد نسبة المحتوى المحلي المطلوبة بوضوح، وتوضيح آلية التحقق والقياس، وتحديد متطلبات توطين الوظائف",
440
- "priority": "عالية",
441
- "benefits": "الامتثال لمتطلبات المحتوى المحلي وتحقيق أهداف رؤية 2030",
442
- "implementation": [
443
- "تحديد نسبة المحتوى المحلي المطلوبة بدقة",
444
- "توضيح آلية حساب وقياس نسبة المحتوى المحلي",
445
- "تحديد متطلبات توظيف الكوادر السعودية",
446
- "تحديد آلية التحقق من الامتثال لمتطلبات المحتوى المحلي"
447
- ]
448
- }
449
- recommendations.append(local_content_recommendation)
450
-
451
- # توصيات لتحسين متطلبات سلسلة الإمداد
452
- supply_chain_recommendation = {
453
- "title": "تحسين متطلبات سلسلة الإمداد",
454
- "description": "تطوير خطة شاملة لإدارة سلسلة الإمداد وتحديد المصادر البديلة",
455
- "priority": "متوسطة",
456
- "benefits": "تقليل مخاطر انقطاع سلسلة الإمداد وضمان استمرارية المشروع",
457
- "implementation": [
458
- "تحديد الموردين الرئيسيين والبدلاء",
459
- "وضع خطة للتعامل مع انقطاع سلسلة الإمداد",
460
- "تحديد المواد والمعدات الحرجة والمصادر البديلة",
461
- "تطوير إجراءات لمتابعة وتقييم أداء الموردين"
462
- ]
463
- }
464
- recommendations.append(supply_chain_recommendation)
465
-
466
  return recommendations
467
-
468
- def _evaluate_requirements(self, requirements: List[Dict[str, Any]], project_type: str) -> Dict[str, Any]:
469
- """
470
- تقييم المتطلبات وفق معايير التقييم
471
- """
472
- evaluation = {
473
- "scores": {},
474
- "overall_score": 0.0,
475
- "comments": []
476
- }
477
-
478
- # تقييم المتطلبات الفنية
479
- technical_score = self._evaluate_technical_requirements(requirements)
480
- evaluation["scores"]["فنية"] = technical_score
481
-
482
- # تقييم المتطلبات المالية
483
- financial_score = self._evaluate_financial_requirements(requirements)
484
- evaluation["scores"]["مالية"] = financial_score
485
-
486
- # تقييم متطلبات المحتوى المحلي
487
- local_content_score = self._evaluate_local_content_requirements(requirements)
488
- evaluation["scores"]["المحتوى المحلي"] = local_content_score
489
-
490
- # حساب التقييم الإجمالي
491
- weights = {
492
- "فنية": self.evaluation_criteria["فنية"]["weight"],
493
- "مالية": self.evaluation_criteria["مالية"]["weight"],
494
- "المحتوى المحلي": self.evaluation_criteria["المحتوى المحلي"]["weight"]
495
- }
496
-
497
- overall_score = (
498
- technical_score * weights["فنية"] +
499
- financial_score * weights["مالية"] +
500
- local_content_score * weights["المحتوى المحلي"]
501
- )
502
-
503
- evaluation["overall_score"] = round(overall_score, 2)
504
-
505
- # إضافة تعليقات
506
- if overall_score >= 0.8:
507
- evaluation["comments"].append("المتطلبات شاملة وتغطي جميع الجوانب الرئيسية")
508
- elif overall_score >= 0.6:
509
- evaluation["comments"].append("المتطلبات جيدة ولكنها تحتاج إلى بعض التحسينات")
510
- else:
511
- evaluation["comments"].append("المتطلبات غير كافية وتحتاج إلى مراجعة شاملة")
512
-
513
- if technical_score < 0.6:
514
- evaluation["comments"].append("المتطلبات الفنية غير كافية وغير واضحة")
515
-
516
- if financial_score < 0.6:
517
- evaluation["comments"].append("المتطلبات المالية غير محددة بوضوح")
518
-
519
- if local_content_score < 0.6:
520
- evaluation["comments"].append("متطلبات المحتوى المحلي غير كافية وتحتاج إلى تحسين")
521
-
522
- return evaluation
523
-
524
- def _evaluate_technical_requirements(self, requirements: List[Dict[str, Any]]) -> float:
525
- """
526
- تقييم المتطلبات الفنية
527
- """
528
- # عدد المتطلبات الفنية
529
- technical_reqs = [req for req in requirements if req.get("category", "") == "فنية"]
530
-
531
- if not technical_reqs:
532
- return 0.0
533
-
534
- # تقييم وضوح المتطلبات
535
- clarity_score = sum(1 for req in technical_reqs if len(req.get("description", "")) > 50) / max(1, len(technical_reqs))
536
-
537
- # تقييم اكتمال المتطلبات
538
- completeness_score = min(1.0, len(technical_reqs) / 10) # افتراض أن 10 متطلبات تقنية هي الحد الأعلى المثالي
539
-
540
- # تقييم تحديد المسؤوليات
541
- responsibility_score = sum(1 for req in technical_reqs if "مسؤولية" in req.get("description", "").lower()) / max(1, len(technical_reqs))
542
-
543
- # حساب النتيجة الإجمالية
544
- total_score = (clarity_score * 0.4) + (completeness_score * 0.4) + (responsibility_score * 0.2)
545
-
546
- return round(total_score, 2)
547
-
548
- def _evaluate_financial_requirements(self, requirements: List[Dict[str, Any]]) -> float:
549
- """
550
- تقييم المتطلبات المالية
551
- """
552
- # عدد المتطلبات المالية
553
- financial_reqs = [req for req in requirements if req.get("category", "") == "مالية"]
554
-
555
- if not financial_reqs:
556
- return 0.0
557
-
558
- # تقييم وضوح المتطلبات
559
- clarity_score = sum(1 for req in financial_reqs if len(req.get("description", "")) > 50) / max(1, len(financial_reqs))
560
-
561
- # تقييم اكتمال المتطلبات
562
- completeness_score = min(1.0, len(financial_reqs) / 5) # افتراض أن 5 متطلبات مالية هي الحد الأعلى المثالي
563
-
564
- # تقييم تحديد شروط الدفع
565
- payment_score = sum(1 for req in financial_reqs if "دفع" in req.get("description", "").lower()) / max(1, len(financial_reqs))
566
-
567
- # حساب النتيجة الإجمالية
568
- total_score = (clarity_score * 0.3) + (completeness_score * 0.3) + (payment_score * 0.4)
569
-
570
- return round(total_score, 2)
571
-
572
- def _evaluate_local_content_requirements(self, requirements: List[Dict[str, Any]]) -> float:
573
- """
574
- تقييم متطلبات المحتوى المحلي
575
- """
576
- # عدد متطلبات المحتوى المحلي
577
- local_content_reqs = []
578
- for req in requirements:
579
- if req.get("category", "") == "محتوى محلي":
580
- local_content_reqs.append(req)
581
- elif "محتوى محلي" in req.get("title", "").lower() or "محتوى محلي" in req.get("description", "").lower():
582
- local_content_reqs.append(req)
583
-
584
- if not local_content_reqs:
585
- return 0.0
586
-
587
- # تقييم وضوح المتطلبات
588
- clarity_score = sum(1 for req in local_content_reqs if len(req.get("description", "")) > 50) / max(1, len(local_content_reqs))
589
-
590
- # تقييم تحديد النسب المطلوبة
591
- percentage_score = sum(1 for req in local_content_reqs if "%" in req.get("description", "")) / max(1, len(local_content_reqs))
592
-
593
- # تقييم آلية التحقق
594
- verification_score = sum(1 for req in local_content_reqs if "تحقق" in req.get("description", "").lower() or "قياس" in req.get("description", "").lower()) / max(1, len(local_content_reqs))
595
-
596
- # حساب النتيجة الإجمالية
597
- total_score = (clarity_score * 0.2) + (percentage_score * 0.5) + (verification_score * 0.3)
598
-
599
- return round(total_score, 2)
600
-
601
- def _analyze_with_ai(self, requirements: List[Dict[str, Any]], extracted_data: Dict[str, Any]) -> Dict[str, Any]:
602
- """
603
- استخدام الذكاء الاصطناعي لتحليل المتطلبات بشكل متقدم
604
- """
605
- ai_analysis = {
606
- "summary": "",
607
- "insights": [],
608
- "recommendations": []
609
- }
610
-
611
- try:
612
- # إعداد سياق للتحليل
613
- context = {
614
- "requirements_count": len(requirements),
615
- "categories": list(set(req.get("category", "عامة") for req in requirements)),
616
- "has_local_content": any("محتوى محلي" in req.get("category", "") for req in requirements),
617
- "text_samples": [req.get("description", "")[:200] for req in requirements[:5]]
618
- }
619
-
620
- # استخدام نموذج LLM لتحليل المتطلبات
621
- # ف�� التطبيق الفعلي، هذا سيستدعي واجهة برمجة تطبيقات مثل Claude أو OpenAI
622
- ai_response = self.llm_processor.analyze_requirements(requirements, context)
623
-
624
- # معالجة استجابة الذكاء الاصطناعي
625
- if isinstance(ai_response, dict):
626
- ai_analysis.update(ai_response)
627
-
628
- except Exception as e:
629
- ai_analysis["error"] = f"حدث خطأ أثناء تحليل المتطلبات باستخدام الذكاء الاصطناعي: {str(e)}"
630
-
631
- return ai_analysis
 
2
  import os
3
  import json
4
  import numpy as np
5
+ from typing import Dict, List, Any
6
  from datetime import datetime
7
 
8
  # استيراد نماذج الذكاء الاصطناعي
9
  from modules.ai_models import LLMProcessor
10
 
11
+
12
  class RequirementAnalyzer:
13
  """
14
  فئة لتحليل متطلبات المناقصة وتقييمها
15
  """
16
+
17
  def __init__(self, use_ai: bool = True):
18
  """
19
  تهيئة محلل المتطلبات
 
 
 
 
 
20
  """
21
  self.use_ai = use_ai
22
+
23
  # تحميل قاعدة بيانات المتطلبات القياسية
24
  self.standard_requirements = self._load_standard_requirements()
25
+
26
  # تحميل معايير التقييم
27
  self.evaluation_criteria = self._load_evaluation_criteria()
28
+
29
+ # إنشاء معالج نماذج الذكاء الاصطناعي إذا تم تفعيله
30
  if self.use_ai:
31
  self.llm_processor = LLMProcessor()
32
+
33
  def _load_standard_requirements(self) -> Dict[str, List[Dict[str, Any]]]:
34
  """
35
  تحميل قاعدة بيانات المتطلبات القياسية
36
  """
 
37
  return {
38
  "عام": [
39
  {
 
50
  "importance": "عالية",
51
  "category": "فنية"
52
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  ]
54
  }
55
+
56
  def _load_evaluation_criteria(self) -> Dict[str, Dict[str, Any]]:
57
  """
58
  تحميل معايير التقييم للمتطلبات
59
  """
 
60
  return {
61
  "فنية": {
62
  "weight": 0.6,
 
74
  "تفاصيل التكاليف": 0.2,
75
  "شروط الدفع": 0.1
76
  }
 
 
 
 
 
 
 
77
  }
78
  }
79
+
80
  def analyze(self, extracted_data: Dict[str, Any]) -> Dict[str, Any]:
81
  """
82
  تحليل البيانات المستخرجة وتقييم المتطلبات
 
 
 
 
 
 
 
 
 
 
83
  """
84
  analysis_results = {
85
  "requirements": [],
 
89
  "recommendations": [],
90
  "evaluation": {}
91
  }
92
+
93
  # استخراج المتطلبات من البيانات المستخرجة
94
+ requirements = extracted_data.get("requirements", [])
95
+
 
 
 
 
 
 
 
96
  # تحليل الامتثال للمتطلبات القياسية
97
  compliance_results = self._analyze_compliance(requirements)
98
  analysis_results["compliance"] = compliance_results
99
+
100
  # تحديد الفجوات في المتطلبات
101
  gaps = self._identify_gaps(requirements, extracted_data)
102
  analysis_results["gaps"] = gaps
103
+
104
  # تحليل المخاطر المتعلقة بالمتطلبات
105
  risks = self._analyze_risks(requirements, extracted_data)
106
  analysis_results["risks"] = risks
107
+
108
  # إعداد التوصيات
109
+ recommendations = self._generate_recommendations(requirements, compliance_results, gaps, risks, extracted_data)
 
 
110
  analysis_results["recommendations"] = recommendations
111
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  return analysis_results
113
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  def _analyze_compliance(self, requirements: List[Dict[str, Any]]) -> Dict[str, Any]:
115
  """
116
  تحليل امتثال المتطلبات للمعايير القياسية
117
  """
118
  compliance_results = {
119
  "compliant": [],
 
120
  "missing": [],
121
  "compliance_rate": 0.0
122
  }
123
+
124
+ standard_reqs = self.standard_requirements["عام"]
125
+
126
+ for std_req in standard_reqs:
127
+ found = any(std_req["title"].lower() in req.get("title", "").lower() for req in requirements)
128
+ if found:
129
+ compliance_results["compliant"].append(std_req)
130
+ else:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  compliance_results["missing"].append(std_req)
132
+
133
+ total_std_reqs = len(standard_reqs)
 
134
  if total_std_reqs > 0:
135
+ compliance_results["compliance_rate"] = round(
136
+ len(compliance_results["compliant"]) / total_std_reqs * 100, 2
137
+ )
138
+
139
  return compliance_results
140
+
141
  def _identify_gaps(self, requirements: List[Dict[str, Any]], extracted_data: Dict[str, Any]) -> List[Dict[str, Any]]:
142
  """
143
  تحديد الفجوات في المتطلبات
144
  """
145
  gaps = []
146
+
 
147
  for missing_req in self.standard_requirements.get("عام", []):
148
+ if not any(missing_req["title"].lower() in req.get("title", "").lower() for req in requirements):
 
 
 
 
 
 
 
149
  gaps.append({
150
  "type": "متطلب قياسي مفقود",
151
  "requirement": missing_req,
152
+ "severity": "عالية"
 
153
  })
154
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  return gaps
156
+
157
+ def _analyze_risks(self, requirements: List[Dict[str, Any]], extracted_data: Dict[str, Any]) -> List[Dict[str, Any]]:
158
  """
159
  تحليل المخاطر المتعلقة بالمتطلبات
160
  """
161
  risks = []
162
+
163
+ # مخاطر وجود متطلبات غامضة
164
+ vague_requirements = [req for req in requirements if len(req.get("description", "")) < 30]
 
 
 
 
 
165
  if vague_requirements:
166
  risks.append({
167
+ "title": "متطلبات غير واضحة",
 
168
  "severity": "عالية",
169
+ "impact": "قد يؤدي إلى نزاعات وتأخير في التنفيذ"
 
 
170
  })
171
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  return risks
173
+
174
+ def _generate_recommendations(self, requirements: List[Dict[str, Any]], compliance_results: Dict[str, Any],
175
+ gaps: List[Dict[str, Any]], risks: List[Dict[str, Any]],
176
+ extracted_data: Dict[str, Any]) -> List[Dict[str, Any]]:
177
  """
178
  إعداد توصيات لتحسين المتطلبات
179
  """
180
  recommendations = []
181
+
182
  # توصيات لسد الفجوات
183
  for gap in gaps:
184
  recommendations.append({
185
  "title": f"معالجة فجوة: {gap['type']}",
186
+ "priority": "عالية"
 
 
187
  })
188
+
189
+ # توصيات لمعالجة المخاطر
190
  for risk in risks:
191
  recommendations.append({
192
  "title": f"معالجة خطر: {risk['title']}",
193
+ "priority": "عالية"
 
 
194
  })
195
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  return recommendations