feat(tactical): add comprehensive Terrain Study (دراسة الأرض) with natural/manmade obstacles and OAKOC intelligence report

This commit is contained in:
Hamza-Ayed
2026-08-18 10:42:04 +03:00
parent 91c36d99c9
commit 6bd0bc0ce5
2 changed files with 695 additions and 13 deletions
+273
View File
@@ -576,3 +576,276 @@ export async function calculateMinefieldAnalysis(
};
}
export interface TerrainStudyResult {
centerLat: number;
centerLng: number;
radiusMeters: number;
areaKm2: number;
sectorName: string;
centerElevation: number;
minElevation: number;
maxElevation: number;
reliefMeters: number;
avgSlopeDegrees: number;
maxSlopeDegrees: number;
slopeDistribution: {
flatPercentage: number; // < 5 deg (Go)
moderatePercentage: number; // 5-15 deg (Slow-Go)
steepPercentage: number; // > 15 deg (No-Go / Obstacle)
};
terrainClassification: string;
terrainClassificationAr: string;
mobilityStatus: 'GO' | 'SLOW-GO' | 'NO-GO';
mobilityStatusAr: string;
naturalObstacles: Array<{
name: string;
type: string;
description: string;
impact: string;
}>;
manMadeObstacles: Array<{
name: string;
type: string;
description: string;
tacticalNote: string;
}>;
urbanAndDemographics: {
density: 'HIGH' | 'MEDIUM' | 'LOW' | 'SPARSE';
densityAr: string;
settlements: string[];
moutComplexity: string;
collateralDamageRisk: string;
};
landCoverAndCover: {
soilType: string;
trafficability: string;
concealmentRating: string;
airObservationExposure: string;
};
oakocAssessment: {
obstacles: string;
avenuesOfApproach: string;
keyTerrain: string;
observationAndFieldsOfFire: string;
coverAndConcealment: string;
};
tacticalRecommendations: string[];
}
/**
* Military Tactical Terrain Intelligence & Environmental Study (OAKOC Doctrine)
* دراسة الأرض الشاملة: التضاريس، الموانع الطبيعية والصناعية، والمناطق المأهولة
*/
export async function calculateTerrainStudy(
centerLat: number,
centerLng: number,
radiusMeters: number = 3000
): Promise<TerrainStudyResult> {
const centerElev = await sampleElevationAt(centerLat, centerLng);
const areaKm2 = Math.round(Math.PI * Math.pow(radiusMeters / 1000, 2) * 10) / 10;
// Multi-point radial sampling across the sector
const samples = 24;
const elevations: number[] = [centerElev];
const slopes: number[] = [];
for (let i = 0; i < samples; i++) {
const angleRad = (i / samples) * 2 * Math.PI;
const dist = radiusMeters * (0.3 + (i % 3) * 0.35);
const R_earth = 6371000;
const dLat = (dist / R_earth) * (180 / Math.PI) * Math.cos(angleRad);
const dLng = (dist / (R_earth * Math.cos((centerLat * Math.PI) / 180))) * (180 / Math.PI) * Math.sin(angleRad);
const sLat = centerLat + dLat;
const sLng = centerLng + dLng;
const el = await sampleElevationAt(sLat, sLng);
elevations.push(el);
const slopeDeg = Math.atan(Math.abs(el - centerElev) / dist) * (180 / Math.PI);
slopes.push(slopeDeg);
}
const minElev = Math.min(...elevations);
const maxElev = Math.max(...elevations);
const relief = maxElev - minElev;
const avgSlope = Math.round((slopes.reduce((a, b) => a + b, 0) / slopes.length) * 10) / 10;
const maxSlope = Math.round(Math.max(...slopes) * 10) / 10;
const flatCount = slopes.filter(s => s < 5).length;
const modCount = slopes.filter(s => s >= 5 && s <= 15).length;
const steepCount = slopes.filter(s => s > 15).length;
const flatPct = Math.round((flatCount / slopes.length) * 100);
const modPct = Math.round((modCount / slopes.length) * 100);
const steepPct = Math.max(0, 100 - flatPct - modPct);
// Sector Geolocation and Regional Characteristics
let sectorName = 'قطاع عمليات ميداني';
let terrainClassificationAr = 'هضاب وتلال متوسطة الوعورة';
let terrainClassification = 'Rolling Hills & Ridges';
let urbanDensity: 'HIGH' | 'MEDIUM' | 'LOW' | 'SPARSE' = 'LOW';
let urbanDensityAr = 'كثافة منخفضة / ريفية';
let settlements: string[] = ['تجمعات سكنية متفرقة', 'مزارع ومنشآت ريفية'];
let soilType = 'تربة طينية صخرية جافة';
let trafficability = 'جيدة للمركبات المدولبة والمجنزرة مع الحذر من الانزلاقات في المنحدرات';
if (centerLat > 32.3 && centerLng < 36.0) {
sectorName = 'قاطع الشمال / حوض اليرموك وإربد';
terrainClassificationAr = 'مرتفعات جبلية تتخللها أودية سحيقة وخوانق مائية';
terrainClassification = 'Highland Plateaus with Deep Gorges';
urbanDensity = 'MEDIUM';
urbanDensityAr = 'كثافة متوسطة (قرى وضواحي ممتدة)';
settlements = ['بلدات وضواحي إربد', 'قرى حوض اليرموك', 'مزارع ومحميات وادي الشلالة'];
soilType = 'تربة زراعية خصبة وصخور كلسية';
trafficability = 'صعبة على حواف الأودية - تتطلب محاور طرق رئيسية';
} else if (centerLat >= 31.8 && centerLat <= 32.2 && centerLng >= 35.8 && centerLng <= 36.1) {
sectorName = 'قاطع الوسط / إقليم العاصمة عمان';
terrainClassificationAr = 'هضاب وكتل جبلية حضرية مكتظة بالعمران';
terrainClassification = 'Urbanized Highland Terrain';
urbanDensity = 'HIGH';
urbanDensityAr = 'كثافة عالية (بيئة قتال مباني MOUT)';
settlements = ['أحياء ومجمعات العاصمة عمان', 'المناطق التجارية والتقاطعات المرورية', 'مناطق صناعية متقدمة'];
soilType = 'أرض معبدة وأرصفة إسمنتية مع تربة صخرية';
trafficability = 'ممتازة على شبكة الطرق ولكنها مقيدة بالاختناقات المرورية والمباني';
} else if (centerLng > 36.1) {
sectorName = 'قاطع البادية والشرق / المفرق والصفاوي';
terrainClassificationAr = 'سهول صحراوية مفتوحة وأراضي حرات بازلتية';
terrainClassification = 'Open Desert Steppe & Basalt Harrah';
urbanDensity = 'SPARSE';
urbanDensityAr = 'شبه خالية / تجمعات بدوية ومزارع متفرقة';
settlements = ['تجمعات ريفية بدوية', 'مواقع عسكرية ونقاط حدودية', 'مزارع صحراوية'];
soilType = 'رمال وحصى بازلتية صلبة';
trafficability = 'حركة حرة مفتوحة للدروع والآليات الصحراوية (Cross-Country GO)';
} else if (centerLat < 31.8 && centerLng < 35.7) {
sectorName = 'قاطع الغور / المنخفض الصدعي والبحر الميت';
terrainClassificationAr = 'أخفـض نقطة على سطح الأرض (جروف حادة ومنحدرات قاسية)';
terrainClassification = 'Rift Valley Escarpment (-400m MSL)';
urbanDensity = 'LOW';
urbanDensityAr = 'كثافة منخفضة (مزارع الغور والمنتجعات)';
settlements = ['مزارع الأغوار الجنوبية', 'مجمعات الفنادق ومصانع البوتاس', 'قرى غور الصافي'];
soilType = 'طمي نهري وسبخات ملحية وصخور رسوبية';
trafficability = 'حذرة جداً بجانب السبخات - ممتازة على طريق البحر الميت الرئيسي';
} else if (centerLat < 31.5 && centerLat > 30.0) {
sectorName = 'قاطع الجنوب الجبلي / مرتفعات الكرك والشوبك';
terrainClassificationAr = 'سلاسل جبلية شاهقة وتلال متصلة ذات إشراف تكتيكي';
terrainClassification = 'High Mountainous Plateaus (>1200m)';
urbanDensity = 'LOW';
urbanDensityAr = 'بلدات جبلية وقرى متفرقة';
settlements = ['مدينة الكرك التاريخية', 'قرى المزار والشوبك', 'مزارع الجبال الجنوبية'];
soilType = 'صخور جيرية صلبة وحجارة متناثرة';
trafficability = 'مقيدة بالممرات الجبلية والمنعطفات الحادة (Slow-Go)';
} else if (centerLat <= 30.0) {
sectorName = 'قاطع الجنوب الصحراوي / وادي رم والعقبة';
terrainClassificationAr = 'جبال رملية شاهقة (Monoliths) تتخللها ممرات ووديان رملية واسعة';
terrainClassification = 'Sandstone Monoliths & Desert Valleys';
urbanDensity = 'SPARSE';
urbanDensityAr = 'شبه خالية (مخيمات سياحية وتجمعات بدوية)';
settlements = ['قرية وادي رم', 'مخيمات الديسة السياحية', 'نقاط المراقبة الجنوبية'];
soilType = 'رمال ناعمة وصخور رملية ضخمة';
trafficability = 'ممتازة للآليات ذات الدفع الرباعي والمجنزرات في بطون الأودية';
}
// Determine Overall Mobility Status
let mobilityStatus: 'GO' | 'SLOW-GO' | 'NO-GO' = 'GO';
let mobilityStatusAr = 'حركة حرة ممتازة للآليات والدروع (Cross-Country GO)';
if (steepPct > 40 || avgSlope > 14) {
mobilityStatus = 'NO-GO';
mobilityStatusAr = 'مانع تضاريسي - حركة مقيدة وشديدة الصعوبة (NO-GO)';
} else if (steepPct > 15 || modPct > 40 || avgSlope > 7) {
mobilityStatus = 'SLOW-GO';
mobilityStatusAr = 'حركة بطيئة تتطلب مسارب وتجهيزاً هندسياً (SLOW-GO)';
}
return {
centerLat,
centerLng,
radiusMeters,
areaKm2,
sectorName,
centerElevation: Math.round(centerElev),
minElevation: Math.round(minElev),
maxElevation: Math.round(maxElev),
reliefMeters: Math.round(relief),
avgSlopeDegrees: avgSlope,
maxSlopeDegrees: maxSlope,
slopeDistribution: {
flatPercentage: flatPct,
moderatePercentage: modPct,
steepPercentage: steepPct
},
terrainClassification,
terrainClassificationAr,
mobilityStatus,
mobilityStatusAr,
naturalObstacles: [
{
name: 'المنحدرات والجروف التضاريسية الحادة',
type: 'انحدار طبوغرافي',
description: `تشكل المناطق ذات الانحدار الشديد (${steepPct}%) مانعاً طبيعياً يحد من تقدم الدروع ويجبرها على الالتفاف.`,
impact: 'إعاقة محاور الهجوم المعادي وتوجيهه نحو الخناق المجهزة بالنيران'
},
{
name: 'الأودية والشعاب ومجاري السيول الطبيعية',
type: 'أودية ومصارف مائية',
description: 'بطون الأودية تمثل ممرات حركة محجوبة عن خط النظر ولكنها عرضة للكمائن والسيول الفجائية.',
impact: 'تصلح كمسارب تسلل للمشاة ولكنها خطرة للآليات الثقيلة'
},
{
name: 'القمم والمرتفعات الحاكمة المجاورة',
type: 'أرض مسيطرة (Key Terrain)',
description: `أعلى قمة في القطاع بارتفاع ${maxElev}م توفر إشرافاً نارياً واستطلاعياً على عمق يصل إلى ${Math.round(radiusMeters / 500)} كم.`,
impact: 'وجوب احتلالها بنقاط مراقبة وأسلحة إسناد مضادة للدروع'
}
],
manMadeObstacles: [
{
name: 'شبكة الطرق والمحاور المعبدة',
type: 'محاور حركة سريعة',
description: 'الطرق الرئيسية المارة بالقطاع تتيح سرعة إعادة انتشار القوات والإمداد اللوجستي.',
tacticalNote: 'تعتبر أهدافاً حيوية يجب تأمينها بنقاط سيطرة وتفتيش وغلق سريع'
},
{
name: 'خطوط نقل الطاقة وأبراج الاتصالات',
type: 'بنية تحتية صناعية',
description: 'أبراج الضغط العالي والاتصالات تشكل عوائق أمام الطيران المنخفض ومواقع محتملة لمحطات الإعاقة اللاسلكية.',
tacticalNote: 'تجنب هبوط المروحيات بالقرب من خطوط الضغط العالي'
},
{
name: 'المباني والمنشآت الخرسانية الممتدة',
type: 'موانع مبنية',
description: 'المباني المتفرقة توفر سواتر خرسانية ممتازة ضد الشظايا ونيران الأسلحة الخفيفة.',
tacticalNote: 'تتطلب تطهيراً هندسياً لضمان خلوها من العبوات والأفخاخ'
}
],
urbanAndDemographics: {
density: urbanDensity,
densityAr: urbanDensityAr,
settlements,
moutComplexity: urbanDensity === 'HIGH' ? 'معقدة جداً وتتطلب تدريب قتال مباني متخصص' : 'بسيطة إلى متوسطة وتقتصر على أطراف القرى',
collateralDamageRisk: urbanDensity === 'HIGH' ? 'عالية جداً وتتطلب ذخائر موجهة وقواعد اشتباك صارمة' : 'منخفضة مع مراعاة حماية الأعيان المدنية'
},
landCoverAndCover: {
soilType,
trafficability,
concealmentRating: steepPct > 20 || urbanDensity === 'HIGH' ? 'ممتازة خلف التموجات والمباني' : 'متوسطة إلى مكشوفة في الأراضي المفتوحة',
airObservationExposure: urbanDensity === 'HIGH' ? 'مختلطة (مباني تحجب الرؤية الجوية)' : 'عالية للرصد الجوي والمسيرات نهاراً'
},
oakocAssessment: {
obstacles: `القطاع يحتوي على ${steepPct}% أراضٍ شديدة الوعورة تشكل موانع طبيعية، مع وجود محاور طرق رئيسية تشكل ممرات حركة سريعة.`,
avenuesOfApproach: 'محاور الاقتراب الرئيسية تتبع بطون الهضاب وشبكة الطرق الفرعية، مما يسهل رصدها وتغطيتها بالمدفعية ومضادات الدروع.',
keyTerrain: `المرتفع ${maxElev}م يشكل الأرض الحاكمة (Decisive Terrain) والسيطرة عليه تمنح تفوقاً نارياً حاسماً.`,
observationAndFieldsOfFire: `حقول الرماية مكشوفة ومثالية في قطاعات (${flatPct}%) المنبسطة، ومقيدة في قطاعات الأودية والعمران.`,
coverAndConcealment: 'السواتر الطبيعية متوفرة على المنحدرات المعاكسة (Reverse Slopes) وفي الجيوب المنخفضة.'
},
tacticalRecommendations: [
`تمركز نقاط المراقبة والرادار على المرتفع الحاكم بارتفاع ${maxElev}م لتأمين الإنذار المبكر.`,
'استغلال المنحدرات الشديدة كمانع طبيعي وزرع حقول الألغام الدفاعية في الممرات الإجبارية والخناق.',
'تأمين محاور الطرق المعبدة وتجهيز خطط غلق هندسي فورية لقطع تقدم أرتال العدو السريعة.',
'نشر وحدات المشاة الآلية في المنحدرات الخلفية لحمايتها من الرصد والنار المباشرة (Defilade).',
'تخصيص مهابط المروحيات والإخلاء في المناطق المستوية ذات الانحدار الأقل من 5 درجات.'
]
};
}