/// <summary> /// Get a stops reader for all the loaded databases. /// </summary> /// <returns></returns> public IStopsReader GetStopsReader() { var newReader = StopsReaderAggregator.CreateFrom( All().Select(tdb => (IStopsReader)tdb.StopsDb.GetReader()).ToList()); if (_cachedStopsReader == null) { _cachedStopsReader = newReader.UseCache(); return(_cachedStopsReader); } // Return a new stospReader which shares the cache with the already existing cache return(new StopSearchCache(newReader, _cachedStopsReader)); }
BuildJourneys(this RealLifeProfile p, string @from, string to, DateTime?departure, DateTime?arrival, bool multipleOptions, Dictionary <string, string> logMessage) { if (departure == null && arrival == null) { throw new ArgumentException( "At least one date should be given, either departure time or arrival time (or both)"); } departure = departure?.ToUniversalTime(); arrival = arrival?.ToUniversalTime(); var reader = p.OperatorSet.GetStopsReader(); var osmIndex = reader.DatabaseIndexes().Max() + 1u; var stopsReader = StopsReaderAggregator.CreateFrom(new List <IStopsReader> { reader, new OsmLocationStopReader(osmIndex, true), }).UseCache(); // We cache here only for this request- only case cache will be missed is around the new stop locations // Calculate the first and last miles, in order to // 1) Detect impossible routes // 2) cache them stopsReader.MoveTo(from); var fromStop = new Stop(stopsReader); stopsReader.MoveTo(to); var toStop = new Stop(stopsReader); p.DetectFirstMileWalks(stopsReader, fromStop, osmIndex, false, "departure"); p.DetectFirstMileWalks(stopsReader, toStop, osmIndex, true, "arrival"); var precalculator = p.OperatorSet.All() .SelectProfile(p) .SetStopsReader(stopsReader) .SelectStops(from, to); var directRoute = CalculateDirectRoute(p, precalculator, fromStop, toStop); WithTime <TransferMetric> calculator; if (departure == null) { // Departure time is null // We calculate one with a latest arrival scan search calculator = precalculator.SelectTimeFrame(arrival.Value.AddDays(-1), arrival.Value); // This will set the time frame correctly var latest = calculator .CalculateLatestDepartureJourney(tuple => tuple.journeyStart - p.SearchLengthCalculator(tuple.journeyStart, tuple.journeyEnd)); if (!multipleOptions) { return(new List <Journey <TransferMetric> > { latest }, directRoute, latest.Root.Time.FromUnixTime(), latest.Time.FromUnixTime()); } } else if (arrival == null || !multipleOptions) { calculator = precalculator.SelectTimeFrame(departure.Value, departure.Value.AddDays(1)); // We do an earliest arrival search in a timewindow of departure time -> latest arrival time (eventually with arrival + 1 day) // This scan is extended for some time, in order to have both // - the automatically calculated latest arrival time // - an isochrone line in order to optimize later on var earliestArrivalJourney = calculator.CalculateEarliestArrivalJourney( tuple => tuple.journeyStart + p.SearchLengthCalculator(tuple.journeyStart, tuple.journeyEnd)); if (earliestArrivalJourney == null) { return(new List <Journey <TransferMetric> >(), directRoute, DateTime.MaxValue, DateTime.MinValue); } logMessage.Add("earliestArrivalJourney:departure", earliestArrivalJourney.Root.Time.FromUnixTime().ToString("s")); logMessage.Add("earliestArrivalJourney:arrival", earliestArrivalJourney.Time.FromUnixTime().ToString("s")); if (!multipleOptions) { return(new List <Journey <TransferMetric> > { earliestArrivalJourney }, directRoute, earliestArrivalJourney.Root.Time.FromUnixTime(), earliestArrivalJourney.Time.FromUnixTime()); } } else { calculator = precalculator.SelectTimeFrame(departure.Value, arrival.Value); // Perform isochrone to speed up 'all journeys' calculator.CalculateIsochroneFrom(); } // We lower the max number of transfers to speed up calculations // p.ApplyMaxNumberOfTransfers(); logMessage.Add("searchTime:pcs:start", calculator.Start.ToString("s")); logMessage.Add("searchTime:pcs:end", calculator.End.ToString("s")); return(calculator.CalculateAllJourneys(), directRoute, calculator.Start, calculator.End); }