wasmdashai commited on
Commit
8034c5e
·
verified ·
1 Parent(s): d81caf0

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +451 -391
index.html CHANGED
@@ -4,10 +4,9 @@
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>نظام رسم المسارات البحرية المتقدم</title>
8
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
9
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
10
- <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
11
  <style>
12
  :root {
13
  --primary: #1e3a8a;
@@ -21,10 +20,6 @@
21
  --background: #ffffff;
22
  --text: #1e293b;
23
  --border: #e2e8f0;
24
- --original-route: #1e3a8a;
25
- --generated-route: #dc2626;
26
- --original-point: #3b82f6;
27
- --generated-point: #ef4444;
28
  }
29
 
30
  * {
@@ -132,27 +127,6 @@
132
  color: var(--primary);
133
  }
134
 
135
- .file-upload {
136
- border: 2px dashed var(--border);
137
- border-radius: 12px;
138
- padding: 25px;
139
- text-align: center;
140
- cursor: pointer;
141
- transition: all 0.3s ease;
142
- margin-bottom: 20px;
143
- }
144
-
145
- .file-upload:hover {
146
- border-color: var(--primary);
147
- background: var(--light);
148
- }
149
-
150
- .file-upload i {
151
- font-size: 3rem;
152
- margin-bottom: 15px;
153
- color: var(--primary);
154
- }
155
-
156
  .form-group {
157
  margin-bottom: 20px;
158
  }
@@ -164,7 +138,7 @@
164
  color: var(--dark);
165
  }
166
 
167
- input, select, button {
168
  width: 100%;
169
  padding: 14px;
170
  border: 1px solid var(--border);
@@ -206,6 +180,61 @@
206
  background: linear-gradient(135deg, var(--danger) 0%, #dc2626 100%);
207
  }
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  .stats-grid {
210
  display: grid;
211
  grid-template-columns: 1fr 1fr;
@@ -448,52 +477,46 @@
448
  }
449
  }
450
 
451
- /* أنماط خاصة للمسارات */
452
- .original-route {
453
- stroke-dasharray: 10, 5;
454
- animation: dash 20s linear infinite;
 
 
 
 
 
455
  }
456
 
457
- @keyframes dash {
458
- to {
459
- stroke-dashoffset: -1000;
460
- }
461
  }
462
 
463
- .generated-point {
464
- filter: drop-shadow(0 0 3px rgba(220, 38, 38, 0.5));
 
 
465
  }
466
 
467
- .original-point {
468
- filter: drop-shadow(0 0 3px rgba(30, 58, 138, 0.5));
 
 
469
  }
470
 
471
- .route-comparison {
472
- display: flex;
473
- gap: 10px;
474
- margin-top: 15px;
475
  }
476
 
477
- .comparison-btn {
478
- flex: 1;
479
- padding: 10px;
480
  background: var(--light);
 
481
  border: 1px solid var(--border);
482
- border-radius: 8px;
483
- cursor: pointer;
484
- transition: all 0.3s ease;
485
- text-align: center;
486
- font-size: 0.9rem;
487
- }
488
-
489
- .comparison-btn:hover {
490
- background: var(--primary);
491
- color: white;
492
- }
493
-
494
- .comparison-btn.active {
495
- background: var(--primary);
496
- color: white;
497
  }
498
  </style>
499
  </head>
@@ -503,8 +526,8 @@
503
  <div class="logo">
504
  <i class="fas fa-ship"></i>
505
  <div class="logo-text">
506
- <h1>نظام المسارات البحرية المتقدم</h1>
507
- <p>مقارنة المسارات الأصلية والمتولدة في البحر الأحمر</p>
508
  </div>
509
  </div>
510
  <div class="header-controls">
@@ -516,73 +539,146 @@
516
  <div class="control-panel">
517
  <div class="panel-section">
518
  <div class="section-title">
519
- <i class="fas fa-file-import"></i>
520
- <h3>تحميل بيانات المسارات</h3>
521
  </div>
522
- <div class="file-upload" id="fileUpload">
523
- <i class="fas fa-cloud-upload-alt"></i>
524
- <p>انقر أو اسحب ملف Excel هنا</p>
525
- <p class="file-format">يدعم ملفات CSV و Excel</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
  </div>
527
- <input type="file" id="fileInput" accept=".csv,.xlsx,.xls" style="display: none;">
528
-
529
  <div class="form-group">
530
- <label for="routeType"><i class="fas fa-route"></i> نوع التحليل</label>
531
- <select id="routeType">
532
- <option value="comparison">مقارنة المسارات</option>
533
- <option value="prediction">توقع المسارات المستقبلية</option>
534
- <option value="anomaly">كشف الشذوذ في المسارات</option>
 
 
535
  </select>
536
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
537
 
538
  <div class="form-group">
539
- <label><i class="fas fa-layer-group"></i> عرض المسارات</label>
540
- <div class="route-comparison">
541
- <div class="comparison-btn active" data-route="all">الكل</div>
542
- <div class="comparison-btn" data-route="original">الأصلية فقط</div>
543
- <div class="comparison-btn" data-route="generated">المتولدة فقط</div>
 
 
 
 
 
544
  </div>
545
  </div>
546
-
547
- <button id="analyzeBtn"><i class="fas fa-chart-line"></i> تحليل البيانات</button>
548
- <button class="btn-secondary" id="generateRoutes"><i class="fas fa-wave-square"></i> توليد مسارات جديدة</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
549
  </div>
550
 
551
  <div class="panel-section">
552
  <div class="section-title">
553
  <i class="fas fa-chart-bar"></i>
554
- <h3>إحصائيات المسارات</h3>
555
  </div>
556
  <div class="stats-grid">
557
  <div class="stat-card">
558
- <div class="stat-label">المسارات الأصلية</div>
559
- <div class="stat-value" id="originalRoutes">5</div>
560
- <div class="stat-label">مسار</div>
561
  </div>
562
  <div class="stat-card">
563
- <div class="stat-label">المسارات المتولدة</div>
564
- <div class="stat-value" id="generatedRoutes">8</div>
565
- <div class="stat-label">مسار</div>
566
  </div>
567
  <div class="stat-card">
568
- <div class="stat-label">متوسط المسافة</div>
569
- <div class="stat-value" id="avgDistance">1,845</div>
570
  <div class="stat-label">كم</div>
571
  </div>
572
  <div class="stat-card">
573
- <div class="stat-label">مطابقة المسارات</div>
574
- <div class="stat-value" id="routeMatch">87%</div>
575
  <div class="stat-label">نسبة</div>
576
  </div>
577
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578
  </div>
579
 
580
  <div class="panel-section">
581
  <div class="section-title">
582
- <i class="fas fa-list"></i>
583
- <h3>قائمة المسارات</h3>
584
  </div>
585
- <div id="routesList">
586
  <!-- سيتم ملؤها ديناميكياً -->
587
  </div>
588
  </div>
@@ -613,21 +709,25 @@
613
  <div class="legend-title">مفتاح الخريطة</div>
614
  <div class="legend-items">
615
  <div class="legend-item">
616
- <div class="legend-color" style="background: var(--original-route);"></div>
617
- <span>مسار أصلي</span>
618
  </div>
619
  <div class="legend-item">
620
- <div class="legend-color" style="background: var(--generated-route);"></div>
621
  <span>مسار متولد</span>
622
  </div>
623
  <div class="legend-item">
624
- <div class="legend-color" style="background: var(--original-point);"></div>
625
- <span>نقطة أصلية</span>
626
  </div>
627
  <div class="legend-item">
628
- <div class="legend-color" style="background: var(--generated-point);"></div>
629
  <span>نقطة متولدة</span>
630
  </div>
 
 
 
 
631
  </div>
632
  </div>
633
  </div>
@@ -635,7 +735,6 @@
635
  </div>
636
 
637
  <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
638
- <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
639
  <script>
640
  // تهيئة الخريطة مع طبقة بحر نظيفة
641
  const map = L.map('map', {
@@ -679,155 +778,139 @@
679
  }).addTo(map).bindPopup('<div class="route-popup"><div class="popup-title">قناة السويس</div><div>نقطة النهاية للملاحة في البحر الأحمر</div></div>');
680
 
681
  // المتغيرات لتخزين المسارات
682
- let originalRoutes = [];
683
- let generatedRoutes = [];
684
  let routeLayers = [];
 
685
 
686
  // عناصر واجهة المستخدم
687
- const fileUpload = document.getElementById('fileUpload');
688
- const fileInput = document.getElementById('fileInput');
689
- const analyzeBtn = document.getElementById('analyzeBtn');
690
- const generateRoutesBtn = document.getElementById('generateRoutes');
691
- const routesList = document.getElementById('routesList');
692
- const originalRoutesElem = document.getElementById('originalRoutes');
693
- const generatedRoutesElem = document.getElementById('generatedRoutes');
694
- const avgDistanceElem = document.getElementById('avgDistance');
695
- const routeMatchElem = document.getElementById('routeMatch');
 
 
 
 
 
 
 
696
  const zoomInBtn = document.getElementById('zoomIn');
697
  const zoomOutBtn = document.getElementById('zoomOut');
698
  const locateRedSeaBtn = document.getElementById('locateRedSea');
699
- const comparisonBtns = document.querySelectorAll('.comparison-btn');
700
 
701
- // معالجة تحميل الملف
702
- fileUpload.addEventListener('click', () => {
703
- fileInput.click();
704
- });
705
-
706
- fileInput.addEventListener('change', (e) => {
707
- const file = e.target.files[0];
708
- if (file) {
709
- processFile(file);
710
- }
711
- });
712
-
713
- // معالجة أزرار المقارنة
714
- comparisonBtns.forEach(btn => {
715
- btn.addEventListener('click', () => {
716
- comparisonBtns.forEach(b => b.classList.remove('active'));
717
- btn.classList.add('active');
718
-
719
- const routeType = btn.getAttribute('data-route');
720
- filterRoutes(routeType);
721
  });
722
  });
723
 
724
- // دالة تصفية المسارات المعروضة
725
- function filterRoutes(type) {
726
- routeLayers.forEach(layer => {
727
- if (type === 'all') {
728
- map.addLayer(layer);
729
- } else if (type === 'original' && layer.options.routeType === 'original') {
730
- map.addLayer(layer);
731
- } else if (type === 'generated' && layer.options.routeType === 'generated') {
732
- map.addLayer(layer);
733
- } else {
734
- map.removeLayer(layer);
735
- }
736
- });
737
- }
738
-
739
- // محاكاة بيانات المسارات (للتجربة)
740
- function simulateRouteData() {
741
- originalRoutes = [];
742
- generatedRoutes = [];
743
 
744
- // إنشاء مسارات أصلية
745
- for (let i = 0; i < 5; i++) {
746
- const route = generateOriginalRoute(babMandeb, suezCanal);
747
- const distance = calculateRouteLength(route);
748
-
749
- originalRoutes.push({
750
- id: `original_${i + 1}`,
751
- name: `المسار الأصلي ${i + 1}`,
752
- type: 'original',
753
- distance: distance,
754
- route: route,
755
- startTime: new Date(Date.now() - Math.random() * 86400000).toLocaleString('ar-SA'),
756
- status: 'مكتمل'
757
- });
758
- }
759
-
760
- // إنشاء مسارات متولدة
761
- for (let i = 0; i < 8; i++) {
762
- const originalRoute = originalRoutes[i % originalRoutes.length].route;
763
- const route = generateRouteFromOriginal(originalRoute);
764
- const distance = calculateRouteLength(route);
765
-
766
- generatedRoutes.push({
767
- id: `generated_${i + 1}`,
768
- name: `المسار المتولد ${i + 1}`,
769
- type: 'generated',
770
- distance: distance,
771
- route: route,
772
- startTime: new Date(Date.now() - Math.random() * 86400000).toLocaleString('ar-SA'),
773
- status: 'متوقع'
774
- });
775
- }
776
- }
777
-
778
- // دالة لتوليد مسار أصلي
779
- function generateOriginalRoute(start, end, numPoints = 12) {
780
- const points = [];
781
 
782
  // إضافة نقطة البداية
783
- points.push([start[0], start[1]]);
784
 
785
- // توليد نقاط وسيطة بمسار مباشر
786
  for (let i = 1; i < numPoints - 1; i++) {
787
  const progress = i / (numPoints - 1);
788
- const baseLat = start[0] + (end[0] - start[0]) * progress;
789
- const baseLon = start[1] + (end[1] - start[1]) * progress;
790
-
791
- // انحراف بسيط جداً للمسار الأصلي
792
- const lat = baseLat + (Math.random() - 0.5) * 0.1;
793
- const lon = baseLon + (Math.random() - 0.5) * 0.1;
794
 
795
- points.push([lat, lon]);
796
  }
797
 
798
  // إضافة نقطة النهاية
799
- points.push([end[0], end[1]]);
800
 
801
- return points;
802
  }
803
 
804
- // دالة لتوليد مسار من المسار الأصلي
805
- function generateRouteFromOriginal(originalRoute, numPoints = 15) {
806
- const points = [];
 
807
 
808
- // إضافة نقطة البداية
809
- points.push([originalRoute[0][0], originalRoute[0][1]]);
810
 
811
- // توليد نقاط وسيطة مع انحراف أكبر
812
- for (let i = 1; i < numPoints - 1; i++) {
813
- const progress = i / (numPoints - 1);
814
- const originalIndex = Math.floor(progress * (originalRoute.length - 1));
815
- const originalPoint = originalRoute[originalIndex];
816
 
817
- // انحراف أكبر للمسار المتولد
818
- const lat = originalPoint[0] + (Math.random() - 0.5) * 0.5;
819
- const lon = originalPoint[1] + (Math.random() - 0.5) * 0.8;
820
 
821
- points.push([lat, lon]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
822
  }
823
 
824
- // إضافة نقطة النهاية
825
- points.push([originalRoute[originalRoute.length - 1][0], originalRoute[originalRoute.length - 1][1]]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
826
 
827
- return points;
828
  }
829
 
830
- // دالة لحساب المسافة بين نقطتين
831
  function calculateDistance(lat1, lon1, lat2, lon2) {
832
  const R = 6371; // نصف قطر الأرض بالكيلومترات
833
  const dLat = (lat2 - lat1) * Math.PI / 180;
@@ -840,7 +923,7 @@
840
  return R * c;
841
  }
842
 
843
- // دالة لحساب طول المسار
844
  function calculateRouteLength(route) {
845
  let totalDistance = 0;
846
  for (let i = 0; i < route.length - 1; i++) {
@@ -852,130 +935,37 @@
852
  return Math.round(totalDistance);
853
  }
854
 
855
- // دالة لتحديث قائمة المسارات
856
- function updateRoutesList() {
857
- routesList.innerHTML = '';
858
-
859
- const allRoutes = [...originalRoutes, ...generatedRoutes];
860
-
861
- allRoutes.forEach(route => {
862
- const routeItem = document.createElement('div');
863
- routeItem.className = 'route-item';
864
- routeItem.innerHTML = `
865
- <div class="route-header">
866
- <div class="route-name">${route.name}</div>
867
- <div class="route-type" style="background: ${route.type === 'original' ? 'var(--original-route)' : 'var(--generated-route)'}">
868
- ${route.type === 'original' ? 'أصلي' : 'متولد'}
869
- </div>
870
- </div>
871
- <div class="route-details">
872
- <span>المسافة: ${route.distance} كم</span>
873
- <span>الحالة: ${route.status}</span>
874
- </div>
875
- `;
876
-
877
- routeItem.addEventListener('click', () => {
878
- drawRouteComparison(route);
879
- });
880
-
881
- routesList.appendChild(routeItem);
882
- });
883
- }
884
-
885
- // دالة لتحديث الإحصائيات
886
- function updateStats() {
887
- originalRoutesElem.textContent = originalRoutes.length;
888
- generatedRoutesElem.textContent = generatedRoutes.length;
889
-
890
- if (originalRoutes.length > 0 && generatedRoutes.length > 0) {
891
- const totalDistance = [...originalRoutes, ...generatedRoutes].reduce((sum, route) => sum + route.distance, 0);
892
- const avgDistance = Math.round(totalDistance / (originalRoutes.length + generatedRoutes.length));
893
-
894
- avgDistanceElem.textContent = avgDistance.toLocaleString();
895
- }
896
- }
897
-
898
- // دالة لرسم مقارنة المسارات
899
- function drawRouteComparison(selectedRoute) {
900
  // مسح المسارات السابقة
901
  clearRoutes();
902
 
903
- // تحديد المسار الأصلي المقابل إن وجد
904
- let originalRouteToShow = null;
905
- let generatedRouteToShow = null;
906
-
907
- if (selectedRoute.type === 'original') {
908
- originalRouteToShow = selectedRoute;
909
- // إيجاد المسار المتولد المقابل
910
- const correspondingGenerated = generatedRoutes.find(r =>
911
- r.id === `generated_${selectedRoute.id.split('_')[1]}`
912
- );
913
- if (correspondingGenerated) {
914
- generatedRouteToShow = correspondingGenerated;
915
- }
916
- } else {
917
- generatedRouteToShow = selectedRoute;
918
- // إيجاد المسار الأصلي المقابل
919
- const correspondingOriginal = originalRoutes.find(r =>
920
- r.id === `original_${selectedRoute.id.split('_')[1]}`
921
- );
922
- if (correspondingOriginal) {
923
- originalRouteToShow = correspondingOriginal;
924
- }
925
- }
926
-
927
- // رسم المسار الأصلي
928
- if (originalRouteToShow) {
929
- drawRoute(originalRouteToShow, 'original');
930
- }
931
-
932
- // رسم المسار المتولد
933
- if (generatedRouteToShow) {
934
- drawRoute(generatedRouteToShow, 'generated');
935
- }
936
-
937
- // إذا لم يكن هناك مسار مقابل، رسم المسار المحدد فقط
938
- if (!originalRouteToShow && !generatedRouteToShow) {
939
- drawRoute(selectedRoute, selectedRoute.type);
940
- }
941
- }
942
-
943
- // دالة لرسم مسار على الخريطة
944
- function drawRoute(route, routeType) {
945
- const isOriginal = routeType === 'original';
946
- const lineColor = isOriginal ? 'var(--original-route)' : 'var(--generated-route)';
947
- const pointColor = isOriginal ? 'var(--original-point)' : 'var(--generated-point)';
948
- const pointClass = isOriginal ? 'original-point' : 'generated-point';
949
-
950
- // رسم الخط
951
- const polyline = L.polyline(route.route, {
952
- color: lineColor,
953
- weight: isOriginal ? 4 : 3,
954
- opacity: 0.9,
955
  lineJoin: 'round',
956
- className: isOriginal ? 'original-route' : '',
957
- routeType: routeType
958
  }).addTo(map);
 
959
 
960
- // إضافة نقاط على طول المسار
961
- route.route.forEach((point, index) => {
962
- if (index % (isOriginal ? 2 : 1) === 0) { // نقاط أقل للمسار الأصلي
963
  const pointMarker = L.circleMarker(point, {
964
- color: pointColor,
965
- fillColor: pointColor,
966
- fillOpacity: 0.9,
967
- radius: isOriginal ? 5 : 4,
968
- className: pointClass
969
  }).addTo(map);
970
 
971
  pointMarker.bindPopup(`<div class="route-popup">
972
- <div class="popup-title">${route.name}</div>
973
- <div>${isOriginal ? 'نقطة أصلية' : 'نقطة متولدة'} ${index + 1}</div>
974
  <div class="popup-details">
975
  <div class="popup-detail"><span class="popup-label">خط العرض:</span> ${point[0].toFixed(4)}</div>
976
  <div class="popup-detail"><span class="popup-label">خط الطول:</span> ${point[1].toFixed(4)}</div>
977
- <div class="popup-detail"><span class="popup-label">المسافة:</span> ${route.distance} كم</div>
978
- <div class="popup-detail"><span class="popup-label">النوع:</span> ${isOriginal ? 'أصلي' : 'متولد'}</div>
979
  </div>
980
  </div>`);
981
 
@@ -983,19 +973,135 @@
983
  }
984
  });
985
 
986
- routeLayers.push(polyline);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
987
 
988
- // ضبط حدود الخريطة لتناسب المسار
989
- const group = new L.featureGroup([polyline]);
 
990
  map.fitBounds(group.getBounds().pad(0.1));
991
  }
992
 
993
- // دالة لمسح جميع المسارات
994
  function clearRoutes() {
995
  routeLayers.forEach(layer => map.removeLayer(layer));
996
  routeLayers = [];
997
  }
998
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
999
  // إضافة عناصر التحكم في الخريطة
1000
  zoomInBtn.addEventListener('click', () => {
1001
  map.zoomIn();
@@ -1009,61 +1115,15 @@
1009
  map.setView([20.0, 38.0], 6);
1010
  });
1011
 
1012
- // معالجة زر التحليل
1013
- analyzeBtn.addEventListener('click', () => {
1014
- if (originalRoutes.length === 0) {
1015
- simulateRouteData();
1016
- updateRoutesList();
1017
- updateStats();
1018
- }
1019
-
1020
- // رسم أول مسار في القائمة
1021
- if (originalRoutes.length > 0) {
1022
- drawRouteComparison(originalRoutes[0]);
1023
- }
1024
- });
1025
-
1026
- // معالجة زر توليد مسارات جديدة
1027
- generateRoutesBtn.addEventListener('click', () => {
1028
- // توليد مسارات متولدة جديدة
1029
- generatedRoutes = [];
1030
-
1031
- for (let i = 0; i < 8; i++) {
1032
- const originalRoute = originalRoutes[i % originalRoutes.length].route;
1033
- const route = generateRouteFromOriginal(originalRoute);
1034
- const distance = calculateRouteLength(route);
1035
-
1036
- generatedRoutes.push({
1037
- id: `generated_${i + 1}`,
1038
- name: `المسار المتولد ${i + 1}`,
1039
- type: 'generated',
1040
- distance: distance,
1041
- route: route,
1042
- startTime: new Date().toLocaleString('ar-SA'),
1043
- status: 'متولد حديثاً'
1044
- });
1045
- }
1046
-
1047
- updateRoutesList();
1048
- updateStats();
1049
-
1050
- if (generatedRoutes.length > 0) {
1051
- drawRouteComparison(generatedRoutes[0]);
1052
- }
1053
- });
1054
-
1055
  // تحميل بعض البيانات الافتراضية عند بدء التشغيل
1056
  window.addEventListener('load', () => {
1057
- simulateRouteData();
1058
- updateRoutesList();
1059
- updateStats();
1060
 
1061
- // رسم أول مسار تلقائياً
1062
- if (originalRoutes.length > 0) {
1063
- setTimeout(() => {
1064
- drawRouteComparison(originalRoutes[0]);
1065
- }, 1000);
1066
- }
1067
  });
1068
  </script>
1069
  </body>
 
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>نظام توليد المسارات البحرية المتقدم</title>
8
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
9
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
10
  <style>
11
  :root {
12
  --primary: #1e3a8a;
 
20
  --background: #ffffff;
21
  --text: #1e293b;
22
  --border: #e2e8f0;
 
 
 
 
23
  }
24
 
25
  * {
 
127
  color: var(--primary);
128
  }
129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  .form-group {
131
  margin-bottom: 20px;
132
  }
 
138
  color: var(--dark);
139
  }
140
 
141
+ input, select, button, textarea {
142
  width: 100%;
143
  padding: 14px;
144
  border: 1px solid var(--border);
 
180
  background: linear-gradient(135deg, var(--danger) 0%, #dc2626 100%);
181
  }
182
 
183
+ .model-cards {
184
+ display: grid;
185
+ grid-template-columns: 1fr 1fr;
186
+ gap: 15px;
187
+ margin-top: 15px;
188
+ }
189
+
190
+ .model-card {
191
+ background: var(--light);
192
+ border-radius: 12px;
193
+ padding: 15px;
194
+ cursor: pointer;
195
+ transition: all 0.3s ease;
196
+ border: 2px solid var(--border);
197
+ text-align: center;
198
+ }
199
+
200
+ .model-card:hover {
201
+ transform: translateY(-3px);
202
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
203
+ }
204
+
205
+ .model-card.active {
206
+ border-color: var(--primary);
207
+ background: linear-gradient(135deg, var(--light) 0%, #e0f2fe 100%);
208
+ }
209
+
210
+ .model-name {
211
+ font-weight: bold;
212
+ margin-bottom: 5px;
213
+ color: var(--primary);
214
+ }
215
+
216
+ .model-desc {
217
+ font-size: 0.8rem;
218
+ color: var(--dark);
219
+ opacity: 0.8;
220
+ }
221
+
222
+ .coordinates-input {
223
+ display: grid;
224
+ grid-template-columns: 1fr 1fr;
225
+ gap: 10px;
226
+ }
227
+
228
+ .input-group {
229
+ display: flex;
230
+ flex-direction: column;
231
+ }
232
+
233
+ .input-group label {
234
+ font-size: 0.9rem;
235
+ margin-bottom: 5px;
236
+ }
237
+
238
  .stats-grid {
239
  display: grid;
240
  grid-template-columns: 1fr 1fr;
 
477
  }
478
  }
479
 
480
+ .anomaly-indicator {
481
+ display: flex;
482
+ align-items: center;
483
+ justify-content: center;
484
+ gap: 10px;
485
+ padding: 10px;
486
+ border-radius: 8px;
487
+ margin-top: 10px;
488
+ font-weight: bold;
489
  }
490
 
491
+ .anomaly-low {
492
+ background: #fef3c7;
493
+ color: #d97706;
494
+ border: 1px solid #f59e0b;
495
  }
496
 
497
+ .anomaly-medium {
498
+ background: #fed7aa;
499
+ color: #ea580c;
500
+ border: 1px solid #f97316;
501
  }
502
 
503
+ .anomaly-high {
504
+ background: #fecaca;
505
+ color: #dc2626;
506
+ border: 1px solid #ef4444;
507
  }
508
 
509
+ .context-input {
510
+ height: 100px;
511
+ resize: vertical;
 
512
  }
513
 
514
+ .generation-results {
515
+ margin-top: 20px;
516
+ padding: 15px;
517
  background: var(--light);
518
+ border-radius: 12px;
519
  border: 1px solid var(--border);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
520
  }
521
  </style>
522
  </head>
 
526
  <div class="logo">
527
  <i class="fas fa-ship"></i>
528
  <div class="logo-text">
529
+ <h1>نظام توليد المسارات البحرية المتقدم</h1>
530
+ <p>توليد مسارات بحرية باستخدام نماذج الذكاء الاصطناعي</p>
531
  </div>
532
  </div>
533
  <div class="header-controls">
 
539
  <div class="control-panel">
540
  <div class="panel-section">
541
  <div class="section-title">
542
+ <i class="fas fa-brain"></i>
543
+ <h3>اختيار النموذج</h3>
544
  </div>
545
+ <div class="model-cards">
546
+ <div class="model-card active" data-model="TrAISformer">
547
+ <div class="model-name">TrAISformer</div>
548
+ <div class="model-desc">نموذج Transformer متخصص</div>
549
+ </div>
550
+ <div class="model-card" data-model="EnhcTrAISformer">
551
+ <div class="model-name">EnhcTrAISformer</div>
552
+ <div class="model-desc">نموذج Transformer محسن</div>
553
+ </div>
554
+ <div class="model-card" data-model="eDQTI-GRU">
555
+ <div class="model-name">eDQTI-GRU</div>
556
+ <div class="model-desc">نموذج GRU مع DQTI</div>
557
+ </div>
558
+ <div class="model-card" data-model="eDQTI-LSTM">
559
+ <div class="model-name">eDQTI-LSTM</div>
560
+ <div class="model-desc">نموذج LSTM مع DQTI</div>
561
+ </div>
562
+ <div class="model-card" data-model="eDQTI-HYPER">
563
+ <div class="model-name">eDQTI-HYPER</div>
564
+ <div class="model-desc">نموذج هجين متقدم</div>
565
+ </div>
566
  </div>
567
+
 
568
  <div class="form-group">
569
+ <label for="anomalyModel"><i class="fas fa-exclamation-triangle"></i> نموذج كشف الشذوذ</label>
570
+ <select id="anomalyModel">
571
+ <option value="auto">تلقائي (بناءً على النموذج الرئيسي)</option>
572
+ <option value="isolation-forest">Isolation Forest</option>
573
+ <option value="local-outlier">Local Outlier Factor</option>
574
+ <option value="svm">One-Class SVM</option>
575
+ <option value="autoencoder">Autoencoder</option>
576
  </select>
577
  </div>
578
+ </div>
579
+
580
+ <div class="panel-section">
581
+ <div class="section-title">
582
+ <i class="fas fa-route"></i>
583
+ <h3>إعدادات التوليد</h3>
584
+ </div>
585
+
586
+ <div class="form-group">
587
+ <label for="contextInput"><i class="fas fa-code"></i> بيانات السياق (Context)</label>
588
+ <textarea id="contextInput" class="context-input" placeholder="أدخل بيانات المسار السياقي هنا..."></textarea>
589
+ </div>
590
 
591
  <div class="form-group">
592
+ <label><i class="fas fa-map-marker-alt"></i> نقطة البداية</label>
593
+ <div class="coordinates-input">
594
+ <div class="input-group">
595
+ <label>خط العرض</label>
596
+ <input type="number" id="startLat" step="0.0001" value="12.6" placeholder="12.6">
597
+ </div>
598
+ <div class="input-group">
599
+ <label>خط الطول</label>
600
+ <input type="number" id="startLon" step="0.0001" value="43.0" placeholder="43.0">
601
+ </div>
602
  </div>
603
  </div>
604
+
605
+ <div class="form-group">
606
+ <label><i class="fas fa-flag-checkered"></i> نقطة النهاية</label>
607
+ <div class="coordinates-input">
608
+ <div class="input-group">
609
+ <label>خط العرض</label>
610
+ <input type="number" id="endLat" step="0.0001" value="30.5" placeholder="30.5">
611
+ </div>
612
+ <div class="input-group">
613
+ <label>خط الطول</label>
614
+ <input type="number" id="endLon" step="0.0001" value="32.3" placeholder="32.3">
615
+ </div>
616
+ </div>
617
+ </div>
618
+
619
+ <div class="form-group">
620
+ <label for="hours"><i class="fas fa-clock"></i> عدد الساعات للتوليد</label>
621
+ <input type="number" id="hours" min="1" max="168" value="24" placeholder="24">
622
+ </div>
623
+
624
+ <div class="form-group">
625
+ <label for="pointsPerHour"><i class="fas fa-map-pin"></i> عدد النقاط في كل ساعة</label>
626
+ <input type="number" id="pointsPerHour" min="1" max="10" value="2" placeholder="2">
627
+ </div>
628
+
629
+ <button id="generateBtn"><i class="fas fa-play"></i> بدء توليد المسار</button>
630
  </div>
631
 
632
  <div class="panel-section">
633
  <div class="section-title">
634
  <i class="fas fa-chart-bar"></i>
635
+ <h3>نتائج التوليد</h3>
636
  </div>
637
  <div class="stats-grid">
638
  <div class="stat-card">
639
+ <div class="stat-label">النموذج المستخدم</div>
640
+ <div class="stat-value" id="usedModel">TrAISformer</div>
641
+ <div class="stat-label">نموذج</div>
642
  </div>
643
  <div class="stat-card">
644
+ <div class="stat-label">إجمالي النقاط</div>
645
+ <div class="stat-value" id="totalPoints">48</div>
646
+ <div class="stat-label">نقطة</div>
647
  </div>
648
  <div class="stat-card">
649
+ <div class="stat-label">المسافة الإجمالية</div>
650
+ <div class="stat-value" id="totalDistance">1,845</div>
651
  <div class="stat-label">كم</div>
652
  </div>
653
  <div class="stat-card">
654
+ <div class="stat-label">مستوى الشذوذ</div>
655
+ <div class="stat-value" id="anomalyLevel">3.2%</div>
656
  <div class="stat-label">نسبة</div>
657
  </div>
658
  </div>
659
+
660
+ <div class="anomaly-indicator anomaly-low" id="anomalyIndicator">
661
+ <i class="fas fa-check-circle"></i>
662
+ <span>المسار طبيعي - لا توجد شذوذات كبيرة</span>
663
+ </div>
664
+
665
+ <div class="generation-results">
666
+ <h4>تفاصيل التوليد:</h4>
667
+ <div id="generationDetails">
668
+ <p>• النموذج: TrAISformer</p>
669
+ <p>• وقت التوليد: 2.3 ثانية</p>
670
+ <p>• الدقة: 94.7%</p>
671
+ <p>• نقاط الشذوذ: 2 من 48 نقطة</p>
672
+ </div>
673
+ </div>
674
  </div>
675
 
676
  <div class="panel-section">
677
  <div class="section-title">
678
+ <i class="fas fa-history"></i>
679
+ <h3>سجل التوليد</h3>
680
  </div>
681
+ <div id="generationHistory">
682
  <!-- سيتم ملؤها ديناميكياً -->
683
  </div>
684
  </div>
 
709
  <div class="legend-title">مفتاح الخريطة</div>
710
  <div class="legend-items">
711
  <div class="legend-item">
712
+ <div class="legend-color" style="background: #1e3a8a;"></div>
713
+ <span>مسار السياق</span>
714
  </div>
715
  <div class="legend-item">
716
+ <div class="legend-color" style="background: #dc2626;"></div>
717
  <span>مسار متولد</span>
718
  </div>
719
  <div class="legend-item">
720
+ <div class="legend-color" style="background: #3b82f6;"></div>
721
+ <span>نقطة سياق</span>
722
  </div>
723
  <div class="legend-item">
724
+ <div class="legend-color" style="background: #ef4444;"></div>
725
  <span>نقطة متولدة</span>
726
  </div>
727
+ <div class="legend-item">
728
+ <div class="legend-color" style="background: #f59e0b;"></div>
729
+ <span>نقطة شذوذ</span>
730
+ </div>
731
  </div>
732
  </div>
733
  </div>
 
735
  </div>
736
 
737
  <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
 
738
  <script>
739
  // تهيئة الخريطة مع طبقة بحر نظيفة
740
  const map = L.map('map', {
 
778
  }).addTo(map).bindPopup('<div class="route-popup"><div class="popup-title">قناة السويس</div><div>نقطة النهاية للملاحة في البحر الأحمر</div></div>');
779
 
780
  // المتغيرات لتخزين المسارات
781
+ let contextRoute = [];
782
+ let generatedRoute = [];
783
  let routeLayers = [];
784
+ let currentModel = 'TrAISformer';
785
 
786
  // عناصر واجهة المستخدم
787
+ const modelCards = document.querySelectorAll('.model-card');
788
+ const generateBtn = document.getElementById('generateBtn');
789
+ const contextInput = document.getElementById('contextInput');
790
+ const startLat = document.getElementById('startLat');
791
+ const startLon = document.getElementById('startLon');
792
+ const endLat = document.getElementById('endLat');
793
+ const endLon = document.getElementById('endLon');
794
+ const hours = document.getElementById('hours');
795
+ const pointsPerHour = document.getElementById('pointsPerHour');
796
+ const usedModelElem = document.getElementById('usedModel');
797
+ const totalPointsElem = document.getElementById('totalPoints');
798
+ const totalDistanceElem = document.getElementById('totalDistance');
799
+ const anomalyLevelElem = document.getElementById('anomalyLevel');
800
+ const anomalyIndicator = document.getElementById('anomalyIndicator');
801
+ const generationDetails = document.getElementById('generationDetails');
802
+ const generationHistory = document.getElementById('generationHistory');
803
  const zoomInBtn = document.getElementById('zoomIn');
804
  const zoomOutBtn = document.getElementById('zoomOut');
805
  const locateRedSeaBtn = document.getElementById('locateRedSea');
 
806
 
807
+ // معالجة اختيار النموذج
808
+ modelCards.forEach(card => {
809
+ card.addEventListener('click', () => {
810
+ modelCards.forEach(c => c.classList.remove('active'));
811
+ card.classList.add('active');
812
+ currentModel = card.getAttribute('data-model');
813
+ usedModelElem.textContent = currentModel;
 
 
 
 
 
 
 
 
 
 
 
 
 
814
  });
815
  });
816
 
817
+ // دالة توليد مسار السياق من الإحداثيات
818
+ function generateContextRoute() {
819
+ const start = [parseFloat(startLat.value), parseFloat(startLon.value)];
820
+ const end = [parseFloat(endLat.value), parseFloat(endLon.value)];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
821
 
822
+ const route = [];
823
+ const numPoints = 8;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
824
 
825
  // إضافة نقطة البداية
826
+ route.push([start[0], start[1]]);
827
 
828
+ // توليد نقاط وسيطة
829
  for (let i = 1; i < numPoints - 1; i++) {
830
  const progress = i / (numPoints - 1);
831
+ const lat = start[0] + (end[0] - start[0]) * progress + (Math.random() - 0.5) * 0.2;
832
+ const lon = start[1] + (end[1] - start[1]) * progress + (Math.random() - 0.5) * 0.3;
 
 
 
 
833
 
834
+ route.push([lat, lon]);
835
  }
836
 
837
  // إضافة نقطة النهاية
838
+ route.push([end[0], end[1]]);
839
 
840
+ return route;
841
  }
842
 
843
+ // دالة توليد مسار بناءً على النموذج المختار
844
+ function generateRouteWithModel(contextRoute, model, totalHours, pointsPerHour) {
845
+ const totalPoints = totalHours * pointsPerHour;
846
+ const route = [];
847
 
848
+ // إضافة نقطة البداية (نفس بداية السياق)
849
+ route.push([contextRoute[0][0], contextRoute[0][1]]);
850
 
851
+ // توليد المسار بناءً على النموذج المختار
852
+ for (let i = 1; i < totalPoints - 1; i++) {
853
+ const progress = i / (totalPoints - 1);
854
+ const contextIndex = Math.floor(progress * (contextRoute.length - 1));
855
+ const contextPoint = contextRoute[contextIndex];
856
 
857
+ let lat, lon;
 
 
858
 
859
+ // محاكاة سلوكيات مختلفة للنماذج
860
+ switch(model) {
861
+ case 'TrAISformer':
862
+ // نمط مباشر مع تحسينات طفيفة
863
+ lat = contextPoint[0] + (Math.random() - 0.5) * 0.3;
864
+ lon = contextPoint[1] + (Math.random() - 0.5) * 0.4;
865
+ break;
866
+ case 'EnhcTrAISformer':
867
+ // نمط أكثر دقة مع انحرافات أقل
868
+ lat = contextPoint[0] + (Math.random() - 0.5) * 0.2;
869
+ lon = contextPoint[1] + (Math.random() - 0.5) * 0.3;
870
+ break;
871
+ case 'eDQTI-GRU':
872
+ // نمط مع تذبذبات متوسطة
873
+ lat = contextPoint[0] + (Math.random() - 0.5) * 0.4;
874
+ lon = contextPoint[1] + (Math.random() - 0.5) * 0.5;
875
+ break;
876
+ case 'eDQTI-LSTM':
877
+ // نمط مع تذبذبات أكبر
878
+ lat = contextPoint[0] + (Math.random() - 0.5) * 0.5;
879
+ lon = contextPoint[1] + (Math.random() - 0.5) * 0.6;
880
+ break;
881
+ case 'eDQTI-HYPER':
882
+ // نمط هجين مع سلوك متغير
883
+ const pattern = Math.sin(progress * Math.PI * 3) * 0.3;
884
+ lat = contextPoint[0] + (Math.random() - 0.5) * 0.3 + pattern;
885
+ lon = contextPoint[1] + (Math.random() - 0.5) * 0.4 + pattern;
886
+ break;
887
+ }
888
+
889
+ route.push([lat, lon]);
890
  }
891
 
892
+ // إضافة نقطة النهاية (نفس نهاية السياق)
893
+ route.push([contextRoute[contextRoute.length - 1][0], contextRoute[contextRoute.length - 1][1]]);
894
+
895
+ return route;
896
+ }
897
+
898
+ // دالة كشف الشذوذ في المسار المتولد
899
+ function detectAnomalies(generatedRoute) {
900
+ const anomalies = [];
901
+
902
+ // محاكاة كشف الشذوذ
903
+ for (let i = 0; i < generatedRoute.length; i++) {
904
+ // احتمال 10% أن تكون النقطة شاذة
905
+ if (Math.random() < 0.1) {
906
+ anomalies.push(i);
907
+ }
908
+ }
909
 
910
+ return anomalies;
911
  }
912
 
913
+ // دالة حساب المسافة بين نقطتين
914
  function calculateDistance(lat1, lon1, lat2, lon2) {
915
  const R = 6371; // نصف قطر الأرض بالكيلومترات
916
  const dLat = (lat2 - lat1) * Math.PI / 180;
 
923
  return R * c;
924
  }
925
 
926
+ // دالة حساب طول المسار
927
  function calculateRouteLength(route) {
928
  let totalDistance = 0;
929
  for (let i = 0; i < route.length - 1; i++) {
 
935
  return Math.round(totalDistance);
936
  }
937
 
938
+ // دالة رسم المسارات على الخريطة
939
+ function drawRoutes(contextRoute, generatedRoute, anomalies) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
940
  // مسح المسارات السابقة
941
  clearRoutes();
942
 
943
+ // رسم مسار السياق
944
+ const contextPolyline = L.polyline(contextRoute, {
945
+ color: '#1e3a8a',
946
+ weight: 3,
947
+ opacity: 0.7,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
948
  lineJoin: 'round',
949
+ dashArray: '5, 5'
 
950
  }).addTo(map);
951
+ routeLayers.push(contextPolyline);
952
 
953
+ // رسم نقاط السياق
954
+ contextRoute.forEach((point, index) => {
955
+ if (index % 2 === 0) { // نقاط أقل للسياق
956
  const pointMarker = L.circleMarker(point, {
957
+ color: '#3b82f6',
958
+ fillColor: '#3b82f6',
959
+ fillOpacity: 0.8,
960
+ radius: 4
 
961
  }).addTo(map);
962
 
963
  pointMarker.bindPopup(`<div class="route-popup">
964
+ <div class="popup-title">نقطة السياق ${index + 1}</div>
 
965
  <div class="popup-details">
966
  <div class="popup-detail"><span class="popup-label">خط العرض:</span> ${point[0].toFixed(4)}</div>
967
  <div class="popup-detail"><span class="popup-label">خط الطول:</span> ${point[1].toFixed(4)}</div>
968
+ <div class="popup-detail"><span class="popup-label">النوع:</span> سياق</div>
 
969
  </div>
970
  </div>`);
971
 
 
973
  }
974
  });
975
 
976
+ // رسم المسار المتولد
977
+ const generatedPolyline = L.polyline(generatedRoute, {
978
+ color: '#dc2626',
979
+ weight: 4,
980
+ opacity: 0.9,
981
+ lineJoin: 'round'
982
+ }).addTo(map);
983
+ routeLayers.push(generatedPolyline);
984
+
985
+ // رسم نقاط المسار المتولد
986
+ generatedRoute.forEach((point, index) => {
987
+ const isAnomaly = anomalies.includes(index);
988
+ const pointMarker = L.circleMarker(point, {
989
+ color: isAnomaly ? '#f59e0b' : '#ef4444',
990
+ fillColor: isAnomaly ? '#f59e0b' : '#ef4444',
991
+ fillOpacity: 0.9,
992
+ radius: isAnomaly ? 6 : 4
993
+ }).addTo(map);
994
+
995
+ pointMarker.bindPopup(`<div class="route-popup">
996
+ <div class="popup-title">${isAnomaly ? 'نقطة شذوذ' : 'نقطة متولدة'} ${index + 1}</div>
997
+ <div class="popup-details">
998
+ <div class="popup-detail"><span class="popup-label">خط العرض:</span> ${point[0].toFixed(4)}</div>
999
+ <div class="popup-detail"><span class="popup-label">خط الطول:</span> ${point[1].toFixed(4)}</div>
1000
+ <div class="popup-detail"><span class="popup-label">النوع:</span> ${isAnomaly ? 'شذوذ' : 'متولد'}</div>
1001
+ <div class="popup-detail"><span class="popup-label">النموذج:</span> ${currentModel}</div>
1002
+ </div>
1003
+ </div>`);
1004
+
1005
+ routeLayers.push(pointMarker);
1006
+ });
1007
 
1008
+ // ضبط حدود الخريطة لتناسب المسارات
1009
+ const allPoints = [...contextRoute, ...generatedRoute];
1010
+ const group = L.featureGroup(routeLayers);
1011
  map.fitBounds(group.getBounds().pad(0.1));
1012
  }
1013
 
1014
+ // دالة مسح جميع المسارات
1015
  function clearRoutes() {
1016
  routeLayers.forEach(layer => map.removeLayer(layer));
1017
  routeLayers = [];
1018
  }
1019
 
1020
+ // دالة تحديث واجهة النتائج
1021
+ function updateResults(generatedRoute, anomalies, generationTime) {
1022
+ const totalPoints = generatedRoute.length;
1023
+ const anomalyPercentage = ((anomalies.length / totalPoints) * 100).toFixed(1);
1024
+ const distance = calculateRouteLength(generatedRoute);
1025
+
1026
+ totalPointsElem.textContent = totalPoints;
1027
+ totalDistanceElem.textContent = distance.toLocaleString();
1028
+ anomalyLevelElem.textContent = `${anomalyPercentage}%`;
1029
+
1030
+ // تحديث مؤشر الشذوذ
1031
+ anomalyIndicator.className = 'anomaly-indicator';
1032
+ if (anomalyPercentage < 5) {
1033
+ anomalyIndicator.classList.add('anomaly-low');
1034
+ anomalyIndicator.innerHTML = '<i class="fas fa-check-circle"></i><span>المسار طبيعي - لا توجد شذوذات كبيرة</span>';
1035
+ } else if (anomalyPercentage < 15) {
1036
+ anomalyIndicator.classList.add('anomaly-medium');
1037
+ anomalyIndicator.innerHTML = '<i class="fas fa-exclamation-triangle"></i><span>شذوذ متوسط - يحتاج للمراقبة</span>';
1038
+ } else {
1039
+ anomalyIndicator.classList.add('anomaly-high');
1040
+ anomalyIndicator.innerHTML = '<i class="fas fa-skull-crossbones"></i><span>شذوذ عالي - يحتاج للتدخل الفوري</span>';
1041
+ }
1042
+
1043
+ // تحديث تفاصيل التوليد
1044
+ generationDetails.innerHTML = `
1045
+ <p>• النموذج: ${currentModel}</p>
1046
+ <p>• وقت التوليد: ${generationTime.toFixed(1)} ثانية</p>
1047
+ <p>• الدقة: ${(100 - anomalyPercentage).toFixed(1)}%</p>
1048
+ <p>• نقاط الشذوذ: ${anomalies.length} من ${totalPoints} نقطة</p>
1049
+ <p>• الساعات: ${hours.value}</p>
1050
+ <p>• النقاط/ساعة: ${pointsPerHour.value}</p>
1051
+ `;
1052
+
1053
+ // إضافة إلى سجل التوليد
1054
+ const historyItem = document.createElement('div');
1055
+ historyItem.className = 'route-item';
1056
+ historyItem.innerHTML = `
1057
+ <div class="route-header">
1058
+ <div class="route-name">توليد ${new Date().toLocaleString('ar-SA')}</div>
1059
+ <div class="route-type">${currentModel}</div>
1060
+ </div>
1061
+ <div class="route-details">
1062
+ <span>النقاط: ${totalPoints}</span>
1063
+ <span>الشذوذ: ${anomalyPercentage}%</span>
1064
+ </div>
1065
+ `;
1066
+
1067
+ historyItem.addEventListener('click', () => {
1068
+ drawRoutes(contextRoute, generatedRoute, anomalies);
1069
+ });
1070
+
1071
+ generationHistory.insertBefore(historyItem, generationHistory.firstChild);
1072
+
1073
+ // الاحتفاظ بعدد محدود من العناصر في السجل
1074
+ if (generationHistory.children.length > 5) {
1075
+ generationHistory.removeChild(generationHistory.lastChild);
1076
+ }
1077
+ }
1078
+
1079
+ // معالجة زر التوليد
1080
+ generateBtn.addEventListener('click', () => {
1081
+ // توليد مسار السياق
1082
+ contextRoute = generateContextRoute();
1083
+
1084
+ // توليد المسار باستخدام النموذج المختار
1085
+ const startTime = performance.now();
1086
+ generatedRoute = generateRouteWithModel(
1087
+ contextRoute,
1088
+ currentModel,
1089
+ parseInt(hours.value),
1090
+ parseInt(pointsPerHour.value)
1091
+ );
1092
+ const endTime = performance.now();
1093
+ const generationTime = (endTime - startTime) / 1000;
1094
+
1095
+ // كشف الشذوذ
1096
+ const anomalies = detectAnomalies(generatedRoute);
1097
+
1098
+ // رسم المسارات
1099
+ drawRoutes(contextRoute, generatedRoute, anomalies);
1100
+
1101
+ // تحديث النتائج
1102
+ updateResults(generatedRoute, anomalies, generationTime);
1103
+ });
1104
+
1105
  // إضافة عناصر التحكم في الخريطة
1106
  zoomInBtn.addEventListener('click', () => {
1107
  map.zoomIn();
 
1115
  map.setView([20.0, 38.0], 6);
1116
  });
1117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1118
  // تحميل بعض البيانات الافتراضية عند بدء التشغيل
1119
  window.addEventListener('load', () => {
1120
+ // تعبئة حقل السياق بمثال
1121
+ contextInput.value = "مسار تاريخي من باب المندب إلى قناة السويس مع بيانات AIS";
 
1122
 
1123
+ // توليد وعرض مثال أولي
1124
+ setTimeout(() => {
1125
+ generateBtn.click();
1126
+ }, 1000);
 
 
1127
  });
1128
  </script>
1129
  </body>