diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/DrtModeAvailabilityWrapper.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/DrtModeAvailabilityWrapper.java index e8a0dd2b4..edb5b681e 100644 --- a/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/DrtModeAvailabilityWrapper.java +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/DrtModeAvailabilityWrapper.java @@ -4,16 +4,26 @@ import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; import org.matsim.contribs.discrete_mode_choice.model.mode_availability.ModeAvailability; +import org.matsim.core.config.Config; import java.util.Collection; +import java.util.Collections; import java.util.List; public class DrtModeAvailabilityWrapper implements ModeAvailability { private final Collection drtModes; private final ModeAvailability delegate; + public DrtModeAvailabilityWrapper(Config config, ModeAvailability delegate) { + this((MultiModeDrtConfigGroup) config.getModules().get(MultiModeDrtConfigGroup.GROUP_NAME), delegate); + } + public DrtModeAvailabilityWrapper(MultiModeDrtConfigGroup multiModeDrtConfigGroup, ModeAvailability delegate) { - this.drtModes = multiModeDrtConfigGroup.modes().toList(); + if(multiModeDrtConfigGroup != null) { + this.drtModes = multiModeDrtConfigGroup.modes().toList(); + } else { + this.drtModes = Collections.emptyList(); + } this.delegate = delegate; } diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/feeder_drt/mode_choice/FeederDrtModeAvailabilityWrapper.java b/core/src/main/java/org/eqasim/core/simulation/modes/feeder_drt/mode_choice/FeederDrtModeAvailabilityWrapper.java index 4aae5ab0d..e166a4300 100644 --- a/core/src/main/java/org/eqasim/core/simulation/modes/feeder_drt/mode_choice/FeederDrtModeAvailabilityWrapper.java +++ b/core/src/main/java/org/eqasim/core/simulation/modes/feeder_drt/mode_choice/FeederDrtModeAvailabilityWrapper.java @@ -1,25 +1,43 @@ package org.eqasim.core.simulation.modes.feeder_drt.mode_choice; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.eqasim.core.simulation.modes.feeder_drt.config.MultiModeFeederDrtConfigGroup; import org.matsim.api.core.v01.population.Person; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; import org.matsim.contribs.discrete_mode_choice.model.mode_availability.ModeAvailability; +import org.matsim.core.config.Config; -import java.util.Collection; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; public class FeederDrtModeAvailabilityWrapper implements ModeAvailability { + private final static Logger logger = LogManager.getLogger(FeederDrtModeAvailabilityWrapper.class); private final Set extraModes; private final ModeAvailability delegate; + public FeederDrtModeAvailabilityWrapper(Config config, ModeAvailability delegate) { + this((MultiModeDrtConfigGroup) config.getModules().get(MultiModeDrtConfigGroup.GROUP_NAME), (MultiModeFeederDrtConfigGroup) config.getModules().get(MultiModeFeederDrtConfigGroup.GROUP_NAME), delegate); + } + public FeederDrtModeAvailabilityWrapper(MultiModeDrtConfigGroup multiModeDrtConfigGroup, MultiModeFeederDrtConfigGroup multiModeFeederDrtConfigGroup, ModeAvailability delegate) { this.delegate = delegate; - this.extraModes = multiModeFeederDrtConfigGroup.modes().collect(Collectors.toSet()); - Collection coveredDrtModes = multiModeFeederDrtConfigGroup.getModalElements().stream().map(cfg -> cfg.accessEgressModeName).toList(); - this.extraModes.addAll(multiModeDrtConfigGroup.modes().filter(mode -> !coveredDrtModes.contains(mode)).toList()); + Collection coveredDrtModes; + if(multiModeFeederDrtConfigGroup == null) { + this.extraModes = new HashSet<>(); + coveredDrtModes = Collections.emptyList(); + } else { + this.extraModes = multiModeFeederDrtConfigGroup.modes().collect(Collectors.toSet()); + coveredDrtModes = multiModeFeederDrtConfigGroup.getModalElements().stream().map(cfg -> cfg.accessEgressModeName).toList(); + } + if(multiModeDrtConfigGroup == null) { + if(multiModeFeederDrtConfigGroup != null) { + logger.warn(String.format("A %s config was supplied but a %s was not, DRT modes not covered by a feeder mode will not be considered", MultiModeFeederDrtConfigGroup.GROUP_NAME, MultiModeDrtConfigGroup.GROUP_NAME)); + } + } else { + this.extraModes.addAll(multiModeDrtConfigGroup.modes().filter(mode -> !coveredDrtModes.contains(mode)).toList()); + } } @Override diff --git a/core/src/test/java/org/eqasim/TestSimulationPipeline.java b/core/src/test/java/org/eqasim/TestSimulationPipeline.java index 1c6293a6e..154d65025 100644 --- a/core/src/test/java/org/eqasim/TestSimulationPipeline.java +++ b/core/src/test/java/org/eqasim/TestSimulationPipeline.java @@ -1,5 +1,7 @@ package org.eqasim; +import com.google.inject.Inject; +import com.google.inject.Provider; import org.apache.commons.io.FileUtils; import org.eqasim.core.analysis.run.RunLegAnalysis; import org.eqasim.core.analysis.run.RunPublicTransportLegAnalysis; @@ -13,6 +15,7 @@ import org.eqasim.core.simulation.modes.drt.analysis.run.RunDrtPassengerAnalysis; import org.eqasim.core.simulation.modes.drt.analysis.run.RunDrtVehicleAnalysis; import org.eqasim.core.simulation.modes.feeder_drt.analysis.run.RunFeederDrtPassengerAnalysis; +import org.eqasim.core.simulation.modes.feeder_drt.mode_choice.FeederDrtModeAvailabilityWrapper; import org.eqasim.core.simulation.modes.feeder_drt.utils.AdaptConfigForFeederDrt; import org.eqasim.core.tools.*; import org.eqasim.core.simulation.modes.drt.utils.AdaptConfigForDrt; @@ -22,6 +25,7 @@ import org.junit.Test; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.TransportMode; +import org.matsim.contribs.discrete_mode_choice.model.mode_availability.ModeAvailability; import org.matsim.core.config.CommandLine; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; @@ -49,7 +53,7 @@ public void tearDown() throws IOException { FileUtils.deleteDirectory(new File("melun_test")); } - private void runMelunSimulation(String configPath, String outputPath, Collection extraModes) { + private void runMelunSimulation(String configPath, String outputPath) { EqasimConfigurator eqasimConfigurator = new EqasimConfigurator(); Config config = ConfigUtils.loadConfig(configPath, eqasimConfigurator.getConfigGroups()); ((ControlerConfigGroup) config.getModules().get(ControlerConfigGroup.GROUP_NAME)).setOutputDirectory(outputPath); @@ -69,19 +73,25 @@ private void runMelunSimulation(String configPath, String outputPath, Collection @Override protected void installEqasimExtension() { bind(ModeParameters.class); - bindModeAvailability("DefaultModeAvailability").toProvider(() -> (person, trips) -> { - Set modes = new HashSet<>(); - modes.add(TransportMode.walk); - modes.add(TransportMode.pt); - modes.add(TransportMode.car); - modes.add(TransportMode.bike); - // Add special mode "car_passenger" if applicable - Boolean isCarPassenger = (Boolean) person.getAttributes().getAttribute("isPassenger"); - if(isCarPassenger) { - modes.add("car_passenger"); + bindModeAvailability("DefaultModeAvailability").toProvider(new Provider<>() { + @Inject + private Config config; + @Override + public ModeAvailability get() { + return new FeederDrtModeAvailabilityWrapper(config, (person, trips) -> { + Set modes = new HashSet<>(); + modes.add(TransportMode.walk); + modes.add(TransportMode.pt); + modes.add(TransportMode.car); + modes.add(TransportMode.bike); + // Add special mode "car_passenger" if applicable + Boolean isCarPassenger = (Boolean) person.getAttributes().getAttribute("isPassenger"); + if(isCarPassenger) { + modes.add("car_passenger"); + } + return modes; + }); } - modes.addAll(extraModes); - return modes; }).asEagerSingleton(); } }); @@ -194,7 +204,7 @@ public void testDrt() throws IOException, CommandLine.ConfigurationException { "--vehicles-paths", "melun_test/input/drt_vehicles_a.xml.gz,melun_test/input/drt_vehicles_b.xml.gz" }); - runMelunSimulation("melun_test/input/config_drt.xml", "melun_test/output_drt", List.of("drt_a", "drt_b")); + runMelunSimulation("melun_test/input/config_drt.xml", "melun_test/output_drt"); RunDrtPassengerAnalysis.main(new String[] { "--events-path", "melun_test/output_drt/output_events.xml.gz", @@ -243,7 +253,7 @@ public void testFeeder() throws IOException, CommandLine.ConfigurationException "--access-egress-transit-stop-modes", "rail|tram|subway" }); - runMelunSimulation("melun_test/input/config_feeder.xml", "melun_test/output_feeder", List.of("feeder_a", "feeder_b")); + runMelunSimulation("melun_test/input/config_feeder.xml", "melun_test/output_feeder"); RunFeederDrtPassengerAnalysis.main(new String[] { "--config-path", "melun_test/input/config_feeder.xml", @@ -260,12 +270,12 @@ public void testEpsilon() throws CommandLine.ConfigurationException { "--output-config-path", "melun_test/input/config_epsilon.xml" }); - runMelunSimulation("melun_test/input/config_epsilon.xml", "melun_test/output_epsilon", Collections.emptyList()); + runMelunSimulation("melun_test/input/config_epsilon.xml", "melun_test/output_epsilon"); } @Test public void testPipeline() throws Exception { - runMelunSimulation("melun_test/input/config.xml", "melun_test/output", Collections.emptyList()); + runMelunSimulation("melun_test/input/config.xml", "melun_test/output"); runAnalyses(); runExports(); }