|
""" |
|
وحدة الخرائط والمواقع - نظام تحليل المناقصات |
|
""" |
|
|
|
import streamlit as st |
|
import pandas as pd |
|
import numpy as np |
|
import folium |
|
from streamlit_folium import folium_static |
|
import json |
|
import os |
|
import sys |
|
from pathlib import Path |
|
|
|
|
|
sys.path.append(str(Path(__file__).parent.parent)) |
|
|
|
|
|
from styling.enhanced_ui import UIEnhancer |
|
|
|
class MapsApp: |
|
"""تطبيق الخرائط والمواقع""" |
|
|
|
def __init__(self): |
|
"""تهيئة تطبيق الخرائط والمواقع""" |
|
self.ui = UIEnhancer(page_title="الخرائط والمواقع - نظام تحليل المناقصات", page_icon="🗺️") |
|
self.ui.apply_theme_colors() |
|
|
|
|
|
self.projects_data = [ |
|
{ |
|
"id": "P001", |
|
"name": "إنشاء مبنى إداري - الرياض", |
|
"location": "الرياض", |
|
"coordinates": [24.7136, 46.6753], |
|
"status": "جاري التنفيذ", |
|
"budget": 15000000, |
|
"completion": 45, |
|
"client": "وزارة الإسكان", |
|
"start_date": "2024-10-15", |
|
"end_date": "2025-12-30" |
|
}, |
|
{ |
|
"id": "P002", |
|
"name": "تطوير طريق الملك فهد - جدة", |
|
"location": "جدة", |
|
"coordinates": [21.5433, 39.1728], |
|
"status": "قيد الدراسة", |
|
"budget": 8500000, |
|
"completion": 0, |
|
"client": "أمانة جدة", |
|
"start_date": "2025-05-01", |
|
"end_date": "2026-02-28" |
|
}, |
|
{ |
|
"id": "P003", |
|
"name": "إنشاء مجمع سكني - الدمام", |
|
"location": "الدمام", |
|
"coordinates": [26.4207, 50.0888], |
|
"status": "مكتمل", |
|
"budget": 22000000, |
|
"completion": 100, |
|
"client": "شركة الإسكان للتطوير", |
|
"start_date": "2023-08-10", |
|
"end_date": "2025-01-15" |
|
}, |
|
{ |
|
"id": "P004", |
|
"name": "بناء مدرسة - أبها", |
|
"location": "أبها", |
|
"coordinates": [18.2164, 42.5053], |
|
"status": "جاري التنفيذ", |
|
"budget": 5200000, |
|
"completion": 75, |
|
"client": "وزارة التعليم", |
|
"start_date": "2024-06-20", |
|
"end_date": "2025-07-30" |
|
}, |
|
{ |
|
"id": "P005", |
|
"name": "تطوير شبكة مياه - المدينة المنورة", |
|
"location": "المدينة المنورة", |
|
"coordinates": [24.5247, 39.5692], |
|
"status": "جاري التنفيذ", |
|
"budget": 12800000, |
|
"completion": 30, |
|
"client": "شركة المياه الوطنية", |
|
"start_date": "2024-11-05", |
|
"end_date": "2026-03-15" |
|
} |
|
] |
|
|
|
def run(self): |
|
"""تشغيل تطبيق الخرائط والمواقع""" |
|
|
|
menu_items = [ |
|
{"name": "لوحة المعلومات", "icon": "house"}, |
|
{"name": "المناقصات والعقود", "icon": "file-text"}, |
|
{"name": "تحليل المستندات", "icon": "file-earmark-text"}, |
|
{"name": "نظام التسعير", "icon": "calculator"}, |
|
{"name": "حاسبة تكاليف البناء", "icon": "building"}, |
|
{"name": "الموارد والتكاليف", "icon": "people"}, |
|
{"name": "تحليل المخاطر", "icon": "exclamation-triangle"}, |
|
{"name": "إدارة المشاريع", "icon": "kanban"}, |
|
{"name": "الخرائط والمواقع", "icon": "geo-alt"}, |
|
{"name": "الجدول الزمني", "icon": "calendar3"}, |
|
{"name": "الإشعارات", "icon": "bell"}, |
|
{"name": "مقارنة المستندات", "icon": "files"}, |
|
{"name": "المساعد الذكي", "icon": "robot"}, |
|
{"name": "التقارير", "icon": "bar-chart"}, |
|
{"name": "الإعدادات", "icon": "gear"} |
|
] |
|
|
|
|
|
selected = self.ui.create_sidebar(menu_items) |
|
|
|
|
|
self.ui.create_header("الخرائط والمواقع", "عرض وإدارة مواقع المشاريع") |
|
|
|
|
|
tabs = st.tabs(["خريطة المشاريع", "تفاصيل المواقع", "إضافة موقع جديد", "تحليل المناطق"]) |
|
|
|
|
|
with tabs[0]: |
|
self.show_projects_map() |
|
|
|
|
|
with tabs[1]: |
|
self.show_location_details() |
|
|
|
|
|
with tabs[2]: |
|
self.add_new_location() |
|
|
|
|
|
with tabs[3]: |
|
self.analyze_regions() |
|
|
|
def show_projects_map(self): |
|
"""عرض خريطة المشاريع""" |
|
|
|
col1, col2, col3 = st.columns(3) |
|
|
|
with col1: |
|
status_filter = st.multiselect( |
|
"حالة المشروع", |
|
options=["الكل", "جاري التنفيذ", "قيد الدراسة", "مكتمل"], |
|
default=["الكل"] |
|
) |
|
|
|
with col2: |
|
location_filter = st.multiselect( |
|
"الموقع", |
|
options=["الكل"] + list(set([p["location"] for p in self.projects_data])), |
|
default=["الكل"] |
|
) |
|
|
|
with col3: |
|
budget_range = st.slider( |
|
"نطاق الميزانية (مليون ريال)", |
|
0.0, 25.0, (0.0, 25.0), |
|
step=0.5 |
|
) |
|
|
|
|
|
filtered_projects = self.projects_data |
|
|
|
if "الكل" not in status_filter and status_filter: |
|
filtered_projects = [p for p in filtered_projects if p["status"] in status_filter] |
|
|
|
if "الكل" not in location_filter and location_filter: |
|
filtered_projects = [p for p in filtered_projects if p["location"] in location_filter] |
|
|
|
filtered_projects = [p for p in filtered_projects if budget_range[0] * 1000000 <= p["budget"] <= budget_range[1] * 1000000] |
|
|
|
|
|
st.markdown("### خريطة المشاريع") |
|
|
|
|
|
center = [24.0, 45.0] |
|
|
|
|
|
m = folium.Map(location=center, zoom_start=5, tiles="OpenStreetMap") |
|
|
|
|
|
for project in filtered_projects: |
|
|
|
if project["status"] == "جاري التنفيذ": |
|
color = "blue" |
|
elif project["status"] == "قيد الدراسة": |
|
color = "orange" |
|
elif project["status"] == "مكتمل": |
|
color = "green" |
|
else: |
|
color = "gray" |
|
|
|
|
|
popup_text = f""" |
|
<div dir="rtl" style="text-align: right; width: 200px;"> |
|
<h4>{project['name']}</h4> |
|
<p><strong>الحالة:</strong> {project['status']}</p> |
|
<p><strong>الميزانية:</strong> {project['budget']:,} ريال</p> |
|
<p><strong>نسبة الإنجاز:</strong> {project['completion']}%</p> |
|
<p><strong>العميل:</strong> {project['client']}</p> |
|
<p><strong>تاريخ البدء:</strong> {project['start_date']}</p> |
|
<p><strong>تاريخ الانتهاء:</strong> {project['end_date']}</p> |
|
<a href="#" onclick="alert('تم فتح تفاصيل المشروع');">عرض التفاصيل</a> |
|
</div> |
|
""" |
|
|
|
|
|
folium.Marker( |
|
location=project["coordinates"], |
|
popup=folium.Popup(popup_text, max_width=300), |
|
tooltip=project["name"], |
|
icon=folium.Icon(color=color, icon="info-sign") |
|
).add_to(m) |
|
|
|
|
|
folium_static(m, width=1000, height=500) |
|
|
|
|
|
st.markdown("### إحصائيات المشاريع") |
|
|
|
col1, col2, col3, col4 = st.columns(4) |
|
|
|
with col1: |
|
self.ui.create_metric_card( |
|
"إجمالي المشاريع", |
|
str(len(filtered_projects)), |
|
None, |
|
self.ui.COLORS['primary'] |
|
) |
|
|
|
with col2: |
|
projects_in_progress = len([p for p in filtered_projects if p["status"] == "جاري التنفيذ"]) |
|
self.ui.create_metric_card( |
|
"مشاريع جارية", |
|
str(projects_in_progress), |
|
None, |
|
self.ui.COLORS['secondary'] |
|
) |
|
|
|
with col3: |
|
total_budget = sum([p["budget"] for p in filtered_projects]) |
|
self.ui.create_metric_card( |
|
"إجمالي الميزانية", |
|
f"{total_budget/1000000:.1f} مليون ريال", |
|
None, |
|
self.ui.COLORS['accent'] |
|
) |
|
|
|
with col4: |
|
avg_completion = np.mean([p["completion"] for p in filtered_projects]) |
|
self.ui.create_metric_card( |
|
"متوسط نسبة الإنجاز", |
|
f"{avg_completion:.1f}%", |
|
None, |
|
self.ui.COLORS['success'] |
|
) |
|
|
|
def show_location_details(self): |
|
"""عرض تفاصيل المواقع""" |
|
st.markdown("### تفاصيل مواقع المشاريع") |
|
|
|
|
|
projects_df = pd.DataFrame(self.projects_data) |
|
projects_df = projects_df.rename(columns={ |
|
"id": "رقم المشروع", |
|
"name": "اسم المشروع", |
|
"location": "الموقع", |
|
"status": "الحالة", |
|
"budget": "الميزانية (ريال)", |
|
"completion": "نسبة الإنجاز (%)", |
|
"client": "العميل", |
|
"start_date": "تاريخ البدء", |
|
"end_date": "تاريخ الانتهاء" |
|
}) |
|
|
|
|
|
projects_df = projects_df.drop(columns=["coordinates"]) |
|
|
|
|
|
st.dataframe( |
|
projects_df, |
|
use_container_width=True, |
|
hide_index=True |
|
) |
|
|
|
|
|
col1, col2 = st.columns([1, 5]) |
|
with col1: |
|
self.ui.create_button("تصدير البيانات", "primary") |
|
|
|
|
|
st.markdown("### تفاصيل مشروع محدد") |
|
|
|
selected_project = st.selectbox( |
|
"اختر مشروعاً لعرض التفاصيل", |
|
options=[p["name"] for p in self.projects_data] |
|
) |
|
|
|
|
|
project = next((p for p in self.projects_data if p["name"] == selected_project), None) |
|
|
|
if project: |
|
col1, col2 = st.columns([2, 1]) |
|
|
|
with col1: |
|
|
|
st.markdown(f"#### {project['name']}") |
|
st.markdown(f"**الموقع:** {project['location']}") |
|
st.markdown(f"**الحالة:** {project['status']}") |
|
st.markdown(f"**الميزانية:** {project['budget']:,} ريال") |
|
st.markdown(f"**نسبة الإنجاز:** {project['completion']}%") |
|
st.markdown(f"**العميل:** {project['client']}") |
|
st.markdown(f"**تاريخ البدء:** {project['start_date']}") |
|
st.markdown(f"**تاريخ الانتهاء:** {project['end_date']}") |
|
|
|
|
|
col1, col2, col3 = st.columns(3) |
|
with col1: |
|
self.ui.create_button("تعديل البيانات", "primary") |
|
with col2: |
|
self.ui.create_button("عرض المستندات", "secondary") |
|
with col3: |
|
self.ui.create_button("تقرير الموقع", "accent") |
|
|
|
with col2: |
|
|
|
m = folium.Map(location=project["coordinates"], zoom_start=12) |
|
folium.Marker( |
|
location=project["coordinates"], |
|
tooltip=project["name"], |
|
icon=folium.Icon(color="red", icon="info-sign") |
|
).add_to(m) |
|
folium_static(m, width=300, height=300) |
|
|
|
def add_new_location(self): |
|
"""إضافة موقع جديد""" |
|
st.markdown("### إضافة موقع مشروع جديد") |
|
|
|
|
|
with st.form("new_location_form"): |
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
project_id = st.text_input("رقم المشروع", value="P00" + str(len(self.projects_data) + 1)) |
|
project_name = st.text_input("اسم المشروع") |
|
location = st.text_input("الموقع") |
|
status = st.selectbox( |
|
"الحالة", |
|
options=["جاري التنفيذ", "قيد الدراسة", "مكتمل"] |
|
) |
|
budget = st.number_input("الميزانية (ريال)", min_value=0, step=100000) |
|
|
|
with col2: |
|
completion = st.slider("نسبة الإنجاز (%)", 0, 100, 0) |
|
client = st.text_input("العميل") |
|
start_date = st.date_input("تاريخ البدء") |
|
end_date = st.date_input("تاريخ الانتهاء") |
|
|
|
st.markdown("### تحديد الموقع على الخريطة") |
|
st.markdown("انقر على الخريطة لتحديد موقع المشروع أو أدخل الإحداثيات يدوياً") |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
latitude = st.number_input("خط العرض", value=24.0, format="%.4f") |
|
|
|
with col2: |
|
longitude = st.number_input("خط الطول", value=45.0, format="%.4f") |
|
|
|
|
|
m = folium.Map(location=[latitude, longitude], zoom_start=5) |
|
folium.Marker( |
|
location=[latitude, longitude], |
|
tooltip="موقع المشروع الجديد", |
|
icon=folium.Icon(color="red", icon="info-sign") |
|
).add_to(m) |
|
folium_static(m, width=700, height=300) |
|
|
|
|
|
submit_button = st.form_submit_button("إضافة المشروع") |
|
|
|
if submit_button: |
|
|
|
st.success("تم إضافة المشروع بنجاح!") |
|
|
|
|
|
st.experimental_rerun() |
|
|
|
def analyze_regions(self): |
|
"""تحليل المناطق""" |
|
st.markdown("### تحليل المناطق") |
|
|
|
|
|
regions_data = { |
|
"المنطقة": ["الرياض", "مكة المكرمة", "المدينة المنورة", "القصيم", "المنطقة الشرقية", "عسير", "تبوك", "حائل", "الحدود الشمالية", "جازان", "نجران", "الباحة", "الجوف"], |
|
"عدد المشاريع": [15, 12, 8, 5, 18, 7, 4, 3, 2, 6, 3, 2, 3], |
|
"إجمالي الميزانية (مليون ريال)": [120, 95, 45, 30, 150, 40, 25, 18, 12, 35, 20, 15, 22], |
|
"متوسط مدة المشروع (شهر)": [18, 16, 14, 12, 20, 15, 12, 10, 9, 14, 12, 10, 11] |
|
} |
|
|
|
regions_df = pd.DataFrame(regions_data) |
|
|
|
|
|
st.markdown("#### توزيع المشاريع حسب المناطق") |
|
|
|
|
|
st.image("https://via.placeholder.com/800x400?text=خريطة+حرارية+للمشاريع+حسب+المناطق", use_column_width=True) |
|
|
|
|
|
st.markdown("#### إحصائيات المناطق") |
|
|
|
|
|
st.dataframe( |
|
regions_df, |
|
use_container_width=True, |
|
hide_index=True |
|
) |
|
|
|
|
|
st.markdown("#### مقارنة المناطق") |
|
|
|
chart_type = st.radio( |
|
"نوع الرسم البياني", |
|
options=["عدد المشاريع", "إجمالي الميزانية", "متوسط مدة المشروع"], |
|
horizontal=True |
|
) |
|
|
|
if chart_type == "عدد المشاريع": |
|
chart_data = regions_df[["المنطقة", "عدد المشاريع"]].sort_values(by="عدد المشاريع", ascending=False) |
|
st.bar_chart(chart_data.set_index("المنطقة")) |
|
elif chart_type == "إجمالي الميزانية": |
|
chart_data = regions_df[["المنطقة", "إجمالي الميزانية (مليون ريال)"]].sort_values(by="إجمالي الميزانية (مليون ريال)", ascending=False) |
|
st.bar_chart(chart_data.set_index("المنطقة")) |
|
else: |
|
chart_data = regions_df[["المنطقة", "متوسط مدة المشروع (شهر)"]].sort_values(by="متوسط مدة المشروع (شهر)", ascending=False) |
|
st.bar_chart(chart_data.set_index("المنطقة")) |
|
|
|
|
|
st.markdown("#### تحليل كثافة المشاريع") |
|
st.markdown(""" |
|
يوضح هذا التحليل توزيع المشاريع حسب المناطق الجغرافية، مما يساعد في: |
|
- تحديد المناطق ذات النشاط العالي |
|
- تحديد فرص النمو في المناطق الأقل نشاطاً |
|
- تخطيط الموارد بناءً على التوزيع الجغرافي |
|
""") |
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
maps_app = MapsApp() |
|
maps_app.run() |
|
|