diff --git a/contribs/emissions/src/main/java/org/matsim/contrib/emissions/events/EmissionEvent.java b/contribs/emissions/src/main/java/org/matsim/contrib/emissions/events/EmissionEvent.java index ae7c9c59e2a..180e79ca9fc 100644 --- a/contribs/emissions/src/main/java/org/matsim/contrib/emissions/events/EmissionEvent.java +++ b/contribs/emissions/src/main/java/org/matsim/contrib/emissions/events/EmissionEvent.java @@ -25,6 +25,7 @@ import org.matsim.api.core.v01.events.Event; import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.emissions.Pollutant; +import org.matsim.core.utils.io.XmlUtils; import org.matsim.vehicles.Vehicle; import java.util.Map; @@ -67,4 +68,20 @@ public Map getAttributes() { } return attributes; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes common attributes + writeXMLStart(out); + + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_LINK_ID, this.linkId.toString()); + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_VEHICLE_ID, this.vehicleId.toString()); + + for (Map.Entry entry : emissions.entrySet()) { + out.append(entry.getKey().name()).append("=\""); + out.append((double) entry.getValue()).append("\" "); + } + + writeXMLEnd(out); + } } diff --git a/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java b/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java index a3059795499..1f0ccd3eaf5 100644 --- a/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java +++ b/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java @@ -201,7 +201,7 @@ public void handleEvent(Event event) { } private VehicleType createVehicleType() { - VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("dieselCarFullSpecified", VehicleType.class)); + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("dieselCarFullSpecified", VehicleType.class), TransportMode.car); EngineInformation engineInformation = vehicleType.getEngineInformation(); VehicleUtils.setHbefaVehicleCategory(engineInformation, "PASSENGER_CAR"); VehicleUtils.setHbefaTechnology(engineInformation, "diesel"); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java index 61718d49850..92e2bacc590 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java @@ -24,6 +24,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; import org.matsim.core.gbl.Gbl; import org.matsim.core.utils.io.MatsimXmlParser; import org.matsim.vehicles.CostInformation; @@ -54,6 +55,9 @@ public void startTag( String name, Attributes attributes, Stack context if(name.equals("vehicleType")){ Id currentTypeId = Id.create( attributes.getValue( "id" ), VehicleType.class ); this.currentType = VehicleUtils.getFactory().createVehicleType( currentTypeId ) ; + // If no network mode is given, assume car, this is to be backwards compatible + // The v2 format will not make this assumption, and the network mode will be required + this.currentType.setNetworkMode(TransportMode.car); } if(name.equals("allowableWeight")){ // String weight = atts.getValue("weight"); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeTest.java index 24328872de2..a95fac8d1ec 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeTest.java @@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; import org.matsim.freight.carriers.CarrierVehicleTypes; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.*; @@ -53,6 +54,7 @@ public void setUp() { VehicleCapacity vehicleCapacity = mediumType.getCapacity(); vehicleCapacity.setWeightInTons( 30 ); mediumType.setDescription( "Medium Vehicle" ).setMaximumVelocity( 13.89 ); + mediumType.setNetworkMode(TransportMode.truck); types = new CarrierVehicleTypes(); types.getVehicleTypes().put( mediumType.getId(), mediumType ); } @@ -77,6 +79,7 @@ public void setUp() { capacity.setWeightInTons( 16 ) ; // VehicleType smallType = CarriersUtils.CarrierVehicleTypeBuilder.newInstance( smallTypeId, mediumType ) smallType.setDescription( "Small Vehicle" ).setMaximumVelocity( 10.0 ) ; + smallType.setNetworkMode(TransportMode.car); types.getVehicleTypes().put( smallType.getId(), smallType); } } diff --git a/contribs/minibus/src/main/java/org/matsim/contrib/minibus/hook/PVehiclesFactory.java b/contribs/minibus/src/main/java/org/matsim/contrib/minibus/hook/PVehiclesFactory.java index cca689ac56c..7069b4c3b0a 100644 --- a/contribs/minibus/src/main/java/org/matsim/contrib/minibus/hook/PVehiclesFactory.java +++ b/contribs/minibus/src/main/java/org/matsim/contrib/minibus/hook/PVehiclesFactory.java @@ -22,6 +22,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; import org.matsim.contrib.minibus.PConfigGroup; import org.matsim.pt.transitSchedule.api.Departure; import org.matsim.pt.transitSchedule.api.TransitLine; @@ -31,15 +32,15 @@ /** * Generates vehicles for a whole transit schedule - * + * * @author aneumann * */ class PVehiclesFactory { - + @SuppressWarnings("unused") private final static Logger log = LogManager.getLogger(PVehiclesFactory.class); - + private final PConfigGroup pConfig; public PVehiclesFactory(PConfigGroup pConfig) { @@ -48,11 +49,11 @@ public PVehiclesFactory(PConfigGroup pConfig) { /** * Create vehicles for each departure of the given transit schedule. - * + * * @return Vehicles used by paratranit lines */ - public Vehicles createVehicles(TransitSchedule pTransitSchedule){ - Vehicles vehicles = VehicleUtils.createVehiclesContainer(); + public Vehicles createVehicles(TransitSchedule pTransitSchedule){ + Vehicles vehicles = VehicleUtils.createVehiclesContainer(); VehiclesFactory vehFactory = vehicles.getFactory(); VehicleType vehType = vehFactory.createVehicleType(Id.create(this.pConfig.getPIdentifier(), VehicleType.class)); // VehicleCapacity capacity = new VehicleCapacity(); @@ -61,11 +62,12 @@ public Vehicles createVehicles(TransitSchedule pTransitSchedule){ // vehType.setCapacity(capacity); vehType.setPcuEquivalents(this.pConfig.getPassengerCarEquivalents()); vehType.setMaximumVelocity(this.pConfig.getVehicleMaximumVelocity()); + vehType.setNetworkMode(TransportMode.car); VehicleUtils.setAccessTime(vehType, this.pConfig.getDelayPerBoardingPassenger()); VehicleUtils.setEgressTime(vehType, this.pConfig.getDelayPerAlightingPassenger()); VehicleUtils.setDoorOperationMode(vehType, this.pConfig.getDoorOperationMode()) ; vehicles.addVehicleType( vehType); - + for (TransitLine line : pTransitSchedule.getTransitLines().values()) { for (TransitRoute route : line.getRoutes().values()) { for (Departure departure : route.getDepartures().values()) { @@ -76,7 +78,7 @@ public Vehicles createVehicles(TransitSchedule pTransitSchedule){ } } } - + return vehicles; } } diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/DefaultDashboardProvider.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/DefaultDashboardProvider.java index a01674f4856..5cb80fec839 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/DefaultDashboardProvider.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/DefaultDashboardProvider.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * Default dashboards suited for every run. @@ -19,7 +20,7 @@ public List getDashboards(Config config, SimWrapper simWrapper) { List result = new ArrayList<>(List.of( new OverviewDashboard(), new TripDashboard(), - new TrafficDashboard() + new TrafficDashboard(Set.copyOf(config.qsim().getMainModes())) )); if (config.transit().isUseTransit()) { diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/DefaultUnhandledServicesSolution.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/DefaultUnhandledServicesSolution.java index 4928ce2a401..735a2d8f44a 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/DefaultUnhandledServicesSolution.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/DefaultUnhandledServicesSolution.java @@ -34,61 +34,12 @@ public List createListOfCarrierWithUnhandledJobs(Scenario scenario){ return carriersWithUnhandledJobs; } - public int getServiceTimePerStop(Carrier carrier, GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes, int additionalTravelBufferPerIterationInMinutes) { - GenerateSmallScaleCommercialTrafficDemand.ServiceDurationPerCategoryKey key = null; - if (carrierAttributes.smallScaleCommercialTrafficType().equals( - GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) - key = GenerateSmallScaleCommercialTrafficDemand.makeServiceDurationPerCategoryKey(carrierAttributes.selectedStartCategory(), null, carrierAttributes.smallScaleCommercialTrafficType()); - else if (carrierAttributes.smallScaleCommercialTrafficType().equals( - GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - key = GenerateSmallScaleCommercialTrafficDemand.makeServiceDurationPerCategoryKey(carrierAttributes.selectedStartCategory(), carrierAttributes.modeORvehType(), carrierAttributes.smallScaleCommercialTrafficType()); - } - - //possible new Version by Ricardo - double maxVehicleAvailability = carrier.getCarrierCapabilities().getCarrierVehicles().values().stream().mapToDouble(vehicle -> vehicle.getLatestEndTime() - vehicle.getEarliestStartTime()).max().orElse(0); - int usedTravelTimeBuffer = additionalTravelBufferPerIterationInMinutes * 60; // buffer for the driving time; for unsolved carriers the buffer will be increased over time - for (int j = 0; j < 200; j++) { - GenerateSmallScaleCommercialTrafficDemand.DurationsBounds serviceDurationBounds = generator.getServiceDurationTimeSelector().get(key).sample(); - - for (int i = 0; i < 10; i++) { - int serviceDurationLowerBound = serviceDurationBounds.minDuration(); - int serviceDurationUpperBound = serviceDurationBounds.maxDuration(); - int possibleValue = rnd.nextInt(serviceDurationLowerBound * 60, serviceDurationUpperBound * 60); - // checks if the service duration will not exceed the vehicle availability including the buffer - if (possibleValue + usedTravelTimeBuffer <= maxVehicleAvailability) - return possibleValue; - } - if (j > 100){ - CarrierVehicle carrierVehicleToChange = carrier.getCarrierCapabilities().getCarrierVehicles().values().stream().sorted(Comparator.comparingDouble(vehicle -> vehicle.getLatestEndTime() - vehicle.getEarliestStartTime())).toList().getFirst(); - log.info("Changing vehicle availability for carrier {}. Old maxVehicleAvailability: {}", carrier.getId(), maxVehicleAvailability); - int tourDuration = 0; - int vehicleStartTime = 0; - int vehicleEndTime = 0; - while (tourDuration < maxVehicleAvailability) { - GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration t = generator.getTourDistribution().get(carrierAttributes.smallScaleCommercialTrafficType()).sample(); - vehicleStartTime = t.getVehicleStartTime(); - tourDuration = t.getVehicleTourDuration(); - vehicleEndTime = vehicleStartTime + tourDuration; - } - CarrierVehicle newCarrierVehicle = CarrierVehicle.Builder.newInstance(carrierVehicleToChange.getId(), carrierVehicleToChange.getLinkId(), - carrierVehicleToChange.getType()).setEarliestStart(vehicleStartTime).setLatestEnd(vehicleEndTime).build(); - carrier.getCarrierCapabilities().getCarrierVehicles().remove(carrierVehicleToChange.getId()); - carrier.getCarrierCapabilities().getCarrierVehicles().put(newCarrierVehicle.getId(), newCarrierVehicle); - maxVehicleAvailability = carrier.getCarrierCapabilities().getCarrierVehicles().values().stream().mapToDouble(vehicle -> vehicle.getLatestEndTime() - vehicle.getEarliestStartTime()).max().orElse(0); - log.info("New maxVehicleAvailability: {}", maxVehicleAvailability); - } - } - - throw new RuntimeException("No possible service duration found for employee category '" + carrierAttributes.selectedStartCategory() + "' and mode '" - + carrierAttributes.modeORvehType() + "' in traffic type '" + carrierAttributes.smallScaleCommercialTrafficType() + "'"); - } - /** * Redraws the service-durations of all {@link CarrierService}s of the given {@link Carrier}. */ private void redrawAllServiceDurations(Carrier carrier, GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes, int additionalTravelBufferPerIterationInMinutes) { for (CarrierService service : carrier.getServices().values()) { - double newServiceDuration = getServiceTimePerStop(carrier, carrierAttributes, additionalTravelBufferPerIterationInMinutes); + double newServiceDuration = generator.getServiceTimePerStop(carrier, carrierAttributes, additionalTravelBufferPerIterationInMinutes); CarrierService redrawnService = CarrierService.Builder.newInstance(service.getId(), service.getLocationLinkId()) .setServiceDuration(newServiceDuration).setServiceStartTimeWindow(service.getServiceStartTimeWindow()).build(); carrier.getServices().put(redrawnService.getId(), redrawnService); @@ -105,7 +56,6 @@ public void tryToSolveAllCarriersCompletely(Scenario scenario, List non for (Carrier nonCompleteSolvedCarrier : nonCompleteSolvedCarriers) { //Delete old plan of carrier nonCompleteSolvedCarrier.clearPlans(); - nonCompleteSolvedCarrier.setSelectedPlan(null); GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes = generator.getCarrierId2carrierAttributes().get(nonCompleteSolvedCarrier.getId()); // Generate new services. The new service batch should have a smaller sum of serviceDurations than before (or otherwise it will not change anything) @@ -133,4 +83,61 @@ public void tryToSolveAllCarriersCompletely(Scenario scenario, List non } } + /** + * Change the service duration for a given carrier, because the service could not be handled in the last solution. + * + * @param carrier The carrier for which we generate the serviceTime + * @param carrierAttributes attributes of the carrier to generate the service time for. + * @param key key for the service duration + * @param additionalTravelBufferPerIterationInMinutes additional buffer for the travel time + * @return new service duration + */ + @Override + public int changeServiceTimePerStop(Carrier carrier, GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes, + GenerateSmallScaleCommercialTrafficDemand.ServiceDurationPerCategoryKey key, + int additionalTravelBufferPerIterationInMinutes) { + + double maxVehicleAvailability = carrier.getCarrierCapabilities().getCarrierVehicles().values().stream().mapToDouble(vehicle -> vehicle.getLatestEndTime() - vehicle.getEarliestStartTime()).max().orElse(0); + int usedTravelTimeBuffer = additionalTravelBufferPerIterationInMinutes * 60; // buffer for the driving time; for unsolved carriers the buffer will be increased over time + for (int j = 0; j < 200; j++) { + if (generator.getServiceDurationTimeSelector().get(key) == null) { + System.out.println("key: " + key); + System.out.println(generator.getServiceDurationTimeSelector().keySet()); + throw new RuntimeException("No service duration found for employee category '" + carrierAttributes.selectedStartCategory() + "' and mode '" + + carrierAttributes.modeORvehType() + "' in traffic type '" + carrierAttributes.smallScaleCommercialTrafficType() + "'"); + } + GenerateSmallScaleCommercialTrafficDemand.DurationsBounds serviceDurationBounds = generator.getServiceDurationTimeSelector().get(key).sample(); + + for (int i = 0; i < 10; i++) { + int serviceDurationLowerBound = serviceDurationBounds.minDuration(); + int serviceDurationUpperBound = serviceDurationBounds.maxDuration(); + int possibleValue = rnd.nextInt(serviceDurationLowerBound * 60, serviceDurationUpperBound * 60); + // checks if the service duration will not exceed the vehicle availability including the buffer + if (possibleValue + usedTravelTimeBuffer <= maxVehicleAvailability) + return possibleValue; + } + if (j > 100){ + CarrierVehicle carrierVehicleToChange = carrier.getCarrierCapabilities().getCarrierVehicles().values().stream().sorted(Comparator.comparingDouble(vehicle -> vehicle.getLatestEndTime() - vehicle.getEarliestStartTime())).toList().getFirst(); + log.info("Changing vehicle availability for carrier {}. Old maxVehicleAvailability: {}", carrier.getId(), maxVehicleAvailability); + int tourDuration = 0; + int vehicleStartTime = 0; + int vehicleEndTime = 0; + while (tourDuration < maxVehicleAvailability) { + GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration t = generator.getTourDistribution().get(carrierAttributes.smallScaleCommercialTrafficType()).sample(); + vehicleStartTime = t.getVehicleStartTime(); + tourDuration = t.getVehicleTourDuration(); + vehicleEndTime = vehicleStartTime + tourDuration; + } + CarrierVehicle newCarrierVehicle = CarrierVehicle.Builder.newInstance(carrierVehicleToChange.getId(), carrierVehicleToChange.getLinkId(), + carrierVehicleToChange.getType()).setEarliestStart(vehicleStartTime).setLatestEnd(vehicleEndTime).build(); + carrier.getCarrierCapabilities().getCarrierVehicles().remove(carrierVehicleToChange.getId()); + carrier.getCarrierCapabilities().getCarrierVehicles().put(newCarrierVehicle.getId(), newCarrierVehicle); + maxVehicleAvailability = carrier.getCarrierCapabilities().getCarrierVehicles().values().stream().mapToDouble(vehicle -> vehicle.getLatestEndTime() - vehicle.getEarliestStartTime()).max().orElse(0); + log.info("New maxVehicleAvailability: {}", maxVehicleAvailability); + } + } + + throw new RuntimeException("No possible service duration found for employee category '" + carrierAttributes.selectedStartCategory() + "' and mode '" + + carrierAttributes.modeORvehType() + "' in traffic type '" + carrierAttributes.smallScaleCommercialTrafficType() + "'"); + } } diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java index 553b9abc689..094c2f753f4 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java @@ -481,7 +481,8 @@ private void solveSeparatedVRPs(Scenario originalScenario) throws Exception { // Map the values to the new subcarriers for (Id oldCarrierId : carrierId2subCarrierIds.keySet()) { for (Id newCarrierId : carrierId2subCarrierIds.get(oldCarrierId)) { - carrierId2carrierAttributes.put(newCarrierId, carrierId2carrierAttributes.get(oldCarrierId)); + if (carrierId2carrierAttributes.putIfAbsent(newCarrierId, carrierId2carrierAttributes.get(oldCarrierId)) != null) + throw new Exception("CarrierAttributes already exist for the carrier " + newCarrierId.toString()); } } @@ -679,14 +680,26 @@ public void createCarriers(Scenario scenario, vehicleTypes.add(possibleVehicleType); } - // find a (random) start category with existing employees in this zone Collections.shuffle(odMatrixEntry.possibleStartCategories, rnd); String selectedStartCategory = odMatrixEntry.possibleStartCategories.getFirst(); + // Find a (random) start category with existing employees in this zone + // we start with count = 1 because the first category is already selected, and if this category has employees, we can use it. + // Otherwise, we have to find another category. for (int count = 1; resultingDataPerZone.get(startZone).getDouble(selectedStartCategory) == 0; count++) { - if (count <= odMatrixEntry.possibleStartCategories.size()) - selectedStartCategory = odMatrixEntry.possibleStartCategories.get(rnd.nextInt(odMatrixEntry.possibleStartCategories.size())); - else + if (count < odMatrixEntry.possibleStartCategories.size()) + selectedStartCategory = odMatrixEntry.possibleStartCategories.get(count); + else { + // if no possible start category with employees is found, take a random category of the stop categories, + // the reason that no start category with employees is found is that traffic volume for employees in general is created, + // so that it is possible that we have traffic, although we have no employees in the given start category. + // That's why we exclude Inhabitants as a possible start category. selectedStartCategory = odMatrixEntry.possibleStopCategories.get(rnd.nextInt(odMatrixEntry.possibleStopCategories.size())); + if (selectedStartCategory.equals("Inhabitants")) + selectedStartCategory = odMatrixEntry.possibleStopCategories.get(rnd.nextInt(odMatrixEntry.possibleStopCategories.size())); + if (resultingDataPerZone.get(startZone).getDouble(selectedStartCategory) > 0) + log.warn("No possible start category with employees found for zone {}. Take a random category of the stop categories: {}. The possible start categories are: {}", + startZone, selectedStartCategory, odMatrixEntry.possibleStartCategories); + } } // Generate carrierName @@ -709,11 +722,10 @@ public void createCarriers(Scenario scenario, CarrierAttributes carrierAttributes = new CarrierAttributes(purpose, startZone, selectedStartCategory, modeORvehType, smallScaleCommercialTrafficType, vehicleDepots, odMatrixEntry); - carrierId2carrierAttributes.put(Id.create(carrierName, Carrier.class), carrierAttributes); + if(carrierId2carrierAttributes.putIfAbsent(Id.create(carrierName, Carrier.class), carrierAttributes) != null) + throw new RuntimeException("CarrierAttributes already exist for the carrier " + carrierName); - createNewCarrierAndAddVehicleTypes( - scenario, carrierName, carrierAttributes, - vehicleTypes, numberOfDepots, fleetSize, + createNewCarrierAndAddVehicleTypes(scenario, carrierName, carrierAttributes, vehicleTypes, numberOfDepots, fleetSize, fixedNumberOfVehiclePerTypeAndLocation); // Now Create services for this carrier @@ -731,8 +743,7 @@ public void createCarriers(Scenario scenario, /** * Generates and adds the services for the given carrier. */ - private void createServices(Carrier newCarrier, - CarrierAttributes carrierAttributes) { + private void createServices(Carrier newCarrier, CarrierAttributes carrierAttributes) { log.info("Create services for carrier: {}", newCarrier.getId()); for (String stopZone : odMatrix.getListOfZones()) { int trafficVolumeForOD = Math.round((float)odMatrix.getTripDistributionValue(carrierAttributes.startZone, @@ -745,25 +756,54 @@ private void createServices(Carrier newCarrier, while (resultingDataPerZone.get(stopZone).getDouble(selectedStopCategory) == 0) selectedStopCategory = carrierAttributes.odMatrixEntry.possibleStopCategories.get(rnd.nextInt(carrierAttributes.odMatrixEntry.possibleStopCategories.size())); for (int i = 0; i < numberOfJobs; i++) { - int serviceTimePerStop; - if (carrierAttributes.selectedStartCategory.equals("Inhabitants")){ - CarrierAttributes inhabitantAttributes = new CarrierAttributes(carrierAttributes.purpose, carrierAttributes.startZone, - carrierAttributes.odMatrixEntry.possibleStartCategories.getFirst(), carrierAttributes.modeORvehType, - carrierAttributes.smallScaleCommercialTrafficType, carrierAttributes.vehicleDepots, carrierAttributes.odMatrixEntry); - serviceTimePerStop = unhandledServicesSolution.getServiceTimePerStop(newCarrier, inhabitantAttributes, 0); - - } - else { - serviceTimePerStop = unhandledServicesSolution.getServiceTimePerStop(newCarrier, carrierAttributes, 0); - } + // additionalTravelBufferPerIterationInMinutes is only used for recalculation of the service time if a carrier solution could not handle all services + int serviceTimePerStop = getServiceTimePerStop(newCarrier, carrierAttributes, 0); - TimeWindow serviceTimeWindow = TimeWindow.newInstance(0, - 36 * 3600); // extended time window, so that late tours can handle it + TimeWindow serviceTimeWindow = TimeWindow.newInstance(0, 36 * 3600); // extended time window, so that late tours can handle it createService(newCarrier, carrierAttributes.vehicleDepots, selectedStopCategory, stopZone, serviceTimePerStop, serviceTimeWindow); } } } + /** + * Give a service duration based on the purpose and the trafficType under a given probability + * + * @param carrier The carrier for which the service time should be calculated + * @param carrierAttributes The attributes of the carrier + * @param additionalTravelBufferPerIterationInMinutes Additional travel buffer per recalculation iteration for a carrier in minutes + * @return The service time in seconds + */ + public Integer getServiceTimePerStop(Carrier carrier, GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes, + int additionalTravelBufferPerIterationInMinutes) { + GenerateSmallScaleCommercialTrafficDemand.ServiceDurationPerCategoryKey key; + // we use the start category for the service time selection because the start category represents the employees + if (carrierAttributes.smallScaleCommercialTrafficType().equals( + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { + if (!carrierAttributes.odMatrixEntry().possibleStartCategories.contains(carrierAttributes.selectedStartCategory())) + key = GenerateSmallScaleCommercialTrafficDemand.makeServiceDurationPerCategoryKey(carrierAttributes.odMatrixEntry().possibleStartCategories.get(rnd.nextInt(carrierAttributes.odMatrixEntry().possibleStartCategories.size())), null, carrierAttributes.smallScaleCommercialTrafficType()); + else + key = GenerateSmallScaleCommercialTrafficDemand.makeServiceDurationPerCategoryKey(carrierAttributes.selectedStartCategory(), null, + carrierAttributes.smallScaleCommercialTrafficType()); + } + else if (carrierAttributes.smallScaleCommercialTrafficType().equals( + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString())) { + key = GenerateSmallScaleCommercialTrafficDemand.makeServiceDurationPerCategoryKey(carrierAttributes.selectedStartCategory(), + carrierAttributes.modeORvehType(), carrierAttributes.smallScaleCommercialTrafficType()); + } else { + throw new RuntimeException("Unknown traffic type: " + carrierAttributes.smallScaleCommercialTrafficType()); + } + // additionalTravelBufferPerIterationInMinutes is only used for recalculation of the service time if a carrier solution could not handle all services + if (additionalTravelBufferPerIterationInMinutes == 0) { + GenerateSmallScaleCommercialTrafficDemand.DurationsBounds serviceDurationBounds = serviceDurationTimeSelector.get(key).sample(); + + int serviceDurationLowerBound = serviceDurationBounds.minDuration(); + int serviceDurationUpperBound = serviceDurationBounds.maxDuration(); + return rnd.nextInt(serviceDurationLowerBound * 60, serviceDurationUpperBound * 60); + } else { + return unhandledServicesSolution.changeServiceTimePerStop(carrier, carrierAttributes, key, additionalTravelBufferPerIterationInMinutes); + } + } + /** * Adds a service with the given attributes to the carrier. */ @@ -814,7 +854,6 @@ private void createNewCarrierAndAddVehicleTypes(Scenario scenario, String carrie for (String singleDepot : carrierAttributes.vehicleDepots) { GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration t = tourDistribution.get(carrierAttributes.smallScaleCommercialTrafficType).sample(); - int vehicleStartTime = t.getVehicleStartTime(); int tourDuration = t.getVehicleTourDuration(); int vehicleEndTime = vehicleStartTime + tourDuration; diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/UnhandledServicesSolution.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/UnhandledServicesSolution.java index e5db51e8557..c65c75deee7 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/UnhandledServicesSolution.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/UnhandledServicesSolution.java @@ -17,17 +17,6 @@ public interface UnhandledServicesSolution { */ List createListOfCarrierWithUnhandledJobs(Scenario scenario); - /** - * Give a service duration based on the purpose and the trafficType under a given probability - * - * @param carrier The carrier for which we generate the serviceTime - * @param carrierAttributes attributes of the carrier to generate the service time for. - * selectedStartCategory: the category of the employee - * @param additionalTravelBufferPerIterationInMinutes additional buffer for the travel time - * @return the service duration - */ - int getServiceTimePerStop(Carrier carrier, GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes, int additionalTravelBufferPerIterationInMinutes); - /** * * Checks and recalculates plans of carriers, which did not serve all services. @@ -36,4 +25,15 @@ public interface UnhandledServicesSolution { * @param nonCompleteSolvedCarriers List of carriers, that are not solved. Can be obtained by {@link UnhandledServicesSolution#createListOfCarrierWithUnhandledJobs(Scenario)} */ void tryToSolveAllCarriersCompletely(Scenario scenario, List nonCompleteSolvedCarriers); + + /** + * Change the service duration for a given carrier, because the service could not be handled in the last solution. + * + * @param carrier The carrier for which we generate the serviceTime + * @param carrierAttributes attributes of the carrier to generate the service time for. + * @param key key for the service duration + * @param additionalTravelBufferPerIterationInMinutes additional buffer for the travel time + * @return new service duration + */ + int changeServiceTimePerStop(Carrier carrier, GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes, GenerateSmallScaleCommercialTrafficDemand.ServiceDurationPerCategoryKey key, int additionalTravelBufferPerIterationInMinutes); } diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java index 7aeefbf5925..999ea549ccf 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java @@ -73,7 +73,7 @@ void testMainRunAndResults() { String sample = "0.1"; String jspritIterations = "2"; String creationOption = "createNewCarrierFile"; - String smallScaleCommercialTrafficType = "commercialPersonTraffic"; + String smallScaleCommercialTrafficType = "completeSmallScaleCommercialTraffic"; String zoneShapeFileName = utils.getPackageInputDirectory() + "/shp/testZones.shp"; String zoneShapeFileNameColumn = "name"; String shapeCRS = "EPSG:4326"; diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_startPerZone_10pt.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_startPerZone_10pt.csv new file mode 100644 index 00000000000..bb4a958810a --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_startPerZone_10pt.csv @@ -0,0 +1,16 @@ +zoneID mode/vehType 1 2 3 4 5 +area1 vehTyp3 0 1 4 4 3 +area2 vehTyp4 0 0 1 4 1 +area3 vehTyp5 0 0 1 3 1 +area1 vehTyp4 0 0 1 1 0 +area2 vehTyp5 0 0 3 21 9 +area1 vehTyp1 1 2 10 4 3 +area2 vehTyp2 0 0 2 3 7 +area3 vehTyp3 0 0 1 2 1 +area1 vehTyp2 0 0 2 1 2 +area2 vehTyp3 0 1 4 13 8 +area3 vehTyp4 0 0 0 1 0 +area3 vehTyp1 0 0 2 1 1 +area2 vehTyp1 1 2 11 10 9 +area3 vehTyp2 0 0 0 0 1 +area1 vehTyp5 0 0 3 7 3 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_stopPerZone_10pt.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_stopPerZone_10pt.csv new file mode 100644 index 00000000000..8eacf8fd4d5 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_stopPerZone_10pt.csv @@ -0,0 +1,16 @@ +zoneID mode/vehType 1 2 3 4 5 +area1 vehTyp3 0 1 3 7 1 +area2 vehTyp4 0 0 1 2 0 +area3 vehTyp5 0 0 0 3 0 +area1 vehTyp4 0 0 0 2 0 +area2 vehTyp5 0 1 3 12 1 +area1 vehTyp1 1 2 7 5 1 +area2 vehTyp2 0 0 1 2 1 +area3 vehTyp3 0 0 1 1 0 +area1 vehTyp2 0 0 1 2 1 +area2 vehTyp3 0 1 3 7 1 +area3 vehTyp4 0 0 0 0 0 +area3 vehTyp1 0 0 2 1 0 +area2 vehTyp1 1 2 9 5 1 +area3 vehTyp2 0 0 0 0 0 +area1 vehTyp5 0 1 2 13 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose1.csv new file mode 100644 index 00000000000..cc8a668c7b8 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose1.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 1 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose2.csv new file mode 100644 index 00000000000..de59ab8889f --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose2.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 0 0 +area2 1 2 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose3.csv new file mode 100644 index 00000000000..26a96bff6fd --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose3.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 3 3 0 +area2 4 5 1 +area3 0 1 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose4.csv new file mode 100644 index 00000000000..12ec403fccd --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose4.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 2 1 0 +area2 3 4 0 +area3 0 0 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose5.csv new file mode 100644 index 00000000000..7e6891a86a5 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose5.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 0 0 +area2 0 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose6.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose6.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose6.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose1.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose1.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose2.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose2.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose3.csv new file mode 100644 index 00000000000..2bf59089a18 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose3.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 1 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose4.csv new file mode 100644 index 00000000000..0ae1ae162f4 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose4.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 1 0 +area2 2 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose5.csv new file mode 100644 index 00000000000..c53d46eaaae --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose5.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 1 1 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose6.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose6.csv new file mode 100644 index 00000000000..2bf59089a18 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose6.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 1 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose1.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose1.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose2.csv new file mode 100644 index 00000000000..cc8a668c7b8 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose2.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 1 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose3.csv new file mode 100644 index 00000000000..72ffd6bb344 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose3.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 2 0 +area2 2 1 0 +area3 0 0 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose4.csv new file mode 100644 index 00000000000..4f435ce0431 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose4.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 1 0 +area2 5 5 1 +area3 1 1 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose5.csv new file mode 100644 index 00000000000..cc8a668c7b8 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose5.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 1 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose6.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose6.csv new file mode 100644 index 00000000000..8b670f48efc --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose6.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 1 2 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose1.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose1.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose2.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose2.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose3.csv new file mode 100644 index 00000000000..89e40cb7518 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose3.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 1 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose4.csv new file mode 100644 index 00000000000..9a8d21f3eeb --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose4.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 1 1 0 +area3 1 1 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose5.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose5.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose6.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose6.csv new file mode 100644 index 00000000000..7e6891a86a5 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose6.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 0 0 +area2 0 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose1.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose1.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose2.csv new file mode 100644 index 00000000000..7e6891a86a5 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose2.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 0 0 +area2 0 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose3.csv new file mode 100644 index 00000000000..dae6ecd671c --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose3.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 2 0 +area2 2 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose4.csv new file mode 100644 index 00000000000..ab520bdffca --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose4.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 3 3 1 +area2 9 8 2 +area3 1 1 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose5.csv new file mode 100644 index 00000000000..2bf59089a18 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose5.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 1 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose6.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose6.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose6.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz index e9f770072c4..1e5c09a053f 100644 Binary files a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz and b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz differ diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz index e9f770072c4..b110aa96838 100644 Binary files a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz and b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz differ diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz index 4cac3132da0..23c2766f7c3 100644 Binary files a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz and b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz differ diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml index efe44ed5710..48a47d32b8b 100644 --- a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml @@ -146,7 +146,7 @@ - + Heavy Vehicle 26t @@ -167,7 +167,7 @@ - + Heavy Vehicle 40t @@ -187,7 +187,7 @@ - + @@ -226,5 +226,6 @@ + - \ No newline at end of file + diff --git a/examples/scenarios/emissions-sampleScenario/testv2_Vehv2/sample_emissionVehicles_v2.xml b/examples/scenarios/emissions-sampleScenario/testv2_Vehv2/sample_emissionVehicles_v2.xml index 566a49585bd..36079e8d101 100644 --- a/examples/scenarios/emissions-sampleScenario/testv2_Vehv2/sample_emissionVehicles_v2.xml +++ b/examples/scenarios/emissions-sampleScenario/testv2_Vehv2/sample_emissionVehicles_v2.xml @@ -14,6 +14,7 @@ average + @@ -27,6 +28,7 @@ PC-P-Euro-1 + @@ -40,6 +42,7 @@ PC-D-Euro-3 + @@ -56,6 +59,7 @@ average + @@ -66,4 +70,4 @@ - \ No newline at end of file + diff --git a/examples/scenarios/freight-chessboard-9x9/vehicleTypes.xml b/examples/scenarios/freight-chessboard-9x9/vehicleTypes.xml index 27a7d8e1255..df4c6c7c95f 100644 --- a/examples/scenarios/freight-chessboard-9x9/vehicleTypes.xml +++ b/examples/scenarios/freight-chessboard-9x9/vehicleTypes.xml @@ -10,11 +10,13 @@ A heavy truck + A light truck + - \ No newline at end of file + diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityEndEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityEndEvent.java index 39e0e36bbac..76bc4427498 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityEndEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityEndEvent.java @@ -29,6 +29,8 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.facilities.ActivityFacility; +import static org.matsim.core.utils.io.XmlUtils.writeEncodedAttributeKeyValue; + public final class ActivityEndEvent extends Event implements HasPersonId, HasLinkId, HasFacilityId, BasicLocation { public static final String EVENT_TYPE = "actend"; @@ -49,7 +51,7 @@ public ActivityEndEvent( final double time, final Id agentId, final Id agentId, final Id linkId, + public ActivityEndEvent(final double time, final Id agentId, final Id linkId, final Id facilityId, final String acttype, final Coord coord) { super(time); this.linkId = linkId; @@ -79,7 +81,7 @@ public String getActType() { @Override public Id getPersonId() { return this.personId; } - + @Override public Map getAttributes() { Map attr = super.getAttributes(); @@ -95,4 +97,12 @@ public void setCoord( Coord coord ) { // yy this is to retrofit the coordinate into existing events that don't have it. this.coord = coord; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes common attributes + writeXMLStart(out); + writeEncodedAttributeKeyValue(out, ATTRIBUTE_ACTTYPE, this.acttype); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityStartEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityStartEvent.java index f58a5b9a506..b0786093572 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityStartEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityStartEvent.java @@ -20,8 +20,6 @@ package org.matsim.api.core.v01.events; -import java.util.Map; - import org.matsim.api.core.v01.BasicLocation; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; @@ -29,6 +27,10 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.facilities.ActivityFacility; +import java.util.Map; + +import static org.matsim.core.utils.io.XmlUtils.writeEncodedAttributeKeyValue; + public class ActivityStartEvent extends Event implements HasFacilityId, HasPersonId, HasLinkId, BasicLocation{ public static final String EVENT_TYPE = "actstart"; @@ -91,7 +93,7 @@ public String getActType() { @Override public Id getPersonId() { return this.personId; } - + @Override public Map getAttributes() { Map attr = super.getAttributes(); @@ -109,4 +111,12 @@ public void setCoord( Coord coord ) { // yy this is to retrofit the coordinate into existing events that don't have it. :-( kai, mar'20 this.coord = coord; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes common attributes + writeXMLStart(out); + writeEncodedAttributeKeyValue(out, ATTRIBUTE_ACTTYPE, this.acttype); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/Event.java b/matsim/src/main/java/org/matsim/api/core/v01/events/Event.java index 09852740b7a..c51a90610fe 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/Event.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/Event.java @@ -24,6 +24,9 @@ import java.util.Map; import org.matsim.api.core.v01.BasicLocation; +import org.matsim.core.utils.io.XmlUtils; + +import static org.matsim.core.utils.io.XmlUtils.writeEncodedAttributeValue; public abstract class Event { @@ -105,6 +108,69 @@ public boolean equals(Object obj) { public int hashCode() { return getAttributes().hashCode(); // Two equal events must at least have the same attributes, so they will get the same hashCode like this. } + + + /** + * Write the start of the xml representation and some common attributes. This method should be called first by {@link #writeAsXML(StringBuilder)}. + */ + protected final void writeXMLStart(StringBuilder out) { + out.append("\t\n"); + } + + /** + * Write a xml representation of this event to the given writer. + * The implementation must write the whole xml element . Starting with \t and adding a newline at the end. + * + * The provided default implementation writes the whole element based on {@link #getAttributes()}. This is slow and should be overridden. + * The overriding implementation must *not* call the super method. + */ + public void writeAsXML(StringBuilder out) { + out.append("\t attr = getAttributes(); + for (Map.Entry entry : attr.entrySet()) { + out.append(entry.getKey()); + out.append("=\""); + out.append(XmlUtils.encodeAttributeValue(entry.getValue())); + out.append("\" "); + } + out.append(" />\n"); + } + } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/LinkEnterEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/LinkEnterEvent.java index 63250efa333..310521abc11 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/LinkEnterEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/LinkEnterEvent.java @@ -73,4 +73,11 @@ public Map getAttributes() { // linkId, vehicleId handled by superclass return atts; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/LinkLeaveEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/LinkLeaveEvent.java index 06018363204..0491771b110 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/LinkLeaveEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/LinkLeaveEvent.java @@ -76,4 +76,11 @@ public Map getAttributes() { // linkId, vehicleId handled by superclass return atts; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonArrivalEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonArrivalEvent.java index 6e947aaff11..9e45e10e7da 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonArrivalEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonArrivalEvent.java @@ -26,6 +26,8 @@ import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.population.Person; +import static org.matsim.core.utils.io.XmlUtils.writeEncodedAttributeKeyValue; + public class PersonArrivalEvent extends Event implements HasPersonId, HasLinkId { public static final String EVENT_TYPE = "arrival"; @@ -71,4 +73,14 @@ public Map getAttributes() { } return attr; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + if (this.legMode != null) { + writeEncodedAttributeKeyValue(out, ATTRIBUTE_LEGMODE, this.legMode); + } + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonDepartureEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonDepartureEvent.java index 425d8ad4e78..d98e05e8708 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonDepartureEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonDepartureEvent.java @@ -25,6 +25,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.population.Person; +import org.matsim.core.utils.io.XmlUtils; public class PersonDepartureEvent extends Event implements HasPersonId, HasLinkId { @@ -82,4 +83,16 @@ public Map getAttributes() { } return attr; } + + @Override + public void writeAsXML(StringBuilder out) { + writeXMLStart(out); + if (this.legMode != null) { + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_LEGMODE, this.legMode); + } + if (this.routingMode != null) { + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_ROUTING_MODE, this.routingMode); + } + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonEntersVehicleEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonEntersVehicleEvent.java index a3e051f44c4..db694dff953 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonEntersVehicleEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonEntersVehicleEvent.java @@ -68,4 +68,11 @@ public Map getAttributes() { // personId, vehicleId handled by superclass return atts; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonLeavesVehicleEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonLeavesVehicleEvent.java index 27a3b5b2bdd..3a2bad23e44 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonLeavesVehicleEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonLeavesVehicleEvent.java @@ -69,4 +69,11 @@ public Map getAttributes() { // personId, vehicleId handled by superclass return attrs; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonMoneyEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonMoneyEvent.java index e61a8a85b32..1b08399d47f 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonMoneyEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonMoneyEvent.java @@ -25,6 +25,8 @@ import java.util.Map; +import static org.matsim.core.utils.io.XmlUtils.writeEncodedAttributeKeyValue; + /** * This event specifies that an agent has gained (or paid) some money. * Scoring functions should handle these Events by adding the amount somehow @@ -134,4 +136,23 @@ public Map getAttributes() { } return attr; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + + out.append("amount=\"").append(this.amount).append("\" "); + if (this.purpose != null) { + writeEncodedAttributeKeyValue(out, ATTRIBUTE_PURPOSE, this.purpose); + } + if (this.transactionPartner != null) { + writeEncodedAttributeKeyValue(out, ATTRIBUTE_TRANSACTION_PARTNER, this.transactionPartner); + } + if (this.reference != null) { + writeEncodedAttributeKeyValue(out, ATTRIBUTE_REFERENCE, this.reference); + } + + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonScoreEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonScoreEvent.java index 96019b6242f..893769df004 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonScoreEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonScoreEvent.java @@ -20,6 +20,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.population.Person; +import org.matsim.core.utils.io.XmlUtils; import java.util.Map; @@ -75,4 +76,14 @@ public Map getAttributes() { } return attr; } + + @Override + public void writeAsXML(StringBuilder out) { + writeXMLStart(out); + out.append("amount=\"").append(this.amount).append("\" "); + if (this.kind != null) { + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_KIND, this.kind); + } + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonStuckEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonStuckEvent.java index b2439dd8b96..2eca25c0eab 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonStuckEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonStuckEvent.java @@ -25,6 +25,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.population.Person; +import org.matsim.core.utils.io.XmlUtils; public class PersonStuckEvent extends Event implements HasPersonId, HasLinkId { @@ -71,4 +72,16 @@ public Map getAttributes() { } return attr; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + + if (this.legMode != null) { + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_LEGMODE, this.legMode); + } + + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/TransitDriverStartsEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/TransitDriverStartsEvent.java index f58b1536fa9..801b2ec44c4 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/TransitDriverStartsEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/TransitDriverStartsEvent.java @@ -23,6 +23,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.population.Person; +import org.matsim.core.utils.io.XmlUtils; import org.matsim.pt.transitSchedule.api.Departure; import org.matsim.pt.transitSchedule.api.TransitLine; import org.matsim.pt.transitSchedule.api.TransitRoute; @@ -45,7 +46,7 @@ public class TransitDriverStartsEvent extends Event { private final Id transitLineId; private final Id departureId; - public TransitDriverStartsEvent(final double time, final Id driverId, final Id vehicleId, + public TransitDriverStartsEvent(final double time, final Id driverId, final Id vehicleId, final Id transitLineId, final Id transitRouteId, final Id departureId) { super(time); this.driverId = driverId; @@ -54,23 +55,23 @@ public TransitDriverStartsEvent(final double time, final Id driverId, fi this.transitLineId = transitLineId; this.departureId = departureId; } - + public Id getDriverId() { return driverId; } - + public Id getVehicleId() { return vehicleId; } - + public Id getTransitRouteId() { return transitRouteId; } - + public Id getTransitLineId() { return transitLineId; } - + public Id getDepartureId() { return departureId; } @@ -79,7 +80,7 @@ public Id getDepartureId() { public String getEventType() { return EVENT_TYPE; } - + @Override public Map getAttributes() { Map atts = super.getAttributes(); @@ -90,4 +91,17 @@ public Map getAttributes() { atts.put(ATTRIBUTE_DEPARTURE_ID, this.getDepartureId().toString()); return atts; } -} \ No newline at end of file + + @Override + public void writeAsXML(StringBuilder out) { + writeXMLStart(out); + + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_DRIVER_ID, this.getDriverId().toString()); + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_VEHICLE_ID, this.getVehicleId().toString()); + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_TRANSIT_LINE_ID, this.getTransitLineId().toString()); + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_TRANSIT_ROUTE_ID, this.getTransitRouteId().toString()); + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_DEPARTURE_ID, this.getDepartureId().toString()); + + writeXMLEnd(out); + } +} diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/VehicleAbortsEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/VehicleAbortsEvent.java index a623a758bd0..ba0ec9bbeff 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/VehicleAbortsEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/VehicleAbortsEvent.java @@ -61,4 +61,10 @@ public Map getAttributes() { // linkId, vehicleId handled by superclass return atts; } + + @Override + public void writeAsXML(StringBuilder out) { + writeXMLStart(out); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/core/events/algorithms/EventWriterXML.java b/matsim/src/main/java/org/matsim/core/events/algorithms/EventWriterXML.java index 54b731771e1..4b29ae4ac55 100644 --- a/matsim/src/main/java/org/matsim/core/events/algorithms/EventWriterXML.java +++ b/matsim/src/main/java/org/matsim/core/events/algorithms/EventWriterXML.java @@ -32,13 +32,17 @@ import java.io.OutputStreamWriter; import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; -import java.util.Map; public class EventWriterXML implements EventWriter, BasicEventHandler { private static final Logger LOG = LogManager.getLogger(EventWriterXML.class); private final BufferedWriter out; + /** + * Cache for StringBuilder instances to avoid creating a new one for each event. + */ + private final ThreadLocal stringBuilder = ThreadLocal.withInitial(StringBuilder::new); + public EventWriterXML(final String outfilename) { this.out = IOUtils.getBufferedWriter(outfilename); this.writeHeader(); @@ -83,73 +87,14 @@ public void reset(final int iter) { @Override public void handleEvent(final Event event) { try { - this.out.append("\t attr = event.getAttributes(); - for (Map.Entry entry : attr.entrySet()) { - this.out.append(entry.getKey()); - this.out.append("=\""); - this.out.append(encodeAttributeValue(entry.getValue())); - this.out.append("\" "); - } - this.out.append(" />\n"); - } catch (IOException e) { - LOG.error(e.getMessage(), e); - } - } + StringBuilder b = stringBuilder.get(); - // the following method was taken from MatsimXmlWriter in order to correctly encode attributes, but - // to forego the overhead of using the full MatsimXmlWriter. - /** - * Encodes the given string in such a way that it no longer contains - * characters that have a special meaning in xml. - * - * @see http://www.w3.org/International/questions/qa-escapes#use - * @param attributeValue - * @return String with some characters replaced by their xml-encoding. - */ - private String encodeAttributeValue(final String attributeValue) { - if (attributeValue == null) { - return null; - } - int len = attributeValue.length(); - boolean encode = false; - for (int pos = 0; pos < len; pos++) { - char ch = attributeValue.charAt(pos); - if (ch == '<') { - encode = true; - break; - } else if (ch == '>') { - encode = true; - break; - } else if (ch == '\"') { - encode = true; - break; - } else if (ch == '&') { - encode = true; - break; - } - } - if (encode) { - StringBuilder bf = new StringBuilder(attributeValue.length() + 30); - for (int pos = 0; pos < len; pos++) { - char ch = attributeValue.charAt(pos); - if (ch == '<') { - bf.append("<"); - } else if (ch == '>') { - bf.append(">"); - } else if (ch == '\"') { - bf.append("""); - } else if (ch == '&') { - bf.append("&"); - } else { - bf.append(ch); - } - } + b.setLength(0); + event.writeAsXML(b); + this.out.append(b); - return bf.toString(); + } catch (IOException e) { + LOG.error(e.getMessage(), e); } - return attributeValue; - } - } diff --git a/matsim/src/main/java/org/matsim/core/utils/io/XmlUtils.java b/matsim/src/main/java/org/matsim/core/utils/io/XmlUtils.java index 57fa2f0b63a..85df85a9fd5 100644 --- a/matsim/src/main/java/org/matsim/core/utils/io/XmlUtils.java +++ b/matsim/src/main/java/org/matsim/core/utils/io/XmlUtils.java @@ -39,12 +39,88 @@ private XmlUtils() { * @return String with some characters replaced by their xml-encoding. */ public static String encodeAttributeValue(final String attributeValue) { - if (attributeValue.contains("&") || attributeValue.contains("\"") || attributeValue.contains("<") || attributeValue.contains(">")) { - return attributeValue.replace("&", "&").replace("\"", """).replace("<", "<").replace(">", ">"); + if (attributeValue == null) { + return null; + } + int len = attributeValue.length(); + boolean encode = false; + for (int pos = 0; pos < len; pos++) { + char ch = attributeValue.charAt(pos); + if (ch == '<') { + encode = true; + break; + } else if (ch == '>') { + encode = true; + break; + } else if (ch == '\"') { + encode = true; + break; + } else if (ch == '&') { + encode = true; + break; + } + } + if (encode) { + StringBuilder bf = new StringBuilder(attributeValue.length() + 30); + for (int pos = 0; pos < len; pos++) { + char ch = attributeValue.charAt(pos); + if (ch == '<') { + bf.append("<"); + } else if (ch == '>') { + bf.append(">"); + } else if (ch == '\"') { + bf.append("""); + } else if (ch == '&') { + bf.append("&"); + } else { + bf.append(ch); + } + } + + return bf.toString(); } return attributeValue; } + /** + * Write encoded attribute value to the given StringBuilder. + * This is an optimized version of {@link #encodeAttributeValue(String)}, which does not create any intermediate objects. + */ + public static StringBuilder writeEncodedAttributeValue(StringBuilder out, String attributeValue) { + + if (attributeValue == null) { + // By convention, null values are written as "null" in the xml output. + out.append("null"); + return out; + } + + int len = attributeValue.length(); + + for (int pos = 0; pos < len; pos++) { + char ch = attributeValue.charAt(pos); + switch (ch) { + case '<' -> out.append("<"); + case '>' -> out.append(">"); + case '\"' -> out.append("""); + case '&' -> out.append("&"); + default -> out.append(ch); + }; + } + + return out; + } + + /** + * Helper function to write an attribute key-value pair to the given StringBuilder. + * Note, do not use this for primitive types as these don't need to be encoded and the {@link StringBuilder} has specialized methods fot these. + */ + public static StringBuilder writeEncodedAttributeKeyValue(StringBuilder out, String key, String value) { + out.append(key).append("=\""); + writeEncodedAttributeValue(out, value); + out.append("\" "); + return out; + } + public static String encodeContent(final String content) { if (content.contains("&") || content.contains("<") || content.contains(">")) { return content.replace("&", "&").replace("<", "<").replace(">", ">"); diff --git a/matsim/src/main/java/org/matsim/vehicles/VehicleReaderV1.java b/matsim/src/main/java/org/matsim/vehicles/VehicleReaderV1.java index 697958b0fd6..b2847dc404e 100644 --- a/matsim/src/main/java/org/matsim/vehicles/VehicleReaderV1.java +++ b/matsim/src/main/java/org/matsim/vehicles/VehicleReaderV1.java @@ -3,6 +3,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; import org.matsim.core.utils.io.MatsimXmlParser; import org.xml.sax.Attributes; @@ -38,6 +39,10 @@ public void endTag( final String name, final String content, final Stack public void startTag( final String name, final Attributes atts, final Stack context ){ if( VehicleSchemaV1Names.VEHICLETYPE.equalsIgnoreCase( name ) ){ this.currentVehType = this.builder.createVehicleType( Id.create( atts.getValue( VehicleSchemaV1Names.ID ), VehicleType.class ) ); + // In the old format there is no network mode, and everything was basically a car. + // Vehicle type does not contain a default network mode anymore, therefore we need to set it here. + this.currentVehType.setNetworkMode( TransportMode.car ); + } else if( VehicleSchemaV1Names.LENGTH.equalsIgnoreCase( name ) ){ this.currentVehType.setLength( Double.parseDouble( atts.getValue( VehicleSchemaV1Names.METER ) ) ); } else if( VehicleSchemaV1Names.WIDTH.equalsIgnoreCase( name ) ){ diff --git a/matsim/src/main/java/org/matsim/vehicles/VehicleType.java b/matsim/src/main/java/org/matsim/vehicles/VehicleType.java index 9aef2a705e1..512705d4f0d 100644 --- a/matsim/src/main/java/org/matsim/vehicles/VehicleType.java +++ b/matsim/src/main/java/org/matsim/vehicles/VehicleType.java @@ -26,6 +26,8 @@ import org.matsim.utils.objectattributes.attributable.Attributes; import org.matsim.utils.objectattributes.attributable.AttributesImpl; +import java.util.Objects; + /** * @author dgrether */ @@ -46,13 +48,22 @@ public final class VehicleType implements Attributable, Identifiable id; private final Attributes attributes = new AttributesImpl(); VehicleType( Id typeId ) { this.id = typeId; + // For car typ default network mode is assumed, for others it needs to be set explicitly. + if (typeId != null && Objects.equals(typeId.toString(), TransportMode.car)) + this.networkMode = TransportMode.car; + } + + VehicleType(Id typeId, String networkMode) { + this.id = typeId; + this.networkMode = networkMode; } + public final String getDescription() { return description; } @@ -114,7 +125,7 @@ public final CostInformation getCostInformation() { return costInformation; } public final String getNetworkMode() { - return networkMode; + return Objects.requireNonNull(networkMode, () -> "Network mode not set for vehicle type %s. Network mode needs to be set explicitly for non car modes. You can do this in XML by adding \t\n".formatted(id, id)); } public final VehicleType setNetworkMode( String networkMode ) { this.networkMode = networkMode; diff --git a/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java b/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java index aac3e537da9..b5908ff38c1 100644 --- a/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java +++ b/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java @@ -64,6 +64,10 @@ public static VehicleType createVehicleType( Id typeId ){ return new VehicleType( typeId ); } + public static VehicleType createVehicleType( Id typeId, String networkMode){ + return new VehicleType( typeId, networkMode ); + } + public static VehiclesFactory getFactory() { return new VehiclesFactoryImpl(); } @@ -75,9 +79,9 @@ public static Vehicles createVehiclesContainer() { public static VehicleType createDefaultVehicleType() { VehicleType defaultVehicleType = VehicleUtils.getFactory() .createVehicleType(Id.create(DEFAULT_VEHICLE_TYPE_ID, VehicleType.class)); - + defaultVehicleType.getCapacity().setSeats(4); - + return defaultVehicleType; } @@ -434,7 +438,7 @@ public static void writeVehicles( Vehicles vehicles, String filename ) { new MatsimVehicleWriter( vehicles ).writeFile( filename ); } - + public static Id getInitialLinkId(Vehicle vehicle) { String attribute = (String) vehicle.getAttributes().getAttribute(INITIAL_LINK_ID); return attribute == null ? null : Id.createLinkId(attribute); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SpeedCalculatorTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SpeedCalculatorTest.java index ed394e4bd46..a697a42a9a7 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SpeedCalculatorTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SpeedCalculatorTest.java @@ -40,7 +40,7 @@ public class SpeedCalculatorTest{ @Test void limitedByVehicleSpeed() { Link link = createLinkWithNoGradientAndNoSpecialSurface(); - VehicleType type = VehicleUtils.createVehicleType(Id.create("no-bike", VehicleType.class ) ); + VehicleType type = VehicleUtils.createVehicleType(Id.create("no-bike", VehicleType.class ), TransportMode.car ); type.setMaximumVelocity(link.getFreespeed() / 2); // less than the link's freespeed QVehicle vehicle = new QVehicleImpl(VehicleUtils.createVehicle(Id.createVehicleId(1), type)); @@ -55,7 +55,7 @@ void limitedByLinkSpeed() { Link link = createLinkWithNoGradientAndNoSpecialSurface(); - VehicleType type = VehicleUtils.createVehicleType(Id.create("no-bike", VehicleType.class ) ); + VehicleType type = VehicleUtils.createVehicleType(Id.create("no-bike", VehicleType.class ), TransportMode.car ); type.setMaximumVelocity(link.getFreespeed() * 2); // _more_ than the link's freespeed QVehicle vehicle = new QVehicleImpl(VehicleUtils.createVehicle(Id.createVehicleId(1), type));