diff --git a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java index 42c95fb70ad..3037716368c 100644 --- a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java +++ b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java @@ -27,6 +27,9 @@ import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.events.Event; import org.matsim.api.core.v01.events.LinkEnterEvent; +import org.matsim.api.core.v01.events.LinkLeaveEvent; +import org.matsim.api.core.v01.events.VehicleEntersTrafficEvent; +import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.Tour; @@ -55,15 +58,21 @@ public class FreightTimeAndDistanceAnalysisEventsHandler implements BasicEventHa private final Map, Double> vehicleId2TourDuration = new LinkedHashMap<>(); private final Map, Double> vehicleId2TourLength = new LinkedHashMap<>(); + private final Map, Double> vehicleId2TravelTime = new LinkedHashMap<>(); + private final Map, Id> vehicleId2CarrierId = new LinkedHashMap<>(); private final Map, Id> vehicleId2TourId = new LinkedHashMap<>(); - private final Map, Double> vehicleTypeId2SumOfDuration = new LinkedHashMap<>(); + private final Map, Double> vehicleTypeId2SumOfTourDuration = new LinkedHashMap<>(); private final Map, Double> vehicleTypeId2Mileage = new LinkedHashMap<>(); + private final Map, Double> vehicleTypeId2TravelTime = new LinkedHashMap<>(); + private final Map, VehicleType> vehicleId2VehicleType = new TreeMap<>(); private final Map tourStartTime = new LinkedHashMap<>(); + private final Map, Double> vehicleEnteredLinkTime = new LinkedHashMap<>(); + public FreightTimeAndDistanceAnalysisEventsHandler(Scenario scenario) { this.scenario = scenario; @@ -81,7 +90,7 @@ private void handleEvent(CarrierTourEndEvent event) { double tourDuration = event.getTime() - tourStartTime.get(key); vehicleId2TourDuration.put(event.getVehicleId(), tourDuration); VehicleType vehType = VehicleUtils.findVehicle(event.getVehicleId(), scenario).getType(); - vehicleTypeId2SumOfDuration.merge(vehType.getId(), tourDuration, Double::sum); + vehicleTypeId2SumOfTourDuration.merge(vehType.getId(), tourDuration, Double::sum); //Some general information for this vehicle vehicleId2CarrierId.putIfAbsent(event.getVehicleId(), event.getCarrierId()); @@ -93,23 +102,61 @@ private void handleEvent(CarrierTourEndEvent event) { private void handleEvent(LinkEnterEvent event) { final double distance = scenario.getNetwork().getLinks().get(event.getLinkId()).getLength(); vehicleId2TourLength.merge(event.getVehicleId(), distance, Double::sum); + vehicleEnteredLinkTime.put(event.getVehicleId(), event.getTime()); //Safe time when entering the link. final Id vehTypeId = VehicleUtils.findVehicle(event.getVehicleId(), scenario).getType().getId(); vehicleTypeId2Mileage.merge(vehTypeId, distance, Double::sum); } - @Override public void handleEvent(Event event) { + //If the vehicle leaves a link at the end, the travelTime is calculated and stored. + private void handleEvent(LinkLeaveEvent event){ + final Id vehicleId = event.getVehicleId(); + if (vehicleEnteredLinkTime.containsKey(vehicleId)){ + double tt = event.getTime() - vehicleEnteredLinkTime.get(vehicleId); + vehicleId2TravelTime.merge(vehicleId, tt, Double::sum); //per vehicle + + final Id vehTypeId = VehicleUtils.findVehicle(event.getVehicleId(), scenario).getType().getId(); + vehicleTypeId2TravelTime.merge(vehTypeId, tt, Double::sum); // per VehType + + vehicleEnteredLinkTime.remove(vehicleId); //remove from that list. + } + } + + //If the vehicle leaves a link because it reached its destination, the travelTime is calculated and stored. + private void handleEvent(VehicleLeavesTrafficEvent event){ + final Id vehicleId = event.getVehicleId(); + if (vehicleEnteredLinkTime.containsKey(vehicleId)){ + double tt = event.getTime() - vehicleEnteredLinkTime.get(vehicleId); + vehicleId2TravelTime.merge(vehicleId, tt, Double::sum);//per vehicle + + final Id vehTypeId = VehicleUtils.findVehicle(event.getVehicleId(), scenario).getType().getId(); + vehicleTypeId2TravelTime.merge(vehTypeId, tt, Double::sum); // per VehType + + vehicleEnteredLinkTime.remove(vehicleId); //remove from that list. + } + } + + private void handleEvent(VehicleEntersTrafficEvent event){ + vehicleEnteredLinkTime.put(event.getVehicleId(), event.getTime()); + } + @Override public void handleEvent(Event event) { if (event instanceof CarrierTourStartEvent carrierTourStartEvent) { handleEvent(carrierTourStartEvent); } else if (event instanceof CarrierTourEndEvent carrierTourEndEvent) { handleEvent(carrierTourEndEvent); } else if (event instanceof LinkEnterEvent linkEnterEvent) { handleEvent(linkEnterEvent); + } else if (event instanceof LinkLeaveEvent linkLeaveEvent) { + handleEvent(linkLeaveEvent); + } else if (event instanceof VehicleLeavesTrafficEvent vehicleLeavesTrafficEvent) { + handleEvent(vehicleLeavesTrafficEvent); + } else if (event instanceof VehicleEntersTrafficEvent vehicleEntersTrafficEvent) { + handleEvent(vehicleEntersTrafficEvent); } } - void writeTravelTimeAndDistance(String analysisOutputDirectory, Scenario scenario) throws IOException { + void writeTravelTimeAndDistancePerVehicle(String analysisOutputDirectory, Scenario scenario) throws IOException { log.info("Writing out Time & Distance & Costs ... perVehicle"); //Travel time and distance per vehicle String fileName = analysisOutputDirectory + "TimeDistance_perVehicle.tsv"; @@ -117,14 +164,19 @@ void writeTravelTimeAndDistance(String analysisOutputDirectory, Scenario scenari BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileName)); //Write headline: - bw1.write("vehicleId \t carrierId \t vehicleTypeId \t tourId \t tourDuration[s] \t travelDistance[m] \t " + - "costPerSecond[EUR/s] \t costPerMeter[EUR/m] \t fixedCosts[EUR] \t varCostsTime[EUR] \t varCostsDist[EUR] \t totalCosts[EUR]"); + bw1.write("vehicleId \t carrierId \t vehicleTypeId \t tourId \t " + + "tourDuration[s] \t tourDuration[h] \t" + + "travelDistance[m] \t travelDistance[km] \t " + + "travelTime[s] \t travelTime[h] \t" + + "costPerSecond[EUR/s] \t costPerMeter[EUR/m] \t fixedCosts[EUR] \t varCostsTime[EUR] \t varCostsDist[EUR] \t totalCosts[EUR]"); bw1.newLine(); for (Id vehicleId : vehicleId2VehicleType.keySet()) { final Double durationInSeconds = vehicleId2TourDuration.get(vehicleId); final Double distanceInMeters = vehicleId2TourLength.get(vehicleId); + final Double travelTimeInSeconds = vehicleId2TravelTime.get(vehicleId); + final VehicleType vehicleType = VehicleUtils.findVehicle(vehicleId, scenario).getType(); final Double costsPerSecond = vehicleType.getCostInformation().getCostsPerSecond(); @@ -141,7 +193,14 @@ void writeTravelTimeAndDistance(String analysisOutputDirectory, Scenario scenari bw1.write("\t" + vehicleId2TourId.get(vehicleId)); bw1.write("\t" + durationInSeconds); + bw1.write("\t" + durationInSeconds /3600); + bw1.write("\t" + distanceInMeters); + bw1.write("\t" + distanceInMeters/1000); + + bw1.write("\t" + travelTimeInSeconds); + bw1.write("\t" + travelTimeInSeconds /3600); + bw1.write("\t" + costsPerSecond); bw1.write("\t" + costsPerMeter); bw1.write("\t" + fixedCost); @@ -161,7 +220,6 @@ void writeTravelTimeAndDistancePerVehicleType(String analysisOutputDirectory, Sc log.info("Writing out Time & Distance & Costs ... perVehicleType"); //----- All VehicleTypes in CarriervehicleTypes container. Used so that even unused vehTypes appear in the output - TreeMap, VehicleType> vehicleTypesMap = new TreeMap<>(CarriersUtils.getCarrierVehicleTypes(scenario).getVehicleTypes()); //For the case that there are additional vehicle types found in the events. for (VehicleType vehicleType : vehicleId2VehicleType.values()) { @@ -171,34 +229,39 @@ void writeTravelTimeAndDistancePerVehicleType(String analysisOutputDirectory, Sc String fileName = analysisOutputDirectory + "TimeDistance_perVehicleType.tsv"; BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileName)); - //Write headline: - bw1.write("vehicleTypeId \t nuOfVehicles \t SumOfTourDuration[s] \t SumOfTravelDistances[m] \t " + + bw1.write("vehicleTypeId \t nuOfVehicles \t " + + "SumOfTourDuration[s] \t SumOfTourDuration[h] \t" + + "SumOfTravelDistances[m] \t SumOfTravelDistances[km] \t " + + "SumOfTravelTime[s] \t SumOfTravelTime[h] \t" + "costPerSecond[EUR/s] \t costPerMeter[EUR/m] \t fixedCosts[EUR/veh] \t" + "varCostsTime[EUR] \t varCostsDist[EUR] \t fixedCosts[EUR] \t totalCosts[EUR]"); bw1.newLine(); - for (VehicleType vehicleType : vehicleTypesMap.values()) { - long nuOfVehicles = vehicleId2VehicleType.values().stream().filter(vehType -> vehType.getId() == vehicleType.getId()).count(); final Double costRatePerSecond = vehicleType.getCostInformation().getCostsPerSecond(); final Double costRatePerMeter = vehicleType.getCostInformation().getCostsPerMeter(); final Double fixedCostPerVeh = vehicleType.getCostInformation().getFixedCosts(); - final Double sumOfDurationInSeconds = vehicleTypeId2SumOfDuration.getOrDefault(vehicleType.getId(), 0.); + final Double sumOfTourDurationInSeconds = vehicleTypeId2SumOfTourDuration.getOrDefault(vehicleType.getId(), 0.); final Double sumOfDistanceInMeters = vehicleTypeId2Mileage.getOrDefault(vehicleType.getId(), 0.); + final Double sumOfTravelTimeInSeconds = vehicleTypeId2TravelTime.getOrDefault(vehicleType.getId(), 0.); - final double sumOfVarCostsTime = sumOfDurationInSeconds * costRatePerSecond; + final double sumOfVarCostsTime = sumOfTourDurationInSeconds * costRatePerSecond; final double sumOfVarCostsDistance = sumOfDistanceInMeters * costRatePerMeter; final double sumOfFixCosts = nuOfVehicles * fixedCostPerVeh; bw1.write(vehicleType.getId().toString()); bw1.write("\t" + nuOfVehicles); - bw1.write("\t" + sumOfDurationInSeconds); + bw1.write("\t" + sumOfTourDurationInSeconds); + bw1.write("\t" + sumOfTourDurationInSeconds / 3600); bw1.write("\t" + sumOfDistanceInMeters); + bw1.write("\t" + sumOfDistanceInMeters / 1000); + bw1.write("\t" + sumOfTravelTimeInSeconds); + bw1.write("\t" + sumOfTravelTimeInSeconds / 3600); bw1.write("\t" + costRatePerSecond); bw1.write("\t" + costRatePerMeter); bw1.write("\t" + fixedCostPerVeh); diff --git a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java index 86249801bd0..44374d18dd7 100644 --- a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java +++ b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java @@ -120,7 +120,7 @@ public void runAnalysis() throws IOException { log.info("Analysis completed."); log.info("Writing output..."); - freightTimeAndDistanceAnalysisEventsHandler.writeTravelTimeAndDistance(analysisOutputDirectory, scenario); + freightTimeAndDistanceAnalysisEventsHandler.writeTravelTimeAndDistancePerVehicle(analysisOutputDirectory, scenario); freightTimeAndDistanceAnalysisEventsHandler.writeTravelTimeAndDistancePerVehicleType(analysisOutputDirectory, scenario); carrierLoadAnalysis.writeLoadPerVehicle(analysisOutputDirectory, scenario); } diff --git a/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicle.tsv b/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicle.tsv index a3716b50cdc..d39ab8f1eb1 100644 --- a/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicle.tsv +++ b/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicle.tsv @@ -1 +1 @@ -vehicleId carrierId vehicleTypeId tourId tourDuration[s] travelDistance[m] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR] varCostsTime[EUR] varCostsDist[EUR] totalCosts[EUR] +vehicleId carrierId vehicleTypeId tourId tourDuration[s] tourDuration[h] travelDistance[m] travelDistance[km] travelTime[s] travelTime[h] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR] varCostsTime[EUR] varCostsDist[EUR] totalCosts[EUR] diff --git a/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicleType.tsv b/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicleType.tsv index dacd1779828..2125ae69db1 100644 --- a/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicleType.tsv +++ b/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/TimeDistance_perVehicleType.tsv @@ -1,2 +1,2 @@ -vehicleTypeId nuOfVehicles SumOfTourDuration[s] SumOfTravelDistances[m] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR/veh] varCostsTime[EUR] varCostsDist[EUR] fixedCosts[EUR] totalCosts[EUR] -light 0 0.0 60000.0 0.008 4.7E-4 84.0 0.0 28.2 0.0 28.2 +vehicleTypeId nuOfVehicles SumOfTourDuration[s] SumOfTourDuration[h] SumOfTravelDistances[m] SumOfTravelDistances[km] SumOfTravelTime[s] SumOfTravelTime[h] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR/veh] varCostsTime[EUR] varCostsDist[EUR] fixedCosts[EUR] totalCosts[EUR] +light 0 0.0 0.0 60000.0 60.0 8040.0 2.2333333333333334 0.008 4.7E-4 84.0 0.0 28.2 0.0 28.2