/// <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));
        }
Exemple #2
0
        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);
        }