示例#1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Journey"/> class.
 /// </summary>
 /// <param name="id">
 /// The id.
 /// </param>
 /// <param name="route">
 /// The route.
 /// </param>
 /// <param name="departureDate">
 /// The departure date.
 /// </param>
 /// <param name="returnDate">
 /// The return date.
 /// </param>
 public Journey(long id, TravelRoute route, DateTime departureDate, DateTime returnDate)
     : this(route)
 {
     this.Id = id;
     this.DepartureDate = departureDate;
     this.ReturnDate = returnDate;
 }
示例#2
0
        /// <summary>
        /// The export data.
        /// </summary>
        /// <param name="targetStream">
        /// The target stream.
        /// </param>
        /// <param name="route">
        /// The route.
        /// </param>
        public override void ExportData(Stream targetStream, TravelRoute route)
        {
            if (route == null || route.Journeys.Count < 1)
            {
                return;
            }

            var exporter = new MatrixDataExporter();
            exporter.ExportData(targetStream, route);
        }
示例#3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="FlightStatisticForm"/> class.
        /// </summary>
        /// <param name="data">
        /// The data.
        /// </param>
        /// <param name="executionParam">
        /// The execution param.
        /// </param>
        /// <param name="isMainForm">
        /// The is main form.
        /// </param>
        public FlightStatisticForm(IList<TravelRoute> data, ExecutionParam executionParam, bool isMainForm)
        {
            this.InitializeComponent();
            this._isMainForm = isMainForm;
            this._routeData = data;
            if (data != null && data.Count > 0)
            {
                this._activeRoute = data[0];
                this.ReloadRoutes();
            }

            this._executionParam = executionParam;
            this.InitializeView();
        }
示例#4
0
        /// <summary>
        /// Bind the list view asynchronously
        /// </summary>
        /// <param name="route">
        /// The route.
        /// </param>
        /// <param name="departureDate">
        /// The departure Date.
        /// </param>
        /// <param name="returnDate">
        /// The return Date.
        /// </param>
        /// <param name="priceLimit">
        /// The price Limit.
        /// </param>
        /// <param name="allHistory">
        /// The all History.
        /// </param>
        /// <param name="amountOfPrices">
        /// The amount Of Prices.
        /// </param>
        /// <param name="minDuration">
        /// The min Duration.
        /// </param>
        /// <param name="maxDuration">
        /// The max Duration.
        /// </param>
        /// <param name="opearators">
        /// The opearators.
        /// </param>
        /// <param name="populateData">
        /// The populate Data.
        /// </param>
        private void BindListViewAsync(
            TravelRoute route,
            DateTime departureDate,
            DateTime returnDate,
            double priceLimit,
            bool allHistory,
            int amountOfPrices,
            int minDuration,
            int maxDuration,
            Dictionary<string, bool> opearators,
            bool populateData)
        {
            if (!this._formLoaded)
            {
                return;
            }

            ThreadPool.QueueUserWorkItem(
                o =>
                    {
                        AppUtil.NameCurrentThread(this.GetType().Name + "-BindListView");
                        this.BindListView(
                            route,
                            departureDate,
                            returnDate,
                            priceLimit,
                            allHistory,
                            amountOfPrices,
                            minDuration,
                            maxDuration,
                            opearators,
                            populateData);
                    });
        }
示例#5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="JourneyEventArgs"/> class.
 /// </summary>
 /// <param name="route">
 /// The route.
 /// </param>
 /// <param name="requestState">
 /// The request state.
 /// </param>
 /// <param name="initiatedDate">
 /// The initiated date.
 /// </param>
 public JourneyEventArgs(TravelRoute route, DataRequestState requestState, DateTime initiatedDate)
 {
     this.ResultRoute = route;
     this.RequestState = requestState;
     this.RequestInitiatedDate = initiatedDate;
 }
示例#6
0
        /// <summary>
        /// The get routes.
        /// </summary>
        /// <param name="loadJourneys">
        /// The load journeys.
        /// </param>
        /// <param name="loadJourneyData">
        /// The load journey data.
        /// </param>
        /// <param name="loadHistory">
        /// The load history.
        /// </param>
        /// <param name="loadFlights">
        /// The load flights.
        /// </param>
        /// <param name="callback">
        /// The callback.
        /// </param>
        /// <returns>
        /// The <see cref="IList"/>.
        /// </returns>
        public IList<TravelRoute> GetRoutes(bool loadJourneys, bool loadJourneyData, bool loadHistory, bool loadFlights, IProgressCallback callback)
        {
            this.Logger.DebugFormat(
                "Get available routes [{0}{1}{2}{3}]",
                loadJourneys ? "J" : null,
                loadJourneyData ? "D" : null,
                loadHistory ? "H" : null,
                loadFlights ? "F" : null);
            var result = new List<TravelRoute>();
            using (var connection = new SQLiteConnection(this._connectionString))
            {
                using (var getPlacesCmd = new SQLiteCommand("SELECT LID, SDEPARTURE, SDESTINATION FROM ROUTE", connection))
                {
                    connection.Open();
                    using (var reader = getPlacesCmd.ExecuteReader())
                    {
                        if (reader.HasRows)
                        {
                            int iLid = reader.GetOrdinal("LID");
                            int iDeparture = reader.GetOrdinal("SDEPARTURE");
                            int iDestination = reader.GetOrdinal("SDESTINATION");

                            while (reader.Read())
                            {
                                long id = reader.GetInt64(iLid);
                                string origin = reader.GetString(iDeparture);
                                string destination = reader.GetString(iDestination);
                                var newRoute = new TravelRoute(id, AirportDataProvider.FromIATA(origin), AirportDataProvider.FromIATA(destination));

                                if (loadJourneys)
                                {
                                    this.LoadData(newRoute, loadJourneyData, loadHistory, loadFlights, callback);
                                }

                                result.Add(newRoute);
                            }
                        }
                    }
                }
            }

            return result;
        }
示例#7
0
        public void FlightDataListViewTest()
        {
            // To generate code for this test, select "Generate Code for Coded UI Test" from the shortcut menu and select one of the menu items.
            // For more information on generated code, see http://go.microsoft.com/fwlink/?LinkId=179463
            using (var frm = new Form())
            {
                using (var lv = new FlightDataListView { Dock = DockStyle.Fill })
                {
                    var route = new TravelRoute(1, AirportDataProvider.FromIATA("HEL"), AirportDataProvider.FromIATA("SGN"));
                    var j = new Journey(1, route, DateTime.Now, DateTime.Now.AddDays(7));
                    var d = new JourneyData(1, "EUR", DateTime.Now);

                    var ds = new List<Flight>(100);

                    /* TODO FIX Unit test
                    for (int i = 0; i < 100; i++)
                    {
                        var f = new Flight(
                            d,
                            Guid.NewGuid().ToString(),
                            i + 10,
                            new TravelAgency(Guid.NewGuid().ToString(), "http://google.com"),
                            new FlightLeg(DateTime.Now, DateTime.Now.AddDays(1), TimeSpan.FromHours(i + 12), 2),
                            new FlightLeg(DateTime.Now.AddDays(7), DateTime.Now.AddDays(8), TimeSpan.FromHours(i + 13), 2));
                        ds.Add(f);
                    }
                     */

                    j.AddData(d);
                    d.SetFlightLinks();
                    lv.SetDataSourceAsync(ds, true);
                    frm.Controls.Add(lv);
                    frm.ShowDialog();
                }
            }
        }
示例#8
0
 /// <summary>
 /// The export data.
 /// </summary>
 /// <param name="targetStream">
 /// The target stream.
 /// </param>
 /// <param name="route">
 /// The route.
 /// </param>
 public abstract void ExportData(Stream targetStream, TravelRoute route);
示例#9
0
        /// <summary>
        /// Check if 2 routes have the same departure and destination airport
        /// </summary>
        /// <param name="other">
        /// The other.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool IsSameRoute(TravelRoute other)
        {
            if (other == null)
            {
                return false;
            }

            return string.Equals(this.Departure.IATA, other.Departure.IATA, StringComparison.OrdinalIgnoreCase)
                   && string.Equals(this.Destination.IATA, other.Destination.IATA, StringComparison.OrdinalIgnoreCase);
        }
示例#10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TravelRoute"/> class.
 /// </summary>
 /// <param name="route">
 /// The route.
 /// </param>
 public TravelRoute(TravelRoute route)
     : this(route.Id, route.Departure, route.Destination)
 {
 }
示例#11
0
        /// <summary>
        /// The generate file name.
        /// </summary>
        /// <param name="route">
        /// The route.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        private string GenerateFileName(TravelRoute route)
        {
            string origin = route.Departure.IATA;
            string dest = route.Destination.IATA;
            long minId = int.MaxValue, maxId = 0;

            foreach (var j in route.Journeys)
            {
                var id = j.Id;
                if (id > maxId)
                {
                    maxId = id;
                }

                if (id < minId)
                {
                    minId = id;
                }
            }

            var fileName = string.Format(
                CultureInfo.InvariantCulture,
                "{0}-{1}.[{2}]-[{3}]-({4}-{5}){6}({7})",
                this.FareDataProvider.ServiceName,
                route.Id,
                origin,
                dest,
                minId,
                maxId,
                DateTime.Now.ToString(NamingRule.DATE_FORMAT, CultureInfo.InvariantCulture),
                route.Journeys.Count);
            var processedName = PathUtil.RemoveInvalidFileNameChars(fileName);
            return processedName;
        }
示例#12
0
 /// <summary>
 /// The export data.
 /// </summary>
 /// <param name="data">
 /// The data.
 /// </param>
 /// <param name="destinationPath">
 /// The destination path.
 /// </param>
 /// <param name="format">
 /// The format.
 /// </param>
 /// <param name="callback">
 /// The callback.
 /// </param>
 /// <returns>
 /// The <see cref="string"/>.
 /// </returns>
 public string ExportData(TravelRoute data, string destinationPath, DataFormat format, IProgressCallback callback)
 {
     return this.ExportData(new List<TravelRoute> { data }, destinationPath, format, callback);
 }
示例#13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="JourneyProgressChangedEventArgs"/> class.
 /// </summary>
 /// <param name="percentage">
 /// The percentage.
 /// </param>
 /// <param name="resultRoute">
 /// The result route.
 /// </param>
 /// <param name="request">
 /// The request.
 /// </param>
 /// <param name="stateObj">
 /// The state obj.
 /// </param>
 public JourneyProgressChangedEventArgs(int percentage, TravelRoute resultRoute, FlightFareRequest request, object stateObj)
     : base(percentage, stateObj)
 {
     this.ResultRoute = resultRoute;
     this.Request = request;
 }
示例#14
0
        /// <summary>
        /// The parse web archive.
        /// </summary>
        /// <param name="webDocument">
        /// The web document.
        /// </param>
        /// <returns>
        /// The <see cref="RouteDataResult"/>.
        /// </returns>
        internal RouteDataResult ParseWebArchive(HtmlDocument webDocument)
        {
            HtmlNode originInput = webDocument.GetElementbyId("flight_places");
            if (originInput == null)
            {
                // Data is not ready yet
                return new RouteDataResult(DataResult.NotReady, null);
            }

            var resultDivs = webDocument.DocumentNode.SelectNodes("//div[@id='results_list']//div[@class='flights_a']");
            if (resultDivs == null || resultDivs.Count < 1)
            {
                // Data is not ready yet
                return new RouteDataResult(DataResult.NotReady, null);
            }

            var route = new TravelRoute(0, this.Departure, this.Destination);

            foreach (var resultSection in resultDivs)
            {
                // Each result set
                DateTime dataDate = DateTime.Now;
                var operatorData = new Dictionary<string, List<Flight>>();
                var newData = new JourneyData(0, "EUR", dataDate);

                FlightLeg outboundLeg = null, inboundLeg = null;
                string flightOperator = null;
                TravelAgency travelAgency = null;
                double price = 0.0;
                List<Fare> fares = new List<Fare>();

                var priceContainers = resultSection.SelectNodes(".//div[@class='f_price_container']//div[@class='row']");
                if (priceContainers == null || priceContainers.Count < 1)
                {
                    continue;
                }

                foreach (var priceContainer in priceContainers)
                {
                    string onClickStr = priceContainer.GetAttributeValue("onclick", string.Empty);
                    travelAgency = this.TryGetTravelAgency(onClickStr, false);

                    var priceNode = priceContainer.SelectSingleNode(".//div[@class='f_price']");
                    if (priceNode == null)
                    {
                        continue;
                    }

                    string priceStr = Regex.Match(priceNode.InnerText.Replace(",", "."), @"\d+(.\d+)?").Value;
                    double.TryParse(priceStr, NumberStyles.Any, NamingRule.NumberCulture, out price);
                    fares.Add(new Fare { TravelAgency = travelAgency, Price = price });
                }

                // Loop through each column in table
                var flightNode = resultSection.SelectSingleNode(".//div[@class='f_normal_info']");
                if (flightNode == null)
                {
                    continue;
                }

                foreach (HtmlNode flightDetailNode in flightNode.ChildNodes)
                {
                    // Fetch the flight detail from the row
                    if (flightDetailNode.Name != "div")
                    {
                        continue;
                    }

                    string className = flightDetailNode.GetAttributeValue("class", string.Empty);
                    switch (className)
                    {
                        case "f_outbound":
                        case "f_outbound_only":
                        case "f_return":
                            var divNodes = flightDetailNode.Descendants("div");
                            if (divNodes != null)
                            {
                                string depDatePartStr = null, depTimePartStr = null, stopStr = null, arrDatePartStr = null, arrTimePartStr = null;
                                TimeSpan duration = TimeSpan.Zero;
                                foreach (var dataNode in divNodes)
                                {
                                    // Each flight
                                    string dataClass = dataNode.GetAttributeValue("class", string.Empty);
                                    switch (dataClass)
                                    {
                                        case "f_dep_date":
                                            depDatePartStr = dataNode.InnerText;
                                            break;
                                        case "f_departure":
                                            depTimePartStr = dataNode.InnerText;
                                            break;
                                        case "f_arr_date":
                                            arrDatePartStr = dataNode.InnerText;
                                            break;
                                        case "f_arrival":
                                            arrTimePartStr = dataNode.InnerText;
                                            break;
                                        case "f_duration":
                                            duration = this.TryGetDuration(dataNode.InnerText);
                                            break;
                                        case "f_stops":
                                            stopStr = TryGetNumberString(dataNode.InnerText);
                                            break;
                                    }
                                }

                                // Validate that we got all required data
                                string depDateStr = string.Format(CultureInfo.InvariantCulture, "{0} {1}", depDatePartStr, depTimePartStr),
                                       arrDateStr = string.Format(CultureInfo.InvariantCulture, "{0} {1}", arrDatePartStr, arrTimePartStr);
                                DateTime deptDate, arrDate;
                                if (DateTime.TryParseExact(
                                    depDateStr,
                                    "dd.MM.yy HH:mm",
                                    CultureInfo.InvariantCulture,
                                    DateTimeStyles.None,
                                    out deptDate) && deptDate.IsDefined()
                                    && DateTime.TryParseExact(
                                        arrDateStr,
                                        "dd.MM.yy HH:mm",
                                        CultureInfo.InvariantCulture,
                                        DateTimeStyles.None,
                                        out arrDate) && arrDate.IsDefined())
                                {
                                    if (duration > TimeSpan.Zero)
                                    {
                                        int transit;
                                        int.TryParse(stopStr, out transit); // This might fail for straight flight: Just ignore it
                                        var flightLeg = new FlightLeg(deptDate, arrDate, duration, transit);
                                        if (className == "f_return")
                                        {
                                            inboundLeg = flightLeg;
                                        }
                                        else
                                        {
                                            outboundLeg = flightLeg;
                                        }
                                    }
                                }
                            }

                            break;

                        case "f_company":
                            flightOperator = flightDetailNode.InnerText.Replace("mm. ", string.Empty);
                            break;
                    }
                }

                if (outboundLeg != null)
                {
                    bool shouldAdd;
                    if (shouldAdd = !operatorData.ContainsKey(flightOperator))
                    {
                        // Flight will always be added if it is the first from this operator
                        if (operatorData.Keys.Count == this.MaxAirlines)
                        {
                            // If we reached the limit for number of flight operators
                            continue;
                        }

                        operatorData.Add(flightOperator, new List<Flight>(this.MaxFlightsPerAirline));
                    }

                    var opearatorFlights = operatorData[flightOperator];
                    if (!shouldAdd)
                    {
                        // This is not the first fly from this operator
                        TimeSpan totalDuration = (outboundLeg == null ? TimeSpan.Zero : outboundLeg.Duration)
                                                 + (inboundLeg == null ? TimeSpan.Zero : inboundLeg.Duration);
                        var lastFlight = opearatorFlights[opearatorFlights.Count - 1];

                        if ((price - lastFlight.Price) > this.MinPriceMargin)
                        {
                            // If the price differs enough, add new flight if we still have space
                            if (opearatorFlights.Count < this.MaxFlightsPerAirline)
                            {
                                shouldAdd = true;
                            }
                        }
                        else
                        {
                            // The new price does not differ enough from last flight: Add or replace existing flight if the duration is shorter
                            for (int i = opearatorFlights.Count - 1; i >= 0; i--)
                            {
                                var f = opearatorFlights[i];
                                if ((price - f.Price) <= this.MinPriceMargin && totalDuration < f.Duration)
                                {
                                    opearatorFlights.RemoveAt(i);
                                    shouldAdd = true;
                                    break;
                                }
                            }
                        }
                    }

                    if (shouldAdd && fares.Count > 0)
                    {
                        var newFlight = new Flight(newData, flightOperator, outboundLeg, inboundLeg) { Fares = fares };
                        newData.AddFlight(newFlight);
                        opearatorFlights.Add(newFlight);
                    }
                }

                if (newData.Flights.Count > 0)
                {
                    Journey existJourney = null;
                    DateTime deptDate = newData.Flights[0].OutboundLeg.Departure.Date;
                    DateTime retDate = DateTime.MinValue;
                    if (newData.Flights[0].InboundLeg != null)
                    {
                        retDate = newData.Flights[0].InboundLeg.Departure.Date;
                    }

                    foreach (var j in route.Journeys)
                    {
                        if (j.DepartureDate == deptDate && j.ReturnDate == retDate)
                        {
                            existJourney = j;
                            break;
                        }
                    }

                    if (existJourney == null)
                    {
                        existJourney = new Journey();
                        route.AddJourney(existJourney);
                    }

                    existJourney.AddData(newData);
                    existJourney.DepartureDate = deptDate;
                    existJourney.ReturnDate = retDate;
                }
            }

            return new RouteDataResult(DataResult.Ready, route);
        }
示例#15
0
 /// <summary>
 /// The reset.
 /// </summary>
 public void Reset()
 {
     this.LastDataDate = this.LastRequestStartedDate = DateTime.MinValue;
     this._lastRetrievedRoute = null;
     this.RequestState = DataRequestState.Pending;
 }
示例#16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DataRequestResult"/> struct.
 /// </summary>
 /// <param name="requestState">
 /// The request state.
 /// </param>
 /// <param name="resultRoute">
 /// The result route.
 /// </param>
 public DataRequestResult(DataRequestState requestState, TravelRoute resultRoute)
 {
     this.RequestState = requestState;
     this.ResultRoute = resultRoute;
 }
示例#17
0
        /// <summary>
        /// The bind data.
        /// </summary>
        /// <param name="route">
        /// The route.
        /// </param>
        private void BindData(TravelRoute route)
        {
            if (route != null && route.Journeys.Count > 0 && route.Journeys[0].Data.Count > 0)
            {
                DateTime dataDate = DateTime.Now;
                var flights = new List<Flight>();
                var jData = route.Journeys[0].Data;
                foreach (var d in jData)
                {
                    d.DataDate = dataDate;
                    if (d.Flights != null && d.Flights.Count > 0)
                    {
                        flights.AddRange(d.Flights);
                    }
                }

                this.lvFlightData.SetDataSourceAsync(flights, true);
                this.lvFlightData.SetWatermark(null);
            }
            else if (this.RequestState == DataRequestState.NoData)
            {
                this.lvFlightData.SetWatermark(
                    "There is no data for selected journey. Probably there is no flight on that date or there is no flight between two destinations!");
            }
            else if (this.LastException != null)
            {
                this.lvFlightData.SetWatermark("Failed to retrieve data: " + this.LastException.Message);
            }
            else
            {
                this.lvFlightData.SetWatermark("The request was not properly handled or aborted");
            }
        }
示例#18
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Journey"/> class.
 /// </summary>
 /// <param name="route">
 /// The route.
 /// </param>
 public Journey(TravelRoute route)
     : this()
 {
     this.Route = route;
 }
示例#19
0
        /// <summary>
        /// The do request data.
        /// </summary>
        /// <param name="request">
        /// The request.
        /// </param>
        private void DoRequestData(FlightFareRequest request)
        {
            if (!Monitor.TryEnter(this._syncObject))
            {
                return;
            }

            try
            {
                this.IsStopping = false;
                if (this.IsDestructed() || this.IsStopping)
                {
                    return;
                }

                // First, reset all data
                this.Reset();
                var reqName = StringUtil.GetPeriodString(request.DepartureDate, request.ReturnDate);
                this.lvFlightData.SafeInvoke(
                    new Action(
                        () =>
                        {
                            this.lvFlightData.Name = reqName;
                            this.lvFlightData.SetWatermark("Requesting data... Please wait...");
                        }));

                // Create a thread to get the data
                DataRequestResult dataRequestResult = DataRequestResult.Empty;
                var workResult = BackgroundThread.DoWork(
                    () =>
                    {
                        this.lvFlightData.SetWatermark(
                            "Data request was started on " + DateTime.Now + Environment.NewLine
                            + "Please wait while the application retrieves fare data...");
                        this.RequestState = DataRequestState.Requested;
                        this.LastRequestStartedDate = DateTime.Now;
                        dataRequestResult = this.DataHandler.QueryData(request, this.OnProgressChanged);
                    },
                    this.TimeoutInSeconds,
                    reqName,
                    AppContext.Logger);

                if (workResult.Succeeded)
                {
                    this.RequestState = dataRequestResult.ResultRoute == null ? DataRequestState.NoData : DataRequestState.Ok;
                }
                else
                {
                    this.RequestState = DataRequestState.Failed;
                    if (workResult.IsTimedout)
                    {
                        string err = "Request timed out after " + this.TimeoutInSeconds + "s";
                        this.LastException = new TimeoutException(err);
                        this.Logger.ErrorFormat(err);
                    }
                    else if (workResult.Exception != null)
                    {
                        this.LastException = workResult.Exception;
                        this.Logger.Error("Failed to request journey data: " + workResult.Exception.Message);
                    }
                }

                this.RequestState = dataRequestResult.RequestState;
                this._lastRetrievedRoute = dataRequestResult.ResultRoute;
                if (this.RequestState > DataRequestState.Requested)
                {
                    this.LastDataDate = DateTime.Now;
                    if (this._lastRetrievedRoute != null && this._lastRetrievedRoute.Journeys.Count > 0)
                    {
                        foreach (var j in this._lastRetrievedRoute.Journeys)
                        {
                            foreach (var d in j.Data)
                            {
                                if (d.DataDate.IsUndefined())
                                {
                                    d.DataDate = this.LastDataDate;
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.LastException = ex;
                this.RequestState = DataRequestState.Failed;
                this.Logger.Error("Failed to request data: " + ex);
            }
            finally
            {
                Monitor.Exit(this._syncObject); // Release the lock at the end
                this.OnGetJourneyCompleted(new JourneyEventArgs(this.LastRetrievedRoute, this.RequestState, this.LastRequestInitiatedDate));
                this.IsStopping = false;
            }
        }
示例#20
0
        /// <summary>
        /// The do export database.
        /// </summary>
        /// <param name="exportPath">
        /// The export path.
        /// </param>
        /// <param name="format">
        /// The format.
        /// </param>
        /// <param name="batchSize">
        /// The batch size.
        /// </param>
        /// <param name="callback">
        /// The callback.
        /// </param>
        private void DoExportDatabase(string exportPath, DataFormat format, int batchSize, IProgressCallback callback)
        {
            var routes = this.ResultEnvironment.FareDatabase.GetRoutes(true, false, false, false, callback);
            var journeyBatch = new List<Journey>();
            var routesBatch = new List<TravelRoute>();
            var jCount = routes.Sum(r => r.Journeys.Count);
            int stackCount = 0;

            callback.Begin(0, jCount);
            callback.Title = string.Format("Processing {0} journeys...", jCount);
            int routesCount = routes.Count;
            int lastRoutesIdx = routesCount - 1;

            for (int i = 0; i < routesCount; i++)
            {
                if (callback.IsAborting)
                {
                    return;
                }

                TravelRoute route = routes[i];
                callback.Text = string.Format("{0} - {1}", route.Departure, route.Destination);
                var journeys = route.Journeys;
                int journeysCount = journeys.Count;
                int lastJourneyIdx = journeysCount - 1;
                if (journeysCount > 0)
                {
                    for (int j = 0; j < journeysCount; j++)
                    {
                        var journey = journeys[j];
                        journeyBatch.Add(journey);
                        if (journeyBatch.Count >= batchSize || j == lastJourneyIdx)
                        {
                            // Batch is full or this is the last item
                            var expRoute = new TravelRoute(route); // Gather journeys into 1 exported route
                            expRoute.AddJourney(journeyBatch, false);
                            this.ResultEnvironment.FareDatabase.LoadData(journeyBatch, true, AppContext.ProgressCallback);
                            routesBatch.Add(expRoute);
                            stackCount += journeyBatch.Count;
                            journeyBatch.Clear();
                        }

                        if (stackCount >= batchSize || i == lastRoutesIdx)
                        {
                            if (routesBatch.Count > 0)
                            {
                                this.ResultEnvironment.ArchiveManager.ExportData(routesBatch, exportPath, format, AppContext.ProgressCallback);
                                routesBatch.Clear();
                            }

                            callback.Increment(stackCount);
                            stackCount = 0;
                        }
                    }
                }

                callback.Increment(1);
            }
        }
示例#21
0
        /// <summary>
        /// The selected location changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void SelectedLocationChanged(object sender, EventArgs e)
        {
            // If this event was triggered due to changing of another combobox: Return
            if (this._changingLocation)
            {
                return;
            }

            this._changingLocation = true;
            try
            {
                if (this._routeData == null)
                {
                    return;
                }

                Airport selDeparture = null;
                Airport selDestination = null;
                if (sender == this.cbDeparture)
                {
                    // If departure location was changed
                    if (this.cbDeparture.Items.Count < 1)
                    {
                        return;
                    }

                    if (this._loadingRoutes)
                    {
                        if (this._executionParam.Departure != null)
                        {
                            this.cbDeparture.SelectedAirportCode = this._executionParam.Departure.IATA;
                        }

                        if (this.cbDeparture.SelectedItem == null && this.cbDeparture.Items.Count > 0)
                        {
                            // If the configured departure does not exist in database
                            this.cbDeparture.SelectedItem = this.cbDeparture.Items[0];
                        }
                    }

                    selDeparture = this.cbDeparture.SelectedAirport;
                    List<Airport> destList = null;
                    if (this._routeData != null)
                    {
                        destList = new List<Airport>();
                        foreach (var r in this._routeData)
                        {
                            if (string.Equals(r.Departure.IATA, selDeparture.IATA, StringComparison.OrdinalIgnoreCase)
                                && !destList.Contains(r.Destination))
                            {
                                destList.Add(r.Destination);
                            }
                        }
                    }

                    this.cbDestination.DataSource = destList;
                    if (this._loadingRoutes)
                    {
                        if (this._executionParam.Destination != null)
                        {
                            this.cbDestination.SelectedAirport = this._executionParam.Destination;
                        }

                        if (this.cbDestination.SelectedItem == null && this.cbDestination.Items.Count > 0)
                        {
                            // If the configured destination does not exist in database
                            this.cbDestination.SelectedItem = this.cbDestination.Items[0]; // Select the first item available
                        }
                    }
                }
                else
                {
                    selDeparture = this.cbDeparture.SelectedAirport;
                }

                // If the destination was specified before: Try to match it with the new data
                selDestination = this.cbDestination.SelectedAirport;
                if (this._isMainForm)
                {
                    this._activeRoute = null; // Clear the active route first
                    if (selDeparture != null && selDestination != null)
                    {
                        // Reload data only if we are running on main form
                        foreach (var r in this._routeData)
                        {
                            string deptCode = r.Departure.IATA, destCode = r.Destination.IATA;
                            if (string.Equals(deptCode, selDeparture.IATA, StringComparison.OrdinalIgnoreCase)
                                && string.Equals(destCode, selDestination.IATA, StringComparison.OrdinalIgnoreCase))
                            {
                                this._activeRoute = r;
                                this.Logger.DebugFormat("Reloading routes [{0}]-[{1}]...", deptCode, destCode);
                                this.FareDatabase.LoadData(this._activeRoute, false, false, false, AppContext.ProgressCallback);
                                break;
                            }
                        }
                    }
                }

                this.FlightFilter_Changed(null, e);
            }
            finally
            {
                this._changingLocation = false;
            }
        }
示例#22
0
        /// <summary>
        /// The load data.
        /// </summary>
        /// <param name="route">
        /// The route.
        /// </param>
        /// <param name="loadJourneyData">
        /// The load journey data.
        /// </param>
        /// <param name="loadHistory">
        /// The load history.
        /// </param>
        /// <param name="loadFlights">
        /// The load flights.
        /// </param>
        /// <param name="callback">
        /// The callback.
        /// </param>
        /// <exception cref="ArgumentException">
        /// </exception>
        public void LoadData(TravelRoute route, bool loadJourneyData, bool loadHistory, bool loadFlights, IProgressCallback callback)
        {
            this.Logger.DebugFormat(
                "Load data for route [{0}-{1}] [{2}{3}{4}]",
                route.Departure.IATA,
                route.Destination.IATA,
                loadJourneyData ? "D" : null,
                loadHistory ? "H" : null,
                loadFlights ? "F" : null);
            using (var connection = new SQLiteConnection(this._connectionString))
            {
                if (route.Id < 1)
                {
                    throw new ArgumentException("Invalid Route Id");
                }

                route.Journeys.Clear();
                string selectSql = "SELECT J.LID, J.TDEPARTURE, J.TRETURN"
                                   + (loadJourneyData
                                          ? (", D.LID DATAID, D.SCURRENCY, " + (loadHistory ? "D.TUPDATE" : "MAX(D.TUPDATE) TUPDATE")
                                             + (loadFlights ? ", D.BFLIGHT" : string.Empty))
                                          : string.Empty) + " FROM JOURNEY J" + (loadJourneyData ? ", JOURNEY_DATA D " : string.Empty) + " WHERE J.LROUTEID = @lRouteId "
                                   + (loadJourneyData ? " AND D.LJOURNEYID = J.LID " + (loadHistory ? string.Empty : " GROUP BY (D.LJOURNEYID) ") : string.Empty);

                using (var getJourneyCmd = new SQLiteCommand(selectSql, connection))
                {
                    getJourneyCmd.Parameters.AddWithValue("@lRouteId", route.Id);

                    connection.Open();
                    using (var reader = getJourneyCmd.ExecuteReader())
                    {
                        if (reader.HasRows)
                        {
                            int iId = reader.GetOrdinal("LID");
                            int iDeparture = reader.GetOrdinal("TDEPARTURE");
                            int iReturn = reader.GetOrdinal("TRETURN");
                            int iUpdate = reader.GetOrdinal("TUPDATE");
                            int iCurrency = loadJourneyData ? reader.GetOrdinal("SCURRENCY") : -1;
                            int iDataId = loadJourneyData ? reader.GetOrdinal("DATAID") : -1;
                            int iFlight = loadJourneyData ? reader.GetOrdinal("BFLIGHT") : -1;

                            while (reader.Read())
                            {
                                long journeyId = reader.GetInt64(iId);
                                Journey journey = null;
                                var allJourneys = route.Journeys;
                                foreach (var j in allJourneys)
                                {
                                    if (j.Id == journeyId)
                                    {
                                        journey = j;
                                        break;
                                    }
                                }

                                if (journey == null)
                                {
                                    var deptDate = DateTime.ParseExact(reader.GetString(iDeparture), DATE_FORMAT, CultureInfo.InvariantCulture);
                                    var retDate = DateTime.ParseExact(reader.GetString(iReturn), DATE_FORMAT, CultureInfo.InvariantCulture);
                                    journey = new Journey(journeyId, route, deptDate, retDate);
                                    route.AddJourney(journey);
                                }

                                if (loadJourneyData)
                                {
                                    var dataDate = DateTime.ParseExact(
                                        reader.GetString(iUpdate),
                                        DATETIME_FORMAT,
                                        CultureInfo.InvariantCulture,
                                        DateTimeStyles.AssumeUniversal);
                                    var newData = new JourneyData(reader.GetInt64(iDataId), reader.GetString(iCurrency), dataDate);

                                    if (loadFlights)
                                    {
                                        var dbFlights = this._formatter.FromRaw<List<Flight>>((byte[])reader[iFlight]);
                                        if (dbFlights != null && dbFlights.Count > 0)
                                        {
                                            newData.AddFlights(dbFlights);
                                        }
                                    }

                                    journey.AddData(newData);
                                }
                            }
                        }
                    }
                }
            }
        }
示例#23
0
        /// <summary>
        /// The bind list view.
        /// </summary>
        /// <param name="route">
        /// The route.
        /// </param>
        /// <param name="departureDate">
        /// The departure date.
        /// </param>
        /// <param name="returnDate">
        /// The return date.
        /// </param>
        /// <param name="priceLimit">
        /// The price limit.
        /// </param>
        /// <param name="viewAllHistory">
        /// The view all history.
        /// </param>
        /// <param name="amountFlightsPerData">
        /// The amount flights per data.
        /// </param>
        /// <param name="minDuration">
        /// The min duration.
        /// </param>
        /// <param name="maxDuration">
        /// The max duration.
        /// </param>
        /// <param name="opearators">
        /// The opearators.
        /// </param>
        /// <param name="populateData">
        /// The populate data.
        /// </param>
        private void BindListView(
            TravelRoute route,
            DateTime departureDate,
            DateTime returnDate,
            double priceLimit,
            bool viewAllHistory,
            int amountFlightsPerData,
            int minDuration,
            int maxDuration,
            Dictionary<string, bool> opearators,
            bool populateData)
        {
            DateTime requestDate = DateTime.Now;
            if (!Monitor.TryEnter(this._lockObj))
            {
                // The view is being refreshed: Send a signal
                this._lvChangeRequested = true;
                this._lvChangeRequestDate = requestDate;
                Monitor.Enter(this._lockObj);
            }

            this._lvChangeRequested = false;
            try
            {
                if (requestDate < this._lvChangeRequestDate)
                {
                    // Another request has come in: Let the later one passes through
                    return;
                }

                var data = route.Journeys;
                if (data == null || data.Count < 1)
                {
                    return;
                }

                this.SafeInvoke(
                    (Action)delegate
                        {
                            progressBar.ShowInTaskbar = progressBar.Visible = true;
                            progressBar.Style = ProgressBarStyle.Marquee;
                        });

                // Get all the needed data according to the Date filter condition
                IEnumerable<Journey> journeyCollection = null;
                if (departureDate.IsDefined())
                {
                    // Known departure date
                    if (returnDate == DateTime.MaxValue)
                    {
                        // Unknown return date
                        journeyCollection = data.Where(o => o.DepartureDate.Date == departureDate.Date).OrderByDescending(o => o.ReturnDate);
                    }
                    else
                    {
                        // Known return date or one-way trip for DateTime.MinValue
                        journeyCollection = data.Where(o => o.DepartureDate.Date == departureDate.Date && o.ReturnDate.Date == returnDate.Date);
                    }
                }
                else
                {
                    // Unknown departure date
                    if (returnDate == DateTime.MaxValue)
                    {
                        // Unknown return date
                        journeyCollection = data.OrderBy(o => o.DepartureDate).ThenByDescending(o => o.ReturnDate);
                    }
                    else
                    {
                        // Known return date or one-way trip for DateTime.MinValue
                        journeyCollection = data.Where(o => o.ReturnDate.Date == returnDate.Date).OrderBy(o => o.DepartureDate);
                    }
                }

                var newOperators = new List<string>();
                var existOperatorSelections = new List<CheckBoxComboBoxItem>();

                if (populateData)
                {
                    this.SetStatus("Loading flight data...");
                    const int loadSize = 1000;
                    var loadBatch = new List<Journey>();
                    foreach (var j in journeyCollection)
                    {
                        loadBatch.Add(j);
                        if (loadBatch.Count == loadSize)
                        {
                            this.FareDatabase.LoadData(loadBatch, viewAllHistory, AppContext.ProgressCallback);
                            loadBatch.Clear();
                        }

                        if (this._lvChangeRequested)
                        {
                            return;
                        }
                    }

                    if (!this._lvChangeRequested && loadBatch.Count > 0)
                    {
                        this.FareDatabase.LoadData(loadBatch, viewAllHistory, AppContext.ProgressCallback);
                    }
                }

                this.SetStatus("Processing data...");

                int totalJourneysCount = journeyCollection.Count();
                int totalFlightsCount = 0;
                int skippedDuration = 0, skippedPrice = 0, skippedIgnored = 0;
                var flightsData = new List<Flight>();

                this.SafeInvoke(
                    (Action)delegate
                        {
                            progressBar.Style = ProgressBarStyle.Continuous;
                            progressBar.Value = 0;
                            progressBar.Maximum = totalJourneysCount;
                            existOperatorSelections.AddRange(cbAirlines.CheckBoxItems);
                        });

                // Only filter based on duration if there is undefined departure or return date, and user did not choose one-way trip
                bool checkDuration = (departureDate.IsUndefined() || returnDate.IsUndefined()) && returnDate != DateTime.MinValue;
                foreach (Journey j in journeyCollection)
                {
                    this.SafeInvoke((Action)delegate { progressBar.Value++; });
                    if (this._lvChangeRequested)
                    {
                        return;
                    }

                    bool skippedJourney = false;
                    if (checkDuration)
                    {
                        int stayDuration = (int)(j.ReturnDate.Date - j.DepartureDate.Date).TotalDays;
                        if (stayDuration < 0)
                        {
                            // One-way trip
                            stayDuration = 0;
                        }

                        skippedJourney = stayDuration < minDuration || stayDuration > maxDuration;
                    }

                    List<Flight> journeyFlights = skippedJourney ? null : new List<Flight>();
                    foreach (var d in j.Data)
                    {
                        // Keep counts for statistics
                        totalFlightsCount += d.Flights.Count;

                        if (skippedJourney)
                        {
                            skippedDuration += d.Flights.Count;
                        }
                        else
                        {
                            var flights = d.Flights;
                            flights.Sort(FlightPriceComparer.Instance);

                            int taking = amountFlightsPerData > flights.Count ? flights.Count : amountFlightsPerData;
                            skippedIgnored += flights.Count - taking;
                            for (int i = 0; i < taking; i++)
                            {
                                if (flights[i].Price > priceLimit)
                                {
                                    skippedPrice += taking - i;
                                    break;
                                }

                                journeyFlights.Add(flights[i]);
                            }
                        }
                    }

                    if (journeyFlights == null)
                    {
                        continue;
                    }

                    // Fill the list of flight operators for filter purpose
                    foreach (Flight flight in journeyFlights)
                    {
                        string flightOperator = flight.Operator;
                        if (opearators != null)
                        {
                            if (opearators.ContainsKey(flightOperator) && !opearators[flightOperator])
                            {
                                continue;
                            }
                        }

                        flightsData.Add(flight);

                        if (!newOperators.Contains(flightOperator))
                        {
                            newOperators.Add(flightOperator);
                        }
                    }
                }

                this.SetStatus("Rendering view...");
                this.SafeInvoke(
                    new Action(
                        () =>
                            {
                                this.progressBar.Style = ProgressBarStyle.Marquee;
                                this.lvFlightData.SetDataSourceAsync(flightsData, true);

                                if (opearators == null)
                                {
                                    // Reload data - Refill list of operators
                                    var newOperatorCheckList = new Dictionary<string, bool>();
                                    if (opearators != null)
                                    {
                                        foreach (var v in opearators)
                                        {
                                            newOperatorCheckList.Add(v.Key, v.Value);
                                        }
                                    }

                                    foreach (string s in newOperators)
                                    {
                                        if (!newOperatorCheckList.ContainsKey(s))
                                        {
                                            newOperatorCheckList.Add(s, true);
                                        }
                                    }

                                    List<KeyValuePair<string, bool>> sortedOps = newOperatorCheckList.OrderBy(p => p.Key).ToList();

                                    this.cbAirlines.SelectedValueChanged -= this.FlightFilter_Changed;
                                    this.cbAirlines.TextChanged -= this.FlightFilter_Changed;
                                    this.cbAirlines.Text = null;
                                    this.cbAirlines.Items.Clear();
                                    this.cbAirlines.CheckBoxItems.Clear();

                                    sortedOps.ForEach(
                                        p =>
                                            {
                                                int pos = this.cbAirlines.Items.Add(p.Key);
                                                this.cbAirlines.CheckBoxItems[pos].Checked = p.Value;
                                            });
                                    this.cbAirlines.SelectedValueChanged += this.FlightFilter_Changed;
                                    this.cbAirlines.TextChanged += this.FlightFilter_Changed;
                                }

                                this.btnToCsv.Enabled = this.btnGraph.Enabled = flightsData.Count > 0;
                                this.progressBar.Visible = false;

                                string status;
                                if (totalFlightsCount == 0)
                                {
                                    status = "There is no flight data for this date";
                                }
                                else
                                {
                                    string journeyStr = totalJourneysCount > 1 ? " (" + totalJourneysCount + " dates)" : null;
                                    var parts = new List<string>();
                                    if (skippedDuration > 0)
                                    {
                                        parts.Add(skippedDuration + " not in duration range");
                                    }

                                    if (skippedPrice > 0)
                                    {
                                        parts.Add(skippedPrice + " too expensive");
                                    }

                                    if (skippedIgnored > 0)
                                    {
                                        parts.Add(skippedIgnored + " ignored");
                                    }

                                    if (flightsData.Count > 0)
                                    {
                                        parts.Add(flightsData.Count + " displayed");
                                    }

                                    string skipStr = parts.Count > 0 ? " | " + string.Join(", ", parts.ToArray()) : string.Empty;
                                    status = string.Format("Available flights: {0}{1}{2}", totalFlightsCount, journeyStr, skipStr);
                                }

                                this.numMinDuration.Enabled = this.numMaxDuration.Enabled = checkDuration;
                                this.SetStatus(status);
                            }));
            }
            catch (Exception ex)
            {
                this.Logger.Error(ex);
                MessageBox.Show(this, ex.ToString(), "Could not display data");
                this.SetStatus("An internal error occured");
            }
            finally
            {
                this.SafeInvoke(
                    (Action)(() =>
                        {
                            this.progressBar.ShowInTaskbar = this.progressBar.Visible = false;
                            this.progressBar.Value = 0;
                        }));
                Monitor.Exit(this._lockObj);
            }
        }
示例#24
0
        /// <summary>
        /// The export data.
        /// </summary>
        /// <param name="targetStream">
        /// The target stream.
        /// </param>
        /// <param name="route">
        /// The route.
        /// </param>
        /// <exception cref="ArgumentException">
        /// </exception>
        public void ExportData(Stream targetStream, TravelRoute route)
        {
            if (targetStream == null)
            {
                throw new ArgumentException("targetStream cannot be null");
            }

            if (route == null)
            {
                throw new ArgumentException("route cannot be null");
            }

            var setting = new XmlWriterSettings();
            setting.OmitXmlDeclaration = true;
            setting.Indent = true;
            setting.Encoding = Encoding.Default;

            /* TODO :FIX XML stream writer
            using (XmlWriter writer = XmlWriter.Create(targetStream, setting))
            {
                writer.WriteStartElement("body");

                writer.WriteStartElement("input");
                writer.WriteAttributeString("id", "text_fly_from");
                writer.WriteAttributeString("value", route.Departure.IATA);
                writer.WriteEndElement();
                writer.WriteStartElement("input");
                writer.WriteAttributeString("id", "text_fly_to");
                writer.WriteAttributeString("value", route.Destination.IATA);
                writer.WriteEndElement();

                foreach (var journey in route.Journeys)
                {
                    foreach (var data in journey.Data)
                    {
                        writer.WriteStartElement("div");
                        writer.WriteAttributeString("id", "results_list");
                        writer.WriteAttributeString("dataDate", XmlConvert.ToString(data.DataDate, XmlDateTimeSerializationMode.Utc));

                        foreach (Flight f in data.Flights)
                        {
                            var outboundLeg = f.OutboundLeg;
                            if (outboundLeg == null)
                            {
                                continue;
                            }

                            writer.WriteStartElement("div");
                            writer.WriteAttributeString("class", "flights_b");
                            writer.WriteAttributeString("id", "flight_result_0");
                            if (f.TravelAgency != null && !string.IsNullOrEmpty(f.TravelAgency.Url))
                            {
                                writer.WriteAttributeString("onclick", "click('" + f.TravelAgency.Url + "')");
                            }

                            // Outbound
                            writer.WriteStartElement("div");
                            writer.WriteAttributeString("class", "f_outbound");

                            writer.WriteStartElement("div");
                            writer.WriteAttributeString("class", "f_dep_date");
                            writer.WriteString(outboundLeg.Departure.ToString("dd.MM.yy"));
                            writer.WriteEndElement();

                            writer.WriteStartElement("div");
                            writer.WriteAttributeString("class", "f_departure");
                            writer.WriteString(outboundLeg.Departure.ToString("HH:mm"));
                            writer.WriteEndElement();

                            writer.WriteStartElement("div");
                            writer.WriteAttributeString("class", "f_arr_date");
                            writer.WriteString(outboundLeg.Arrival.ToString("dd.MM.yy"));
                            writer.WriteEndElement();

                            writer.WriteStartElement("div");
                            writer.WriteAttributeString("class", "f_arrival");
                            writer.WriteString(outboundLeg.Arrival.ToString("HH:mm"));
                            writer.WriteEndElement();

                            writer.WriteStartElement("div");
                            writer.WriteAttributeString("class", "f_stops");
                            writer.WriteString(outboundLeg.Transit.ToString(CultureInfo.InvariantCulture));
                            writer.WriteEndElement();

                            writer.WriteStartElement("div");
                            writer.WriteAttributeString("class", "f_duration");
                            writer.WriteString(outboundLeg.Duration + "h");
                            writer.WriteEndElement();
                            writer.WriteEndElement();

                            // Return trip
                            var inboundLeg = f.InboundLeg;
                            if (inboundLeg != null)
                            {
                                writer.WriteStartElement("div");
                                writer.WriteAttributeString("class", "f_return");

                                writer.WriteStartElement("div");
                                writer.WriteAttributeString("class", "f_dep_date");
                                writer.WriteString(inboundLeg.Departure.ToString("dd.MM.yy"));
                                writer.WriteEndElement();

                                writer.WriteStartElement("div");
                                writer.WriteAttributeString("class", "f_departure");
                                writer.WriteString(inboundLeg.Departure.ToString("HH:mm"));
                                writer.WriteEndElement();

                                writer.WriteStartElement("div");
                                writer.WriteAttributeString("class", "f_arr_date");
                                writer.WriteString(inboundLeg.Arrival.ToString("dd.MM.yy"));
                                writer.WriteEndElement();

                                writer.WriteStartElement("div");
                                writer.WriteAttributeString("class", "f_arrival");
                                writer.WriteString(inboundLeg.Arrival.ToString("HH:mm"));
                                writer.WriteEndElement();

                                writer.WriteStartElement("div");
                                writer.WriteAttributeString("class", "f_stops");
                                writer.WriteString(inboundLeg.Transit.ToString(CultureInfo.InvariantCulture));
                                writer.WriteEndElement();

                                writer.WriteStartElement("div");
                                writer.WriteAttributeString("class", "f_duration");
                                writer.WriteString(inboundLeg.Duration + "h");
                                writer.WriteEndElement();

                                writer.WriteEndElement();
                            }

                            writer.WriteStartElement("div");
                            writer.WriteAttributeString("class", "f_company");
                            writer.WriteString(f.Operator);
                            writer.WriteEndElement();

                            writer.WriteStartElement("div");
                            writer.WriteAttributeString("class", "f_price");
                            writer.WriteString(f.Price.ToString(CultureInfo.InvariantCulture) + " €");
                            writer.WriteEndElement();

                            writer.WriteEndElement();
                        }

                        writer.WriteEndElement();
                    }
                }

                writer.WriteEndElement();
            }
             */
        }
示例#25
0
        /// <summary>The extract tab data.</summary>
        /// <returns>The <see cref="IList" />.</returns>
        private IList<TravelRoute> ExtractTabData()
        {
            AppContext.Logger.Debug("Generating journey from all tabs...");
            var result = new List<TravelRoute>();

            foreach (TabPage tab in this.fareBrowserTabs.TabPages)
            {
                try
                {
                    var request = tab.Tag as FareMonitorRequest;
                    if (request != null && request.BrowserControl != null)
                    {
                        TravelRoute route = request.BrowserControl.LastRetrievedRoute;
                        if (route != null)
                        {
                            TravelRoute existRoute = null;
                            foreach (var r in result)
                            {
                                if (r.IsSameRoute(route))
                                {
                                    existRoute = r;
                                    break;
                                }
                            }

                            if (existRoute == null)
                            {
                                existRoute = new TravelRoute(route);
                                result.Add(route);
                            }

                            existRoute.AddJourney(route.Journeys, false);
                        }
                    }
                }
                catch (Exception ex)
                {
                    AppContext.Logger.ErrorFormat("Failed to get data from tab: " + ex);
                }
            }

            return result;
        }