2026-04-13-2

This commit is contained in:
Hamza-Ayed
2026-04-13 02:34:23 +03:00
parent 3b43ff983a
commit 018fc72d9d
3 changed files with 151 additions and 44 deletions
+22 -40
View File
@@ -4,6 +4,8 @@ import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import { RoadSpeedProfile } from './road-speed-profile.entity';
import axios from 'axios';
import { RoadSegmentStat } from './road-stat.entity';
import { TrafficGridService } from './traffic-grid.service';
@Injectable()
export class MapsService {
@@ -11,9 +13,9 @@ export class MapsService {
constructor(
private configService: ConfigService,
@InjectRepository(RoadSpeedProfile)
private speedProfileRepo: Repository<RoadSpeedProfile>,
private dataSource: DataSource
@InjectRepository(RoadSegmentStat)
private roadStatRepo: Repository<RoadSegmentStat>,
private trafficGrid: TrafficGridService
) {
this.graphHopperUrl = this.configService.get('GRAPH_HOPPER_URL', 'http://routing:8080');
}
@@ -33,13 +35,17 @@ export class MapsService {
locale: 'en',
calc_points: true,
points_encoded: true,
algorithm: 'alternative_route',
'ch.disable': true, // Required for alternative routes
'alternative_route.max_paths': 2, // Return main route + 1 alternative
'alternative_route.max_weight_factor': 1.6,
'alternative_route.max_share_factor': 0.6
};
// GraphHopper ONLY supports alternative routes if there are exactly 2 points (Start and End)
if (waypoints.length === 2) {
payload.algorithm = 'alternative_route';
payload['ch.disable'] = true; // Required for alternative routes
payload['alternative_route.max_paths'] = 2; // Return main route + 1 alternative
payload['alternative_route.max_weight_factor'] = 1.6;
payload['alternative_route.max_share_factor'] = 0.6;
}
console.log(`Routing Request: ${waypoints.length} points via ${profile} on ${this.graphHopperUrl}`);
const response = await axios.post(`${this.graphHopperUrl}/route`, payload, { timeout: 10000 });
@@ -49,40 +55,16 @@ export class MapsService {
const route = paths[0];
// --- PHASE 3: TRAFFIC-AWARE ADJUSTMENT ---
let baseDuration = route.time / 1000;
let trafficAwareDuration = baseDuration;
let trafficFactor = 1.0;
// --- PHASE 3: TRAFFIC-AWARE ADJUSTMENT (V3 Optimized) ---
const now = new Date();
const hr = now.getHours();
const dow = now.getDay();
try {
const now = new Date();
const hr = now.getHours();
const dow = now.getDay();
const coords = this.decodePolyline(route.points);
const trafficFactor = this.trafficGrid.getTrafficFactor(coords, hr, dow);
// Decode polyline for spatial mapping (server-side only)
const coords = this.decodePolyline(route.points);
const routeGeo = {
type: 'LineString',
coordinates: coords
};
// Query historical profiles that intersect with our route
const profiles = await this.dataSource.query(`
SELECT AVG(p."averageSpeed") as profile_speed, AVG(s."averageSpeed") as base_speed
FROM road_speed_profiles p
JOIN road_segment_stats s ON p."segmentId" = s."segmentId"
WHERE p."hourOfDay" = $1 AND p."dayOfWeek" = $2
AND ST_DWithin(s.geometry, ST_GeomFromGeoJSON($3), 0.0002)
`, [hr, dow, JSON.stringify(routeGeo)]);
if (profiles[0] && profiles[0].profile_speed && profiles[0].base_speed) {
trafficFactor = profiles[0].base_speed / Math.max(profiles[0].profile_speed, 1);
trafficFactor = Math.min(Math.max(trafficFactor, 0.8), 3.0);
trafficAwareDuration = baseDuration * trafficFactor;
}
} catch (e) {
console.warn('Traffic adjustment failed, using calibrated base:', e.message);
}
const baseDuration = route.time / 1000;
const trafficAwareDuration = baseDuration * trafficFactor;
// Process alternative routes if any without breaking existing frontend variables
const alternatives = paths.slice(1).map(alt => ({