diff --git a/src/index.js b/src/index.js index 9596f42..4f60b52 100644 --- a/src/index.js +++ b/src/index.js @@ -228,9 +228,14 @@ ipcMain.on("start:route-generation", (event, routingArgs) => { nodes: {}, dist: {}, cost: {} } - let minNumVehicles = Math.max(routingArgs.numVehicles, Math.floor(routingArgs.stops.length / routingArgs.maxCapacity)); + type_Capacity = typeof routingArgs.maxCapacity; + if (type_Capacity !== 'object') { + routingArgs.maxCapacity = [Number(routingArgs.maxCapacity)]; + } + routingArgs.maxCapacity.sort((a,b)=> b-a); + let minNumVehicles = Math.max(routingArgs.numVehicles, Math.floor(routingArgs.stops.length / routingArgs.maxCapacity[0])); routingArgs.numVehicles = minNumVehicles; - routeOptimizer.optimize(cachedODMatrix, routingArgs) + routeOptimizer.optimize(cachedODMatrix, routingArgs); }) // Evento chamado pelo nosso worker quando ele terminar de gerar a rota diff --git a/src/main/routing/clarke-wright-schoolbus-routing.js b/src/main/routing/clarke-wright-schoolbus-routing.js index b91b917..3658db5 100644 --- a/src/main/routing/clarke-wright-schoolbus-routing.js +++ b/src/main/routing/clarke-wright-schoolbus-routing.js @@ -112,6 +112,7 @@ class ClarkeWrightSchoolBusRouting { // console.log("PASSENGERS", totalPassengers, "MAX CAPACITY", this.maxCapacity) // console.log("TRAV DISTANCE", totalTravDistance, "MAX DIST", this.maxTravDist) // console.log("TRAV TIME", totalTravTime, "MAX TIME", this.maxTravTime) + // console.log("\n") // We can merge! let canMerge = false; diff --git a/src/main/routing/routing-optimization.js b/src/main/routing/routing-optimization.js index fc6c2a9..8592847 100644 --- a/src/main/routing/routing-optimization.js +++ b/src/main/routing/routing-optimization.js @@ -6,6 +6,7 @@ var ClarkeWrightSchoolBusRouting = require("./clarke-wright-schoolbus-routing.js var TwoOpt = require("./twoopt.js"); var SchoolBusKMeans = require("./kmeans.js"); var { Worker, isMainThread, parentPort, workerData } = require('worker_threads'); +const { toNumber } = require("lodash"); class RoutingOptimizationWorker { constructor(cachedODMatrix, routingParams, spatialiteDB) { @@ -13,6 +14,15 @@ class RoutingOptimizationWorker { this.routingParams = routingParams; this.spatialiteDB = spatialiteDB; this.reverseMap = new Map(); + + // IDENTIFICANDO O MODO DE SOLUÇÃO + if (typeof this.routingParams["maxCapacity"] == typeof []) { + this.heterogeneous = true; + console.log("\n *** FROTA HETEROGÊNEA ***\n") + } else { + this.heterogeneous = false; + console.log("\n *** FROTA HOMOGÊNEA ***\n") + } routingParams["stops"].forEach((s) => { let key = Number(s["lat"]).toFixed(10) + "-" + Number(s["lng"]).toFixed(10); @@ -45,6 +55,34 @@ class RoutingOptimizationWorker { return stops; } + SortClustersMaxToMin(clusterizedStops){ + let ClustersSorted = {}; + for (let i = 0; i < clusterizedStops.length; i++) { + let clusterStops = clusterizedStops[i]; + let countPassagers = 0; + for (let z = 0; z < clusterStops.length; z++) { + countPassagers = countPassagers + clusterStops[z].passengers; + } + ClustersSorted[countPassagers] = clusterStops; + } + //console.log("ClustersSorted = ",ClustersSorted); + + let IndexByCluester = Array(); + Object.keys(ClustersSorted).forEach((index)=>{ + IndexByCluester.push(Number(index)); + }); + IndexByCluester.sort((a,b)=> b-a); + //console.log("IndexByCluester = ",IndexByCluester); + + let SortClusters = Array(); + for (let i = 0; i < IndexByCluester.length; i++) { + SortClusters.push(ClustersSorted[IndexByCluester[i]]); + } + + //console.log("SortClusters = ",SortClusters); + return SortClusters; + } + optimize() { return new Promise((resolve, reject) => { // Activate spatial db @@ -57,33 +95,46 @@ class RoutingOptimizationWorker { let busRoutes = new Array(); let kmeans = new SchoolBusKMeans(this.routingParams); let routingGraph; + let IterCapacity = 0; kmeans.partition(this.routingParams["numVehicles"]) .then(clusters => { let clusterizedStops = new Array(); clusters.forEach((c) => clusterizedStops.push(this.getStops(c.cluster))) + // CASO PARTICULAR PARA FROTA HETEROGÊNEA + if (this.heterogeneous == true) { + clusterizedStops = this.SortClustersMaxToMin(clusterizedStops); + } + let clarkAlgorithmsPromise = new Array(); clusterizedStops.forEach((cs) => { let param = Object.assign({}, this.routingParams); param["stops"] = cs; + // CASO PARTICULAR PARA FROTA HETEROGÊNEA + if (this.heterogeneous == true) { + param["maxCapacity"] = this.routingParams["maxCapacity"][IterCapacity]; + IterCapacity++; + } + // Deixar apenas as escolas que atendem os alunos no conjunto - let clusterSchoolsSet = new Set() - cs.forEach(student => clusterSchoolsSet.add(student["school"])) - let clusterSchools = new Array() + let clusterSchoolsSet = new Set(); + cs.forEach(student => clusterSchoolsSet.add(student["school"])); + let clusterSchools = new Array(); this.routingParams.schools.forEach(school => { if (clusterSchoolsSet.has(school["key"])) { clusterSchools.push(school); } - }) + }); param["schools"] = clusterSchools; - + let cwalg = new ClarkeWrightSchoolBusRouting(this.cachedODMatrix, param, this.spatialiteDB); clarkAlgorithmsPromise.push(cwalg.spatialRoute()); routers.push(cwalg); - }) - + + }); + // let schoolBusRouter = new ClarkeWrightSchoolBusRouting(this.routingParams, this.spatialiteDB); // schoolBusRouter.spatialRoute().then((busRoutes) => { return Promise.all(clarkAlgorithmsPromise) @@ -164,7 +215,6 @@ class RoutingOptimizationWorker { }; } - if (isMainThread) { module.exports = class RoutingOptimization { constructor(app, dbPath) { @@ -218,12 +268,12 @@ if (isMainThread) { .then((res) => { console.log("WORKER FINISHED") parentPort.postMessage({ error: false, result: res }) - // process.exit(0) + //process.exit(0) }) .catch((err) => { console.log("WORKER ERROR") parentPort.postMessage({ error: true, result: err }) - // process.exit(1) + //process.exit(1) }) }) diff --git a/src/renderer/img/icones/lancha-marcador2.png b/src/renderer/img/icones/lancha-marcador2.png new file mode 100644 index 0000000..76aac45 Binary files /dev/null and b/src/renderer/img/icones/lancha-marcador2.png differ diff --git a/src/renderer/img/icones/onibus-marcador2.png b/src/renderer/img/icones/onibus-marcador2.png new file mode 100644 index 0000000..2d707fb Binary files /dev/null and b/src/renderer/img/icones/onibus-marcador2.png differ diff --git a/src/renderer/modules/rota/rota-sugestao-ctrl.js b/src/renderer/modules/rota/rota-sugestao-ctrl.js index 6bd45db..cb0d643 100644 --- a/src/renderer/modules/rota/rota-sugestao-ctrl.js +++ b/src/renderer/modules/rota/rota-sugestao-ctrl.js @@ -473,7 +473,6 @@ function transformaEscolaEmArray(mapaEscolas) { return escolasArray; } - function listaElementos() { alunos = transformaAlunosEmArray([...alunoMap]) escolas = transformaEscolaEmArray([...escolaMap]) @@ -938,16 +937,17 @@ function initSimulation() { loadingFn("Simulando...") // Juntar dados em um objeto + // Prof. deixei assim para facilitar sua correção os códigos original estão ao lado. let routeGenerationInputData = { - "maxTravDist": Number($("#maxDist").val()) * 1000, - "maxTravTime": Number($("#maxTime").val()) * 60, + "maxTravDist": 999999999,//Number($("#maxDist").val()) * 1000, + "maxTravTime": 999999999,//Number($("#maxTime").val()) * 60, "optTarget": "maxTravDist", - "numVehicles": Number($("#numVehicles").val()), - "maxCapacity": Number($("#maxCapacity").val()), + "numVehicles": 1,//Number($("#numVehicles").val()), + "maxCapacity": [4,1,1],//Number($("#maxCapacity").val()), "busSpeed": Number($("#velMedia").val()) / 3.6, // converte de km/h para m/s "garage": garagens, "stops": alunos, - "schools": escolas, + "schools": escolas }; ipcRenderer.send('start:route-generation', routeGenerationInputData);