/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.integration.benchmark; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Random; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.Options; import org.apache.commons.cli.Parser; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.node.ObjectNode; import org.onebusaway.gtfs.model.Stop; import org.onebusaway.gtfs.serialization.GtfsReader; import org.onebusaway.gtfs.services.GenericMutableDao; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; /** * Generate a benchmark plan (see {@link RunBenchmarkPlanMain} from a GTFS feed * by randomly picking pairs of Stops from the feed and generating from-to trip * requests between the pairs. The resulting trip plan file can be fed into * {@link RunBenchmarkPlanMain} to run a benchmark of those plans. * * @author bdferris * */ public class GenerateBenchmarkPlanMain { private static final String ARG_TIME = "time"; private static final String ARG_SAMPLES = "samples"; private static final String ARG_LAT_NOISE = "latNoise"; private static final String ARG_LON_NOISE = "lonNoise"; private static final String ARG_ENVELOPE = "envelope"; public static void main(String[] args) throws Exception { Options options = new Options(); options.addOption(ARG_TIME, true, "time to plan trip"); options.addOption(ARG_SAMPLES, true, "number of samples to generate"); options.addOption(ARG_LAT_NOISE, true, "lat noise"); options.addOption(ARG_LON_NOISE, true, "lon noise"); options.addOption(ARG_ENVELOPE, true, "envelope"); Parser parser = new GnuParser(); CommandLine cli = parser.parse(options, args); args = cli.getArgs(); if (args.length != 2) { System.err.println("usage: input_gtfs output_file"); System.exit(-1); } GenerateBenchmarkPlanMain task = new GenerateBenchmarkPlanMain(); task.setInputPath(new File(args[0])); task.setOutputPath(new File(args[1])); if (cli.hasOption(ARG_TIME)) { Date time = DateLibrary.getIso8601StringAsDate(cli.getOptionValue(ARG_TIME)); task.setTime(time); } if (cli.hasOption(ARG_SAMPLES)) { int samples = Integer.parseInt(cli.getOptionValue(ARG_SAMPLES)); task.setSamples(samples); } if (cli.hasOption(ARG_LAT_NOISE)) task.setLatNoise(Double.parseDouble(cli.getOptionValue(ARG_LAT_NOISE))); if (cli.hasOption(ARG_LON_NOISE)) task.setLatNoise(Double.parseDouble(cli.getOptionValue(ARG_LON_NOISE))); if (cli.hasOption(ARG_ENVELOPE)) { String value = cli.getOptionValue(ARG_ENVELOPE); String[] tokens = value.split(","); if (tokens.length != 4) { System.err.println("usage: -envelope latMin,lonMin,latMax,lonMax"); System.exit(-1); } Coordinate c1 = new Coordinate(Double.parseDouble(tokens[1]), Double.parseDouble(tokens[0])); Coordinate c2 = new Coordinate(Double.parseDouble(tokens[3]), Double.parseDouble(tokens[2])); task.setEnvelope(new Envelope(c1, c2)); } task.run(); } private static Random _random = new Random(); private File _inputPath; private File _outputPath; private Date _time = new Date(); private int _samples = 100; private double _latNoise = 0.0002; private double _lonNoise = 0.002; private Envelope _envelope = null; ObjectMapper mapper = new ObjectMapper(); public void setInputPath(File file) { _inputPath = file; } public void setOutputPath(File file) { _outputPath = file; } public void setTime(Date time) { _time = time; } public void setSamples(int samples) { _samples = samples; } public void setLatNoise(double latNoise) { _latNoise = latNoise; } public void setLonNoise(double lonNoise) { _lonNoise = lonNoise; } public void setEnvelope(Envelope envelope) { _envelope = envelope; } public void run() throws IOException { List<Stop> stops = readStopsFromGtfs(); String timeAsString = DateLibrary.getTimeAsIso8601String(_time); PrintWriter out = new PrintWriter(_outputPath); for (int i = 0; i < _samples; i++) { ObjectNode from = getRandomLocationNearTransitStop(stops); ObjectNode to = getRandomLocationNearTransitStop(stops); ObjectNode row = mapper.createObjectNode(); row.put("from", from); row.put("to", to); row.put("time", timeAsString); out.println(row.toString()); } out.close(); } private List<Stop> readStopsFromGtfs() throws IOException { GtfsReader reader = new GtfsReader(); reader.setDefaultAgencyId("agency"); reader.setInputLocation(_inputPath); // We only want to read in stops List<Class<?>> classes = reader.getEntityClasses(); classes.clear(); classes.add(Stop.class); reader.run(); GenericMutableDao dao = reader.getEntityStore(); Collection<Stop> stops = dao.getAllEntitiesForType(Stop.class); List<Stop> stopsToInclude = new ArrayList<Stop>(); for (Stop stop : stops) { if (_envelope != null) { Coordinate c = new Coordinate(stop.getLon(), stop.getLat()); if (!_envelope.contains(c)) continue; } stopsToInclude.add(stop); } return stopsToInclude; } private ObjectNode getRandomLocationNearTransitStop(List<Stop> stops) { int index = _random.nextInt(stops.size()); Stop stop = stops.get(index); double lat = stop.getLat() + _random.nextGaussian() * _latNoise; double lon = stop.getLon() + _random.nextGaussian() * _lonNoise; ObjectNode obj = mapper.createObjectNode(); obj.put("lat", lat); obj.put("lon", lon); return obj; } }