|
""" |
|
وحدة الذكاء الاصطناعي - التطبيق الرئيسي |
|
""" |
|
|
|
import streamlit as st |
|
import pandas as pd |
|
import numpy as np |
|
import matplotlib.pyplot as plt |
|
import plotly.express as px |
|
import plotly.graph_objects as go |
|
from datetime import datetime |
|
import time |
|
import io |
|
import os |
|
import json |
|
import base64 |
|
from pathlib import Path |
|
|
|
class AIAssistantApp: |
|
"""وحدة الذكاء الاصطناعي""" |
|
|
|
def __init__(self): |
|
"""تهيئة وحدة الذكاء الاصطناعي""" |
|
|
|
|
|
if 'chat_history' not in st.session_state: |
|
st.session_state.chat_history = [ |
|
{ |
|
'role': 'assistant', |
|
'content': 'مرحباً! أنا مساعدك الذكي لإدارة المناقصات. كيف يمكنني مساعدتك اليوم؟' |
|
} |
|
] |
|
|
|
if 'document_summaries' not in st.session_state: |
|
st.session_state.document_summaries = [ |
|
{ |
|
'id': 1, |
|
'title': 'كراسة الشروط والمواصفات - مشروع إنشاء مبنى إداري', |
|
'date': '2024-03-15', |
|
'summary': 'تتضمن كراسة الشروط والمواصفات لمشروع إنشاء مبنى إداري متطلبات المشروع وشروط التنفيذ والمواصفات الفنية للأعمال المطلوبة. يتكون المبنى من 5 طوابق بمساحة إجمالية 5000 متر مربع. تشمل الأعمال الأساسية: الأعمال الإنشائية، الأعمال المعمارية، الأعمال الكهربائية، الأعمال الميكانيكية، وأعمال التشطيبات.', |
|
'key_points': [ |
|
'مدة التنفيذ: 18 شهراً', |
|
'قيمة الضمان الابتدائي: 2% من قيمة العطاء', |
|
'قيمة الضمان النهائي: 5% من قيمة العقد', |
|
'غرامة التأخير: 1% من قيمة العقد عن كل أسبوع تأخير بحد أقصى 10%', |
|
'شروط الدفع: دفعات شهرية حسب نسبة الإنجاز' |
|
], |
|
'entities': { |
|
'الجهة المالكة': 'وزارة المالية', |
|
'موقع المشروع': 'الرياض - حي العليا', |
|
'رقم المناقصة': 'T-2024-001', |
|
'تاريخ الطرح': '2024-03-01', |
|
'تاريخ الإقفال': '2024-04-15' |
|
} |
|
}, |
|
{ |
|
'id': 2, |
|
'title': 'جدول الكميات - مشروع تطوير شبكة طرق', |
|
'date': '2024-03-20', |
|
'summary': 'يتضمن جدول الكميات لمشروع تطوير شبكة طرق تفاصيل الأعمال المطلوبة والكميات التقديرية. يشمل المشروع إنشاء طرق جديدة بطول 15 كم وتطوير طرق قائمة بطول 10 كم، بالإضافة إلى إنشاء 3 جسور و5 أنفاق.', |
|
'key_points': [ |
|
'إجمالي أعمال الحفر: 250,000 م3', |
|
'إجمالي أعمال الردم: 180,000 م3', |
|
'إجمالي أعمال الخرسانة: 45,000 م3', |
|
'إجمالي أعمال الأسفلت: 120,000 م2', |
|
'إجمالي أعمال الإنارة: 500 عمود إنارة' |
|
], |
|
'entities': { |
|
'الجهة المالكة': 'وزارة النقل', |
|
'موقع المشروع': 'جدة', |
|
'رقم المناقصة': 'T-2024-002', |
|
'تاريخ الطرح': '2024-03-10', |
|
'تاريخ الإقفال': '2024-04-20' |
|
} |
|
}, |
|
{ |
|
'id': 3, |
|
'title': 'المواصفات الفنية - مشروع بناء مدرسة', |
|
'date': '2024-03-25', |
|
'summary': 'تتضمن المواصفات الفنية لمشروع بناء مدرسة تفاصيل المتطلبات الفنية للمشروع. تتكون المدرسة من 3 طوابق بمساحة إجمالية 3000 متر مربع، وتشمل 20 فصلاً دراسياً، ومختبرات علوم، وقاعة متعددة الأغراض، ومكتبة، وغرف إدارية.', |
|
'key_points': [ |
|
'نوع الهيكل: خرساني مسلح', |
|
'نظام التكييف: نظام مركزي', |
|
'نظام الإنارة: LED موفر للطاقة', |
|
'نظام مكافحة الحريق: نظام رش آلي', |
|
'متطلبات خاصة: نظام طاقة شمسية لتوفير 30% من احتياجات الطاقة' |
|
], |
|
'entities': { |
|
'الجهة المالكة': 'وزارة التعليم', |
|
'موقع المشروع': 'الدمام', |
|
'رقم المناقصة': 'T-2024-003', |
|
'تاريخ الطرح': '2024-03-15', |
|
'تاريخ الإقفال': '2024-04-25' |
|
} |
|
} |
|
] |
|
|
|
if 'ai_models' not in st.session_state: |
|
st.session_state.ai_models = [ |
|
{ |
|
'id': 1, |
|
'name': 'نموذج تحليل المستندات', |
|
'description': 'نموذج ذكاء اصطناعي لتحليل مستندات المناقصات واستخراج المعلومات الرئيسية منها.', |
|
'type': 'معالجة اللغة الطبيعية', |
|
'accuracy': 92, |
|
'last_updated': '2024-03-01' |
|
}, |
|
{ |
|
'id': 2, |
|
'name': 'نموذج تقدير التكاليف', |
|
'description': 'نموذج ذكاء اصطناعي لتقدير تكاليف المشاريع بناءً على بيانات المشاريع السابقة.', |
|
'type': 'تعلم آلي', |
|
'accuracy': 85, |
|
'last_updated': '2024-02-15' |
|
}, |
|
{ |
|
'id': 3, |
|
'name': 'نموذج تحليل المخاطر', |
|
'description': 'نموذج ذكاء اصطناعي لتحليل المخاطر المحتملة للمشاريع وتقديم توصيات للتخفيف منها.', |
|
'type': 'تعلم آلي', |
|
'accuracy': 88, |
|
'last_updated': '2024-02-20' |
|
}, |
|
{ |
|
'id': 4, |
|
'name': 'نموذج تحليل المنافسين', |
|
'description': 'نموذج ذكاء اصطناعي لتحليل بيانات المنافسين وتقديم توصيات للتسعير التنافسي.', |
|
'type': 'تعلم آلي', |
|
'accuracy': 80, |
|
'last_updated': '2024-03-10' |
|
}, |
|
{ |
|
'id': 5, |
|
'name': 'نموذج المساعد الذكي', |
|
'description': 'نموذج ذكاء اصطناعي للإجابة على الاستفسارات وتقديم المساعدة في إدارة المناقصات.', |
|
'type': 'معالجة اللغة الطبيعية', |
|
'accuracy': 90, |
|
'last_updated': '2024-03-15' |
|
} |
|
] |
|
|
|
def render(self): |
|
"""عرض واجهة وحدة الذكاء الاصطناعي""" |
|
|
|
st.markdown("<h1 class='module-title'>وحدة الذكاء الاصطناعي</h1>", unsafe_allow_html=True) |
|
|
|
tabs = st.tabs([ |
|
"المساعد الذكي", |
|
"تحليل المستندات", |
|
"تقدير التكاليف", |
|
"تحليل المخاطر", |
|
"نماذج الذكاء الاصطناعي" |
|
]) |
|
|
|
with tabs[0]: |
|
self._render_ai_assistant_tab() |
|
|
|
with tabs[1]: |
|
self._render_document_analysis_tab() |
|
|
|
with tabs[2]: |
|
self._render_cost_estimation_tab() |
|
|
|
with tabs[3]: |
|
self._render_risk_analysis_tab() |
|
|
|
with tabs[4]: |
|
self._render_ai_models_tab() |
|
|
|
def _render_ai_assistant_tab(self): |
|
"""عرض تبويب المساعد الذكي""" |
|
|
|
st.markdown("### المساعد الذكي") |
|
|
|
|
|
chat_container = st.container() |
|
|
|
with chat_container: |
|
for message in st.session_state.chat_history: |
|
if message['role'] == 'user': |
|
st.markdown(f"<div style='background-color: #e6f7ff; padding: 10px; border-radius: 10px; margin-bottom: 10px; text-align: right;'><strong>أنت:</strong> {message['content']}</div>", unsafe_allow_html=True) |
|
else: |
|
st.markdown(f"<div style='background-color: #f0f0f0; padding: 10px; border-radius: 10px; margin-bottom: 10px;'><strong>المساعد:</strong> {message['content']}</div>", unsafe_allow_html=True) |
|
|
|
|
|
with st.form(key="chat_form"): |
|
user_input = st.text_area("اكتب رسالتك هنا:", key="user_input", height=100) |
|
submit_button = st.form_submit_button("إرسال") |
|
|
|
if submit_button and user_input: |
|
|
|
st.session_state.chat_history.append({ |
|
'role': 'user', |
|
'content': user_input |
|
}) |
|
|
|
|
|
ai_responses = { |
|
"تكلفة": "بناءً على تحليل بيانات المشاريع السابقة، أتوقع أن تكون تكلفة هذا المشروع في حدود 15-18 مليون ريال. يمكنني تقديم تحليل تفصيلي إذا وفرت لي المزيد من المعلومات عن نطاق المشروع والمواصفات المطلوبة.", |
|
"مخاطر": "من أهم المخاطر المحتملة لهذا النوع من المشاريع: تأخر التوريدات، نقص العمالة الماهرة، التغييرات في نطاق العمل، والظروف الجوية غير المتوقعة. أنصح بوضع خطة إدارة مخاطر شاملة وتخصيص احتياطي للطوارئ بنسبة 10-15% من قيمة المشروع.", |
|
"منافس": "بناءً على تحليل المناقصات السابقة، يبدو أن المنافس الرئيسي يقدم أسعاراً أقل بنسبة 5-8% من متوسط السوق، لكنه يواجه تحديات في الالتزام بالجداول الزمنية. يمكنك التركيز على نقاط قوتك في الالتزام بالمواعيد وجودة التنفيذ في عرضك.", |
|
"مستند": "يمكنني تحليل مستندات المناقصة لاستخراج المعلومات الرئيسية مثل نطاق العمل، الشروط والمواصفات، الجداول الزمنية، وشروط الدفع. يرجى تحميل المستندات في تبويب تحليل المستندات.", |
|
"تسعير": "لتحسين استراتيجية التسعير، أنصح بتحليل هيكل التكاليف بدقة، ودراسة أسعار المنافسين، وتقييم القيمة المضافة التي تقدمها. يمكنك استخدام وحدة التسعير لإنشاء سيناريوهات تسعير مختلفة ومقارنتها.", |
|
"موارد": "بناءً على نطاق المشروع، أتوقع أنك ستحتاج إلى فريق من 15-20 مهندساً وفنياً، بالإضافة إلى معدات إنشائية رئيسية. يمكنك استخدام وحدة الموارد لتخطيط احتياجات المشروع بشكل تفصيلي." |
|
} |
|
|
|
|
|
response = "أشكرك على رسالتك. يمكنني مساعدتك في إدارة المناقصات وتحليل المستندات وتقدير التكاليف وتحليل المخاطر. يرجى توضيح ما تحتاجه بالتحديد." |
|
|
|
for keyword, resp in ai_responses.items(): |
|
if keyword in user_input: |
|
response = resp |
|
break |
|
|
|
|
|
st.session_state.chat_history.append({ |
|
'role': 'assistant', |
|
'content': response |
|
}) |
|
|
|
|
|
st.rerun() |
|
|
|
|
|
st.markdown("### اقتراحات للأسئلة") |
|
|
|
suggestions = [ |
|
"كيف يمكنني تقدير تكلفة مشروع إنشاء مبنى إداري؟", |
|
"ما هي المخاطر المحتملة لمشروع تطوير شبكة طرق؟", |
|
"كيف يمكنني تحليل استراتيجية المنافس الرئيسي؟", |
|
"كيف يمكنني تحليل مستندات المناقصة بسرعة؟", |
|
"ما هي أفضل استراتيجية للتسعير التنافسي؟", |
|
"كيف يمكنني تخطيط الموارد اللازمة للمشروع؟" |
|
] |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
for i in range(0, len(suggestions), 2): |
|
if st.button(suggestions[i], key=f"suggestion_{i}"): |
|
|
|
st.session_state.chat_history.append({ |
|
'role': 'user', |
|
'content': suggestions[i] |
|
}) |
|
|
|
|
|
for keyword, resp in ai_responses.items(): |
|
if keyword in suggestions[i].lower(): |
|
response = resp |
|
break |
|
else: |
|
response = "أشكرك على سؤالك. يمكنني مساعدتك في ذلك. يرجى تقديم المزيد من التفاصيل حول احتياجاتك المحددة." |
|
|
|
|
|
st.session_state.chat_history.append({ |
|
'role': 'assistant', |
|
'content': response |
|
}) |
|
|
|
|
|
st.rerun() |
|
|
|
with col2: |
|
for i in range(1, len(suggestions), 2): |
|
if st.button(suggestions[i], key=f"suggestion_{i}"): |
|
|
|
st.session_state.chat_history.append({ |
|
'role': 'user', |
|
'content': suggestions[i] |
|
}) |
|
|
|
|
|
for keyword, resp in ai_responses.items(): |
|
if keyword in suggestions[i].lower(): |
|
response = resp |
|
break |
|
else: |
|
response = "أشكرك على سؤالك. يمكنني مساعدتك في ذلك. يرجى تقديم المزيد من التفاصيل حول احتياجاتك المحددة." |
|
|
|
|
|
st.session_state.chat_history.append({ |
|
'role': 'assistant', |
|
'content': response |
|
}) |
|
|
|
|
|
st.rerun() |
|
|
|
def _render_document_analysis_tab(self): |
|
"""عرض تبويب تحليل المستندات""" |
|
|
|
st.markdown("### تحليل المستندات باستخدام الذكاء الاصطناعي") |
|
|
|
|
|
st.markdown("#### تحميل المستندات") |
|
|
|
uploaded_file = st.file_uploader("قم بتحميل مستند المناقصة (PDF, DOCX)", type=["pdf", "docx"]) |
|
|
|
if uploaded_file is not None: |
|
if st.button("تحليل المستند"): |
|
|
|
with st.spinner("جاري تحليل المستند..."): |
|
time.sleep(2) |
|
st.success("تم تحليل المستند بنجاح!") |
|
|
|
|
|
new_id = max([item['id'] for item in st.session_state.document_summaries], default=0) + 1 |
|
|
|
st.session_state.document_summaries.append({ |
|
'id': new_id, |
|
'title': uploaded_file.name, |
|
'date': time.strftime("%Y-%m-%d"), |
|
'summary': 'تم تحليل المستند واستخراج المعلومات الرئيسية منه. يتضمن المستند شروط ومواصفات المناقصة، ونطاق العمل، والجدول الزمني، وشروط الدفع.', |
|
'key_points': [ |
|
'مدة التنفيذ: 12 شهراً', |
|
'قيمة الضمان الابتدائي: 2% من قيمة العطاء', |
|
'قيمة الضمان النهائي: 5% من قيمة العقد', |
|
'غرامة التأخير: 1% من قيمة العقد عن كل أسبوع تأخير بحد أقصى 10%', |
|
'شروط الدفع: دفعات شهرية حسب نسبة الإنجاز' |
|
], |
|
'entities': { |
|
'الجهة المالكة': 'وزارة الإسكان', |
|
'موقع المشروع': 'الرياض', |
|
'رقم المناقصة': 'T-2024-004', |
|
'تاريخ الطرح': '2024-03-25', |
|
'تاريخ الإقفال': '2024-05-01' |
|
} |
|
}) |
|
|
|
|
|
st.markdown("#### ملخصات المستندات") |
|
|
|
for summary in st.session_state.document_summaries: |
|
with st.expander(f"{summary['title']} - {summary['date']}"): |
|
st.markdown(f"**ملخص المستند:** {summary['summary']}") |
|
|
|
st.markdown("**النقاط الرئيسية:**") |
|
for point in summary['key_points']: |
|
st.markdown(f"- {point}") |
|
|
|
st.markdown("**الكيانات المستخرجة:**") |
|
for entity, value in summary['entities'].items(): |
|
st.markdown(f"- **{entity}:** {value}") |
|
|
|
col1, col2, col3 = st.columns(3) |
|
|
|
with col1: |
|
if st.button("تصدير الملخص", key=f"export_summary_{summary['id']}"): |
|
st.success("تم تصدير الملخص بنجاح!") |
|
|
|
with col2: |
|
if st.button("إرسال إلى وحدة التسعير", key=f"send_to_pricing_{summary['id']}"): |
|
st.success("تم إرسال البيانات إلى وحدة التسعير بنجاح!") |
|
|
|
with col3: |
|
if st.button("إرسال إلى وحدة المخاطر", key=f"send_to_risk_{summary['id']}"): |
|
st.success("تم إرسال البيانات إلى وحدة المخاطر بنجاح!") |
|
|
|
|
|
st.markdown("#### استخراج جدول الكميات") |
|
|
|
boq_file = st.file_uploader("قم بتحميل جدول الكميات (PDF, XLSX)", type=["pdf", "xlsx"]) |
|
|
|
if boq_file is not None: |
|
if st.button("استخراج جدول الكميات"): |
|
|
|
with st.spinner("جاري استخراج جدول الكميات..."): |
|
time.sleep(2) |
|
st.success("تم استخراج جدول الكميات بنجاح!") |
|
|
|
|
|
boq_data = { |
|
'الكود': ['A-001', 'A-002', 'A-003', 'B-001', 'B-002'], |
|
'الوصف': [ |
|
'أعمال الحفر والردم', |
|
'توريد وصب خرسانة عادية', |
|
'توريد وصب خرسانة مسلحة للأساسات', |
|
'توريد وتركيب حديد تسليح', |
|
'توريد وبناء طابوق' |
|
], |
|
'الوحدة': ['م3', 'م3', 'م3', 'طن', 'م2'], |
|
'الكمية': [2000, 300, 200, 20, 500], |
|
'سعر الوحدة': [45, 350, 450, 3500, 120], |
|
'الإجمالي': [90000, 105000, 90000, 70000, 60000] |
|
} |
|
|
|
boq_df = pd.DataFrame(boq_data) |
|
st.dataframe(boq_df, use_container_width=True, hide_index=True) |
|
|
|
if st.button("إرسال إلى وحدة التسعير", key="send_boq_to_pricing"): |
|
st.success("تم إرسال جدول الكميات إلى وحدة التسعير بنجاح!") |
|
|
|
|
|
st.markdown("#### تحليل الشروط والمواصفات") |
|
|
|
specs_file = st.file_uploader("قم بتحميل الشروط والمواصفات (PDF, DOCX)", type=["pdf", "docx"]) |
|
|
|
if specs_file is not None: |
|
if st.button("تحليل الشروط والمواصفات"): |
|
|
|
with st.spinner("جاري تحليل الشروط والمواصفات..."): |
|
time.sleep(2) |
|
st.success("تم تحليل الشروط والمواصفات بنجاح!") |
|
|
|
|
|
st.markdown("**الشروط الرئيسية:**") |
|
st.markdown("- مدة التنفيذ: 12 شهراً") |
|
st.markdown("- قيمة الضمان الابتدائي: 2% من قيمة العطاء") |
|
st.markdown("- قيمة الضمان النهائي: 5% من قيمة العقد") |
|
st.markdown("- غرامة التأخير: 1% من قيمة العقد عن كل أسبوع تأخير بحد أقصى 10%") |
|
st.markdown("- شروط الدفع: دفعات شهرية حسب نسبة الإنجاز") |
|
|
|
st.markdown("**المواصفات الفنية الرئيسية:**") |
|
st.markdown("- نوع الهيكل: خرساني مسلح") |
|
st.markdown("- نظام التكييف: نظام مركزي") |
|
st.markdown("- نظام الإنارة: LED موفر للطاقة") |
|
st.markdown("- نظام مكافحة الحريق: نظام رش آلي") |
|
st.markdown("- متطلبات خاصة: نظام طاقة شمسية لتوفير 30% من احتياجات الطاقة") |
|
|
|
if st.button("إرسال إلى وحدة المخاطر", key="send_specs_to_risk"): |
|
st.success("تم إرسال تحليل الشروط والمواصفات إلى وحدة المخاطر بنجاح!") |
|
|
|
def _render_cost_estimation_tab(self): |
|
"""عرض تبويب تقدير التكاليف""" |
|
|
|
st.markdown("### تقدير التكاليف باستخدام الذكاء الاصطناعي") |
|
|
|
|
|
st.markdown("#### معلومات المشروع") |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
project_type = st.selectbox( |
|
"نوع المشروع", |
|
["مبنى إداري", "مبنى سكني", "مدرسة", "مستشفى", "طرق", "جسور", "بنية تحتية", "أخرى"] |
|
) |
|
|
|
project_area = st.number_input("المساحة الإجمالية (م2)", min_value=0, value=5000) |
|
|
|
project_location = st.selectbox( |
|
"موقع المشروع", |
|
["الرياض", "جدة", "الدمام", "مكة", "المدينة", "أبها", "تبوك", "أخرى"] |
|
) |
|
|
|
with col2: |
|
project_duration = st.number_input("مدة التنفيذ (شهر)", min_value=1, value=18) |
|
|
|
project_quality = st.select_slider( |
|
"مستوى الجودة", |
|
options=["اقتصادي", "متوسط", "عالي", "ممتاز"] |
|
) |
|
|
|
project_complexity = st.select_slider( |
|
"مستوى التعقيد", |
|
options=["بسيط", "متوسط", "معقد", "معقد جداً"] |
|
) |
|
|
|
|
|
if st.button("تقدير التكاليف"): |
|
|
|
with st.spinner("جاري تقدير التكاليف..."): |
|
time.sleep(2) |
|
st.success("تم تقدير التكاليف بنجاح!") |
|
|
|
|
|
st.markdown("#### نتائج تقدير التكاليف") |
|
|
|
|
|
base_cost_per_sqm = { |
|
"مبنى إداري": 3500, |
|
"مبنى سكني": 3000, |
|
"مدرسة": 3200, |
|
"مستشفى": 5000, |
|
"طرق": 1500, |
|
"جسور": 8000, |
|
"بنية تحتية": 2500, |
|
"أخرى": 3000 |
|
} |
|
|
|
|
|
location_factor = { |
|
"الرياض": 1.0, |
|
"جدة": 1.05, |
|
"الدمام": 0.95, |
|
"مكة": 1.1, |
|
"المدينة": 1.0, |
|
"أبها": 0.9, |
|
"تبوك": 0.85, |
|
"أخرى": 1.0 |
|
} |
|
|
|
|
|
quality_factor = { |
|
"اقتصادي": 0.8, |
|
"متوسط": 1.0, |
|
"عالي": 1.2, |
|
"ممتاز": 1.5 |
|
} |
|
|
|
|
|
complexity_factor = { |
|
"بسيط": 0.9, |
|
"متوسط": 1.0, |
|
"معقد": 1.2, |
|
"معقد جداً": 1.4 |
|
} |
|
|
|
|
|
base_cost = base_cost_per_sqm[project_type] * project_area |
|
adjusted_cost = base_cost * location_factor[project_location] * quality_factor[project_quality] * complexity_factor[project_complexity] |
|
|
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
st.metric("التكلفة التقديرية", f"{adjusted_cost:,.0f} ريال") |
|
|
|
with col2: |
|
st.metric("التكلفة لكل متر مربع", f"{adjusted_cost / project_area:,.0f} ريال/م2") |
|
|
|
|
|
st.markdown("#### تفاصيل التكاليف") |
|
|
|
|
|
cost_breakdown = { |
|
"الأعمال الإنشائية": 0.35, |
|
"الأعمال المعمارية": 0.25, |
|
"الأعمال الكهربائية": 0.15, |
|
"الأعمال الميكانيكية": 0.15, |
|
"أعمال الموقع والتجهيزات": 0.10 |
|
} |
|
|
|
cost_details = { |
|
"الفئة": list(cost_breakdown.keys()), |
|
"النسبة": [f"{v * 100:.0f}%" for v in cost_breakdown.values()], |
|
"التكلفة": [adjusted_cost * v for v in cost_breakdown.values()] |
|
} |
|
|
|
cost_df = pd.DataFrame(cost_details) |
|
st.dataframe(cost_df, use_container_width=True, hide_index=True) |
|
|
|
|
|
fig = px.pie( |
|
cost_df, |
|
values="التكلفة", |
|
names="الفئة", |
|
title="توزيع التكاليف حسب الفئة" |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### تحليل التكاليف المباشرة وغير المباشرة") |
|
|
|
direct_cost = adjusted_cost * 0.85 |
|
indirect_cost = adjusted_cost * 0.15 |
|
|
|
direct_indirect_data = { |
|
"نوع التكلفة": ["تكاليف مباشرة", "تكاليف غير مباشرة"], |
|
"النسبة": ["85%", "15%"], |
|
"التكلفة": [direct_cost, indirect_cost] |
|
} |
|
|
|
direct_indirect_df = pd.DataFrame(direct_indirect_data) |
|
st.dataframe(direct_indirect_df, use_container_width=True, hide_index=True) |
|
|
|
|
|
fig = px.bar( |
|
direct_indirect_df, |
|
x="نوع التكلفة", |
|
y="التكلفة", |
|
title="التكاليف المباشرة وغير المباشرة", |
|
color="نوع التكلفة", |
|
text_auto='.2s' |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### توصيات لتحسين التكاليف") |
|
|
|
st.markdown("1. **تحسين تصميم المشروع:** يمكن تحسين التصميم لتقليل التكاليف مع الحفاظ على الجودة.") |
|
st.markdown("2. **استخدام مواد بديلة:** يمكن استخدام مواد بديلة بتكلفة أقل مع الحفاظ على الجودة.") |
|
st.markdown("3. **تحسين جدولة المشروع:** يمكن تحسين جدولة المشروع لتقليل مدة التنفيذ وبالتالي تقليل التكاليف غير المباشرة.") |
|
st.markdown("4. **تحسين إدارة الموارد:** يمكن تحسين إدارة الموارد لتقليل الهدر وزيادة الإنتاجية.") |
|
st.markdown("5. **التفاوض مع الموردين:** يمكن التفاوض مع الموردين للحصول على أسعار أفضل.") |
|
|
|
|
|
if st.button("إرسال إلى وحدة التسعير", key="send_estimate_to_pricing"): |
|
st.success("تم إرسال تقدير التكاليف إلى وحدة التسعير بنجاح!") |
|
|
|
|
|
st.markdown("#### مقارنة التكاليف مع المشاريع السابقة") |
|
|
|
|
|
previous_projects_data = { |
|
"المشروع": ["مبنى إداري - الرياض", "مبنى إداري - جدة", "مبنى إداري - الدمام", "مبنى سكني - الرياض", "مدرسة - جدة"], |
|
"المساحة (م2)": [4500, 5200, 4800, 6000, 3500], |
|
"التكلفة الإجمالية": [16200000, 19500000, 15800000, 18500000, 11200000], |
|
"التكلفة لكل متر مربع": [3600, 3750, 3290, 3080, 3200] |
|
} |
|
|
|
previous_projects_df = pd.DataFrame(previous_projects_data) |
|
st.dataframe(previous_projects_df, use_container_width=True, hide_index=True) |
|
|
|
|
|
fig = px.bar( |
|
previous_projects_df, |
|
x="المشروع", |
|
y="التكلفة لكل متر مربع", |
|
title="مقارنة التكلفة لكل متر مربع للمشاريع السابقة", |
|
color="المشروع", |
|
text_auto='.0f' |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
def _render_risk_analysis_tab(self): |
|
"""عرض تبويب تحليل المخاطر""" |
|
|
|
st.markdown("### تحليل المخاطر باستخدام الذكاء الاصطناعي") |
|
|
|
|
|
st.markdown("#### معلومات المشروع") |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
project_type = st.selectbox( |
|
"نوع المشروع", |
|
["مبنى إداري", "مبنى سكني", "مدرسة", "مستشفى", "طرق", "جسور", "بنية تحتية", "أخرى"], |
|
key="risk_project_type" |
|
) |
|
|
|
project_budget = st.number_input("ميزانية المشروع (ريال)", min_value=0, value=15000000) |
|
|
|
project_location = st.selectbox( |
|
"موقع المشروع", |
|
["الرياض", "جدة", "الدمام", "مكة", "المدينة", "أبها", "تبوك", "أخرى"], |
|
key="risk_project_location" |
|
) |
|
|
|
with col2: |
|
project_duration = st.number_input("مدة التنفيذ (شهر)", min_value=1, value=18, key="risk_project_duration") |
|
|
|
project_complexity = st.select_slider( |
|
"مستوى التعقيد", |
|
options=["بسيط", "متوسط", "معقد", "معقد جداً"], |
|
key="risk_project_complexity" |
|
) |
|
|
|
project_experience = st.select_slider( |
|
"مستوى الخبرة في هذا النوع من المشاريع", |
|
options=["منخفض", "متوسط", "عالي", "ممتاز"] |
|
) |
|
|
|
|
|
if st.button("تحليل المخاطر"): |
|
|
|
with st.spinner("جاري تحليل المخاطر..."): |
|
time.sleep(2) |
|
st.success("تم تحليل المخاطر بنجاح!") |
|
|
|
|
|
st.markdown("#### نتائج تحليل المخاطر") |
|
|
|
|
|
risks_data = { |
|
"المخاطرة": [ |
|
"تأخر التوريدات", |
|
"نقص العمالة الماهرة", |
|
"التغييرات في نطاق العمل", |
|
"الظروف الجوية غير المتوقعة", |
|
"مشاكل في التصميم", |
|
"تأخر الدفعات", |
|
"مشاكل في الموقع", |
|
"تغيير الأنظمة واللوائح", |
|
"مشاكل في الجودة", |
|
"مشاكل في التنسيق مع الجهات الحكومية" |
|
], |
|
"الاحتمالية": [ |
|
"متوسطة", |
|
"عالية", |
|
"متوسطة", |
|
"منخفضة", |
|
"منخفضة", |
|
"متوسطة", |
|
"منخفضة", |
|
"منخفضة", |
|
"متوسطة", |
|
"عالية" |
|
], |
|
"التأثير": [ |
|
"عالي", |
|
"عالي", |
|
"عالي", |
|
"متوسط", |
|
"عالي", |
|
"متوسط", |
|
"متوسط", |
|
"عالي", |
|
"عالي", |
|
"متوسط" |
|
], |
|
"درجة المخاطرة": [ |
|
"عالية", |
|
"عالية", |
|
"عالية", |
|
"متوسطة", |
|
"متوسطة", |
|
"متوسطة", |
|
"منخفضة", |
|
"متوسطة", |
|
"عالية", |
|
"عالية" |
|
] |
|
} |
|
|
|
risks_df = pd.DataFrame(risks_data) |
|
st.dataframe(risks_df, use_container_width=True, hide_index=True) |
|
|
|
|
|
st.markdown("#### مصفوفة المخاطر") |
|
|
|
|
|
probability_map = {"منخفضة": 1, "متوسطة": 2, "عالية": 3} |
|
impact_map = {"منخفض": 1, "متوسط": 2, "عالي": 3} |
|
|
|
risk_matrix_data = [] |
|
|
|
for i, risk in enumerate(risks_data["المخاطرة"]): |
|
prob = probability_map[risks_data["الاحتمالية"][i]] |
|
impact = impact_map[risks_data["التأثير"][i]] |
|
risk_matrix_data.append({ |
|
"المخاطرة": risk, |
|
"الاحتمالية": prob, |
|
"التأثير": impact, |
|
"درجة المخاطرة": prob * impact |
|
}) |
|
|
|
|
|
risk_matrix = np.zeros((3, 3)) |
|
|
|
for risk in risk_matrix_data: |
|
prob = risk["الاحتمالية"] - 1 |
|
impact = risk["التأثير"] - 1 |
|
risk_matrix[prob, impact] += 1 |
|
|
|
|
|
fig, ax = plt.subplots(figsize=(10, 8)) |
|
|
|
im = ax.imshow(risk_matrix, cmap="YlOrRd") |
|
|
|
|
|
for i in range(3): |
|
for j in range(3): |
|
text = ax.text(j, i, int(risk_matrix[i, j]), ha="center", va="center", color="black") |
|
|
|
|
|
ax.set_xticks(np.arange(3)) |
|
ax.set_yticks(np.arange(3)) |
|
ax.set_xticklabels(["منخفض", "متوسط", "عالي"]) |
|
ax.set_yticklabels(["منخفضة", "متوسطة", "عالية"]) |
|
|
|
|
|
ax.set_xlabel("التأثير") |
|
ax.set_ylabel("الاحتمالية") |
|
ax.set_title("مصفوفة المخاطر") |
|
|
|
|
|
cbar = ax.figure.colorbar(im, ax=ax) |
|
cbar.ax.set_ylabel("عدد المخاطر", rotation=-90, va="bottom") |
|
|
|
|
|
st.pyplot(fig) |
|
|
|
|
|
st.markdown("#### توزيع المخاطر حسب الدرجة") |
|
|
|
risk_degree_counts = { |
|
"منخفضة": sum(1 for degree in risks_data["درجة المخاطرة"] if degree == "منخفضة"), |
|
"متوسطة": sum(1 for degree in risks_data["درجة المخاطرة"] if degree == "متوسطة"), |
|
"عالية": sum(1 for degree in risks_data["درجة المخاطرة"] if degree == "عالية") |
|
} |
|
|
|
risk_degree_df = pd.DataFrame({ |
|
"درجة المخاطرة": list(risk_degree_counts.keys()), |
|
"العدد": list(risk_degree_counts.values()) |
|
}) |
|
|
|
fig = px.pie( |
|
risk_degree_df, |
|
values="العدد", |
|
names="درجة المخاطرة", |
|
title="توزيع المخاطر حسب الدرجة", |
|
color="درجة المخاطرة", |
|
color_discrete_map={"منخفضة": "green", "متوسطة": "orange", "عالية": "red"} |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### خطة إدارة المخاطر") |
|
|
|
|
|
risk_management_data = { |
|
"المخاطرة": [ |
|
"تأخر التوريدات", |
|
"نقص العمالة الماهرة", |
|
"التغييرات في نطاق العمل", |
|
"مشاكل في الجودة", |
|
"مشاكل في التنسيق مع الجهات الحكومية" |
|
], |
|
"استراتيجية المواجهة": [ |
|
"تخفيف", |
|
"تخفيف", |
|
"تجنب", |
|
"تخفيف", |
|
"نقل" |
|
], |
|
"الإجراءات": [ |
|
"التعاقد مع موردين متعددين، وضع جدول زمني للتوريدات مع هامش أمان، متابعة التوريدات بشكل دوري", |
|
"التعاقد مع شركات توريد عمالة موثوقة، تدريب العمالة الحالية، وضع حوافز للعمالة الماهرة", |
|
"توثيق نطاق العمل بشكل دقيق، وضع إجراءات للتغييرات في نطاق العمل، تحديد صلاحيات اعتماد التغييرات", |
|
"وضع خطة لضبط الجودة، تعيين مسؤول للجودة، إجراء اختبارات دورية للجودة", |
|
"التعاقد مع استشاري متخصص في التنسيق مع الجهات الحكومية، تحديد متطلبات الجهات الحكومية مسبقاً" |
|
], |
|
"المسؤول": [ |
|
"مدير المشتريات", |
|
"مدير الموارد البشرية", |
|
"مدير المشروع", |
|
"مدير الجودة", |
|
"مدير العلاقات الحكومية" |
|
], |
|
"الموعد النهائي": [ |
|
"قبل بدء المشروع بشهر", |
|
"قبل بدء المشروع بشهرين", |
|
"قبل بدء المشروع بأسبوعين", |
|
"مستمر طوال فترة المشروع", |
|
"قبل بدء المشروع بشهر" |
|
] |
|
} |
|
|
|
risk_management_df = pd.DataFrame(risk_management_data) |
|
st.dataframe(risk_management_df, use_container_width=True, hide_index=True) |
|
|
|
|
|
st.markdown("#### توصيات لإدارة المخاطر") |
|
|
|
st.markdown("1. **تخصيص احتياطي للطوارئ:** يوصى بتخصيص احتياطي للطوارئ بنسبة 10-15% من قيمة المشروع.") |
|
st.markdown("2. **مراجعة خطة إدارة المخاطر بشكل دوري:** يجب مراجعة خطة إدارة المخاطر بشكل دوري وتحديثها حسب الحاجة.") |
|
st.markdown("3. **تعيين مسؤول لإدارة المخاطر:** يوصى بتعيين مسؤول لإدارة المخاطر في المشروع.") |
|
st.markdown("4. **توثيق الدروس المستفادة:** يجب توثيق الدروس المستفادة من إدارة المخاطر في المشاريع السابقة.") |
|
st.markdown("5. **التواصل المستمر مع أصحاب المصلحة:** يجب التواصل المستمر مع أصحاب المصلحة لتحديد المخاطر المحتملة.") |
|
|
|
|
|
if st.button("إرسال إلى وحدة التسعير", key="send_risk_to_pricing"): |
|
st.success("تم إرسال تحليل المخاطر إلى وحدة التسعير بنجاح!") |
|
|
|
def _render_ai_models_tab(self): |
|
"""عرض تبويب نماذج الذكاء الاصطناعي""" |
|
|
|
st.markdown("### نماذج الذكاء الاصطناعي") |
|
|
|
|
|
st.markdown("#### قائمة نماذج الذكاء الاصطناعي") |
|
|
|
|
|
models_df = pd.DataFrame(st.session_state.ai_models) |
|
|
|
|
|
st.dataframe( |
|
models_df, |
|
column_config={ |
|
"id": st.column_config.NumberColumn("الرقم"), |
|
"name": st.column_config.TextColumn("اسم النموذج"), |
|
"description": st.column_config.TextColumn("الوصف"), |
|
"type": st.column_config.TextColumn("النوع"), |
|
"accuracy": st.column_config.ProgressColumn("الدقة (%)", min_value=0, max_value=100), |
|
"last_updated": st.column_config.DateColumn("تاريخ التحديث") |
|
}, |
|
use_container_width=True, |
|
hide_index=True |
|
) |
|
|
|
|
|
st.markdown("#### تفاصيل النماذج") |
|
|
|
for model in st.session_state.ai_models: |
|
with st.expander(f"{model['name']} - دقة {model['accuracy']}%"): |
|
st.markdown(f"**الوصف:** {model['description']}") |
|
st.markdown(f"**النوع:** {model['type']}") |
|
st.markdown(f"**تاريخ التحديث:** {model['last_updated']}") |
|
|
|
if model['name'] == "نموذج تحليل المستندات": |
|
st.markdown("**القدرات:**") |
|
st.markdown("- استخراج المعلومات الرئيسية من مستندات المناقصات") |
|
st.markdown("- تحليل الشروط والمواصفات") |
|
st.markdown("- استخراج جداول الكميات") |
|
st.markdown("- تحديد الكيانات المهمة مثل الجهة المالكة، موقع المشروع، تواريخ المناقصة") |
|
st.markdown("- تلخيص المستندات الطويلة") |
|
|
|
elif model['name'] == "نموذج تقدير التكاليف": |
|
st.markdown("**القدرات:**") |
|
st.markdown("- تقدير تكاليف المشاريع بناءً على بيانات المشاريع السابقة") |
|
st.markdown("- تحليل العوامل المؤثرة على التكاليف") |
|
st.markdown("- تقديم توصيات لتحسين التكاليف") |
|
st.markdown("- مقارنة التكاليف مع المشاريع المماثلة") |
|
st.markdown("- تحليل التكاليف المباشرة وغير المباشرة") |
|
|
|
elif model['name'] == "نموذج تحليل المخاطر": |
|
st.markdown("**القدرات:**") |
|
st.markdown("- تحديد المخاطر المحتملة للمشاريع") |
|
st.markdown("- تقييم احتمالية وتأثير المخاطر") |
|
st.markdown("- إنشاء مصفوفة المخاطر") |
|
st.markdown("- تقديم توصيات لإدارة المخاطر") |
|
st.markdown("- تحليل المخاطر بناءً على بيانات المشاريع السابقة") |
|
|
|
elif model['name'] == "نموذج تحليل المنافسين": |
|
st.markdown("**القدرات:**") |
|
st.markdown("- تحليل بيانات المنافسين") |
|
st.markdown("- تحديد نقاط القوة والضعف للمنافسين") |
|
st.markdown("- تقديم توصيات للتسعير التنافسي") |
|
st.markdown("- تحليل استراتيجيات المنافسين") |
|
st.markdown("- تحليل حصص السوق") |
|
|
|
elif model['name'] == "نموذج المساعد الذكي": |
|
st.markdown("**القدرات:**") |
|
st.markdown("- الإجابة على الاستفسارات المتعلقة بإدارة المناقصات") |
|
st.markdown("- تقديم توصيات لتحسين إدارة المناقصات") |
|
st.markdown("- مساعدة المستخدمين في استخدام النظام") |
|
st.markdown("- تقديم معلومات عن المشاريع والمناقصات") |
|
st.markdown("- تقديم إحصائيات وتحليلات عن المناقصات") |
|
|
|
|
|
st.markdown("#### أداء النماذج") |
|
|
|
|
|
performance_df = pd.DataFrame({ |
|
"النموذج": [model['name'] for model in st.session_state.ai_models], |
|
"الدقة (%)": [model['accuracy'] for model in st.session_state.ai_models] |
|
}) |
|
|
|
fig = px.bar( |
|
performance_df, |
|
x="النموذج", |
|
y="الدقة (%)", |
|
title="أداء نماذج الذكاء الاصطناعي", |
|
color="الدقة (%)", |
|
text_auto='.0f' |
|
) |
|
|
|
fig.update_layout(yaxis_range=[0, 100]) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### تدريب النماذج") |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
model_to_train = st.selectbox( |
|
"اختر النموذج للتدريب", |
|
[model['name'] for model in st.session_state.ai_models] |
|
) |
|
|
|
with col2: |
|
training_data = st.file_uploader("قم بتحميل بيانات التدريب (CSV, XLSX)", type=["csv", "xlsx"]) |
|
|
|
if st.button("تدريب النموذج"): |
|
|
|
with st.spinner(f"جاري تدريب {model_to_train}..."): |
|
time.sleep(3) |
|
st.success(f"تم تدريب {model_to_train} بنجاح!") |
|
|
|
|
|
for i, model in enumerate(st.session_state.ai_models): |
|
if model['name'] == model_to_train: |
|
|
|
import random |
|
accuracy_increase = random.uniform(1, 3) |
|
new_accuracy = min(model['accuracy'] + accuracy_increase, 99) |
|
st.session_state.ai_models[i]['accuracy'] = new_accuracy |
|
st.session_state.ai_models[i]['last_updated'] = time.strftime("%Y-%m-%d") |
|
|
|
st.metric( |
|
"الدقة الجديدة", |
|
f"{new_accuracy:.1f}%", |
|
f"+{accuracy_increase:.1f}%" |
|
) |
|
|
|
break |
|
|
|
|
|
st.markdown("#### تقييم النماذج") |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
model_to_evaluate = st.selectbox( |
|
"اختر النموذج للتقييم", |
|
[model['name'] for model in st.session_state.ai_models], |
|
key="model_to_evaluate" |
|
) |
|
|
|
with col2: |
|
evaluation_data = st.file_uploader("قم بتحميل بيانات التقييم (CSV, XLSX)", type=["csv", "xlsx"], key="evaluation_data") |
|
|
|
if st.button("تقييم النموذج"): |
|
|
|
with st.spinner(f"جاري تقييم {model_to_evaluate}..."): |
|
time.sleep(2) |
|
st.success(f"تم تقييم {model_to_evaluate} بنجاح!") |
|
|
|
|
|
for model in st.session_state.ai_models: |
|
if model['name'] == model_to_evaluate: |
|
accuracy = model['accuracy'] |
|
break |
|
|
|
evaluation_metrics = { |
|
"المقياس": ["الدقة", "الاستدعاء", "F1", "AUC-ROC"], |
|
"القيمة": [accuracy / 100, (accuracy - 5) / 100, (accuracy - 3) / 100, (accuracy - 2) / 100] |
|
} |
|
|
|
evaluation_df = pd.DataFrame(evaluation_metrics) |
|
st.dataframe(evaluation_df, use_container_width=True, hide_index=True) |
|
|
|
|
|
st.markdown("##### مصفوفة الارتباك") |
|
|
|
|
|
confusion_matrix = np.array([ |
|
[85, 10, 5], |
|
[8, 80, 12], |
|
[7, 13, 80] |
|
]) |
|
|
|
fig, ax = plt.subplots(figsize=(10, 8)) |
|
|
|
im = ax.imshow(confusion_matrix, cmap="Blues") |
|
|
|
|
|
for i in range(3): |
|
for j in range(3): |
|
text = ax.text(j, i, confusion_matrix[i, j], ha="center", va="center", color="black") |
|
|
|
|
|
ax.set_xticks(np.arange(3)) |
|
ax.set_yticks(np.arange(3)) |
|
ax.set_xticklabels(["الفئة 1", "الفئة 2", "الفئة 3"]) |
|
ax.set_yticklabels(["الفئة 1", "الفئة 2", "الفئة 3"]) |
|
|
|
|
|
ax.set_xlabel("الفئة المتوقعة") |
|
ax.set_ylabel("الفئة الحقيقية") |
|
ax.set_title("مصفوفة الارتباك") |
|
|
|
|
|
cbar = ax.figure.colorbar(im, ax=ax) |
|
cbar.ax.set_ylabel("عدد العينات", rotation=-90, va="bottom") |
|
|
|
|
|
st.pyplot(fig) |
|
|