UNPKG

carthorse

Version:

A geospatial trail data processing pipeline for building 3D trail databases with elevation data

157 lines 7.81 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RouteGenerationOrchestratorService = void 0; const ksp_route_generator_service_1 = require("./ksp-route-generator-service"); const loop_route_generator_service_1 = require("./loop-route-generator-service"); const route_discovery_config_loader_1 = require("../../config/route-discovery-config-loader"); class RouteGenerationOrchestratorService { constructor(pgClient, config) { this.pgClient = pgClient; this.config = config; this.kspService = null; this.loopService = null; this.configLoader = route_discovery_config_loader_1.RouteDiscoveryConfigLoader.getInstance(); // Load trailhead configuration from YAML const routeDiscoveryConfig = this.configLoader.loadConfig(); const trailheadConfig = routeDiscoveryConfig.trailheads; console.log(`🔍 DEBUG: RouteGenerationOrchestratorService config:`, { useTrailheadsOnly: this.config.useTrailheadsOnly, trailheadLocations: this.config.trailheadLocations?.length || 0, configEnabled: trailheadConfig.enabled, configStrategy: trailheadConfig.selectionStrategy, configLocations: trailheadConfig.locations?.length || 0 }); if (this.config.generateKspRoutes) { this.kspService = new ksp_route_generator_service_1.KspRouteGeneratorService(this.pgClient, { stagingSchema: this.config.stagingSchema, region: this.config.region, targetRoutesPerPattern: this.config.targetRoutesPerPattern, minDistanceBetweenRoutes: this.config.minDistanceBetweenRoutes, kspKValue: this.config.kspKValue, useTrailheadsOnly: this.config.useTrailheadsOnly !== undefined ? this.config.useTrailheadsOnly : trailheadConfig.enabled, // CLI override takes precedence over YAML config trailheadLocations: this.config.trailheadLocations || trailheadConfig.locations }); } if (this.config.generateLoopRoutes) { this.loopService = new loop_route_generator_service_1.LoopRouteGeneratorService(this.pgClient, { stagingSchema: this.config.stagingSchema, region: this.config.region, targetRoutesPerPattern: this.config.loopConfig?.targetRoutesPerPattern || 3, minDistanceBetweenRoutes: this.config.minDistanceBetweenRoutes, }); } } /** * Generate all route types (KSP and Loop) */ async generateAllRoutes() { console.log('🎯 Generating all route types...'); const kspRoutes = []; const loopRoutes = []; // Generate KSP routes if (this.config.generateKspRoutes && this.kspService) { console.log('🛤️ Generating KSP routes...'); const kspRecommendations = await this.kspService.generateKspRoutes(); await this.kspService.storeRouteRecommendations(kspRecommendations); kspRoutes.push(...kspRecommendations); console.log(`✅ Generated ${kspRecommendations.length} KSP routes`); } // Generate Loop routes if (this.config.generateLoopRoutes && this.loopService) { console.log('🔄 Generating loop routes...'); console.log(`🔍 DEBUG: Loop service config:`, { generateLoopRoutes: this.config.generateLoopRoutes, useHawickCircuits: this.config.loopConfig?.useHawickCircuits, targetRoutesPerPattern: this.config.loopConfig?.targetRoutesPerPattern }); const loopRecommendations = await this.loopService.generateLoopRoutes(); await this.loopService.storeLoopRouteRecommendations(loopRecommendations); loopRoutes.push(...loopRecommendations); console.log(`✅ Generated ${loopRecommendations.length} loop routes`); } else { console.log(`🔍 DEBUG: Loop generation skipped - generateLoopRoutes: ${this.config.generateLoopRoutes}, loopService: ${!!this.loopService}`); } // Post-generation deduplication: keep the longest route for any given routing edge per route shape/type const dedupeByEdgePerType = (routes) => { // Sort descending by recommended_length_km so we keep longest first const sorted = [...routes].sort((a, b) => (b.recommended_length_km || 0) - (a.recommended_length_km || 0)); const kept = []; // Map<route_type_or_shape, Set<edge_id>> to track used edges const usedEdgesByType = new Map(); for (const route of sorted) { const typeKey = route.route_shape || route.route_type || 'unknown'; if (!usedEdgesByType.has(typeKey)) { usedEdgesByType.set(typeKey, new Set()); } const usedSet = usedEdgesByType.get(typeKey); const edges = Array.isArray(route.route_edges) ? route.route_edges : []; // If any edge already used for this typeKey, skip this route const edgeIds = edges.map((e) => e.id).filter((id) => typeof id === 'number'); const hasConflict = edgeIds.some((id) => usedSet.has(id)); if (hasConflict) { continue; } // Keep and mark edges as used kept.push(route); edgeIds.forEach((id) => usedSet.add(id)); } return kept; }; const kspRoutesDeduped = dedupeByEdgePerType(kspRoutes); const loopRoutesDeduped = dedupeByEdgePerType(loopRoutes); const totalRoutes = kspRoutesDeduped.length + loopRoutesDeduped.length; console.log(`🎯 Total routes after dedupe: ${totalRoutes} (${kspRoutesDeduped.length} KSP, ${loopRoutesDeduped.length} loops)`); return { kspRoutes: kspRoutesDeduped, loopRoutes: loopRoutesDeduped, totalRoutes }; } /** * Generate only KSP routes */ async generateKspRoutes() { if (!this.kspService) { throw new Error('KSP route generation is not enabled'); } console.log('🛤️ Generating KSP routes...'); const recommendations = await this.kspService.generateKspRoutes(); await this.kspService.storeRouteRecommendations(recommendations); console.log(`✅ Generated ${recommendations.length} KSP routes`); return recommendations; } /** * Generate only loop routes */ async generateLoopRoutes() { if (!this.loopService) { throw new Error('Loop route generation is not enabled'); } console.log('🔄 Generating loop routes...'); const recommendations = await this.loopService.generateLoopRoutes(); await this.loopService.storeLoopRouteRecommendations(recommendations); console.log(`✅ Generated ${recommendations.length} loop routes`); return recommendations; } /** * Get route generation statistics */ async getRouteGenerationStats() { const stats = { kspEnabled: this.config.generateKspRoutes, loopEnabled: this.config.generateLoopRoutes, totalRoutesGenerated: 0, routeTypes: [] }; if (this.config.generateKspRoutes) { stats.routeTypes.push('KSP'); } if (this.config.generateLoopRoutes) { stats.routeTypes.push('Loop'); } return stats; } } exports.RouteGenerationOrchestratorService = RouteGenerationOrchestratorService; //# sourceMappingURL=route-generation-orchestrator-service.js.map