Commit fdabf4c6 authored by Sebastian Hörl's avatar Sebastian Hörl
Browse files

Merge branch 'one-operator' into 'master'

One operator

See merge request !1
parents 45c0076c dba72c92
import pandas as pd
import geopandas as gpd
import numpy as np
import shapely.geometry as geo
import sys
operating_areas_path = sys.argv[1]
output_path = sys.argv[2]
service_area_attribute_name = sys.argv[3]
waiting_time_zone_attribute_name = sys.argv[4]
hexagon_radius = int(sys.argv[5])
df_operating_areas = gpd.read_file(operating_areas_path)
corners = [
np.array([np.cos(30.0 * np.pi / 180.0), np.sin(30.0 * np.pi / 180.0)]) * hexagon_radius,
np.array([np.cos(90.0 * np.pi / 180.0), np.sin(90.0 * np.pi / 180.0)]) * hexagon_radius,
np.array([np.cos(150.0 * np.pi / 180.0), np.sin(150.0 * np.pi / 180.0)]) * hexagon_radius,
np.array([np.cos(210.0 * np.pi / 180.0), np.sin(210.0 * np.pi / 180.0)]) * hexagon_radius,
np.array([np.cos(270.0 * np.pi / 180.0), np.sin(270.0 * np.pi / 180.0)]) * hexagon_radius,
np.array([np.cos(330.0 * np.pi / 180.0), np.sin(330.0 * np.pi / 180.0)]) * hexagon_radius
]
offset_x = 2.0 * hexagon_radius * np.cos(30.0 * np.pi / 180.0)
t = 2.0 * hexagon_radius * np.cos(30.0 * np.pi / 180.0) / np.sqrt(3.0)
offset_y = hexagon_radius + 0.5 * t
geometry = []
for area_name, area_geometry in zip(df_operating_areas[service_area_attribute_name], df_operating_areas["geometry"]):
min_x, min_y, max_x, max_y = area_geometry.bounds
max_i = int(np.ceil((max_x - min_x) / offset_x)) + 1
max_j = int(np.ceil((max_y - min_y) / offset_y)) + 1
index = 0
for i in range(max_i):
for j in range(max_j):
centroid = np.array([
min_x + offset_x * i + (0.5 * offset_x if j % 2 == 0 else 0.0),
min_y + offset_y * j
])
hexagon = geo.Polygon(corners + centroid)
if hexagon.intersects(area_geometry):
geometry.append((area_name, "%s_%d" % (area_name, index), hexagon))
index += 1
df = pd.DataFrame.from_records(geometry, columns = [service_area_attribute_name, waiting_time_zone_attribute_name, "geometry"])
df = gpd.GeoDataFrame(df, crs = {"init": "EPSG:2056"})
df.to_file(output_path)
package ch.ethz.matsim.projects.astra_2018_002;
import org.matsim.core.config.ReflectiveConfigGroup;
public class ASTRAConfigGroup extends ReflectiveConfigGroup {
public final static String GROUP_NAME = "astra";
private final static String TAXI_FLEET_SIZE = "taxiFleetSize";
private final static String POOLED_FLEET_SIZE = "pooledFleetSize";
private final static String SERVICE_AREA_ATTRIBUTE = "serviceAreaAttribute";
private final static String ACTIVE_SERVICE_AREA = "activeServiceArea";
private final static String SERVICE_AREA_SHAPEFILE = "serviceAreaShapefile";
private final static String WAITING_TIME_ZONE_SHAPEFILE = "waitingTimeZoneShapefile";
private final static String WAITING_TIME_ZONE_IDENTIFIER_ATTRIBUTE = "waitingTimeZoneIdentifierAttribute";
private int taxiFleetSize = 100;
private int pooledFleetSize = 0;
private String serviceAreaAttribute = "OAREA";
private String activeServiceArea = "ZH";
private String serviceAreaShapefile = "service_area.shp";
private String waitingTimeZoneIdentifierAttribute = "WZONE";
private String waitingTimeZoneShapefile = "waiting_time_areas.shp";
public ASTRAConfigGroup() {
super(GROUP_NAME);
}
@StringGetter(TAXI_FLEET_SIZE)
public int getTaxiFleetSize() {
return taxiFleetSize;
}
@StringSetter(TAXI_FLEET_SIZE)
public void setTaxiFleetSize(int taxiFleetSize) {
this.taxiFleetSize = taxiFleetSize;
}
@StringGetter(POOLED_FLEET_SIZE)
public int getPooledFleetSize() {
return pooledFleetSize;
}
@StringSetter(POOLED_FLEET_SIZE)
public void setPooledFleetSize(int pooledFleetSize) {
this.pooledFleetSize = pooledFleetSize;
}
@StringGetter(SERVICE_AREA_ATTRIBUTE)
public String getServiceAreaAttribute() {
return serviceAreaAttribute;
}
@StringSetter(SERVICE_AREA_ATTRIBUTE)
public void setServiceAreaAttribute(String serviceAreaAttribute) {
this.serviceAreaAttribute = serviceAreaAttribute;
}
@StringGetter(ACTIVE_SERVICE_AREA)
public String getActiveServiceArea() {
return activeServiceArea;
}
@StringSetter(ACTIVE_SERVICE_AREA)
public void setActiveServiceArea(String activeServiceArea) {
this.activeServiceArea = activeServiceArea;
}
@StringGetter(SERVICE_AREA_SHAPEFILE)
public String getServiceAreaShapefile() {
return serviceAreaShapefile;
}
@StringSetter(SERVICE_AREA_SHAPEFILE)
public void setServiceAreaShapefile(String serviceAreaShapefile) {
this.serviceAreaShapefile = serviceAreaShapefile;
}
@StringGetter(WAITING_TIME_ZONE_SHAPEFILE)
public String getWaitingTimeZoneShapefile() {
return waitingTimeZoneShapefile;
}
@StringSetter(WAITING_TIME_ZONE_SHAPEFILE)
public void setWaitingTimeZoneShapefile(String waitingTimeZoneShapefile) {
this.waitingTimeZoneShapefile = waitingTimeZoneShapefile;
}
@StringGetter(WAITING_TIME_ZONE_IDENTIFIER_ATTRIBUTE)
public String getWaitingTimeZoneIdentifierAttribute() {
return waitingTimeZoneIdentifierAttribute;
}
@StringSetter(WAITING_TIME_ZONE_IDENTIFIER_ATTRIBUTE)
public void setWaitingTimeZoneIdentifierAttribute(String waitingTimeZoneIdentifierAttribute) {
this.waitingTimeZoneIdentifierAttribute = waitingTimeZoneIdentifierAttribute;
}
}
package ch.ethz.matsim.projects.astra_2018_002;
import java.util.ArrayList;
import java.util.Collection;
import org.matsim.contrib.dynagent.run.DynActivityEnginePlugin;
import org.matsim.core.config.Config;
import org.matsim.core.controler.AbstractModule;
import org.matsim.core.mobsim.qsim.AbstractQSimPlugin;
import org.matsim.core.mobsim.qsim.PopulationPlugin;
import org.matsim.core.mobsim.qsim.TeleportationPlugin;
import org.matsim.core.mobsim.qsim.changeeventsengine.NetworkChangeEventsPlugin;
import org.matsim.core.mobsim.qsim.messagequeueengine.MessageQueuePlugin;
import org.matsim.core.mobsim.qsim.qnetsimengine.QNetsimEnginePlugin;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import ch.ethz.matsim.av.framework.AVQSimPlugin;
import ch.ethz.matsim.baseline_scenario.transit.simulation.BaselineTransitPlugin;
import ch.ethz.matsim.projects.astra_2018_002.av.dynamics.AVModesQSimPlugin;
public class ASTRAQSimModule extends AbstractModule {
@Override
public void install() {
}
@Provides
@Singleton
public Collection<AbstractQSimPlugin> provideAbstractQSimPlugins(Config config) {
final Collection<AbstractQSimPlugin> plugins = new ArrayList<>();
plugins.add(new MessageQueuePlugin(config));
plugins.add(new DynActivityEnginePlugin(config));
plugins.add(new QNetsimEnginePlugin(config));
if (config.network().isTimeVariantNetwork()) {
plugins.add(new NetworkChangeEventsPlugin(config));
}
if (config.transit().isUseTransit()) {
plugins.add(new BaselineTransitPlugin(config));
}
plugins.add(new TeleportationPlugin(config));
plugins.add(new PopulationPlugin(config));
plugins.add(new AVQSimPlugin(config));
plugins.add(new AVModesQSimPlugin(config));
return plugins;
}
}
package ch.ethz.matsim.projects.astra_2018_002;
import java.io.File;
import org.matsim.api.core.v01.Scenario;
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
import org.matsim.contrib.dvrp.trafficmonitoring.DvrpTravelTimeModule;
......@@ -17,9 +15,8 @@ import ch.ethz.matsim.baseline_scenario.config.CommandLine.ConfigurationExceptio
import ch.ethz.matsim.baseline_scenario.transit.BaselineTransitModule;
import ch.ethz.matsim.baseline_scenario.transit.routing.DefaultEnrichedTransitRoute;
import ch.ethz.matsim.baseline_scenario.transit.routing.DefaultEnrichedTransitRouteFactory;
import ch.ethz.matsim.projects.astra_2018_002.av.ASTRAAVModule;
import ch.ethz.matsim.projects.astra_2018_002.av.AVConfigurator;
import ch.ethz.matsim.projects.astra_2018_002.av.operating_area.OperatingAreaModule;
import ch.ethz.matsim.projects.astra_2018_002.av.operator.OperatorModule;
import ch.ethz.matsim.projects.astra_2018_002.flow_efficiency.FlowEfficiencyConfigurator;
import ch.ethz.matsim.projects.astra_2018_002.mode_choice.SwissDiscreteModeChoiceModule;
import ch.ethz.matsim.projects.astra_2018_002.mode_choice.SwissModeChoiceConfigurator;
......@@ -30,12 +27,21 @@ public class RunASTRA2018002 {
static public void main(String[] args) throws ConfigurationException {
CommandLine cmd = new CommandLine.Builder(args) //
.requireOptions("config-path", "model") //
.allowOptions("use-route-choice", "use-only-significant", "operator-path") //
.allowOptions("use-route-choice", "use-only-significant") //
.build();
ASTRAConfigGroup astraConfig = new ASTRAConfigGroup();
astraConfig.setActiveServiceArea("zurich");
astraConfig.setPooledFleetSize(0);
astraConfig.setTaxiFleetSize(100);
astraConfig.setServiceAreaShapefile("gis/operating_areas.shp");
astraConfig.setServiceAreaAttribute("OAREA");
astraConfig.setWaitingTimeZoneShapefile("gis/waiting_time_areas.shp");
astraConfig.setWaitingTimeZoneIdentifierAttribute("WZONE");
// Load config
Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path"), new DvrpConfigGroup(),
new AVConfigGroup());
new AVConfigGroup(), astraConfig);
// Adjust config
SwissModeChoiceConfigurator.configure(config);
......@@ -56,13 +62,12 @@ public class RunASTRA2018002 {
// Set up controller
Controler controler = new Controler(scenario);
controler.addOverridingModule(new DvrpTravelTimeModule());
controler.addOverridingModule(new SwissRailRaptorModule());
controler.addOverridingModule(new DvrpTravelTimeModule());
controler.addOverridingModule(new AVModule());
controler.addOverridingModule(new OperatingAreaModule());
controler.addOverridingModule(new OperatorModule(cmd.getOption("operator-path").map(File::new)));
controler.addOverridingModule(new ASTRAAVModule());
controler.addOverridingModule(new BaselineTransitModule());
// TODO: Consolidate QSim plugins
controler.addOverridingModule(new ASTRAQSimModule());
UtilitySet utilitySet = Enum.valueOf(UtilitySet.class, cmd.getOptionStrict("model"));
boolean useRouteChoice = cmd.getOption("use-route-choice").map(Boolean::parseBoolean).orElse(true);
......
package ch.ethz.matsim.projects.astra_2018_002.av;
import java.net.URL;
import java.util.List;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.PopulationFactory;
import org.matsim.core.config.ConfigGroup;
import org.matsim.core.controler.OutputDirectoryHierarchy;
import org.matsim.core.router.DijkstraFactory;
import org.matsim.core.router.RoutingModule;
import org.matsim.core.router.costcalculators.OnlyTimeDependentTravelDisutility;
import org.matsim.core.router.util.LeastCostPathCalculator;
import org.matsim.core.router.util.TravelTime;
import com.google.inject.Key;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import ch.ethz.matsim.av.config.AVConfig;
import ch.ethz.matsim.av.config.AVGeneratorConfig;
import ch.ethz.matsim.av.config.AVOperatorConfig;
import ch.ethz.matsim.av.framework.AVModule;
import ch.ethz.matsim.av.framework.AVUtils;
import ch.ethz.matsim.av.routing.AVRouteFactory;
import ch.ethz.matsim.discrete_mode_choice.modules.AbstractDiscreteModeChoiceExtension;
import ch.ethz.matsim.projects.astra_2018_002.ASTRAConfigGroup;
import ch.ethz.matsim.projects.astra_2018_002.av.analysis.WaitingTimeListener;
import ch.ethz.matsim.projects.astra_2018_002.av.routing.ASTRAAVRoutingModule;
import ch.ethz.matsim.projects.astra_2018_002.av.service_area.ServiceArea;
import ch.ethz.matsim.projects.astra_2018_002.av.service_area.ServiceAreaConstraint;
import ch.ethz.matsim.projects.astra_2018_002.av.service_area.ServiceAreaGenerator;
import ch.ethz.matsim.projects.astra_2018_002.av.service_area.ServiceAreaReader;
import ch.ethz.matsim.projects.astra_2018_002.av.waiting_time.AVWaitingTime;
import ch.ethz.matsim.projects.astra_2018_002.av.waiting_time.zonal.WaitingTimeZone;
import ch.ethz.matsim.projects.astra_2018_002.av.waiting_time.zonal.WaitingTimeZoneReader;
import ch.ethz.matsim.projects.astra_2018_002.av.waiting_time.zonal.ZonalWaitingTime;
public class ASTRAAVModule extends AbstractDiscreteModeChoiceExtension {
public static final String CONSTRAINT_NAME = "ASTRA";
public static final String GENERATOR_NAME = "ASTRA";
public static final String AV_TAXI = "av_taxi";
public static final String AV_POOL = "av_pool";
public static final String WAITING_TIME_GROUP_ATTRIBUTE = "waitingTimeGroup";
@Override
protected void installExtension() {
bindTripConstraintFactory(CONSTRAINT_NAME).to(ServiceAreaConstraint.Factory.class);
AVUtils.registerGeneratorFactory(binder(), GENERATOR_NAME, ServiceAreaGenerator.Factory.class);
addControlerListenerBinding().to(AVNetworkWriter.class);
bind(Key.get(TravelTime.class, Names.named(AV_TAXI)))
.to(Key.get(TravelTime.class, Names.named(TransportMode.car)));
bind(Key.get(TravelTime.class, Names.named(AV_POOL)))
.to(Key.get(TravelTime.class, Names.named(TransportMode.car)));
addEventHandlerBinding().to(Key.get(ZonalWaitingTime.class, Names.named(AV_TAXI)));
addEventHandlerBinding().to(Key.get(ZonalWaitingTime.class, Names.named(AV_POOL)));
addControlerListenerBinding().to(Key.get(ZonalWaitingTime.class, Names.named(AV_TAXI)));
addControlerListenerBinding().to(Key.get(ZonalWaitingTime.class, Names.named(AV_POOL)));
bind(Key.get(AVWaitingTime.class, Names.named(AV_TAXI)))
.to(Key.get(ZonalWaitingTime.class, Names.named(AV_TAXI)));
bind(Key.get(AVWaitingTime.class, Names.named(AV_POOL)))
.to(Key.get(ZonalWaitingTime.class, Names.named(AV_POOL)));
addControlerListenerBinding().to(WaitingTimeListener.class);
}
@Provides
@Named(AV_TAXI)
public RoutingModule provideAvTaxiRoutingModule(PopulationFactory populationFactory, AVRouteFactory routeFactory,
@Named(TransportMode.walk) RoutingModule walkRoutingModule, @Named(AVModule.AV_MODE) Network network,
@Named(AV_TAXI) AVWaitingTime waitingTime, @Named(AV_TAXI) TravelTime travelTime) {
LeastCostPathCalculator router = new DijkstraFactory().createPathCalculator(network,
new OnlyTimeDependentTravelDisutility(travelTime), travelTime);
return new ASTRAAVRoutingModule(AV_TAXI, populationFactory, routeFactory, walkRoutingModule, router, network,
travelTime, waitingTime);
}
@Provides
@Named(AV_POOL)
public RoutingModule provideAvPoolRoutingModule(PopulationFactory populationFactory, AVRouteFactory routeFactory,
@Named(TransportMode.walk) RoutingModule walkRoutingModule, @Named(AVModule.AV_MODE) Network network,
@Named(AV_POOL) AVWaitingTime waitingTime, @Named(AV_POOL) TravelTime travelTime) {
LeastCostPathCalculator router = new DijkstraFactory().createPathCalculator(network,
new OnlyTimeDependentTravelDisutility(travelTime), travelTime);
return new ASTRAAVRoutingModule(AV_POOL, populationFactory, routeFactory, walkRoutingModule, router, network,
travelTime, waitingTime);
}
@Provides
@Singleton
public ServiceAreaConstraint.Factory provideOperatingAreaConstraintFactory(ServiceArea registry) {
return new ServiceAreaConstraint.Factory(registry);
}
@Provides
@Singleton
public ServiceArea provideServiceArea(@Named(AVModule.AV_MODE) Network network, ASTRAConfigGroup astraConfig) {
ServiceAreaReader reader = new ServiceAreaReader(astraConfig.getServiceAreaAttribute(), network);
URL url = ConfigGroup.getInputFileURL(getConfig().getContext(), astraConfig.getServiceAreaShapefile());
return reader.read(astraConfig.getActiveServiceArea(), url);
}
@Provides
@Singleton
public AVConfig provideAVConfig(ASTRAConfigGroup astraConfig) {
AVConfig avConfig = new AVConfig();
AVOperatorConfig taxiConfig = avConfig.createOperatorConfig(ASTRAAVModule.AV_TAXI);
AVGeneratorConfig taxiGeneratorConfig = taxiConfig.createGeneratorConfig(ASTRAAVModule.GENERATOR_NAME);
taxiGeneratorConfig.setNumberOfVehicles(astraConfig.getTaxiFleetSize());
taxiConfig.createDispatcherConfig("SingleHeuristic");
taxiConfig.createPriceStructureConfig();
AVOperatorConfig poolConfig = avConfig.createOperatorConfig(ASTRAAVModule.AV_POOL);
AVGeneratorConfig poolGeneratorConfig = poolConfig.createGeneratorConfig(ASTRAAVModule.GENERATOR_NAME);
poolGeneratorConfig.setNumberOfVehicles(astraConfig.getPooledFleetSize());
poolConfig.createDispatcherConfig("MultiOD");
poolConfig.createPriceStructureConfig();
return avConfig;
}
@Provides
@Singleton
public List<WaitingTimeZone> provideWaitingTimeZones(@Named(AVModule.AV_MODE) Network network,
ASTRAConfigGroup astraConfig) {
WaitingTimeZoneReader reader = new WaitingTimeZoneReader(astraConfig.getWaitingTimeZoneIdentifierAttribute(),
astraConfig.getServiceAreaAttribute(), network);
URL url = ConfigGroup.getInputFileURL(getConfig().getContext(), astraConfig.getWaitingTimeZoneShapefile());
return reader.read(astraConfig.getActiveServiceArea(), url);
}
@Provides
@Singleton
@Named(AV_TAXI)
private ZonalWaitingTime provideAvTaxiWaitingTime(@Named(AVModule.AV_MODE) Network network,
List<WaitingTimeZone> waitingTimeZones) {
return provideAvWaitingTime(AV_TAXI, network, waitingTimeZones);
}
@Provides
@Singleton
@Named(AV_POOL)
private ZonalWaitingTime provideAvPoolWaitingTime(@Named(AVModule.AV_MODE) Network network,
List<WaitingTimeZone> waitingTimeZones) {
return provideAvWaitingTime(AV_POOL, network, waitingTimeZones);
}
private ZonalWaitingTime provideAvWaitingTime(String mode, Network network,
List<WaitingTimeZone> waitingTimeZones) {
double estimationStartTime = 8.0 * 3600.0;
double estimationEndTime = 22.0 * 3600.0;
double estimationInterval = 900.0;
int horizon = 10;
double defaultWaitingTime = 300.0;
return new ZonalWaitingTime(mode, estimationStartTime, estimationEndTime, estimationInterval, horizon,
defaultWaitingTime, network, waitingTimeZones);
}
@Provides
@Singleton
public WaitingTimeListener provideWaitingTimeListener(@Named(AV_TAXI) AVWaitingTime taxiWaitingTime,
@Named(AV_POOL) AVWaitingTime poolWaitingTime, List<WaitingTimeZone> waitingTimeZones,
OutputDirectoryHierarchy outputHierarchy) {
return new WaitingTimeListener(taxiWaitingTime, poolWaitingTime, waitingTimeZones, outputHierarchy);
}
}
package ch.ethz.matsim.projects.astra_2018_002.av;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.matsim.core.config.Config;
import org.matsim.core.config.groups.PlanCalcScoreConfigGroup.ModeParams;
import ch.ethz.matsim.av.framework.AVModule;
import ch.ethz.matsim.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup;
import ch.ethz.matsim.projects.astra_2018_002.ASTRAConfigGroup;
public class AVConfigurator {
static public void configure(Config config) {
ASTRAConfigGroup astraConfig = (ASTRAConfigGroup) config.getModules().get(ASTRAConfigGroup.GROUP_NAME);
if (astraConfig == null) {
astraConfig = new ASTRAConfigGroup();
config.addModule(astraConfig);
}
ModeParams avParams = new ModeParams(AVModule.AV_MODE);
config.planCalcScore().addModeParams(avParams);
ModeParams poolParams = new ModeParams(ASTRAAVModule.AV_POOL);
config.planCalcScore().addModeParams(poolParams);
ModeParams taxiParams = new ModeParams(ASTRAAVModule.AV_TAXI);
config.planCalcScore().addModeParams(taxiParams);
DiscreteModeChoiceConfigGroup dmcConfig = (DiscreteModeChoiceConfigGroup) config.getModules()
.get(DiscreteModeChoiceConfigGroup.GROUP_NAME);
Set<String> availableModes = new HashSet<>(dmcConfig.getCarModeAvailabilityConfig().getAvailableModes());
if (astraConfig.getTaxiFleetSize() > 0) {
availableModes.add(ASTRAAVModule.AV_TAXI);
}
if (astraConfig.getPooledFleetSize() > 0) {
availableModes.add(ASTRAAVModule.AV_POOL);
}
Collection<String> tripConstraints = new HashSet<>(dmcConfig.getTripConstraints());
tripConstraints.add(ASTRAAVModule.CONSTRAINT_NAME);
dmcConfig.setTripConstraints(tripConstraints);
dmcConfig.getCarModeAvailabilityConfig().setAvailableModes(availableModes);
}
}
package ch.ethz.matsim.projects.astra_2018_002.av;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.network.NetworkWriter;
import org.matsim.core.controler.OutputDirectoryHierarchy;
import org.matsim.core.controler.events.StartupEvent;
import org.matsim.core.controler.listener.StartupListener;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import ch.ethz.matsim.av.framework.AVModule;
public class AVNetworkWriter implements StartupListener {
private final OutputDirectoryHierarchy hierarchy;
private final Network network;
@Inject
public AVNetworkWriter(OutputDirectoryHierarchy hierarchy, @Named(AVModule.AV_MODE) Network network) {
this.hierarchy = hierarchy;
this.network = network;
}
@Override
public void notifyStartup(StartupEvent event) {
new NetworkWriter(network).write(hierarchy.getOutputFilename("av_network.xml.gz"));
}
}
package ch.ethz.matsim.projects.astra_2018_002.av.analysis;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.List;
import java.util.Optional;
import org.matsim.api.core.v01.network.Link;
import org.matsim.core.controler.OutputDirectoryHierarchy;
import org.matsim.core.controler.events.IterationEndsEvent;
import org.matsim.core.controler.listener.IterationEndsListener;
import org.matsim.core.router.LinkWrapperFacility;
import org.matsim.core.utils.misc.Time;
import ch.ethz.matsim.projects.astra_2018_002.av.waiting_time.AVWaitingTime;
import ch.ethz.matsim.projects.astra_2018_002.av.waiting_time.zonal.WaitingTimeZone;
public class WaitingTimeListener implements IterationEndsListener {
private final static String FILE_NAME = "waiting_times.csv";
private final List<WaitingTimeZone> waitingTimeZones;
private final AVWaitingTime taxiWaitingTime;
private final AVWaitingTime poolWaitingTime;
private final OutputDirectoryHierarchy outputHierarchy;
public WaitingTimeListener(AVWaitingTime taxiWaitingTime, AVWaitingTime poolWaitingTime,
List<WaitingTimeZone> waitingTimeZones, OutputDirectoryHierarchy outputHierarchy) {
this.taxiWaitingTime = taxiWaitingTime;
this.poolWaitingTime = poolWaitingTime;
this.waitingTimeZones = waitingTimeZones;
this.outputHierarchy = outputHierarchy;