2026-04-14-8 auth and commercial

This commit is contained in:
Hamza-Ayed
2026-04-14 20:14:48 +03:00
parent be7dcc2652
commit f5b3f9f790
430 changed files with 6074 additions and 751 deletions
+20 -25
View File
@@ -4,42 +4,37 @@ export declare class MapRefinementController {
constructor(analyzerService: TelemetryAnalyzerService);
getSummary(): Promise<{
telemetry: {
totalPoints: number;
last24h: number;
activeDrivers24h: number;
total: any;
};
roadSegments: {
analyzed: number;
roads: {
analyzed: any;
closed: any;
};
candidateRoads: {
total: number;
pending: number;
approved: number;
rejected: number;
candidates: {
total: any;
pending: any;
};
}>;
syncExternal(): Promise<{
imported: number;
}>;
syncExternal(): Promise<void>;
refreshCache(): Promise<{
cachedCount: number;
cachedCount: any;
}>;
analyzeRoadSpeeds(hours?: number): Promise<{
segmentsUpdated: number;
totalPointsProcessed: number;
topAdjustments: any[];
analyzeRoadSpeeds(hours?: number): Promise<any>;
discoverNewRoads(hours?: number): Promise<any>;
getCandidates(status?: string): Promise<import("../maps/candidate-road.entity").CandidateRoad[]>;
discoverClosures(hours?: number): Promise<{
roadsClosed: any;
}>;
discoverNewRoads(hours?: number): Promise<{
candidatesFound: number;
candidates: any[];
}>;
getCongestionData(north: number, south: number, east: number, west: number): Promise<any[]>;
getClosures(): Promise<import("../maps/road-stat.entity").RoadSegmentStat[]>;
getCongestionData(north: number, south: number, east: number, west: number): Promise<any>;
approveCandidate(id: string): Promise<{
message: string;
success: boolean;
id: string;
status: string;
}>;
rejectCandidate(id: string): Promise<{
message: string;
success: boolean;
id: string;
status: string;
}>;
}
+38 -2
View File
@@ -16,6 +16,7 @@ exports.MapRefinementController = void 0;
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const telemetry_analyzer_service_1 = require("./telemetry-analyzer.service");
const api_key_guard_1 = require("../common/guards/api-key.guard");
let MapRefinementController = class MapRefinementController {
analyzerService;
constructor(analyzerService) {
@@ -38,6 +39,15 @@ let MapRefinementController = class MapRefinementController {
const sinceHours = hours ? Number(hours) : 168;
return this.analyzerService.discoverNewRoads(sinceHours);
}
async getCandidates(status) {
return this.analyzerService.getCandidates(status || 'pending');
}
async discoverClosures(hours) {
return this.analyzerService.discoverRoadClosures(hours || 48);
}
async getClosures() {
return this.analyzerService.getClosures();
}
async getCongestionData(north, south, east, west) {
if (!north || !south || !east || !west) {
throw new common_1.HttpException('Bounds required: north, south, east, west / يجب تحديد الحدود الجغرافية', common_1.HttpStatus.BAD_REQUEST);
@@ -50,10 +60,10 @@ let MapRefinementController = class MapRefinementController {
});
}
async approveCandidate(id) {
return { message: `Candidate ${id} approved`, status: 'approved' };
return this.analyzerService.updateCandidateStatus(id, 'approved');
}
async rejectCandidate(id) {
return { message: `Candidate ${id} rejected`, status: 'rejected' };
return this.analyzerService.updateCandidateStatus(id, 'rejected');
}
};
exports.MapRefinementController = MapRefinementController;
@@ -96,6 +106,31 @@ __decorate([
__metadata("design:paramtypes", [Number]),
__metadata("design:returntype", Promise)
], MapRefinementController.prototype, "discoverNewRoads", null);
__decorate([
(0, common_1.Get)('candidates'),
(0, swagger_1.ApiOperation)({ summary: 'Get list of candidate roads / جلب الطرق المرشحة' }),
(0, swagger_1.ApiQuery)({ name: 'status', required: false, enum: ['pending', 'approved', 'rejected'] }),
__param(0, (0, common_1.Query)('status')),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Promise)
], MapRefinementController.prototype, "getCandidates", null);
__decorate([
(0, common_1.Post)('discover-closures'),
(0, swagger_1.ApiOperation)({ summary: 'Run road closure detection 🚧 / تشغيل كشف الإغلاقات' }),
(0, swagger_1.ApiQuery)({ name: 'hours', required: false, description: 'Hours to look back (default: 48)' }),
__param(0, (0, common_1.Query)('hours')),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number]),
__metadata("design:returntype", Promise)
], MapRefinementController.prototype, "discoverClosures", null);
__decorate([
(0, common_1.Get)('closures'),
(0, swagger_1.ApiOperation)({ summary: 'Get currently detected closures / جلب الإغلاقات المكتشفة' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], MapRefinementController.prototype, "getClosures", null);
__decorate([
(0, common_1.Get)('congestion'),
(0, swagger_1.ApiOperation)({ summary: 'Get congestion data for heatmap 🗺️ / بيانات الازدحام' }),
@@ -130,6 +165,7 @@ __decorate([
exports.MapRefinementController = MapRefinementController = __decorate([
(0, swagger_1.ApiTags)('map-refinement'),
(0, common_1.Controller)('map-refinement'),
(0, common_1.UseGuards)(api_key_guard_1.ApiKeyGuard),
__metadata("design:paramtypes", [telemetry_analyzer_service_1.TelemetryAnalyzerService])
], MapRefinementController);
//# sourceMappingURL=map-refinement.controller.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"map-refinement.controller.js","sourceRoot":"","sources":["../../src/telemetry/map-refinement.controller.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"map-refinement.controller.js","sourceRoot":"","sources":["../../src/telemetry/map-refinement.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAwH;AACxH,6CAAkE;AAClE,6EAAwE;AACxE,kEAA6D;AActD,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;IACL;IAA7B,YAA6B,eAAyC;QAAzC,oBAAe,GAAf,eAAe,CAA0B;IAAG,CAAC;IAQpE,AAAN,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,eAAe,CAAC,kBAAkB,EAAE,CAAC;IACnD,CAAC;IAQK,AAAN,KAAK,CAAC,YAAY;QAChB,OAAO,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAIK,AAAN,KAAK,CAAC,YAAY;QAChB,OAAO,IAAI,CAAC,eAAe,CAAC,mBAAmB,EAAE,CAAC;IACpD,CAAC;IAUK,AAAN,KAAK,CAAC,iBAAiB,CAAiB,KAAc;QACpD,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAC5D,CAAC;IASK,AAAN,KAAK,CAAC,gBAAgB,CAAiB,KAAc;QACnD,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAC/C,OAAO,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC3D,CAAC;IAKK,AAAN,KAAK,CAAC,aAAa,CAAkB,MAAe;QAClD,OAAO,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC;IACjE,CAAC;IASK,AAAN,KAAK,CAAC,gBAAgB,CAAiB,KAAc;QACnD,OAAO,IAAI,CAAC,eAAe,CAAC,oBAAoB,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IAIK,AAAN,KAAK,CAAC,WAAW;QACf,OAAO,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC;IAC5C,CAAC;IAYK,AAAN,KAAK,CAAC,iBAAiB,CACL,KAAa,EACb,KAAa,EACd,IAAY,EACZ,IAAY;QAE3B,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACvC,MAAM,IAAI,sBAAa,CACrB,wEAAwE,EACxE,mBAAU,CAAC,WAAW,CACvB,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC;YAC5C,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;YACpB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;YACpB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;YAClB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;SACnB,CAAC,CAAC;IACL,CAAC;IAQK,AAAN,KAAK,CAAC,gBAAgB,CAAc,EAAU;QAC5C,OAAO,IAAI,CAAC,eAAe,CAAC,qBAAqB,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IACpE,CAAC;IAIK,AAAN,KAAK,CAAC,eAAe,CAAc,EAAU;QAC3C,OAAO,IAAI,CAAC,eAAe,CAAC,qBAAqB,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IACpE,CAAC;CACF,CAAA;AA3HY,0DAAuB;AAS5B;IAFL,IAAA,YAAG,EAAC,SAAS,CAAC;IACd,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,wCAAwC,EAAE,CAAC;;;;yDAGnE;AAQK;IAFL,IAAA,aAAI,EAAC,eAAe,CAAC;IACrB,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,mEAAmE,EAAE,CAAC;;;;2DAG9F;AAIK;IAFL,IAAA,aAAI,EAAC,eAAe,CAAC;IACrB,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,yDAAyD,EAAE,CAAC;;;;2DAGpF;AAUK;IAHL,IAAA,aAAI,EAAC,gBAAgB,CAAC;IACtB,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,sDAAsD,EAAE,CAAC;IACjF,IAAA,kBAAQ,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;IACrE,WAAA,IAAA,cAAK,EAAC,OAAO,CAAC,CAAA;;;;gEAGtC;AASK;IAHL,IAAA,aAAI,EAAC,gBAAgB,CAAC;IACtB,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,0DAA0D,EAAE,CAAC;IACrF,IAAA,kBAAQ,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,4CAA4C,EAAE,CAAC;IAChF,WAAA,IAAA,cAAK,EAAC,OAAO,CAAC,CAAA;;;;+DAGrC;AAKK;IAHL,IAAA,YAAG,EAAC,YAAY,CAAC;IACjB,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,iDAAiD,EAAE,CAAC;IAC5E,IAAA,kBAAQ,EAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC;IACpE,WAAA,IAAA,cAAK,EAAC,QAAQ,CAAC,CAAA;;;;4DAEnC;AASK;IAHL,IAAA,aAAI,EAAC,mBAAmB,CAAC;IACzB,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,qDAAqD,EAAE,CAAC;IAChF,IAAA,kBAAQ,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;IACtE,WAAA,IAAA,cAAK,EAAC,OAAO,CAAC,CAAA;;;;+DAErC;AAIK;IAFL,IAAA,YAAG,EAAC,UAAU,CAAC;IACf,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,0DAA0D,EAAE,CAAC;;;;0DAGrF;AAYK;IANL,IAAA,YAAG,EAAC,YAAY,CAAC;IACjB,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,uDAAuD,EAAE,CAAC;IAClF,IAAA,kBAAQ,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,kBAAQ,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,kBAAQ,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1C,IAAA,kBAAQ,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAExC,WAAA,IAAA,cAAK,EAAC,OAAO,CAAC,CAAA;IACd,WAAA,IAAA,cAAK,EAAC,OAAO,CAAC,CAAA;IACd,WAAA,IAAA,cAAK,EAAC,MAAM,CAAC,CAAA;IACb,WAAA,IAAA,cAAK,EAAC,MAAM,CAAC,CAAA;;;;gEAcf;AAQK;IAFL,IAAA,cAAK,EAAC,wBAAwB,CAAC;IAC/B,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,qDAAqD,EAAE,CAAC;IACzD,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;;;;+DAElC;AAIK;IAFL,IAAA,cAAK,EAAC,uBAAuB,CAAC;IAC9B,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,2CAA2C,EAAE,CAAC;IAChD,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;;;;8DAEjC;kCA1HU,uBAAuB;IAHnC,IAAA,iBAAO,EAAC,gBAAgB,CAAC;IACzB,IAAA,mBAAU,EAAC,gBAAgB,CAAC;IAC5B,IAAA,kBAAS,EAAC,2BAAW,CAAC;qCAEyB,qDAAwB;GAD3D,uBAAuB,CA2HnC"}
+38 -33
View File
@@ -2,55 +2,60 @@ import { Repository, DataSource } from 'typeorm';
import { TelemetryLog } from './telemetry.entity';
import { RoadSegmentStat } from '../maps/road-stat.entity';
import { CandidateRoad } from '../maps/candidate-road.entity';
import { RedisService } from '../common/redis.service';
import { ExternalTelemetryService } from './external-telemetry.service';
import { RedisService } from '../common/redis.service';
import { TelegramService } from '../common/telegram.service';
import { TrafficGridService } from '../maps/traffic-grid.service';
export declare class TelemetryAnalyzerService {
private telemetryRepo;
private roadStatRepo;
private candidateRoadRepo;
private dataSource;
private redisService;
private externalTelemetry;
private redisService;
private telegramService;
private trafficGrid;
private dataSource;
private readonly logger;
private readonly TRAFFIC_CACHE_KEY;
constructor(telemetryRepo: Repository<TelemetryLog>, roadStatRepo: Repository<RoadSegmentStat>, candidateRoadRepo: Repository<CandidateRoad>, dataSource: DataSource, redisService: RedisService, externalTelemetry: ExternalTelemetryService);
handleNightlyIntelligence(): Promise<void>;
syncExternalData(days?: number): Promise<{
imported: number;
constructor(telemetryRepo: Repository<TelemetryLog>, roadStatRepo: Repository<RoadSegmentStat>, candidateRoadRepo: Repository<CandidateRoad>, externalTelemetry: ExternalTelemetryService, redisService: RedisService, telegramService: TelegramService, trafficGrid: TrafficGridService, dataSource: DataSource);
runDeepIntelligence(hours?: number): Promise<{
success: boolean;
timestamp: string;
speedAnalysis: any;
temporalAnalysis: any;
roadDiscovery: any;
}>;
handleDeepIntelligence(): void;
syncExternalData(days?: number): Promise<void>;
refreshTrafficCache(): Promise<{
cachedCount: number;
cachedCount: any;
}>;
analyzeRoadSpeeds(sinceHours?: number): Promise<{
segmentsUpdated: number;
totalPointsProcessed: number;
topAdjustments: any[];
}>;
discoverNewRoads(sinceHours?: number): Promise<{
candidatesFound: number;
candidates: any[];
}>;
getCongestionData(bounds: {
north: number;
south: number;
east: number;
west: number;
}): Promise<any[]>;
analyzeRoadSpeeds(sinceHours?: number): Promise<any>;
analyzeTimeProfiles(sinceHours?: number): Promise<any>;
discoverNewRoads(sinceHours?: number): Promise<any>;
getCongestionData(bounds: any): Promise<any>;
getAnalysisSummary(): Promise<{
telemetry: {
totalPoints: number;
last24h: number;
activeDrivers24h: number;
total: any;
};
roadSegments: {
analyzed: number;
roads: {
analyzed: any;
closed: any;
};
candidateRoads: {
total: number;
pending: number;
approved: number;
rejected: number;
candidates: {
total: any;
pending: any;
};
}>;
getCandidates(status?: string, limit?: number): Promise<CandidateRoad[]>;
updateCandidateStatus(id: string, status: string): Promise<{
success: boolean;
id: string;
status: string;
}>;
discoverRoadClosures(sinceHours?: number): Promise<{
roadsClosed: any;
}>;
getClosures(): Promise<RoadSegmentStat[]>;
private calculateConfidence;
}
+301 -248
View File
@@ -15,309 +15,360 @@ var TelemetryAnalyzerService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TelemetryAnalyzerService = void 0;
const common_1 = require("@nestjs/common");
const schedule_1 = require("@nestjs/schedule");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const schedule_1 = require("@nestjs/schedule");
const telemetry_entity_1 = require("./telemetry.entity");
const road_stat_entity_1 = require("../maps/road-stat.entity");
const candidate_road_entity_1 = require("../maps/candidate-road.entity");
const redis_service_1 = require("../common/redis.service");
const external_telemetry_service_1 = require("./external-telemetry.service");
const redis_service_1 = require("../common/redis.service");
const telegram_service_1 = require("../common/telegram.service");
const traffic_grid_service_1 = require("../maps/traffic-grid.service");
let TelemetryAnalyzerService = TelemetryAnalyzerService_1 = class TelemetryAnalyzerService {
telemetryRepo;
roadStatRepo;
candidateRoadRepo;
dataSource;
redisService;
externalTelemetry;
redisService;
telegramService;
trafficGrid;
dataSource;
logger = new common_1.Logger(TelemetryAnalyzerService_1.name);
TRAFFIC_CACHE_KEY = 'traffic_snapshot';
constructor(telemetryRepo, roadStatRepo, candidateRoadRepo, dataSource, redisService, externalTelemetry) {
TRAFFIC_CACHE_KEY = 'live_traffic_congested';
constructor(telemetryRepo, roadStatRepo, candidateRoadRepo, externalTelemetry, redisService, telegramService, trafficGrid, dataSource) {
this.telemetryRepo = telemetryRepo;
this.roadStatRepo = roadStatRepo;
this.candidateRoadRepo = candidateRoadRepo;
this.dataSource = dataSource;
this.redisService = redisService;
this.externalTelemetry = externalTelemetry;
this.redisService = redisService;
this.telegramService = telegramService;
this.trafficGrid = trafficGrid;
this.dataSource = dataSource;
}
async handleNightlyIntelligence() {
this.logger.log('⏰ Starting automated 3 AM intelligence process...');
async runDeepIntelligence(hours = 48) {
this.logger.log(`🚀 Starting Full Intelligence Pipeline (Window: ${hours}h)...`);
await this.syncExternalData(Math.ceil(hours / 24));
const speedResult = await this.analyzeRoadSpeeds(hours);
const temporalResult = await this.analyzeTimeProfiles(hours);
const discoveryResult = await this.discoverNewRoads(hours);
await this.refreshTrafficCache();
await this.trafficGrid.refreshGrid();
const summary = await this.getAnalysisSummary();
await this.telegramService.sendIntelligenceReport({
syncResult: speedResult.totalPointsProcessed || 0,
updatedSegments: speedResult.segmentsUpdated || 0,
discoveredRoads: discoveryResult.candidatesFound || 0,
timeProfiles: temporalResult.bucketsUpdated || 0,
totalPoints: summary.telemetry.total,
days: Math.ceil(hours / 24),
});
this.logger.log('🏁 Intelligence Pipeline Finished Successfully.');
return {
success: true,
timestamp: new Date().toISOString(),
speedAnalysis: speedResult,
temporalAnalysis: temporalResult,
roadDiscovery: discoveryResult,
};
}
handleDeepIntelligence() {
this.runDeepIntelligence(240);
}
async syncExternalData(days = 7) {
this.logger.log(`📡 Starting batch sync (Window: ${days} days)...`);
try {
await this.syncExternalData(1);
await this.analyzeRoadSpeeds(24);
await this.discoverNewRoads(168);
await this.refreshTrafficCache();
this.logger.log('✅ 3 AM intelligence process complete.');
const tracks = await this.externalTelemetry.fetchCarTracks(days);
if (tracks.length === 0)
return;
this.logger.log(`📥 Saving ${tracks.length} points to database...`);
const values = tracks
.filter(t => t.driver_id && t.longitude && t.latitude)
.map(t => `('${t.driver_id}', ST_SetSRID(ST_Point(${t.longitude}, ${t.latitude}), 4326), ${t.latitude}, ${t.longitude}, ${t.speed || 0}, ${t.heading || 0}, '${t.created_at}')`).join(',');
await this.dataSource.query(`
INSERT INTO telemetry_logs ("driverId", location, latitude, longitude, speed, heading, timestamp)
VALUES ${values}
ON CONFLICT DO NOTHING
`);
this.logger.log(`✅ Batch sync complete.`);
}
catch (error) {
this.logger.error('❌ Nightly intelligence failed:', error.stack);
this.logger.error(`❌ Sync failed: ${error.message}`);
throw error;
}
}
async syncExternalData(days = 1) {
this.logger.log(`📡 Starting batch sync (Window: ${days} days)...`);
const tracks = await this.externalTelemetry.fetchCarTracks(days);
if (!tracks || tracks.length === 0) {
this.logger.warn(`⚠️ No tracks found on external server for the last ${days} days.`);
return { imported: 0 };
}
this.logger.log(`✅ Received ${tracks.length} tracks. Commencing batch insertion...`);
this.logger.log(`📥 Saving ${tracks.length} points to database...`);
const entities = tracks.map(t => ({
driverId: t.driver_id,
latitude: t.latitude,
longitude: t.longitude,
speed: t.speed,
heading: t.heading,
timestamp: new Date(t.created_at || t.timestamp),
location: {
type: 'Point',
coordinates: [t.longitude, t.latitude],
},
}));
const CHUNK_SIZE = 1000;
for (let i = 0; i < entities.length; i += CHUNK_SIZE) {
const chunk = entities.slice(i, i + CHUNK_SIZE);
const logs = this.telemetryRepo.create(chunk);
await this.telemetryRepo.save(logs);
}
return { imported: tracks.length };
}
async refreshTrafficCache() {
this.logger.log('🚀 Refreshing Redis traffic snapshot...');
this.logger.log('🚀 Refreshing Redis traffic snapshot (v2.5.2 Optimized)...');
const congested = await this.roadStatRepo.query(`
SELECT
"segmentId",
"congestionFactor",
ST_AsGeoJSON(geometry) as geojson
SELECT "segmentId", "congestionFactor", ST_AsGeoJSON(geometry, 5) as geojson
FROM road_segment_stats
WHERE "congestionFactor" > 1.1
ORDER BY "congestionFactor" DESC
LIMIT 2000
`);
if (congested.length === 0) {
await this.redisService.del(this.TRAFFIC_CACHE_KEY);
return { cachedCount: 0 };
}
await this.redisService.set(this.TRAFFIC_CACHE_KEY, congested);
this.logger.log(`✅ Cached ${congested.length} congested segments in Redis.`);
const snapshot = congested.map(row => ({
sid: row.segmentId,
cf: parseFloat(row.congestionFactor),
geo: JSON.parse(row.geojson)
}));
const sampleSize = Math.min(congested.length, 3);
const topSegments = congested.slice(0, sampleSize).map(s => `${s.segmentId} (F: ${s.congestionFactor})`).join(', ');
const totalSizeKB = Math.round(JSON.stringify(snapshot).length / 1024);
this.logger.log(`📊 Traffic Snapshot Sample (Top ${sampleSize}): ${topSegments}`);
this.logger.log(`📦 Redis Payload Size: ~${totalSizeKB} KB`);
await this.redisService.set(this.TRAFFIC_CACHE_KEY, snapshot);
this.logger.log(`✅ Redis traffic snapshot updated with ${congested.length} segments.`);
return { cachedCount: congested.length };
}
async analyzeRoadSpeeds(sinceHours = 24) {
this.logger.log(`🔍 Starting road speed analysis for last ${sinceHours}h...`);
const matchedData = await this.dataSource.query(`
WITH matched_points AS (
SELECT
t.id AS telemetry_id,
t.speed,
t."driverId",
l.osm_id,
l.name,
l.highway,
l.way_4326,
ST_Distance(t.location::geography, l.way_4326::geography) AS distance_m
FROM telemetry_logs t
CROSS JOIN LATERAL (
SELECT osm_id, name, highway, ST_Transform(way, 4326) AS way_4326
FROM planet_osm_line
WHERE highway IS NOT NULL
ORDER BY way <-> ST_Transform(t.location::geometry, 3857)
LIMIT 1
) l
WHERE t.timestamp >= NOW() - INTERVAL '${sinceHours} hours'
AND t.speed > 2 -- Ignore stationary points / تجاهل النقاط الثابتة
AND ST_Distance(t.location::geography, l.way_4326::geography) < 15 -- 15m snap threshold
this.logger.log(`🔍 Starting road speed analysis v2.5 for last ${sinceHours}h...`);
const query = `
WITH grid_points AS (
-- Group by 5m grid cell first to reduce spatial join volume (v2.5.1 WoW Performance)
SELECT ST_SnapToGrid(ST_Transform(location::geometry, 3857), 5) AS loc,
AVG(speed) as speed
FROM telemetry_logs
WHERE timestamp >= NOW() - INTERVAL '${sinceHours} hours' AND speed > 2
GROUP BY loc
),
matches AS (
-- Bulk Spatial Join (20m radius) with GIST optimization
SELECT l.osm_id::text as id, l.name, l.highway, g.speed, l.way
FROM grid_points g
INNER JOIN planet_osm_line l ON
l.highway IS NOT NULL AND
l.way && ST_Expand(g.loc, 20) AND
ST_DWithin(l.way, g.loc, 20)
),
stats AS (
-- Calculate median speed and aggregate samples
SELECT id, name, highway,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY speed) as avg_speed,
COUNT(*) as samples,
ST_Transform(MIN(way), 4326) as way4326
FROM matches
GROUP BY id, name, highway
HAVING COUNT(*) >= 3
)
SELECT
osm_id::text AS segment_id,
name,
highway,
AVG(speed) AS avg_speed,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY speed) AS median_speed,
COUNT(*) AS sample_count,
COUNT(DISTINCT "driverId") AS unique_drivers,
ST_AsGeoJSON(MIN(way_4326)) AS geojson
FROM matched_points
GROUP BY osm_id, name, highway
HAVING COUNT(*) >= 3 -- Minimum 3 samples for reliability / 3 عينات على الأقل
ORDER BY sample_count DESC
`);
let segmentsUpdated = 0;
let totalPoints = 0;
for (const row of matchedData) {
const medianSpeed = parseFloat(row.median_speed);
const sampleCount = parseInt(row.sample_count);
const geojson = JSON.parse(row.geojson);
totalPoints += sampleCount;
let congestionFactor = 1.0;
const majorRoadTypes = ['primary', 'secondary', 'trunk', 'motorway'];
if (majorRoadTypes.includes(row.highway) && medianSpeed < 30) {
congestionFactor = 30 / Math.max(medianSpeed, 1);
}
await this.roadStatRepo.upsert({
segmentId: row.segment_id,
averageSpeed: medianSpeed,
congestionFactor,
sampleCount,
lastUpdated: new Date(),
geometry: geojson,
}, ['segmentId']);
segmentsUpdated++;
}
return {
segmentsUpdated,
totalPointsProcessed: totalPoints,
topAdjustments: matchedData.slice(0, 10).map(d => ({
segmentId: d.segment_id,
name: d.name || 'Unnamed Road',
speed: Math.round(parseFloat(d.median_speed)),
samples: parseInt(d.sample_count)
}))
};
INSERT INTO road_segment_stats ("segmentId", "averageSpeed", "sampleCount", "lastUpdated", geometry, "congestionFactor")
SELECT id, avg_speed, samples, NOW(), way4326,
CASE WHEN highway IN ('primary','secondary','trunk','motorway') AND avg_speed < 30
THEN 30/GREATEST(avg_speed,1) ELSE 1.0 END
FROM stats
ON CONFLICT ("segmentId") DO UPDATE SET
"averageSpeed"=EXCLUDED."averageSpeed",
"sampleCount"=EXCLUDED."sampleCount",
"lastUpdated"=NOW(),
"geometry"=EXCLUDED."geometry",
"congestionFactor"=EXCLUDED."congestionFactor"
RETURNING "segmentId";
`;
const result = await this.dataSource.query(query);
return { segmentsUpdated: result.length };
}
async analyzeTimeProfiles(sinceHours = 720) {
this.logger.log(`🕒 Starting temporal profiling (Phase 2) for last ${sinceHours}h...`);
const query = `
WITH grid_points AS (
-- Bucket by 10m grid and Time (Hour + DOW)
SELECT
ST_SnapToGrid(ST_Transform(location::geometry, 3857), 10) AS loc,
EXTRACT(HOUR FROM timestamp)::int as hr,
EXTRACT(DOW FROM timestamp)::int as dow,
AVG(speed) as speed
FROM telemetry_logs
WHERE timestamp >= NOW() - INTERVAL '${sinceHours} hours' AND speed > 2
GROUP BY loc, hr, dow
),
matches AS (
-- Map to OSM segments
SELECT l.osm_id::text as sid, g.hr, g.dow, g.speed
FROM grid_points g
INNER JOIN planet_osm_line l ON
l.highway IS NOT NULL AND
l.way && ST_Expand(g.loc, 20) AND
ST_DWithin(l.way, g.loc, 20)
),
temporal_stats AS (
-- Aggregate by segment + time bucket
SELECT sid, hr, dow,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY speed) as avg_spd,
COUNT(*) as smp
FROM matches
GROUP BY sid, hr, dow
HAVING COUNT(*) >= 2 -- Require minimum samples per bucket
)
INSERT INTO road_speed_profiles ("segmentId", "hourOfDay", "dayOfWeek", "averageSpeed", "sampleCount", "lastUpdated")
SELECT sid, hr, dow, avg_spd, smp, NOW()
FROM temporal_stats
ON CONFLICT ("segmentId", "hourOfDay", "dayOfWeek") DO UPDATE SET
"averageSpeed" = EXCLUDED."averageSpeed",
"sampleCount" = EXCLUDED."sampleCount",
"lastUpdated" = NOW()
RETURNING "segmentId";
`;
const result = await this.dataSource.query(query);
this.logger.log(`📊 Time-aware profiling complete: ${result.length} buckets updated.`);
return { bucketsUpdated: result.length };
}
async discoverNewRoads(sinceHours = 168) {
this.logger.log(`🛣️ Starting road discovery for last ${sinceHours}h (${sinceHours / 24}d)...`);
const candidates = await this.dataSource.query(`
WITH off_road_points AS (
SELECT
t.id,
t."driverId",
t.speed,
t.heading,
t.location,
t.timestamp
FROM telemetry_logs t
WHERE t.timestamp >= NOW() - INTERVAL '${sinceHours} hours'
AND t.speed > 5 -- Moving, not parked / متحرك وليس متوقف
AND NOT EXISTS (
SELECT 1
FROM planet_osm_line l
WHERE l.highway IS NOT NULL
AND ST_DWithin(t.location::geography, ST_Transform(l.way, 4326)::geography, 15)
)
this.logger.log(`🛣️ Starting road discovery v2.5 for last ${sinceHours}h...`);
const query = `
WITH grid_points AS (
-- Group by cell and driver to reduce volume for clustering and anti-join (v2.5.1 WoW Performance)
SELECT "driverId", ST_SnapToGrid(ST_Transform(location::geometry, 3857), 10) as loc,
AVG(speed) as speed,
MIN(timestamp) as timestamp
FROM telemetry_logs
WHERE timestamp >= NOW() - INTERVAL '${sinceHours} hours' AND speed > 5
GROUP BY loc, "driverId"
),
off_road AS (
-- Spatial Anti-Join: Only points further than 35m from any existing highway
SELECT g.* FROM grid_points g
LEFT JOIN planet_osm_line l ON
l.highway IS NOT NULL AND
l.way && ST_Expand(g.loc, 35) AND
ST_DWithin(l.way, g.loc, 35)
WHERE l.osm_id IS NULL
),
-- Step 2: Cluster nearby off-road points using DBSCAN
-- الخطوة 2: تجميع النقاط القريبة باستخدام DBSCAN
clustered AS (
SELECT
*,
ST_ClusterDBSCAN(location::geometry, eps := 0.0003, minpoints := 5)
OVER () AS cluster_id
FROM off_road_points
-- Density-based clustering to find linear paths
SELECT *, ST_ClusterDBSCAN(loc, eps := 30, minpoints := 3) OVER () as cid FROM off_road
),
cluster_stats AS (
-- 1. Calculate cluster-wide quality metrics
SELECT cid,
COUNT(DISTINCT "driverId") as drv_count,
COUNT(*) as pt_count,
AVG(speed) as avg_spd
FROM clustered
WHERE cid IS NOT NULL
GROUP BY cid
HAVING COUNT(DISTINCT "driverId") >= 3 AND COUNT(*) >= 15
),
cluster_path AS (
-- 2. Extract unique grid cells per cluster in chronological order
SELECT cid, loc, MIN(timestamp) as ts
FROM clustered
WHERE cid IN (SELECT cid FROM cluster_stats)
GROUP BY cid, loc
),
final_candidates AS (
-- 3. Build geometry and calculate final scoring
SELECT
s.cid,
ST_Transform(ST_MakeLine(p.loc ORDER BY p.ts), 4326) as geom,
s.drv_count,
s.pt_count,
s.avg_spd,
ST_Length(ST_Transform(ST_MakeLine(p.loc ORDER BY p.ts), 4326)::geography) as len
FROM cluster_stats s
JOIN cluster_path p ON s.cid = p.cid
GROUP BY s.cid, s.drv_count, s.pt_count, s.avg_spd
)
-- Step 3: Aggregate clusters into candidate road lines
-- الخطوة 3: تحويل التجمعات إلى خطوط طرق مرشحة
SELECT
cluster_id,
COUNT(*) AS total_points,
COUNT(DISTINCT "driverId") AS unique_drivers,
AVG(speed) AS avg_speed,
ST_AsGeoJSON(ST_MakeLine(location::geometry ORDER BY timestamp)) AS geojson_line,
ST_Length(ST_MakeLine(location::geometry ORDER BY timestamp)::geography) AS length_m
FROM clustered
WHERE cluster_id IS NOT NULL
GROUP BY cluster_id
HAVING COUNT(DISTINCT "driverId") >= 2 -- At least 2 drivers / سائقان على الأقل
AND COUNT(*) >= 10 -- At least 10 points / 10 نقاط على الأقل
ORDER BY unique_drivers DESC, total_points DESC
`);
const savedCandidates = [];
for (const c of candidates) {
const geojson = JSON.parse(c.geojson_line);
const confidence = this.calculateConfidence(parseInt(c.unique_drivers), parseInt(c.total_points), parseFloat(c.length_m));
const candidate = this.candidateRoadRepo.create({
geometry: geojson,
uniqueDriverCount: parseInt(c.unique_drivers),
totalPoints: parseInt(c.total_points),
averageSpeed: parseFloat(c.avg_speed),
lengthMeters: parseFloat(c.length_m),
confidence,
status: 'pending',
});
const saved = await this.candidateRoadRepo.save(candidate);
savedCandidates.push({
id: saved.id,
uniqueDrivers: saved.uniqueDriverCount,
totalPoints: saved.totalPoints,
averageSpeed: Math.round(saved.averageSpeed * 10) / 10,
lengthMeters: Math.round(saved.lengthMeters),
confidence: Math.round(saved.confidence * 100) / 100,
geojson,
});
}
this.logger.log(`✅ Road discovery complete: ${savedCandidates.length} candidates found`);
return {
candidatesFound: savedCandidates.length,
candidates: savedCandidates,
};
INSERT INTO candidate_roads (geometry, "uniqueDriverCount", "totalPoints", "averageSpeed", "lengthMeters", confidence, status)
SELECT geom, drv_count, pt_count, avg_spd, len,
-- SQL port of calculateConfidence logic
ROUND((
LEAST(drv_count::float / 5, 1.0) * 0.4 +
LEAST(pt_count::float / 50, 1.0) * 0.3 +
CASE WHEN len BETWEEN 50 AND 2000 THEN 0.3 ELSE 0.1 END
)::numeric, 2) as conf,
'pending'
FROM final_candidates
RETURNING id;
`;
const result = await this.dataSource.query(query);
return { candidatesFound: result.length };
}
async getCongestionData(bounds) {
return this.dataSource.query(`
SELECT
rs."segmentId" AS segment_id,
rs."averageSpeed" AS avg_speed,
rs."congestionFactor" AS congestion_factor,
rs."sampleCount" AS sample_count,
ST_AsGeoJSON(rs.geometry) AS geojson
SELECT rs."segmentId", rs."averageSpeed", rs."congestionFactor", rs."sampleCount", ST_AsGeoJSON(rs.geometry) as geojson
FROM road_segment_stats rs
WHERE rs.geometry IS NOT NULL
AND ST_Intersects(
rs.geometry::geometry,
ST_MakeEnvelope($1, $2, $3, $4, 4326)
)
AND rs."sampleCount" >= 3
WHERE rs.geometry IS NOT NULL AND ST_Intersects(rs.geometry::geometry, ST_MakeEnvelope($1, $2, $3, $4, 4326))
ORDER BY rs."congestionFactor" DESC
`, [bounds.west, bounds.south, bounds.east, bounds.north]);
}
async getAnalysisSummary() {
const [telemetryCount] = await this.dataSource.query(`SELECT COUNT(*) as count FROM telemetry_logs`);
const [roadStatCount] = await this.dataSource.query(`SELECT COUNT(*) as count FROM road_segment_stats`);
const [candidateCount] = await this.dataSource.query(`SELECT COUNT(*) as count,
COUNT(*) FILTER (WHERE status = 'pending') as pending,
COUNT(*) FILTER (WHERE status = 'approved') as approved,
COUNT(*) FILTER (WHERE status = 'rejected') as rejected
FROM candidate_roads`);
const [recentActivity] = await this.dataSource.query(`
SELECT
COUNT(*) as points_last_24h,
COUNT(DISTINCT "driverId") as active_drivers_24h
FROM telemetry_logs
WHERE timestamp >= NOW() - INTERVAL '24 hours'
`);
const [tCount] = await this.dataSource.query('SELECT COUNT(*) as count FROM telemetry_logs');
const [rCount] = await this.dataSource.query('SELECT COUNT(*) as count FROM road_segment_stats');
const [cCount] = await this.dataSource.query('SELECT COUNT(*) as count, COUNT(*) FILTER (WHERE status=\'pending\') as p FROM candidate_roads');
const [clCount] = await this.dataSource.query('SELECT COUNT(*) as count FROM road_segment_stats WHERE "isClosed" = true');
return {
telemetry: {
totalPoints: parseInt(telemetryCount?.count || '0'),
last24h: parseInt(recentActivity?.points_last_24h || '0'),
activeDrivers24h: parseInt(recentActivity?.active_drivers_24h || '0'),
},
roadSegments: {
analyzed: parseInt(roadStatCount?.count || '0'),
},
candidateRoads: {
total: parseInt(candidateCount?.count || '0'),
pending: parseInt(candidateCount?.pending || '0'),
approved: parseInt(candidateCount?.approved || '0'),
rejected: parseInt(candidateCount?.rejected || '0'),
},
telemetry: { total: tCount.count },
roads: { analyzed: rCount.count, closed: clCount.count },
candidates: { total: cCount.count, pending: cCount.p }
};
}
calculateConfidence(uniqueDrivers, totalPoints, lengthMeters) {
const driverScore = Math.min(uniqueDrivers / 5, 1.0) * 0.4;
const pointScore = Math.min(totalPoints / 50, 1.0) * 0.3;
let lengthScore = 0;
if (lengthMeters >= 50 && lengthMeters <= 2000) {
lengthScore = 0.3;
}
else if (lengthMeters > 2000) {
lengthScore = 0.2;
}
return Math.round((driverScore + pointScore + lengthScore) * 100) / 100;
async getCandidates(status = 'pending', limit = 50) {
return this.candidateRoadRepo.find({
where: { status },
order: { confidence: 'DESC' },
take: limit
});
}
async updateCandidateStatus(id, status) {
await this.candidateRoadRepo.update(id, {
status,
reviewedAt: new Date()
});
return { success: true, id, status };
}
async discoverRoadClosures(sinceHours = 48) {
this.logger.log(`🚧 Analyzing road closures for last ${sinceHours}h...`);
await this.roadStatRepo.update({ isClosed: true }, { isClosed: false });
const query = `
WITH active_area AS (
-- Bounding box of some recent activity to prove drivers are on the map
SELECT ST_Expand(ST_Extent(location::geometry), 0.01) as bbox
FROM telemetry_logs
WHERE timestamp >= NOW() - INTERVAL '${sinceHours} hours'
),
possible_closures AS (
SELECT rs."segmentId"
FROM road_segment_stats rs
WHERE rs."sampleCount" > 50
AND rs.geometry && (SELECT bbox FROM active_area)
AND NOT EXISTS (
SELECT 1 FROM telemetry_logs t
WHERE t.timestamp >= NOW() - INTERVAL '${sinceHours} hours'
AND ST_DWithin(rs.geometry::geometry, t.location::geometry, 35)
)
)
UPDATE road_segment_stats
SET "isClosed" = true
WHERE "segmentId" IN (SELECT "segmentId" FROM possible_closures)
RETURNING "segmentId";
`;
const result = await this.dataSource.query(query);
this.logger.log(`✅ Road closure detection complete: ${result.length} roads flagged as closed.`);
return { roadsClosed: result.length };
}
async getClosures() {
return this.roadStatRepo.find({
where: { isClosed: true },
order: { sampleCount: 'DESC' }
});
}
calculateConfidence(drivers, points, len) {
const dScore = Math.min(drivers / 5, 1.0) * 0.4;
const pScore = Math.min(points / 50, 1.0) * 0.3;
const lScore = (len >= 50 && len <= 2000) ? 0.3 : 0.1;
return Math.round((dScore + pScore + lScore) * 100) / 100;
}
};
exports.TelemetryAnalyzerService = TelemetryAnalyzerService;
__decorate([
(0, schedule_1.Cron)('0 3 * * *'),
(0, schedule_1.Cron)('0 4 */10 * *'),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], TelemetryAnalyzerService.prototype, "handleNightlyIntelligence", null);
__metadata("design:returntype", void 0)
], TelemetryAnalyzerService.prototype, "handleDeepIntelligence", null);
exports.TelemetryAnalyzerService = TelemetryAnalyzerService = TelemetryAnalyzerService_1 = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, typeorm_1.InjectRepository)(telemetry_entity_1.TelemetryLog)),
@@ -326,8 +377,10 @@ exports.TelemetryAnalyzerService = TelemetryAnalyzerService = TelemetryAnalyzerS
__metadata("design:paramtypes", [typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.DataSource,
external_telemetry_service_1.ExternalTelemetryService,
redis_service_1.RedisService,
external_telemetry_service_1.ExternalTelemetryService])
telegram_service_1.TelegramService,
traffic_grid_service_1.TrafficGridService,
typeorm_2.DataSource])
], TelemetryAnalyzerService);
//# sourceMappingURL=telemetry-analyzer.service.js.map
File diff suppressed because one or more lines are too long
+15 -52
View File
@@ -8,69 +8,32 @@ export declare class TelemetryController {
success: boolean;
timestamp: Date;
}>;
sync(): Promise<{
imported: number;
}>;
sync(): Promise<void>;
analyze(hours?: number): Promise<{
success: boolean;
roadAnalysis: {
segmentsUpdated: number;
totalPointsProcessed: number;
topAdjustments: any[];
};
roadDiscovery: {
candidatesFound: number;
candidates: any[];
};
roadAnalysis: any;
roadDiscovery: any;
}>;
processIntelligence(hours?: number): Promise<{
processIntelligence(hours?: string, days?: string): Promise<{
success: boolean;
message: string;
timestamp: Date;
sync: {
imported: number;
};
analysis: {
roads: {
segmentsUpdated: number;
totalPointsProcessed: number;
topAdjustments: any[];
};
discovery: {
candidatesFound: number;
candidates: any[];
};
};
currentStatus: {
telemetry: {
totalPoints: number;
last24h: number;
activeDrivers24h: number;
};
roadSegments: {
analyzed: number;
};
candidateRoads: {
total: number;
pending: number;
approved: number;
rejected: number;
};
window: {
days: number;
hours: number;
};
}>;
getSummary(): Promise<{
telemetry: {
totalPoints: number;
last24h: number;
activeDrivers24h: number;
total: any;
};
roadSegments: {
analyzed: number;
roads: {
analyzed: any;
closed: any;
};
candidateRoads: {
total: number;
pending: number;
approved: number;
rejected: number;
candidates: {
total: any;
pending: any;
};
}>;
getNearby(lat: number, lng: number, radius: number): Promise<import("./telemetry.entity").TelemetryLog[]>;
+12 -14
View File
@@ -13,10 +13,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TelemetryController = void 0;
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const telemetry_service_1 = require("./telemetry.service");
const telemetry_analyzer_service_1 = require("./telemetry-analyzer.service");
const api_key_guard_1 = require("../common/guards/api-key.guard");
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
let TelemetryController = class TelemetryController {
telemetryService;
analyzerService;
@@ -39,20 +40,15 @@ let TelemetryController = class TelemetryController {
roadDiscovery: discoveryResults,
};
}
async processIntelligence(hours) {
const syncResults = await this.analyzerService.syncExternalData();
const roadResults = await this.analyzerService.analyzeRoadSpeeds(hours || 24);
const discoveryResults = await this.analyzerService.discoverNewRoads(hours || 168);
const summary = await this.analyzerService.getAnalysisSummary();
async processIntelligence(hours, days) {
const parsedDays = days ? parseInt(days, 10) : 1;
const parsedHours = hours ? parseInt(hours, 10) : (parsedDays * 24);
this.analyzerService.runDeepIntelligence(parsedHours);
return {
success: true,
message: `Intelligence sync and analysis started for the last ${parsedDays} days. You will receive a summary on Telegram once complete! 🚀`,
timestamp: new Date(),
sync: syncResults,
analysis: {
roads: roadResults,
discovery: discoveryResults,
},
currentStatus: summary,
window: { days: parsedDays, hours: parsedHours },
};
}
async getSummary() {
@@ -90,8 +86,9 @@ __decorate([
(0, common_1.Post)('process-intelligence'),
(0, swagger_1.ApiOperation)({ summary: 'Automated One-Click Sync & Analyze 🚀' }),
__param(0, (0, common_1.Query)('hours')),
__param(1, (0, common_1.Query)('days')),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number]),
__metadata("design:paramtypes", [String, String]),
__metadata("design:returntype", Promise)
], TelemetryController.prototype, "processIntelligence", null);
__decorate([
@@ -114,6 +111,7 @@ __decorate([
exports.TelemetryController = TelemetryController = __decorate([
(0, swagger_1.ApiTags)('telemetry'),
(0, common_1.Controller)('telemetry'),
(0, common_1.UseGuards)(api_key_guard_1.ApiKeyGuard),
__metadata("design:paramtypes", [telemetry_service_1.TelemetryService,
telemetry_analyzer_service_1.TelemetryAnalyzerService])
], TelemetryController);
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"telemetry.controller.js","sourceRoot":"","sources":["../../src/telemetry/telemetry.controller.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"telemetry.controller.js","sourceRoot":"","sources":["../../src/telemetry/telemetry.controller.ts"],"names":[],"mappings":"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"}
+2 -1
View File
@@ -63,6 +63,7 @@ __decorate([
__metadata("design:type", Object)
], TelemetryLog.prototype, "location", void 0);
exports.TelemetryLog = TelemetryLog = __decorate([
(0, typeorm_1.Entity)('telemetry_logs')
(0, typeorm_1.Entity)('telemetry_logs'),
(0, typeorm_1.Index)(['driverId', 'timestamp'], { unique: true })
], TelemetryLog);
//# sourceMappingURL=telemetry.entity.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"telemetry.entity.js","sourceRoot":"","sources":["../../src/telemetry/telemetry.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAA0F;AAGnF,IAAM,YAAY,GAAlB,MAAM,YAAY;IAEvB,EAAE,CAAS;IAIX,QAAQ,CAAS;IAGjB,QAAQ,CAAS;IAGjB,SAAS,CAAS;IAGlB,KAAK,CAAS;IAGd,OAAO,CAAS;IAIhB,SAAS,CAAO;IAWhB,QAAQ,CAAM;CACf,CAAA;AAlCY,oCAAY;AAEvB;IADC,IAAA,gCAAsB,GAAE;;wCACd;AAIX;IAFC,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,GAAE;;8CACS;AAGjB;IADC,IAAA,gBAAM,EAAC,SAAS,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;;8CAC9B;AAGjB;IADC,IAAA,gBAAM,EAAC,SAAS,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;;+CAC7B;AAGlB;IADC,IAAA,gBAAM,EAAC,OAAO,CAAC;;2CACF;AAGd;IADC,IAAA,gBAAM,EAAC,OAAO,CAAC;;6CACA;AAIhB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,eAAK,GAAE;8BACG,IAAI;+CAAC;AAWhB;IAPC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,WAAW;QACjB,kBAAkB,EAAE,OAAO;QAC3B,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,IAAI;KACf,CAAC;IACD,IAAA,eAAK,EAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;8CACX;uBAjCH,YAAY;IADxB,IAAA,gBAAM,EAAC,gBAAgB,CAAC;GACZ,YAAY,CAkCxB"}
{"version":3,"file":"telemetry.entity.js","sourceRoot":"","sources":["../../src/telemetry/telemetry.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAA0F;AAInF,IAAM,YAAY,GAAlB,MAAM,YAAY;IAEvB,EAAE,CAAS;IAIX,QAAQ,CAAS;IAGjB,QAAQ,CAAS;IAGjB,SAAS,CAAS;IAGlB,KAAK,CAAS;IAGd,OAAO,CAAS;IAIhB,SAAS,CAAO;IAWhB,QAAQ,CAAM;CACf,CAAA;AAlCY,oCAAY;AAEvB;IADC,IAAA,gCAAsB,GAAE;;wCACd;AAIX;IAFC,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,GAAE;;8CACS;AAGjB;IADC,IAAA,gBAAM,EAAC,SAAS,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;;8CAC9B;AAGjB;IADC,IAAA,gBAAM,EAAC,SAAS,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;;+CAC7B;AAGlB;IADC,IAAA,gBAAM,EAAC,OAAO,CAAC;;2CACF;AAGd;IADC,IAAA,gBAAM,EAAC,OAAO,CAAC;;6CACA;AAIhB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,eAAK,GAAE;8BACG,IAAI;+CAAC;AAWhB;IAPC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,WAAW;QACjB,kBAAkB,EAAE,OAAO;QAC3B,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,IAAI;KACf,CAAC;IACD,IAAA,eAAK,EAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;8CACX;uBAjCH,YAAY;IAFxB,IAAA,gBAAM,EAAC,gBAAgB,CAAC;IACxB,IAAA,eAAK,EAAC,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;GACtC,YAAY,CAkCxB"}
+15 -3
View File
@@ -17,8 +17,9 @@ const map_refinement_controller_1 = require("./map-refinement.controller");
const road_stat_entity_1 = require("../maps/road-stat.entity");
const candidate_road_entity_1 = require("../maps/candidate-road.entity");
const redis_module_1 = require("../common/redis.module");
const redis_service_1 = require("../common/redis.service");
const maps_module_1 = require("../maps/maps.module");
const external_telemetry_service_1 = require("./external-telemetry.service");
const telegram_service_1 = require("../common/telegram.service");
let TelemetryModule = class TelemetryModule {
};
exports.TelemetryModule = TelemetryModule;
@@ -27,10 +28,21 @@ exports.TelemetryModule = TelemetryModule = __decorate([
imports: [
typeorm_1.TypeOrmModule.forFeature([telemetry_entity_1.TelemetryLog, road_stat_entity_1.RoadSegmentStat, candidate_road_entity_1.CandidateRoad]),
redis_module_1.RedisModule,
maps_module_1.MapsModule,
],
controllers: [telemetry_controller_1.TelemetryController, map_refinement_controller_1.MapRefinementController],
providers: [telemetry_service_1.TelemetryService, telemetry_analyzer_service_1.TelemetryAnalyzerService, redis_service_1.RedisService, external_telemetry_service_1.ExternalTelemetryService],
exports: [telemetry_service_1.TelemetryService, telemetry_analyzer_service_1.TelemetryAnalyzerService, redis_service_1.RedisService, external_telemetry_service_1.ExternalTelemetryService],
providers: [
telemetry_service_1.TelemetryService,
telemetry_analyzer_service_1.TelemetryAnalyzerService,
external_telemetry_service_1.ExternalTelemetryService,
telegram_service_1.TelegramService
],
exports: [
telemetry_service_1.TelemetryService,
telemetry_analyzer_service_1.TelemetryAnalyzerService,
external_telemetry_service_1.ExternalTelemetryService,
telegram_service_1.TelegramService
],
})
], TelemetryModule);
//# sourceMappingURL=telemetry.module.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"telemetry.module.js","sourceRoot":"","sources":["../../src/telemetry/telemetry.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,yDAAkD;AAClD,2DAAuD;AACvD,iEAA6D;AAC7D,6EAAwE;AACxE,2EAAsE;AACtE,+DAA2D;AAC3D,yEAA8D;AAC9D,yDAAqD;AACrD,2DAAuD;AAEvD,6EAAwE;AAWjE,IAAM,eAAe,GAArB,MAAM,eAAe;CAAG,CAAA;AAAlB,0CAAe;0BAAf,eAAe;IAT3B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,uBAAa,CAAC,UAAU,CAAC,CAAC,+BAAY,EAAE,kCAAe,EAAE,qCAAa,CAAC,CAAC;YACxE,0BAAW;SACZ;QACD,WAAW,EAAE,CAAC,0CAAmB,EAAE,mDAAuB,CAAC;QAC3D,SAAS,EAAE,CAAC,oCAAgB,EAAE,qDAAwB,EAAE,4BAAY,EAAE,qDAAwB,CAAC;QAC/F,OAAO,EAAE,CAAC,oCAAgB,EAAE,qDAAwB,EAAE,4BAAY,EAAE,qDAAwB,CAAC;KAC9F,CAAC;GACW,eAAe,CAAG"}
{"version":3,"file":"telemetry.module.js","sourceRoot":"","sources":["../../src/telemetry/telemetry.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,yDAAkD;AAClD,2DAAuD;AACvD,iEAA6D;AAC7D,6EAAwE;AACxE,2EAAsE;AACtE,+DAA2D;AAC3D,yEAA8D;AAC9D,yDAAqD;AAErD,qDAAiD;AAEjD,6EAAwE;AACxE,iEAA6D;AAsBtD,IAAM,eAAe,GAArB,MAAM,eAAe;CAAG,CAAA;AAAlB,0CAAe;0BAAf,eAAe;IApB3B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,uBAAa,CAAC,UAAU,CAAC,CAAC,+BAAY,EAAE,kCAAe,EAAE,qCAAa,CAAC,CAAC;YACxE,0BAAW;YACX,wBAAU;SACX;QACD,WAAW,EAAE,CAAC,0CAAmB,EAAE,mDAAuB,CAAC;QAC3D,SAAS,EAAE;YACT,oCAAgB;YAChB,qDAAwB;YACxB,qDAAwB;YACxB,kCAAe;SAChB;QACD,OAAO,EAAE;YACP,oCAAgB;YAChB,qDAAwB;YACxB,qDAAwB;YACxB,kCAAe;SAChB;KACF,CAAC;GACW,eAAe,CAAG"}