示例#1
0
        /// <summary>
        /// Loads a GTFS data set.
        /// </summary>
        /// <param name="path">The path of the directory containing the feed or the path to the zip file.</param>
        public static GTFSStorage Load(string path)
        {
            GTFSReader <GTFSFeed> reader = new GTFSReader <GTFSFeed>();
            GTFSFeed feed = reader.Read(path);

            return(new GTFSStorage(feed));
        }
示例#2
0
        public void SetFeedInfoTest()
        {
            // create the feed.
            var feed = new GTFSFeed();

            // create the feed info
            var info = new FeedInfo
            {
                StartDate     = "some start date",
                EndDate       = "some end date",
                Lang          = "some language",
                PublisherName = "some publisher",
                PublisherUrl  = "some url",
                Tag           = new object(),
                Version       = "some version"
            };


            // verify initial state.
            var emptyFeedInfo = new FeedInfo();
            var oldFeedInfo   = feed.GetFeedInfo();

            Assert.IsTrue(_comparer.Equals(emptyFeedInfo, oldFeedInfo));

            // set the feed info.
            feed.SetFeedInfo(info);

            // test result.
            var newFeedInfo = feed.GetFeedInfo();

            Assert.IsTrue(_comparer.Equals(info, newFeedInfo));
        }
        public static TimepointStrategy GetTimepointStrategy(GTFSFeed feed)
        {
            var stopTimes =
                from timesUG in feed.StopTimes
                group timesUG by new
            {
                timesUG.TimepointType,
                HasTime = (timesUG.ArrivalTime != null)
            } into times
                select new Tuple <TimePointType, bool>(
                times.First().TimepointType,
                times.First().ArrivalTime != null
                );

            if (stopTimes.Contains(new Tuple <TimePointType, bool>(TimePointType.Exact, true)))
            {
                return(TimepointStrategy.SpecifiedTimepoints);
            }
            else if (stopTimes.Contains(new Tuple <TimePointType, bool>(TimePointType.None, false)))
            {
                return(TimepointStrategy.NullTimepoints);
            }

            return(TimepointStrategy.SelfSufficient);
        }
        public static List <string> GetScheduleHeader(GTFSFeed feed, string route, DirectionType?dir, TimepointStrategy strat)
        {
            IEnumerable <string> timepointList;

            if (strat == TimepointStrategy.SpecifiedTimepoints)
            {
                timepointList = TimepointFinder.DataTimepoints(feed, route, dir, true)
                                .Select(x => x.Item1);
            }
            else if (strat == TimepointStrategy.NullTimepoints)
            {
                timepointList = TimepointFinder.DataTimepoints(feed, route, dir, true)
                                .Select(x => x.Item1);
            }
            else
            {
                timepointList = TimepointFinder.FirstAndLastStopList(feed, route, dir);
            }

            var timepointsOrdered =
                from stops in StopLister.GetStopOrder(feed, route, dir)
                join timepoints in timepointList on stops.Id equals timepoints
                select stops.Id;

            return(timepointsOrdered.ToList());
        }
示例#5
0
        /// <summary>
        /// Builds a GTFS feed with two connections on the same trip.
        /// </summary>
        /// <returns></returns>
        public static IGTFSFeed TwoConnectionsOneTrip(TimeOfDay departureTime1, TimeOfDay arrivalTime1,
                                                      TimeOfDay departureTime2, TimeOfDay arrivalTime2)
        {
            var feed = new GTFSFeed();

            feed.Agencies.Add(new Agency()
            {
                Id = "0"
            });
            feed.Routes.Add(new global::GTFS.Entities.Route()
            {
                Id       = "0",
                AgencyId = "0"
            });
            feed.Trips.Add(new Trip()
            {
                Id      = "0",
                RouteId = "0"
            });
            feed.Stops.Add(new Stop()
            {
                Id        = "0",
                Longitude = 0,
                Latitude  = 0
            });
            feed.Stops.Add(new Stop()
            {
                Id        = "1",
                Longitude = 1,
                Latitude  = 1
            });
            feed.Stops.Add(new Stop()
            {
                Id        = "2",
                Longitude = 2,
                Latitude  = 2
            });
            feed.StopTimes.Add(new StopTime()
            {
                ArrivalTime   = departureTime1,
                StopId        = "0",
                TripId        = "0",
                DepartureTime = departureTime1
            });
            feed.StopTimes.Add(new StopTime()
            {
                ArrivalTime   = arrivalTime1,
                StopId        = "1",
                TripId        = "0",
                DepartureTime = departureTime2
            });
            feed.StopTimes.Add(new StopTime()
            {
                ArrivalTime   = arrivalTime2,
                StopId        = "2",
                TripId        = "0",
                DepartureTime = arrivalTime2
            });
            return(feed);
        }
示例#6
0
文件: Extensions.cs 项目: vta/GTFS
        /// <summary>
        /// Reads a fead from the given directory.
        /// </summary>
        public static GTFSFeed Read(this GTFSReader <GTFSFeed> reader, DirectoryInfo directory)
        {
            var feed = new GTFSFeed();

            using (var source = new GTFSDirectorySource(directory))
            {
                return(reader.Read(feed, source));
            }
        }
示例#7
0
        /// <summary>
        /// Builds a GTFS feed with just one connection.
        /// </summary>
        /// <returns></returns>
        public static IGTFSFeed OneConnection(TimeOfDay departureTime, TimeOfDay arrivalTime)
        {
            var feed = new GTFSFeed();

            feed.Agencies.Add(new Agency()
            {
                Id = "0"
            });
            feed.Routes.Add(new global::GTFS.Entities.Route()
            {
                Id       = "0",
                AgencyId = "0"
            });
            feed.Trips.Add(new Trip()
            {
                Id        = "0",
                RouteId   = "0",
                ServiceId = "0"
            });
            feed.Stops.Add(new Stop()
            {
                Id        = "0",
                Longitude = 0,
                Latitude  = 0
            });
            feed.Stops.Add(new Stop()
            {
                Id        = "1",
                Longitude = 1,
                Latitude  = 1
            });
            feed.StopTimes.Add(new StopTime()
            {
                ArrivalTime   = departureTime,
                StopId        = "0",
                TripId        = "0",
                DepartureTime = departureTime,
                StopSequence  = 0
            });
            feed.StopTimes.Add(new StopTime()
            {
                ArrivalTime   = arrivalTime,
                StopId        = "1",
                TripId        = "0",
                DepartureTime = arrivalTime,
                StopSequence  = 1
            });
            feed.Calendars.Add(new Calendar()
            {
                StartDate = new System.DateTime(2015, 01, 01),
                EndDate   = new System.DateTime(2015, 12, 31),
                Mask      = 127,
                ServiceId = "0"
            });
            return(feed);
        }
 public static IEnumerable <string> LastStops(GTFSFeed feed, string route, DirectionType?dir)
 {
     return
         (from stopTimesUG in feed.StopTimes
          join trips in feed.Trips on stopTimesUG.TripId equals trips.Id
          where trips.RouteId == route &&
          trips.Direction == dir
          orderby stopTimesUG.StopSequence
          group stopTimesUG by stopTimesUG.TripId into stopTimes
          select stopTimes.Last().StopId);
 }
        public static IEnumerable <string> FirstAndLastStopList(GTFSFeed feed, string route, DirectionType?dir)
        {
            List <string> ret = new List <string>();

            foreach (Tuple <string, string> pair in FirstAndLastStopPairs(feed, route, dir))
            {
                ret.Add(pair.Item1);
                ret.Add(pair.Item2);
            }

            return(ret.Distinct());
        }
示例#10
0
        // public static bool PrintStopLists = true; // this one doesn't do anything atm

        static void Main(string[] args)
        {
            var      reader = new GTFSReader <GTFSFeed>();
            GTFSFeed feed   = reader.Read("gtfs/" + GTFSFilename);

            TimepointStrategy strat = TimepointFinder.GetTimepointStrategy(feed);

            var dateRange = CalendarTester.GetFeedDateRange(feed);

            var allUsedServices =
                from trips in feed.Trips
                group trips by trips.ServiceId into narrowTrips
                let servId = narrowTrips.First().ServiceId
                             select new
            {
                Key   = servId,
                Value = CalendarTester.GetDescription(feed, servId, dateRange)
            };

            Dictionary <string, string> serviceDescriptions = allUsedServices.ToDictionary(x => x.Key, x => x.Value);

            foreach (Route route in feed.Routes)
            {
                // What direction(s) does the route run?
                IEnumerable <DirectionType?> dirs =
                    from trips in feed.Trips
                    where trips.RouteId == route.Id
                    group trips by trips.Direction into narrowTrips
                    select narrowTrips.First().Direction;

                // What service(s) does the route run on?
                IEnumerable <string> services =
                    from trips in feed.Trips
                    where trips.RouteId == route.Id
                    group trips by trips.ServiceId into narrowTrips
                    select narrowTrips.First().ServiceId;

                if (PrintSchedules)
                {
                    using StreamWriter output = new StreamWriter($"output/schedules/{route.Id}.md");

                    output.WriteLine("# " + (route.ShortName ?? "") + ((route.ShortName != null && route.LongName != null) ? " - " : "") + (route.LongName ?? ""));

                    foreach (DirectionType?dir in dirs)
                    {
                        output.WriteLine("## " + dir switch
                        {
                            DirectionType.OneDirection => "Main Direction",
                            DirectionType.OppositeDirection => "Opposite Direction",
                            _ => "No Direction"
                        });
        public static IEnumerable <Tuple <string, bool> > DataTimepoints(GTFSFeed feed, string route, DirectionType?dir, bool strict = false)
        {
            var routeStopTimes =
                from stopTimes in feed.StopTimes
                join trips in feed.Trips on stopTimes.TripId equals trips.Id
                where trips.RouteId == route &&
                trips.Direction == dir
                select stopTimes;

            return
                (from stopTimesUngrouped in routeStopTimes
                 group stopTimesUngrouped by stopTimesUngrouped.StopId into stopTimes
                 where stopTimes.Any(x => x.TimepointType == TimePointType.Exact || (!strict && x.TimepointType == TimePointType.None && x.ArrivalTime != null))
                 select new Tuple <string, bool>(
                     stopTimes.First().StopId,
                     stopTimes.All(x => x.TimepointType == TimePointType.Exact || (!strict && x.TimepointType == TimePointType.None && x.ArrivalTime != null))
                     ));
        }
        public static Dictionary <string, int> GetSortTimes(GTFSFeed feed, string route, DirectionType?dir, List <string> timepoints)
        {
            Dictionary <string, int> times = new Dictionary <string, int>();

            times[timepoints[0]] = 0;

            List <string> checkedTimes = new List <string>();

            bool failedLoop = true;

            while (times.Count < timepoints.Count)
            {
                foreach (string stopFrom in timepoints.Intersect(times.Keys).Except(checkedTimes))
                {
                    failedLoop = false;

                    foreach (string stopTo in timepoints.Except(times.Keys))
                    {
                        var differences =
                            from stopTimesUG in feed.StopTimes
                            join trips in feed.Trips on stopTimesUG.TripId equals trips.Id
                            where trips.RouteId == route && trips.Direction == dir
                            group stopTimesUG by stopTimesUG.TripId into stopTimes
                            where stopTimes.Any(x => x.StopId == stopFrom) && stopTimes.Any(x => x.StopId == stopTo)
                            select stopTimes.Where(x => x.StopId == stopTo).First().ArrivalTime.Value.TotalSeconds
                            - stopTimes.Where(x => x.StopId == stopFrom).First().ArrivalTime.Value.TotalSeconds;

                        if (differences.Any())
                        {
                            times[stopTo] = (int)differences.Average() + times[stopFrom];
                        }
                    }

                    checkedTimes.Add(stopFrom);
                }

                if (failedLoop)
                {
                    times[timepoints.Except(checkedTimes).First()] = 0;
                }
            }

            return(times);
        }
示例#13
0
        /// <summary>
        /// Filters the given feed and returns a filtered version.
        /// </summary>
        /// <param name="feed"></param>
        /// <returns></returns>
        public override IGTFSFeed Filter(IGTFSFeed feed)
        {
            var filteredFeed = new GTFSFeed();

            // filter routes.
            var routeIds = new HashSet<string>();
            var agencyIds = new HashSet<string>();
            foreach (var route in feed.Routes)
            {
                if (_routesFilter.Invoke(route))
                { // keep this route.
                    filteredFeed.Routes.Add(route);
                    routeIds.Add(route.Id);

                    // keep agency ids.
                    agencyIds.Add(route.AgencyId);
                }
            }

            // filter trips.
            var serviceIds = new HashSet<string>();
            var tripIds = new HashSet<string>();
            var shapeIds = new HashSet<string>();
            foreach (var trip in feed.Trips)
            {
                if (routeIds.Contains(trip.RouteId))
                { // keep this trip, it is related to at least one stop-time.
                    filteredFeed.Trips.Add(trip);
                    tripIds.Add(trip.Id);

                    // keep serviceId, routeId and shapeId.
                    serviceIds.Add(trip.ServiceId);
                    if (!string.IsNullOrWhiteSpace(trip.ShapeId))
                    {
                        shapeIds.Add(trip.ShapeId);
                    }
                }
            }

            // filter stop-times.
            var stopIds = new HashSet<string>();
            foreach (var stopTime in feed.StopTimes)
            {
                if (tripIds.Contains(stopTime.TripId))
                { // stop is included, keep this stopTime.
                    filteredFeed.StopTimes.Add(stopTime);

                    // save the trip id's to keep.
                    stopIds.Add(stopTime.StopId);
                }
            }

            // filter stops.
            foreach (var stop in feed.Stops)
            {
                if (stopIds.Contains(stop.Id))
                { // stop has to be included.
                    stopIds.Add(stop.Id);
                    filteredFeed.Stops.Add(stop);
                }
            }

            // filter agencies.
            foreach (var agency in feed.Agencies)
            {
                if (agencyIds.Contains(agency.Id))
                { // keep this agency.
                    filteredFeed.Agencies.Add(agency);
                }
            }

            // filter calendars.
            foreach (var calendar in feed.Calendars)
            {
                if (serviceIds.Contains(calendar.ServiceId))
                { // keep this calendar.
                    filteredFeed.Calendars.Add(calendar);
                }
            }

            // filter calendar-dates.
            foreach (var calendarDate in feed.CalendarDates)
            {
                if (serviceIds.Contains(calendarDate.ServiceId))
                { // keep this calendarDate.
                    filteredFeed.CalendarDates.Add(calendarDate);
                }
            }

            // filter fare rules.
            var fareIds = new HashSet<string>();
            foreach (var fareRule in feed.FareRules)
            {
                if (routeIds.Contains(fareRule.RouteId))
                { // keep this fare rule.
                    filteredFeed.FareRules.Add(fareRule);

                    // keep fare ids.
                    fareIds.Add(fareRule.FareId);
                }
            }

            // filter fare attributes.
            foreach (var fareAttribute in feed.FareAttributes)
            {
                if (fareIds.Contains(fareAttribute.FareId))
                { // keep this fare attribute.
                    filteredFeed.FareAttributes.Add(fareAttribute);
                }
            }

            // filter frequencies.
            foreach (var frequency in feed.Frequencies)
            {
                if (tripIds.Contains(frequency.TripId))
                { // keep this frequency.
                    filteredFeed.Frequencies.Add(frequency);
                }
            }

            foreach (var transfer in feed.Transfers)
            {
                if (stopIds.Contains(transfer.FromStopId) &&
                    stopIds.Contains(transfer.ToStopId))
                {
                    filteredFeed.Transfers.Add(transfer);
                }
            }
            return filteredFeed;
        }
        public static Tuple <List <string>, List <Tuple <string, Dictionary <string, TimeOfDay> > > > GetSchedule(GTFSFeed feed, string route, DirectionType?dir, string serviceId, List <string> stopOrder, Dictionary <string, int> sortTimes)
        {
            var filteredTrips =
                from trips in feed.Trips
                where trips.RouteId == route && trips.Direction == dir && trips.ServiceId == serviceId
                select trips.Id;

            List <Tuple <string, Dictionary <string, TimeOfDay>, int> > tripSchedules = new List <Tuple <string, Dictionary <string, TimeOfDay>, int> >();

            foreach (string tripId in filteredTrips)
            {
                var tripTimes =
                    (from times in feed.StopTimes
                     where times.TripId == tripId && stopOrder.Contains(times.StopId)
                     group times by new { times.TripId, times.StopId } into times2
                     select new
                {
                    times2.First().StopId,
                    times2.First().DepartureTime
                }).ToDictionary(x => x.StopId, x => x.DepartureTime.Value);

                int sortTime = 0;

                foreach (string stopId in stopOrder)
                {
                    if (tripTimes.ContainsKey(stopId))
                    {
                        sortTime = tripTimes[stopId].TotalSeconds - sortTimes[stopId];
                        break;
                    }
                }

                tripSchedules.Add(new Tuple <string, Dictionary <string, TimeOfDay>, int>(tripId, tripTimes, sortTime));
            }

            List <Tuple <string, Dictionary <string, TimeOfDay> > > allTrips =
                (from tripScheds in tripSchedules
                 orderby tripScheds.Item3
                 select new Tuple <string, Dictionary <string, TimeOfDay> >(tripScheds.Item1, tripScheds.Item2)).ToList();

            return(new Tuple <List <string>, List <Tuple <string, Dictionary <string, TimeOfDay> > > >(stopOrder, allTrips));
        }
 public static IEnumerable <Tuple <string, string> > FirstAndLastStopPairs(GTFSFeed feed, Route route, DirectionType?dir)
 => FirstAndLastStopPairs(feed, route.Id, dir);
        public static Tuple <List <string>, List <Tuple <string, Dictionary <string, TimeOfDay> > > > GetSchedule(GTFSFeed feed, string route, DirectionType?dir, string serviceId, TimepointStrategy strat)
        {
            var stops = GetScheduleHeader(feed, route, dir, strat);
            var times = GetSortTimes(feed, route, dir, stops);

            return(GetSchedule(feed, route, dir, serviceId, stops, times));
        }
 public static Tuple <List <string>, List <Tuple <string, Dictionary <string, TimeOfDay> > > > GetSchedule(GTFSFeed feed, string route, DirectionType?dir, string serviceId) =>
 GetSchedule(feed, route, dir, serviceId, TimepointFinder.GetTimepointStrategy(feed));
 public static List <string> GetScheduleHeader(GTFSFeed feed, string route, DirectionType?dir) =>
 GetScheduleHeader(feed, route, dir, TimepointFinder.GetTimepointStrategy(feed));
 public static IEnumerable <string> FirstAndLastStopList(GTFSFeed feed, Route route, DirectionType?dir)
 => FirstAndLastStopList(feed, route.Id, dir);
示例#20
0
        private async Task RunAsync(Option option)
        {
            Console.WriteLine(HeadingInfo.Default);
            Console.WriteLine(CopyrightInfo.Default);
            Console.WriteLine("");

            try
            {
                SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(option.Database);
            }
            catch (Exception exception)
            {
                Console.Error.WriteLine(string.Format("ERROR: {0}", exception.Message));
                Console.WriteLine("");

                Environment.Exit(1);
            }

            SqlConnection connection = new SqlConnection(option.Database);

            try
            {
                await connection.OpenAsync();
            }
            catch (SqlException exception)
            {
                Console.Error.WriteLine(string.Format("ERROR: {0}", exception.Message));
                Console.WriteLine("");

                Environment.Exit(1);
            }

            try
            {
                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS AgencyProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS CalendarProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS CalendarDateProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS FareAttributeProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS FareRuleProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS FrequencyProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS LevelProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS PathwayProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS RouteProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS ShapeProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS StopProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS StopTimeProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS TransferProcedure");

                await connection.ExecuteCommandAsync("DROP PROCEDURE IF EXISTS TripProcedure");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS AgencyType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS CalendarType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS CalendarDateType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS FareAttributeType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS FareRuleType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS FrequencyType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS LevelType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS PathwayType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS RouteType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS ShapeType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS StopType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS StopTimeType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS TransferType");

                await connection.ExecuteCommandAsync("DROP TYPE IF EXISTS TripType");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS Agency");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS Calendar");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS CalendarDate");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS FareAttribute");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS FareRule");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS Frequency");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS Level");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS Pathway");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS Route");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS Shape");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS Stop");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS StopTime");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS Transfer");

                await connection.ExecuteCommandAsync("DROP TABLE IF EXISTS Trip");

                await connection.ExecuteCommandAsync("CREATE TABLE Agency (Id nvarchar(255), Name nvarchar(255), URL nvarchar(255), Timezone nvarchar(255), LanguageCode nvarchar(255), Phone nvarchar(255), FareURL nvarchar(255), Email nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TABLE Calendar (ServiceId nvarchar(255) PRIMARY KEY, Monday bit, Tuesday bit, Wednesday bit, Thursday bit, Friday bit, Saturday bit, Sunday bit, StartDate datetime, EndDate datetime)");

                await connection.ExecuteCommandAsync("CREATE TABLE CalendarDate (ServiceId nvarchar(255), Date datetime, ExceptionType int)");

                await connection.ExecuteCommandAsync("CREATE TABLE FareAttribute (FareId nvarchar(255), Price nvarchar(255), CurrencyType nvarchar(255), PaymentMethod int, Transfers int, AgencyId nvarchar(255), TransferDuration nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TABLE FareRule (FareId nvarchar(255), RouteId nvarchar(255), OriginId nvarchar(255), DestinationId nvarchar(255), ContainsId nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TABLE Frequency (TripId nvarchar(255), StartTime nvarchar(255), EndTime nvarchar(255), HeadwaySecs nvarchar(255), ExactTimes bit)");

                await connection.ExecuteCommandAsync("CREATE TABLE Level (Id nvarchar(255), Indexes float, Name nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TABLE Pathway (Id nvarchar(255), FromStopId nvarchar(255), ToStopId nvarchar(255), PathwayMode int, IsBidirectional int, Length float, TraversalTime int, StairCount int, MaxSlope float, MinWidth float, SignpostedAs nvarchar(255), ReversedSignpostedAs nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TABLE Route (Id nvarchar(255) PRIMARY KEY, AgencyId nvarchar(255), ShortName nvarchar(255), LongName nvarchar(255), Description nvarchar(255), Type int, Url nvarchar(255), Color int, TextColor int)");

                await connection.ExecuteCommandAsync("CREATE TABLE Shape (Id nvarchar(255), Latitude float, Longitude float, Sequence int, DistanceTravelled float)");

                await connection.ExecuteCommandAsync("CREATE TABLE Stop (Id nvarchar(255) PRIMARY KEY, Code nvarchar(255), Name nvarchar(255), Description nvarchar(255), Latitude float, Longitude float, Zone nvarchar(255), Url nvarchar(255), LocationType int, ParentStation nvarchar(255), Timezone nvarchar(255), WheelchairBoarding nvarchar(255), LevelId nvarchar(255), PlatformCode nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TABLE StopTime (TripId nvarchar(255), ArrivalTime nvarchar(255), DepartureTime nvarchar(255), StopId nvarchar(255), StopSequence int, StopHeadsign nvarchar(255), PickupType int, DropOffType int, ShapeDistTravelled float, TimepointType int)");

                await connection.ExecuteCommandAsync("CREATE TABLE Transfer (FromStopId nvarchar(255), ToStopId nvarchar(255), TransferType int, MinimumTransferTime nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TABLE Trip (Id nvarchar(255) PRIMARY KEY, RouteId nvarchar(255), ServiceId nvarchar(255), Headsign nvarchar(255), ShortName nvarchar(255), Direction int, BlockId nvarchar(255), ShapeId nvarchar(255), AccessibilityType int)");

                await connection.ExecuteCommandAsync("CREATE TYPE AgencyType AS TABLE (Id nvarchar(255), Name nvarchar(255), URL nvarchar(255), Timezone nvarchar(255), LanguageCode nvarchar(255), Phone nvarchar(255), FareURL nvarchar(255), Email nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TYPE CalendarType AS TABLE (ServiceId nvarchar(255), Monday bit, Tuesday bit, Wednesday bit, Thursday bit, Friday bit, Saturday bit, Sunday bit, StartDate datetime, EndDate datetime)");

                await connection.ExecuteCommandAsync("CREATE TYPE CalendarDateType AS TABLE (ServiceId nvarchar(255), Date datetime, ExceptionType int)");

                await connection.ExecuteCommandAsync("CREATE TYPE FareAttributeType AS TABLE (FareId nvarchar(255), Price nvarchar(255), CurrencyType nvarchar(255), PaymentMethod int, Transfers int, AgencyId nvarchar(255), TransferDuration nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TYPE FareRuleType AS TABLE (FareId nvarchar(255), RouteId nvarchar(255), OriginId nvarchar(255), DestinationId nvarchar(255), ContainsId nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TYPE FrequencyType AS TABLE (TripId nvarchar(255), StartTime nvarchar(255), EndTime nvarchar(255), HeadwaySecs nvarchar(255), ExactTimes bit)");

                await connection.ExecuteCommandAsync("CREATE TYPE LevelType AS TABLE (Id nvarchar(255), Indexes float, Name nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TYPE PathwayType AS TABLE (Id nvarchar(255), FromStopId nvarchar(255), ToStopId nvarchar(255), PathwayMode int, IsBidirectional int, Length float, TraversalTime int, StairCount int, MaxSlope float, MinWidth float, SignpostedAs nvarchar(255), ReversedSignpostedAs nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TYPE RouteType AS TABLE (Id nvarchar(255), AgencyId nvarchar(255), ShortName nvarchar(255), LongName nvarchar(255), Description nvarchar(255), Type int, Url nvarchar(255), Color int, TextColor int)");

                await connection.ExecuteCommandAsync("CREATE TYPE ShapeType AS TABLE (Id nvarchar(255), Latitude float, Longitude float, Sequence int, DistanceTravelled float)");

                await connection.ExecuteCommandAsync("CREATE TYPE StopType AS TABLE (Id nvarchar(255), Code nvarchar(255), Name nvarchar(255), Description nvarchar(255), Latitude float, Longitude float, Zone nvarchar(255), Url nvarchar(255), LocationType int, ParentStation nvarchar(255), Timezone nvarchar(255), WheelchairBoarding nvarchar(255), LevelId nvarchar(255), PlatformCode nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TYPE StopTimeType AS TABLE (TripId nvarchar(255), ArrivalTime nvarchar(255), DepartureTime nvarchar(255), StopId nvarchar(255), StopSequence int, StopHeadsign nvarchar(255), PickupType int, DropOffType int, ShapeDistTravelled float, TimepointType int)");

                await connection.ExecuteCommandAsync("CREATE TYPE TransferType AS TABLE (FromStopId nvarchar(255), ToStopId nvarchar(255), TransferType int, MinimumTransferTime nvarchar(255))");

                await connection.ExecuteCommandAsync("CREATE TYPE TripType AS TABLE (Id nvarchar(255), RouteId nvarchar(255), ServiceId nvarchar(255), Headsign nvarchar(255), ShortName nvarchar(255), Direction int, BlockId nvarchar(255), ShapeId nvarchar(255), AccessibilityType int)");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE AgencyProcedure (@table AgencyType READONLY) AS INSERT INTO Agency (Id, Name, URL, Timezone, LanguageCode, Phone, FareURL, Email) SELECT Id, Name, URL, Timezone, LanguageCode, Phone, FareURL, Email FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE CalendarProcedure (@table CalendarType READONLY) AS INSERT INTO Calendar (ServiceId, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday, StartDate, EndDate) SELECT ServiceId, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday, StartDate, EndDate FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE CalendarDateProcedure (@table CalendarDateType READONLY) AS INSERT INTO CalendarDate (ServiceId, Date, ExceptionType) SELECT ServiceId, Date, ExceptionType FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE FareAttributeProcedure (@table FareAttributeType READONLY) AS INSERT INTO FareAttribute (FareId, Price, CurrencyType, PaymentMethod, Transfers, AgencyId, TransferDuration) SELECT FareId, Price, CurrencyType, PaymentMethod, Transfers, AgencyId, TransferDuration FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE FareRuleProcedure (@table FareRuleType READONLY) AS INSERT INTO FareRule (FareId, RouteId, OriginId, DestinationId, ContainsId) SELECT FareId, RouteId, OriginId, DestinationId, ContainsId FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE FrequencyProcedure (@table FrequencyType READONLY) AS INSERT INTO Frequency (TripId, StartTime, EndTime, HeadwaySecs, ExactTimes) SELECT TripId, StartTime, EndTime, HeadwaySecs, ExactTimes FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE LevelProcedure (@table LevelType READONLY) AS INSERT INTO Level (Id, Indexes, Name) SELECT Id, Indexes, Name FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE PathwayProcedure (@table PathwayType READONLY) AS INSERT INTO Pathway (Id, FromStopId, ToStopId, PathwayMode, IsBidirectional, Length, TraversalTime, StairCount, MaxSlope, MinWidth, SignpostedAs, ReversedSignpostedAs) SELECT Id, FromStopId, ToStopId, PathwayMode, IsBidirectional, Length, TraversalTime, StairCount, MaxSlope, MinWidth, SignpostedAs, ReversedSignpostedAs FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE RouteProcedure (@table RouteType READONLY) AS INSERT INTO Route (Id, AgencyId, ShortName, LongName, Description, Type, Url, Color, TextColor) SELECT Id, AgencyId, ShortName, LongName, Description, Type, Url, Color, TextColor FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE ShapeProcedure (@table ShapeType READONLY) AS INSERT INTO Shape (Id, Latitude, Longitude, Sequence, DistanceTravelled) SELECT Id, Latitude, Longitude, Sequence, DistanceTravelled FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE StopProcedure (@table StopType READONLY) AS INSERT INTO Stop (Id, Code, Name, Description, Latitude, Longitude, Zone, Url, LocationType, ParentStation, Timezone, WheelchairBoarding, LevelId, PlatformCode) SELECT Id, Code, Name, Description, Latitude, Longitude, Zone, Url, LocationType, ParentStation, Timezone, WheelchairBoarding, LevelId, PlatformCode FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE StopTimeProcedure (@table StopTimeType READONLY) AS INSERT INTO StopTime (TripId, ArrivalTime, DepartureTime, StopId, StopSequence, StopHeadsign, PickupType, DropOffType, ShapeDistTravelled, TimepointType) SELECT TripId, ArrivalTime, DepartureTime, StopId, StopSequence, StopHeadsign, PickupType, DropOffType, ShapeDistTravelled, TimepointType FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE TransferProcedure (@table TransferType READONLY) AS INSERT INTO Transfer (FromStopId, ToStopId, TransferType, MinimumTransferTime) SELECT FromStopId, ToStopId, TransferType, MinimumTransferTime FROM @table");

                await connection.ExecuteCommandAsync("CREATE PROCEDURE TripProcedure (@table TripType READONLY) AS INSERT INTO Trip (Id, RouteId, ServiceId, Headsign, ShortName, Direction, BlockId, ShapeId, AccessibilityType) SELECT Id, RouteId, ServiceId, Headsign, ShortName, Direction, BlockId, ShapeId, AccessibilityType FROM @table");

                Console.WriteLine("CREATE: tables");

                GTFSReader <GTFSFeed> reader = new GTFSReader <GTFSFeed>();
                GTFSFeed feed = reader.Read(option.Gtfs);

                DataTable agency = new DataTable();
                agency.Columns.Add("Id", typeof(string));
                agency.Columns.Add("Name", typeof(string));
                agency.Columns.Add("URL", typeof(string));
                agency.Columns.Add("Timezone", typeof(string));
                agency.Columns.Add("LanguageCode", typeof(string));
                agency.Columns.Add("Phone", typeof(string));
                agency.Columns.Add("FareURL", typeof(string));
                agency.Columns.Add("Email", typeof(string));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("AgencyProcedure", agency, feed.Agencies, (dt, agency) => dt.Rows.Add(agency.Id, agency.Name, agency.URL, agency.Timezone, agency.LanguageCode, agency.Phone, agency.FareURL, agency.Email));

                Console.WriteLine("INSERT: agency.txt");

                DataTable calendar = new DataTable();
                calendar.Columns.Add("ServiceId", typeof(string));
                calendar.Columns.Add("Monday", typeof(bool));
                calendar.Columns.Add("Tuesday", typeof(bool));
                calendar.Columns.Add("Wednesday", typeof(bool));
                calendar.Columns.Add("Thursday", typeof(bool));
                calendar.Columns.Add("Friday", typeof(bool));
                calendar.Columns.Add("Saturday", typeof(bool));
                calendar.Columns.Add("Sunday", typeof(bool));
                calendar.Columns.Add("StartDate", typeof(DateTime));
                calendar.Columns.Add("EndDate", typeof(DateTime));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("CalendarProcedure", calendar, feed.Calendars.GroupBy(c => c.ServiceId).Select(c => c.First()), (dt, calendar) => dt.Rows.Add(calendar.ServiceId, calendar.Monday, calendar.Tuesday, calendar.Wednesday, calendar.Thursday, calendar.Friday, calendar.Saturday, calendar.Sunday, calendar.StartDate, calendar.EndDate));

                Console.WriteLine("INSERT: calendar.txt");

                DataTable calendarDate = new DataTable();
                calendarDate.Columns.Add("ServiceId", typeof(string));
                calendarDate.Columns.Add("Date", typeof(DateTime));
                calendarDate.Columns.Add("ExceptionType", typeof(int));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("CalendarDateProcedure", calendarDate, feed.CalendarDates, (dt, calendarDate) => dt.Rows.Add(calendarDate.ServiceId, calendarDate.Date, calendarDate.ExceptionType));

                Console.WriteLine("INSERT: calendar_dates.txt");

                DataTable fareAttribute = new DataTable();
                fareAttribute.Columns.Add("FareId", typeof(string));
                fareAttribute.Columns.Add("Price", typeof(string));
                fareAttribute.Columns.Add("CurrencyType", typeof(string));
                fareAttribute.Columns.Add("PaymentMethod", typeof(int));
                fareAttribute.Columns.Add("Transfers", typeof(int));
                fareAttribute.Columns.Add("AgencyId", typeof(string));
                fareAttribute.Columns.Add("TransferDuration", typeof(string));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("FareAttributeProcedure", fareAttribute, feed.FareAttributes, (dt, fareAttribute) => dt.Rows.Add(fareAttribute.FareId, fareAttribute.Price, fareAttribute.CurrencyType, fareAttribute.PaymentMethod, fareAttribute.Transfers, fareAttribute.AgencyId, fareAttribute.TransferDuration));

                Console.WriteLine("INSERT: fare_attributes.txt");

                DataTable fareRule = new DataTable();
                fareRule.Columns.Add("FareId", typeof(string));
                fareRule.Columns.Add("RouteId", typeof(string));
                fareRule.Columns.Add("OriginId", typeof(string));
                fareRule.Columns.Add("DestinationId", typeof(string));
                fareRule.Columns.Add("ContainsId", typeof(string));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("FareRuleProcedure", fareRule, feed.FareRules, (dt, fareRule) => dt.Rows.Add(fareRule.FareId, fareRule.RouteId, fareRule.OriginId, fareRule.DestinationId, fareRule.ContainsId));

                Console.WriteLine("INSERT: fare_rules.txt");

                DataTable frequency = new DataTable();
                frequency.Columns.Add("TripId", typeof(string));
                frequency.Columns.Add("StartTime", typeof(string));
                frequency.Columns.Add("EndTime", typeof(string));
                frequency.Columns.Add("HeadwaySecs", typeof(string));
                frequency.Columns.Add("ExactTimes", typeof(bool));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("FrequencyProcedure", frequency, feed.Frequencies, (dt, frequency) => dt.Rows.Add(frequency.TripId, frequency.StartTime, frequency.EndTime, frequency.HeadwaySecs, frequency.ExactTimes));

                Console.WriteLine("INSERT: frequencies.txt");

                DataTable level = new DataTable();
                level.Columns.Add("Id", typeof(string));
                level.Columns.Add("Indexes", typeof(double));
                level.Columns.Add("Name", typeof(string));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("LevelProcedure", level, feed.Levels, (dt, level) => dt.Rows.Add(level.Id, level.Index, level.Name));

                Console.WriteLine("INSERT: levels.txt");

                DataTable pathway = new DataTable();
                pathway.Columns.Add("Id", typeof(string));
                pathway.Columns.Add("FromStopId", typeof(string));
                pathway.Columns.Add("ToStopId", typeof(string));
                pathway.Columns.Add("PathwayMode", typeof(int));
                pathway.Columns.Add("IsBidirectional", typeof(int));
                pathway.Columns.Add("Length", typeof(double));
                pathway.Columns.Add("TraversalTime", typeof(int));
                pathway.Columns.Add("StairCount", typeof(int));
                pathway.Columns.Add("MaxSlope", typeof(double));
                pathway.Columns.Add("MinWidth", typeof(double));
                pathway.Columns.Add("SignpostedAs", typeof(string));
                pathway.Columns.Add("ReversedSignpostedAs", typeof(string));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("PathwayProcedure", pathway, feed.Pathways, (dt, pathway) => dt.Rows.Add(pathway.Id, pathway.FromStopId, pathway.ToStopId, pathway.PathwayMode, pathway.IsBidirectional, pathway.Length, pathway.TraversalTime, pathway.StairCount, pathway.MaxSlope, pathway.MinWidth, pathway.SignpostedAs, pathway.ReversedSignpostedAs));

                Console.WriteLine("INSERT: pathways.txt");

                DataTable route = new DataTable();
                route.Columns.Add("Id", typeof(string));
                route.Columns.Add("AgencyId", typeof(string));
                route.Columns.Add("ShortName", typeof(string));
                route.Columns.Add("LongName", typeof(string));
                route.Columns.Add("Description", typeof(string));
                route.Columns.Add("Type", typeof(int));
                route.Columns.Add("Url", typeof(string));
                route.Columns.Add("Color", typeof(int));
                route.Columns.Add("TextColor", typeof(int));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("RouteProcedure", route, feed.Routes.GroupBy(r => r.Id).Select(r => r.First()), (dt, route) => dt.Rows.Add(route.Id, route.AgencyId, route.ShortName, route.LongName, route.Description, route.Type, route.Url, route.Color, route.TextColor));

                Console.WriteLine("INSERT: routes.txt");

                DataTable shape = new DataTable();
                shape.Columns.Add("Id", typeof(string));
                shape.Columns.Add("Latitude", typeof(double));
                shape.Columns.Add("Longitude", typeof(double));
                shape.Columns.Add("Sequence", typeof(int));
                shape.Columns.Add("DistanceTravelled", typeof(double));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("ShapeProcedure", shape, feed.Shapes, (dt, shape) => dt.Rows.Add(shape.Id, shape.Latitude, shape.Longitude, shape.Sequence, shape.DistanceTravelled));

                Console.WriteLine("INSERT: shapes.txt");

                DataTable stop = new DataTable();
                stop.Columns.Add("Id", typeof(string));
                stop.Columns.Add("Code", typeof(string));
                stop.Columns.Add("Name", typeof(string));
                stop.Columns.Add("Description", typeof(string));
                stop.Columns.Add("Latitude", typeof(double));
                stop.Columns.Add("Longitude", typeof(double));
                stop.Columns.Add("Zone", typeof(string));
                stop.Columns.Add("Url", typeof(string));
                stop.Columns.Add("LocationType", typeof(int));
                stop.Columns.Add("ParentStation", typeof(string));
                stop.Columns.Add("Timezone", typeof(string));
                stop.Columns.Add("WheelchairBoarding", typeof(string));
                stop.Columns.Add("LevelId", typeof(string));
                stop.Columns.Add("PlatformCode", typeof(string));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("StopProcedure", stop, feed.Stops.GroupBy(s => s.Id).Select(s => s.First()), (dt, stop) => dt.Rows.Add(stop.Id, stop.Code, stop.Name, stop.Description, stop.Latitude, stop.Longitude, stop.Zone, stop.Url, stop.LocationType, stop.ParentStation, stop.Timezone, stop.WheelchairBoarding, stop.LevelId, stop.PlatformCode));

                Console.WriteLine("INSERT: stops.txt");

                DataTable stopTime = new DataTable();
                stopTime.Columns.Add("TripId", typeof(string));
                stopTime.Columns.Add("ArrivalTime", typeof(string));
                stopTime.Columns.Add("DepartureTime", typeof(string));
                stopTime.Columns.Add("StopId", typeof(string));
                stopTime.Columns.Add("StopSequence", typeof(int));
                stopTime.Columns.Add("StopHeadsign", typeof(string));
                stopTime.Columns.Add("PickupType", typeof(int));
                stopTime.Columns.Add("DropOffType", typeof(int));
                stopTime.Columns.Add("ShapeDistTravelled", typeof(double));
                stopTime.Columns.Add("TimepointType", typeof(int));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("StopTimeProcedure", stopTime, feed.StopTimes, (dt, stopTime) => dt.Rows.Add(stopTime.TripId, stopTime.ArrivalTime, stopTime.DepartureTime, stopTime.StopId, stopTime.StopSequence, stopTime.StopHeadsign, stopTime.PickupType, stopTime.DropOffType, stopTime.ShapeDistTravelled, stopTime.TimepointType));

                Console.WriteLine("INSERT: stop_times.txt");

                DataTable transfer = new DataTable();
                transfer.Columns.Add("FromStopId", typeof(string));
                transfer.Columns.Add("ToStopId", typeof(string));
                transfer.Columns.Add("TransferType", typeof(int));
                transfer.Columns.Add("MinimumTransferTime", typeof(string));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("TransferProcedure", transfer, feed.Transfers, (dt, transfer) => dt.Rows.Add(transfer.FromStopId, transfer.ToStopId, transfer.TransferType, transfer.MinimumTransferTime));

                Console.WriteLine("INSERT: transfers.txt");

                DataTable trip = new DataTable();
                trip.Columns.Add("Id", typeof(string));
                trip.Columns.Add("RouteId", typeof(string));
                trip.Columns.Add("ServiceId", typeof(string));
                trip.Columns.Add("Headsign", typeof(string));
                trip.Columns.Add("ShortName", typeof(string));
                trip.Columns.Add("Direction", typeof(int));
                trip.Columns.Add("BlockId", typeof(string));
                trip.Columns.Add("ShapeId", typeof(string));
                trip.Columns.Add("AccessibilityType", typeof(int));

                await connection.ExecuteStoredProcedureFromTableInBatchesAsync("TripProcedure", trip, feed.Trips.GroupBy(t => t.Id).Select(t => t.First()), (dt, trip) => dt.Rows.Add(trip.Id, trip.RouteId, trip.ServiceId, trip.Headsign, trip.ShortName, trip.Direction, trip.BlockId, trip.ShapeId, trip.AccessibilityType));

                Console.WriteLine("INSERT: trips.txt");

                await connection.ExecuteCommandAsync("CREATE NONCLUSTERED INDEX StopTimeIndexStop ON StopTime (StopId, PickupType) INCLUDE (TripId, ArrivalTime, DepartureTime, StopSequence, StopHeadsign, DropOffType, ShapeDistTravelled, TimepointType) WITH (ONLINE = ON)");

                await connection.ExecuteCommandAsync("CREATE NONCLUSTERED INDEX StopTimeIndexTrip ON StopTime (TripId, PickupType) INCLUDE (ArrivalTime, DepartureTime, StopId, StopSequence, StopHeadsign, DropOffType, ShapeDistTravelled, TimepointType) WITH (ONLINE = ON)");

                Console.WriteLine("CREATE: indexes");
            }
            catch (Exception exception)
            {
                Console.Error.WriteLine(string.Format("ERROR: {0}", exception.Message));
                Console.WriteLine("");

                Environment.Exit(1);
            }
        }
示例#21
0
        public static Tuple <DateTime, DateTime> GetFeedDateRange(GTFSFeed feed)
        {
            FeedInfo info = feed.GetFeedInfo();

            if (info.StartDate != null && info.EndDate != null)
            {
                return(new Tuple <DateTime, DateTime>(
                           DateTime.ParseExact(info.StartDate, "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture),
                           DateTime.ParseExact(info.EndDate, "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture)));
            }

            DateTime?minStartLeft  = null;
            DateTime?minStartRight = null;
            DateTime?maxEndLeft    = null;
            DateTime?maxEndRight   = null;

            DateTime minStart;
            DateTime maxEnd;

            if (feed.Calendars.Any())
            {
                minStartLeft = feed.Calendars.Min(x => x.StartDate);
                maxEndLeft   = feed.Calendars.Max(x => x.EndDate);
            }

            if (feed.CalendarDates.Any())
            {
                minStartRight = feed.CalendarDates.Where(x => x.ExceptionType == ExceptionType.Added).Min(x => x.Date);
                maxEndRight   = feed.CalendarDates.Where(x => x.ExceptionType == ExceptionType.Added).Max(x => x.Date);
            }

            if (minStartLeft.HasValue && minStartRight.HasValue)
            {
                if (minStartLeft > minStartRight)
                {
                    minStart = minStartRight.Value;
                }
                else
                {
                    minStart = minStartLeft.Value;
                }
            }
            else
            {
                if (minStartLeft.HasValue)
                {
                    minStart = minStartLeft.Value;
                }
                else
                {
                    minStart = minStartRight.Value;
                }
            }

            if (maxEndLeft.HasValue && maxEndRight.HasValue)
            {
                if (maxEndLeft > maxEndRight)
                {
                    maxEnd = maxEndLeft.Value;
                }
                else
                {
                    maxEnd = maxEndLeft.Value;
                }
            }
            else
            {
                if (maxEndLeft.HasValue)
                {
                    maxEnd = maxEndLeft.Value;
                }
                else
                {
                    maxEnd = maxEndRight.Value;
                }
            }

            return(new Tuple <DateTime, DateTime>(minStart, maxEnd));
        }
 public static IEnumerable <Tuple <string, bool> > DataTimepoints(GTFSFeed feed, Route route, DirectionType?dir, bool strict = false)
 => DataTimepoints(feed, route.Id, dir, strict);
示例#23
0
        public MainWindow()
        {
            InitializeComponent();

            Thread.CurrentThread.CurrentCulture   = new CultureInfo("en-GB");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");

            // Create StringBuilder
            _sb = new StringBuilder();

            // Read GTFS Static files
            _reader     = new GTFSReader <GTFSFeed>(strict: false);
            _feedStatic = _reader.Read(new DirectoryInfo("GTFS"));

            // Read extra files and create lists with objects
            string[] translationsRaw        = File.ReadAllLines("GTFS\\translations.txt");
            string[] stop_time_overridesRaw = File.ReadAllLines("GTFS\\stop_time_overrides.txt");

            // Create lists with objects
            _stops     = _feedStatic.Stops.ToDictionary(x => x.Id, x => x);
            _trips     = _feedStatic.Trips.ToDictionary(x => x.Id, x => x);
            _routes    = _feedStatic.Routes.ToDictionary(x => x.Id, x => x).ToRouteExtraDictionary();
            _agencies  = _feedStatic.Agencies.ToDictionary(x => x.Id, x => x);
            _calendars = _feedStatic.Calendars.ToDictionary(x => x.ServiceId, x => x);
            _transfers = _feedStatic.Transfers.ToDictionary(x => x.FromStopId, x => x);

            _calendarDates = new Dictionary <string, Dictionary <DateTime, ExceptionType> >();
            foreach (string serviceId in _calendars.Keys)
            {
                _calendarDates.Add(serviceId, new Dictionary <DateTime, ExceptionType>());
            }
            foreach (CalendarDate cd in _feedStatic.CalendarDates)
            {
                _calendarDates[cd.ServiceId].Add(cd.Date, cd.ExceptionType);
            }

            _translations = new Dictionary <string, Dictionary <string, string> >();
            for (int i = 1; i < translationsRaw.Length;)
            {
                string key = new Translation(translationsRaw[i]).Trans_Id;
                Dictionary <string, string> value = new Dictionary <string, string>();

                Translation valueValue = new Translation(translationsRaw[i++]);
                value.Add(valueValue.Language, valueValue.Trans);
                valueValue = new Translation(translationsRaw[i++]);
                value.Add(valueValue.Language, valueValue.Trans);
                valueValue = new Translation(translationsRaw[i++]);
                value.Add(valueValue.Language, valueValue.Trans);
                valueValue = new Translation(translationsRaw[i++]);
                value.Add(valueValue.Language, valueValue.Trans);

                _translations.Add(key, value);
            }

            _stopTimeOverrides = new List <StopTimeOverride>();
            for (int i = 1; i < stop_time_overridesRaw.Length; i++)
            {
                _stopTimeOverrides.Add(new StopTimeOverride(stop_time_overridesRaw[i]));
            }

            // Realtime GTFS
            //FileDownload.UpdateRealtime();
            _feedRealtime = Serializer.Deserialize <FeedMessage>(new FileStream(@"GTFS\c21ac6758dd25af84cca5b707f3cb3de", FileMode.Open, FileAccess.Read));

            // Update ListViews
            UpdateLv(SelectedLv.BeginStationRouteplanner);
            UpdateLv(SelectedLv.EndStationRouteplanner);
            UpdateLv(SelectedLv.StationTripviewer);
            UpdateLv(SelectedLv.StationRealtime);
            UpdateLv(SelectedLv.StationRoutefinder);

            Thread.CurrentThread.CurrentCulture   = new CultureInfo("nl-BE");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("nl-BE");
        }
示例#24
0
        /// <summary>
        /// Lists the stops along a route, in order.
        /// </summary>
        /// <param name="feed">The GTFS feed to use.</param>
        /// <param name="route">The ID of the route to get stops for.</param>
        /// <param name="direction">
        /// The direction of trips to get. Must exactly match the direction
        /// provided in GTFS; <c>null</c> here does not match "any direction"
        /// in the data.
        /// </param>
        public static IEnumerable <Stop> GetStopOrder(GTFSFeed feed, string route, DirectionType?direction = null)
        {
            var routeStopTimes =
                from stopTimes in feed.StopTimes
                join trips in feed.Trips on stopTimes.TripId equals trips.Id
                where trips.RouteId == route &&
                trips.Direction == direction
                select stopTimes;

            // If it's empty, return empty list. Though that shouldn't be possible in well-formed GTFS.
            if (routeStopTimes.Count() == 0)
            {
                return(Enumerable.Empty <Stop>());
            }

            // First, we'll need a listing of every trip, how many stops it has, and how many of those we've already listed.
            var stopsOnTrips =
                from rstListingUngrouped in routeStopTimes
                group rstListingUngrouped by rstListingUngrouped.TripId into rstListingGrouped
                let stopCount = rstListingGrouped.Count()
                                orderby stopCount descending
                                select new
            {
                rstListingGrouped.First().TripId,
                Stops      = stopCount,
                FoundStops = 0
            };

            List <string> outStops = new List <string>();

            while (stopsOnTrips.Count() > 0)
            {
                // First take the first trip with "unlisted" stops
                string newTrip = stopsOnTrips.First().TripId;

                var newStops =
                    (from rstListing in routeStopTimes
                     where rstListing.TripId == newTrip
                     orderby rstListing.StopSequence
                     select rstListing.StopId).Distinct();

                // Handling for first trip searched
                if (outStops.Count == 0)
                {
                    outStops = newStops.Distinct().ToList();
                }
                else
                {
                    // Now merge the listings
                    List <string> foundStops    = new List <string>(outStops);
                    List <string> addingStops   = new List <string>();
                    string        lastFoundStop = null;

                    foreach (string stop in newStops)
                    {
                        int foundIndex = foundStops.IndexOf(stop);
                        if (foundIndex != -1)
                        {
                            // Remove the found stop and all preceding stops from the found-stops list
                            foundStops.RemoveRange(0, foundIndex + 1);

                            // If there were unfound stops, add them to the output too
                            if (addingStops.Count > 0)
                            {
                                int outIndex = outStops.IndexOf(stop);
                                outStops.InsertRange(outIndex, addingStops);
                                addingStops.Clear();
                            }

                            // Also, set the last found stop to this one
                            lastFoundStop = stop;
                        }
                        else
                        {
                            addingStops.Add(stop);
                        }
                    }

                    // Add stray stops just after the last found stop
                    if (lastFoundStop != null)
                    {
                        outStops.InsertRange(outStops.IndexOf(lastFoundStop) + 1, addingStops);
                    }
                    else
                    {
                        // Or on the end if the two segments are, somehow, not linked
                        outStops.AddRange(addingStops);
                    }

                    // Make sure outStops only contains items once
                    outStops = outStops.Distinct().ToList();
                }

                // Now we need to update stopsOnTrips
                stopsOnTrips =
                    from rstListingUngrouped in routeStopTimes
                    group rstListingUngrouped by rstListingUngrouped.TripId into rstListingGrouped
                    let stopCount = rstListingGrouped.Count()
                                    let foundStopCount = rstListingGrouped.Count(x => outStops.Contains(x.StopId))
                                                         where foundStopCount < stopCount
                                                         orderby Math.Sign(stopCount) descending, stopCount - foundStopCount descending, stopCount
                select new
                {
                    rstListingGrouped.First().TripId,
                                              Stops      = rstListingGrouped.Count(),
                                              FoundStops = rstListingGrouped.Count(x => outStops.Contains(x.StopId))
                };
            }

            return
                (from stops in outStops
                 join feedStops in feed.Stops on stops equals feedStops.Id
                 select feedStops);
        }
示例#25
0
 /// <summary>
 /// Lists the stops along a route, in order.
 /// </summary>
 /// <param name="feed">The GTFS feed to use.</param>
 /// <param name="route">The Route to get stops for.</param>
 /// <param name="direction">
 /// The direction of trips to get. Must exactly match the direction
 /// provided in GTFS; <c>null</c> here does not match "any direction"
 /// in the data.
 /// </param>
 public static IEnumerable <Stop> GetStopOrder(GTFSFeed feed, Route route, DirectionType?direction = null) => GetStopOrder(feed, route.Id, direction);
 public static IEnumerable <string> LastStops(GTFSFeed feed, Route route, DirectionType?dir)
 => LastStops(feed, route.Id, dir);
示例#27
0
 /// <summary>
 /// Creates a new GTFS storage.
 /// </summary>
 /// <param name="feed">The GTFSFeed to use.</param>
 public GTFSStorage(GTFSFeed feed)
 {
     _feed = feed;
 }
示例#28
0
        /// <summary>
        /// Builds a GTFS feed with two connections on two different trips, sharing no transfer stop but stops are close together geographically.
        /// The 'middle' stop has two outgoing connections with one 5 minutes later.
        /// </summary>
        /// <returns></returns>
        public static IGTFSFeed ThreeConnectionsThreeTripsCloseStops(TimeOfDay departureTime1, TimeOfDay arrivalTime1,
                                                                     TimeOfDay departureTime2, TimeOfDay arrivalTime2)
        {
            var feed = new GTFSFeed();

            feed.Agencies.Add(new Agency()
            {
                Id = "0"
            });
            feed.Routes.Add(new global::GTFS.Entities.Route()
            {
                Id       = "0",
                AgencyId = "0"
            });
            feed.Routes.Add(new global::GTFS.Entities.Route()
            {
                Id       = "1",
                AgencyId = "0"
            });
            feed.Routes.Add(new global::GTFS.Entities.Route()
            {
                Id       = "2",
                AgencyId = "0"
            });
            feed.Trips.Add(new Trip()
            {
                Id      = "0",
                RouteId = "0"
            });
            feed.Trips.Add(new Trip()
            {
                Id      = "1",
                RouteId = "1"
            });
            feed.Trips.Add(new Trip()
            {
                Id      = "2",
                RouteId = "2"
            });
            feed.Stops.Add(new Stop()
            {
                Id        = "0",
                Longitude = 0,
                Latitude  = 0
            });
            feed.Stops.Add(new Stop()
            {
                Id        = "1",
                Longitude = 1,
                Latitude  = 1
            });
            feed.Stops.Add(new Stop()
            {
                Id        = "10",
                Longitude = 1.0001,
                Latitude  = 1.0001 // approx 15m.
            });
            feed.Stops.Add(new Stop()
            {
                Id        = "2",
                Longitude = 2,
                Latitude  = 2
            });
            feed.StopTimes.Add(new StopTime()
            {
                ArrivalTime   = departureTime1,
                StopId        = "0",
                TripId        = "0",
                DepartureTime = departureTime1
            });
            feed.StopTimes.Add(new StopTime()
            {
                ArrivalTime   = arrivalTime1,
                StopId        = "1",
                TripId        = "0",
                DepartureTime = arrivalTime1
            });
            feed.StopTimes.Add(new StopTime()
            {
                ArrivalTime   = departureTime2,
                StopId        = "10",
                TripId        = "1",
                DepartureTime = departureTime2
            });
            feed.StopTimes.Add(new StopTime()
            {
                ArrivalTime   = arrivalTime2,
                StopId        = "2",
                TripId        = "1",
                DepartureTime = arrivalTime2
            });
            feed.StopTimes.Add(new StopTime()
            {
                ArrivalTime   = TimeOfDay.FromTotalSeconds(departureTime2.TotalSeconds + 60 * 5),
                StopId        = "10",
                TripId        = "2",
                DepartureTime = TimeOfDay.FromTotalSeconds(departureTime2.TotalSeconds + 60 * 5)
            });
            feed.StopTimes.Add(new StopTime()
            {
                ArrivalTime   = TimeOfDay.FromTotalSeconds(arrivalTime2.TotalSeconds + 60 * 5),
                StopId        = "2",
                TripId        = "2",
                DepartureTime = TimeOfDay.FromTotalSeconds(arrivalTime2.TotalSeconds + 60 * 5)
            });
            return(feed);
        }
示例#29
0
        /// <summary>
        /// Filters the given feed and returns a filtered version.
        /// </summary>
        /// <param name="feed"></param>
        /// <returns></returns>
        public override IGTFSFeed Filter(IGTFSFeed feed)
        {
            var filteredFeed = new GTFSFeed();

            // filter routes.
            var routeIds  = new HashSet <string>();
            var agencyIds = new HashSet <string>();

            foreach (var route in feed.Routes)
            {
                if (_routesFilter.Invoke(route))
                { // keep this route.
                    filteredFeed.Routes.Add(route);
                    routeIds.Add(route.Id);

                    // keep agency ids.
                    agencyIds.Add(route.AgencyId);
                }
            }

            // filter trips.
            var serviceIds = new HashSet <string>();
            var tripIds    = new HashSet <string>();
            var shapeIds   = new HashSet <string>();

            foreach (var trip in feed.Trips)
            {
                if (routeIds.Contains(trip.RouteId))
                { // keep this trip, it is related to at least one stop-time.
                    filteredFeed.Trips.Add(trip);
                    tripIds.Add(trip.Id);

                    // keep serviceId, routeId and shapeId.
                    serviceIds.Add(trip.ServiceId);
                    if (!string.IsNullOrWhiteSpace(trip.ShapeId))
                    {
                        shapeIds.Add(trip.ShapeId);
                    }
                }
            }

            // filter stop-times.
            var stopIds = new HashSet <string>();

            foreach (var stopTime in feed.StopTimes)
            {
                if (tripIds.Contains(stopTime.TripId))
                { // stop is included, keep this stopTime.
                    filteredFeed.StopTimes.Add(stopTime);

                    // save the trip id's to keep.
                    stopIds.Add(stopTime.StopId);
                }
            }


            // filter stops.
            foreach (var stop in feed.Stops)
            {
                if (stopIds.Contains(stop.Id))
                { // stop has to be included.
                    stopIds.Add(stop.Id);
                    filteredFeed.Stops.Add(stop);
                }
            }

            // filter agencies.
            foreach (var agency in feed.Agencies)
            {
                if (agencyIds.Contains(agency.Id))
                { // keep this agency.
                    filteredFeed.Agencies.Add(agency);
                }
            }

            // filter calendars.
            foreach (var calendar in feed.Calendars)
            {
                if (serviceIds.Contains(calendar.ServiceId))
                { // keep this calendar.
                    filteredFeed.Calendars.Add(calendar);
                }
            }

            // filter calendar-dates.
            foreach (var calendarDate in feed.CalendarDates)
            {
                if (serviceIds.Contains(calendarDate.ServiceId))
                { // keep this calendarDate.
                    filteredFeed.CalendarDates.Add(calendarDate);
                }
            }

            // filter fare rules.
            var fareIds = new HashSet <string>();

            foreach (var fareRule in feed.FareRules)
            {
                if (routeIds.Contains(fareRule.RouteId))
                { // keep this fare rule.
                    filteredFeed.FareRules.Add(fareRule);

                    // keep fare ids.
                    fareIds.Add(fareRule.FareId);
                }
            }

            // filter fare attributes.
            foreach (var fareAttribute in feed.FareAttributes)
            {
                if (fareIds.Contains(fareAttribute.FareId))
                { // keep this fare attribute.
                    filteredFeed.FareAttributes.Add(fareAttribute);
                }
            }

            // filter frequencies.
            foreach (var frequency in feed.Frequencies)
            {
                if (tripIds.Contains(frequency.TripId))
                { // keep this frequency.
                    filteredFeed.Frequencies.Add(frequency);
                }
            }

            foreach (var transfer in feed.Transfers)
            {
                if (stopIds.Contains(transfer.FromStopId) &&
                    stopIds.Contains(transfer.ToStopId))
                {
                    filteredFeed.Transfers.Add(transfer);
                }
            }
            return(filteredFeed);
        }
示例#30
0
        public static string GetDescription(GTFSFeed feed, string serviceId, Tuple <DateTime, DateTime> dateRange)
        {
            Calendar cal = feed.Calendars.Get(serviceId).FirstOrDefault();
            IEnumerable <CalendarDate> calDates = feed.CalendarDates.Where(x => x.ServiceId == serviceId);

            if (cal == null && !calDates.Any(x => x.ExceptionType == ExceptionType.Added))
            {
                return($"{serviceId} does not exist.");
            }

            if (dateRange == null)
            {
                dateRange = GetFeedDateRange(feed);
            }

            StringBuilder output = new StringBuilder();

            if (cal != null && cal.Mask != 0)
            {
                output.Append($"Operates {DayMasks.Get(cal.Mask)}");

                var rangeOut = RangeExceedsCalendar(cal, dateRange.Item1, dateRange.Item2);

                if (rangeOut.Item1 && rangeOut.Item2)
                {
                    output.Append($", from {cal.StartDate.ToString("yyyy-MM-dd")} to {cal.EndDate.ToString("yyyy-MM-dd")}.");
                }
                else if (rangeOut.Item1)
                {
                    output.Append($", starting {cal.StartDate.ToString("yyyy-MM-dd")}.");
                }
                else if (rangeOut.Item2)
                {
                    output.Append($", until {cal.EndDate.ToString("yyyy-MM-dd")}.");
                }
                else
                {
                    output.Append(".");
                }

                var addedDates   = calDates.Where(x => x.ExceptionType == ExceptionType.Added).Select(x => x.Date).ToList();
                var removedDates = calDates.Where(x => x.ExceptionType == ExceptionType.Removed).Select(x => x.Date).ToList();

                if (addedDates.Count > 0)
                {
                    output.Append(" Also ");
                    output.Append(EnglishList(addedDates, x => x.ToString("yyyy-MM-dd")));
                    output.Append(".");
                }

                if (removedDates.Count > 0)
                {
                    output.Append(" Excludes ");
                    output.Append(EnglishList(removedDates, x => x.ToString("yyyy-MM-dd")));
                    output.Append(".");
                }
            }
            else
            {
                var addedDates = calDates.Where(x => x.ExceptionType == ExceptionType.Added).Select(x => x.Date).ToList();
                output.Append("Operates ");
                output.Append(EnglishList(addedDates, x => x.ToString("yyyy-MM-dd")));
                output.Append(".");
            }

            return(output.ToString());
        }