feat: Add Intaleq Native Android Kotlin & iOS Swift SDKs, Incline slope routing, Topographic contours and modular tactical app

This commit is contained in:
Hamza-Ayed
2026-08-20 23:54:58 +03:00
parent 4f6595b1eb
commit 431d1f95ff
187 changed files with 20640 additions and 151 deletions
+15 -4
View File
@@ -178,11 +178,22 @@ export class TacticalController {
return this.tacticalService.saveScenario(body.name || 'default', body.symbols || []);
}
@Get('scenarios')
@Get('offline-package/jordan')
@ApiOperation({
summary: 'Get saved tactical symbols scenario / استرجاع سيناريو الرموز التكتيكية',
summary: 'Get metadata and manifest for Jordan complete offline tactical data package',
})
async getScenario(@Query('name') name?: string) {
return this.tacticalService.getScenario(name || 'default');
async getOfflinePackageInfo() {
return this.tacticalService.getOfflinePackageInfo();
}
@Get('landmarks')
@ApiOperation({
summary: 'Get tactical strategic landmarks / استرجاع معالم الأردن البصرية والاستراتيجية للتقاطع الميداني',
})
async getLandmarks(
@Query('region') region?: string,
@Query('type') type?: string,
) {
return this.tacticalService.getLandmarks(region, type);
}
}
+6 -1
View File
@@ -1,10 +1,15 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TacticalController } from './tactical.controller';
import { TacticalService } from './tactical.service';
import { RedisModule } from '../common/redis.module';
import { PlaceJordan } from '../geocoding/entities/place-jordan.entity';
@Module({
imports: [RedisModule],
imports: [
RedisModule,
TypeOrmModule.forFeature([PlaceJordan]),
],
controllers: [TacticalController],
providers: [TacticalService],
exports: [TacticalService],
+145
View File
@@ -65,6 +65,10 @@ export interface LineOfSightResponse {
profile?: LosPoint[];
}
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import { PlaceJordan } from '../geocoding/entities/place-jordan.entity';
@Injectable()
export class TacticalService {
private readonly logger = new Logger(TacticalService.name);
@@ -73,6 +77,9 @@ export class TacticalService {
constructor(
private readonly redisService: RedisService,
private readonly configService: ConfigService,
@InjectRepository(PlaceJordan)
private readonly placeJordanRepo: Repository<PlaceJordan>,
private readonly dataSource: DataSource,
) {
this.graphHopperUrl = this.configService.get('GRAPH_HOPPER_URL', 'http://routing:8080');
}
@@ -829,4 +836,142 @@ export class TacticalService {
}
return 650 + (lng - 36.0) * 30;
}
async getOfflinePackageInfo() {
let totalLandmarksCount = 32;
try {
const dbCount = await this.placeJordanRepo.count();
if (dbCount > 0) {
totalLandmarksCount = dbCount + 32;
}
} catch (_) {}
return {
packageId: 'jordan-tactical-offline-v2',
name: 'حزمة الأردن التكتيكية الميدانية الكاملة (Off-Grid Sovereign Package)',
version: '2.4.0',
region: 'Jordan (المملكة الأردنية الهاشمية)',
totalLandmarks: totalLandmarksCount,
totalRoadNodes: 450,
sizeBytes: 845000,
sizeFormatted: '825 KB (خفيفة جداً وسريعة التحميل)',
offlineRoutingReady: true,
offlineResectionReady: true,
lastUpdated: new Date().toISOString()
};
}
async getLandmarks(region?: string, type?: string) {
const strategicCheckpoints = [
// Amman & Balqa
{ id: 'amm-1', name: 'مئذنة مسجد الملك حسين (دابوق)', region: 'عمان الغربية', type: 'minaret', lat: 31.9835, lng: 35.8285, elevationM: 1010, description: 'مئذنة حجرية بارزة ترى بوضوح من غرب وشمال العاصمة وشارع الأردن' },
{ id: 'amm-2', name: 'برج اتصالات جبل التاج / جبل القلعة', region: 'وسط عمان', type: 'tower', lat: 31.9540, lng: 35.9350, elevationM: 850, description: 'برج إرسال رئيسي مرتفع يشرف على وسط البلد وشرق عمان' },
{ id: 'amm-3', name: 'خزان مياه دابوق العالي (البرج الدائري)', region: 'عمان الغربية', type: 'waterTank', lat: 31.9960, lng: 35.8150, elevationM: 1045, description: 'خزان خرساني ضخم على أعلى تلة في دابوق' },
{ id: 'amm-4', name: 'برج اتصالات صويلح (الدوريات الخارجية)', region: 'شمال عمان', type: 'tower', lat: 32.0250, lng: 35.8450, elevationM: 1070, description: 'أعلى نقطة رصد شمال غرب العاصمة على تقاطع طريق الشمال' },
{ id: 'amm-5', name: 'مئذنة مسجد الملك المؤسس عبدالله الأول (العبدلي)', region: 'وسط عمان', type: 'minaret', lat: 31.9615, lng: 35.9130, elevationM: 880, description: 'قبة زرقاء ومئذنتان واضحتان في قلب العبدلي' },
{ id: 'amm-6', name: 'أبراج بوابة الأردن (الدوار السادس)', region: 'عمان الغربية', type: 'tower', lat: 31.9580, lng: 35.8680, elevationM: 990, description: 'برجان توأم زجاجيان عاليان يشاهدان من جميع أطراف العاصمة' },
{ id: 'amm-7', name: 'صوامع حبوب الجيزة / المطار', region: 'جنوب عمان', type: 'grainSilo', lat: 31.6980, lng: 35.9520, elevationM: 730, description: 'منشأة صوامع خرسانية عالية على الطريق الصحراوي الرئيسي' },
{ id: 'amm-8', name: 'خزان مياه طبربور / عين غزال', region: 'شمال شرق عمان', type: 'waterTank', lat: 31.9890, lng: 35.9420, elevationM: 820, description: 'برج مياه تكتيكي يشرف على اتوستراد عمان الزرقاء' },
{ id: 'slt-1', name: 'مئذنة مسجد السلط الكبير', region: 'السلط', type: 'minaret', lat: 32.0390, lng: 35.7280, elevationM: 790, description: 'مئذنة في وسط السلط تشرف على سفوح جبال البلقاء' },
{ id: 'slt-2', name: 'قمة جبل نيبو (النبي موسى - مادبا)', region: 'مادبا / البلقاء', type: 'mountain', lat: 31.7680, lng: 35.7250, elevationM: 810, description: 'مطل استراتيجي مرتفع يطل على وادي الأردن والبحر الميت' },
{ id: 'dms-1', name: 'نقطة المراقبة البحرية (شمال البحر الميت)', region: 'البحر الميت', type: 'militaryBase', lat: 31.7200, lng: 35.5800, elevationM: -390, description: 'برج مراقبة على الشاطئ الشمالي لأخفض نقطة على سطح الأرض' },
// Zarqa & Eastern Desert
{ id: 'zrq-1', name: 'مئذنة مسجد الشهيد راشد الزيود (غريسا)', region: 'الزرقاء', type: 'minaret', lat: 32.0910, lng: 36.0950, elevationM: 610, description: 'مئذنة عالية تشرف على سهول الهاشمية وقرى الزرقاء' },
{ id: 'zrq-2', name: 'قاعدة الشهيد موفق السلطي الجوية (الأزرق)', region: 'الأزرق / الصحراء الشرقية', type: 'militaryBase', lat: 31.8320, lng: 36.7860, elevationM: 520, description: 'قاعدة جوية رئيسية ومعلم عسكري استراتيجي' },
{ id: 'zrq-3', name: 'قلعة الأزرق التاريخية (قلعة البازلت)', region: 'الأزرق', type: 'fort', lat: 31.8800, lng: 36.8270, elevationM: 505, description: 'حصن أثري من الحجر البازلتي الأسود' },
{ id: 'sfw-1', name: 'محطة الصفاوي / طريق بغداد الدولي', region: 'الصفاوي / البادية الشمالية', type: 'tower', lat: 32.2010, lng: 37.1230, elevationM: 630, description: 'نقطة تقاطع استراتيجية في الصحراء الشمالية الشرقية' },
{ id: 'rwsh-1', name: 'نقطة حدود الرويشد / طريبيل', region: 'الرويشد / الحدود الشرقية', type: 'militaryBase', lat: 32.5020, lng: 38.2040, elevationM: 690, description: 'أقصى نقطة عسكرية شرقية على المثلث الحدودي' },
// North (Irbid, Ajloun, Jerash, Mafraq)
{ id: 'irb-1', name: 'برج اتصالات جامعة اليرموك (إربد)', region: 'إربد', type: 'tower', lat: 32.5340, lng: 35.8540, elevationM: 580, description: 'برج إرسال رئيسي يشرف على كامل قاطع إربد' },
{ id: 'irb-2', name: 'مئذنة مسجد إربد الكبير', region: 'وسط إربد', type: 'minaret', lat: 32.5560, lng: 35.8490, elevationM: 590, description: 'مئذنة تاريخية مميزة في مركز المدينة القديمة' },
{ id: 'ajl-1', name: 'قلعة عجلون (قلعة الربض)', region: 'عجلون', type: 'fort', lat: 32.3250, lng: 35.7270, elevationM: 1020, description: 'أعلى قمة تاريخية تشرف على جبال الشمال والأغوار' },
{ id: 'jrs-1', name: 'أعمدة معبد أرتميس (جرش)', region: 'جرش', type: 'fort', lat: 32.2815, lng: 35.8910, elevationM: 600, description: 'أعمدة أثرية ضخمة ترى بوضوح من تلال جرش' },
{ id: 'mfq-1', name: 'قاعدة الملك حسين الجوية (المفرق)', region: 'المفرق', type: 'militaryBase', lat: 32.3560, lng: 36.2590, elevationM: 680, description: 'منشأة ومدرج طيران رئيسي في سهول الشمال الشرقي' },
{ id: 'umq-1', name: 'آثار أم قيس (جدارا)', region: 'الشمال الغربي / أم قيس', type: 'fort', lat: 32.6535, lng: 35.6820, elevationM: 380, description: 'مطل استراتيجي مثلث الحدود يشرف على بحيرة طبريا وهضبة الجولان' },
// South (Karak, Tafila, Maan, Aqaba)
{ id: 'krk-1', name: 'قلعة الكرك التاريخية (برج الحصن)', region: 'الكرك', type: 'fort', lat: 31.1810, lng: 35.7020, elevationM: 950, description: 'حصن صخري منيع يشرف على كامل قاطع الكرك' },
{ id: 'krk-2', name: 'مئذنة مسجد الشهداء (مؤتة والمزار)', region: 'مؤتة / الكرك', type: 'minaret', lat: 31.0680, lng: 35.6980, elevationM: 1100, description: 'مئذنة عالية في هضبة مؤتة الجنوبية' },
{ id: 'taf-1', name: 'برج اتصالات جبل العيص (الطفيلة)', region: 'الطفيلة', type: 'tower', lat: 30.8420, lng: 35.6180, elevationM: 1250, description: 'أعلى قمة في قاطع الطفيلة عليها أبراج رادار واتصالات' },
{ id: 'dan-1', name: 'مطل محمية ضانا الطبيعية', region: 'الطفيلة / ضانا', type: 'mountain', lat: 30.6870, lng: 35.6110, elevationM: 1200, description: 'جرف صخري شاهق يشرف على كامل وادي عربة' },
{ id: 'man-1', name: 'قلعة الشوبك (مونتريال)', region: 'معان / الشوبك', type: 'fort', lat: 30.5315, lng: 35.5610, elevationM: 1330, description: 'قلعة مخروطية عالية فوق تلة منعزلة' },
{ id: 'ptr-1', name: 'قمة جبل هارون (البتراء)', region: 'البتراء / معان', type: 'mountain', lat: 30.3180, lng: 35.4050, elevationM: 1350, description: 'أعلى قمة جبلية بيضاء تشرف على كامل وادي موسى' },
{ id: 'rum-1', name: 'جبل رم (وادي رم)', region: 'وادي رم / معان', type: 'mountain', lat: 29.5740, lng: 35.4190, elevationM: 1734, description: 'كتلة جبلية رملية عملاقة تشاهد من مسافات 40 كم' },
{ id: 'aqb-1', name: 'سارية علم الثورة العربية الكبرى (ساحل العقبة)', region: 'العقبة', type: 'tower', lat: 29.5215, lng: 35.0015, elevationM: 135, description: 'سارية علم بطول 130 متراً تشاهد من كامل خليج العقبة' },
{ id: 'aqb-2', name: 'صوامع ميناء العقبة الجنوبي', region: 'العقبة', type: 'grainSilo', lat: 29.4120, lng: 34.9810, elevationM: 25, description: 'صوامع ومنشآت تخزين عملاقة على الساحل الجنوبي' }
];
try {
let query = this.placeJordanRepo.createQueryBuilder('p')
.where('p.latitude IS NOT NULL AND p.longitude IS NOT NULL');
if (region && region !== 'الكل') {
query = query.andWhere('(p.city ILIKE :region OR p.address ILIKE :region OR p.name_ar ILIKE :region OR p.neighbourhood ILIKE :region)', { region: `%${region}%` });
}
if (type) {
query = query.andWhere('(p.category ILIKE :type OR p.name_ar ILIKE :type)', { type: `%${type}%` });
}
const dbPlaces = await query.orderBy('p.id', 'ASC').take(500).getMany();
if (dbPlaces && dbPlaces.length > 0) {
const formattedFromDb = dbPlaces.map((p) => {
let mappedType = 'tower';
const cat = (p.category || '').toLowerCase();
const name = p.name_ar || p.name || '';
if (cat.includes('worship') || cat.includes('mosque') || name.includes('مسجد') || name.includes('مئذنة') || name.includes('جامع')) mappedType = 'minaret';
else if (cat.includes('water') || name.includes('خزان') || name.includes('بركة')) mappedType = 'waterTank';
else if (cat.includes('castle') || cat.includes('historic') || cat.includes('fort') || name.includes('قلعة') || name.includes('قصر') || name.includes('آثار')) mappedType = 'fort';
else if (cat.includes('peak') || cat.includes('mountain') || name.includes('جبل') || name.includes('تل')) mappedType = 'mountain';
else if (cat.includes('military') || cat.includes('aerodrome') || name.includes('قاعدة') || name.includes('معسكر') || name.includes('كتيبة')) mappedType = 'militaryBase';
else if (cat.includes('silo') || name.includes('صوامع')) mappedType = 'grainSilo';
return {
id: `pg-${p.id}`,
name: p.name_ar || p.name || `معلم استراتيجي #${p.id}`,
region: p.city || p.neighbourhood || 'الأردن',
type: mappedType,
lat: Number(p.latitude),
lng: Number(p.longitude),
elevationM: Math.round(this.calculateElevationSample(Number(p.latitude), Number(p.longitude))),
description: p.description || p.address || p.category || 'معلم تكتيكي مسترجع من قاعدة بيانات PostGIS السيادية',
};
});
// Merge with strategic visual military landmarks
const all = [...strategicCheckpoints, ...formattedFromDb];
const unique = all.filter((lm, index, self) =>
index === self.findIndex((t) => Math.abs(t.lat - lm.lat) < 0.0001 && Math.abs(t.lng - lm.lng) < 0.0001)
);
return {
success: true,
source: 'PostgreSQL PostGIS (Live places_jordan & Tactical checkpoints)',
count: unique.length,
landmarks: unique,
timestamp: new Date().toISOString()
};
}
} catch (err) {
this.logger.warn(`Failed to fetch from places_jordan PostGIS: ${err.message}. Using built-in fallback.`);
}
let result = strategicCheckpoints;
if (region && region !== 'الكل') {
result = result.filter(lm => lm.region.includes(region));
}
if (type) {
result = result.filter(lm => lm.type === type);
}
return {
success: true,
source: 'Tactical Checkpoints (Offline Cache)',
count: result.length,
landmarks: result,
timestamp: new Date().toISOString()
};
}
}