Ejemplo n.º 1
0
        /// <summary>
        /// Load the collection of train trips
        /// </summary>
        private static void LoadTrips()
        {
            // Load the trips
            int numberOfTrips = PersistentStorage.GetIntItem(TrainTripsSizeName, 0);

            trips = new List <TrainTrip>();

            for (int tripIndex = 0; tripIndex < numberOfTrips; ++tripIndex)
            {
                TrainTrip tripToAdd = new TrainTrip {
                    From     = PersistentStorage.GetStringItem(TrainTripFromName + tripIndex, ""),
                    To       = PersistentStorage.GetStringItem(TrainTripToName + tripIndex, ""),
                    FromCode = PersistentStorage.GetStringItem(TrainTripFromCodeName + tripIndex, ""),
                    ToCode   = PersistentStorage.GetStringItem(TrainTripToCodeName + tripIndex, "")
                };
                trips.Add(tripToAdd);
            }

            // Get the current trip
            selectedTrip = PersistentStorage.GetIntItem(TrainTripSelectedName, 0);

            // Make sure that the selected trip is valid
            if (selectedTrip >= trips.Count)
            {
                selectedTrip = trips.Count - 1;
                PersistentStorage.SetIntItem(TrainTripSelectedName, selectedTrip);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Renders the visual contents of a specific widget contents into a RemoteViews object
        /// </summary>
        /// <param name="widgetContext">Widget context.</param>
        /// <param name="widgetId">Widget identifier.</param>
        private RemoteViews RenderWidgetContents(Context context, int widgetId)
        {
            // Initialise the persistent storage
            PersistentStorage.StorageMechanism = new StorageMechanism(context);
            PersistentStorage.UseCache         = false;

            // Create a RemoteView for the widget
            RemoteViews widgetView = new RemoteViews(context.PackageName, Resource.Layout.widget);

            // Extract the current trip details and display them.
            // The trip details and selected trip can be changed independently by the main app so a new set of train trip details need to be read
            TrainTrips.Reset();
            TrainTrip selectedTrip = TrainTrips.SelectedTrip;

            if (selectedTrip != null)
            {
                widgetView.SetTextViewText(Resource.Id.widgetTrip, string.Format("{0}:{1}", selectedTrip.FromCode, selectedTrip.ToCode));
            }

            // Extract the next departure time and display it
            DateTime departureTime = NextDeparture.DepartureTime;

            widgetView.SetTextViewText(Resource.Id.widgetDeparture, departureTime.ToString("HH:mm"));

            // Register pending intents for clicking on the displayed fields
            RegisterClicks(context, widgetView);

            // Show the correct image for the running state of the update service
            if (PersistentStorage.GetBoolItem(UpdateInProgressName, false) == true)
            {
                // An update is actually in progress, so show the progress indicator and hide
                // the service status flags
                widgetView.SetViewVisibility(Resource.Id.layoutProgressBar, Android.Views.ViewStates.Visible);
                widgetView.SetViewVisibility(Resource.Id.imageStart, Android.Views.ViewStates.Gone);
                widgetView.SetViewVisibility(Resource.Id.imageStop, Android.Views.ViewStates.Gone);
            }
            else
            {
                // Hide the progress indicator and show the servide state
                widgetView.SetViewVisibility(Resource.Id.layoutProgressBar, Android.Views.ViewStates.Gone);

                if (PersistentStorage.GetBoolItem(UpdateServiceRunningName, false) == true)
                {
                    widgetView.SetViewVisibility(Resource.Id.imageStart, Android.Views.ViewStates.Gone);
                    widgetView.SetViewVisibility(Resource.Id.imageStop, Android.Views.ViewStates.Visible);
                }
                else
                {
                    widgetView.SetViewVisibility(Resource.Id.imageStart, Android.Views.ViewStates.Visible);
                    widgetView.SetViewVisibility(Resource.Id.imageStop, Android.Views.ViewStates.Gone);
                }
            }

            return(widgetView);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Get a set of journeys for the specified trip
        /// </summary>
        /// <param name="requiredTrip"></param>
        public void GetJourneys(TrainTrip requiredTrip)
        {
            // Save the trip
            trip = requiredTrip;

            // As this is a new request clear the old results
            ClearJourneys();

            // Make the request for one minute from now
            currentRequest = RequestType.NewRequest;
            MakeRequestAfterSpecifiedTime(DateTime.Now);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Make a request for journeys for the current trip one minute after the specified time
        /// </summary>
        private void MakeRequestAfterSpecifiedTime(DateTime specifiedTime, TrainTrip requiredTrip)
        {
            // Make the request for one minute from specifiedTime
            DateTime requestTime = specifiedTime + TimeSpan.FromMinutes(1);

            // Record the day of the request
            requestDate = requestTime.Date;

            // Pass a cancellation token in case this request needs to be cancelled
            tokenSource = new CancellationTokenSource();

            trainJourneyRequest.GetJourneys(requiredTrip.From, requiredTrip.To, requestTime, tokenSource.Token);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Add a new trip to the collection and store.
        /// </summary>
        /// <param name="trip"></param>
        public static void AddTrip(TrainTrip trip)
        {
            // Store the trip
            PersistentStorage.SetStringItem(TrainTripFromName + Trips.Count, trip.From);
            PersistentStorage.SetStringItem(TrainTripToName + Trips.Count, trip.To);
            PersistentStorage.SetStringItem(TrainTripFromCodeName + Trips.Count, trip.FromCode);
            PersistentStorage.SetStringItem(TrainTripToCodeName + Trips.Count, trip.ToCode);

            // Add to the list
            Trips.Add(trip);

            // Update the count
            PersistentStorage.SetIntItem(TrainTripsSizeName, Trips.Count);
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Get a set of journeys for the specified trip
 /// </summary>
 /// <param name="requiredTrip"></param>
 public void GetJourneys(TrainTrip requiredTrip)
 {
     // Make the request for one minute from now
     MakeRequestAfterSpecifiedTime(DateTime.Now, requiredTrip);
 }
Ejemplo n.º 7
0
        /// <summary>
        /// Called when a trip item has been long clicked.
        /// Confirm deletion and then delete the item.
        /// This may involve changing the currently selected trip
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TripLongClick(object sender, TripAdapter.LongClickEventArgs e)
        {
            TrainTrip tripToDelete = TrainTrips.Trips[e.TripPosition];

            // Display a confirmation dialogue
            new AlertDialog.Builder(this)
            .SetTitle("Confirm trip deletion")
            .SetMessage(string.Format("Do you realy want to delete the '{0} to {1}' trip?", tripToDelete.From, tripToDelete.To))
            .SetPositiveButton("Yes", (senderAlert, args) => {
                // If the position of the trip to delete is greater than the currently selected trip then just delete it
                if (e.TripPosition > TrainTrips.Selected)
                {
                    // Delete the trip
                    TrainTrips.DeleteTrip(e.TripPosition);

                    // Refresh the spinner adapter
                    spinnerAdapter.ReloadSpinner(TrainTrips.TripStrings());
                }
                // If the position of the trip to delete is less than the currently selected trip the delete it and reduce the
                // index of the selected trip
                else if (e.TripPosition < TrainTrips.Selected)
                {
                    // Delete the trip
                    TrainTrips.DeleteTrip(e.TripPosition);

                    // Refresh the spinner adapter
                    spinnerAdapter.ReloadSpinner(TrainTrips.TripStrings());

                    // Select the previous trip
                    tripSpinner.SetSelection(TrainTrips.Selected - 1);
                }
                // If the selected trip is being deleted then either keep the selected index the same and refresh it, or if
                // the end of the list has been reached then reduce the selected trip index. If there are no items left then set the index to -1
                // and make sure that the results are cleared
                else
                {
                    // Delete the trip
                    TrainTrips.DeleteTrip(e.TripPosition);

                    // Refresh the spinner adapter
                    spinnerAdapter.ReloadSpinner(TrainTrips.TripStrings());

                    if (TrainTrips.Selected >= TrainTrips.Trips.Count)
                    {
                        if (TrainTrips.Selected > 0)
                        {
                            // Select the previous trip
                            tripSpinner.SetSelection(TrainTrips.Selected - 1);
                        }
                        else
                        {
                            // Clear the selection. This will not cause the selected event to be called so clear the journey details explicitly
                            tripSpinner.SetSelection(-1);

                            TrainTrips.Selected = -1;

                            // Clear the currently displayed data
                            trainJourneyRetrieval.ClearJourneys();

                            // Reset the update time
                            updateTimer.ResetTimer();
                        }
                    }
                    else
                    {
                        // Need to simulate a selection changed event
                        TripItemSelected(null, new AdapterView.ItemSelectedEventArgs(null, null, TrainTrips.Selected, 0));
                    }
                }
            })
            .SetNegativeButton("No", (EventHandler <DialogClickEventArgs>)null)
            .Create()
            .Show();
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Retrieve a set of journeys for the specified from and to stations.
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        public async void GetJourneys(string from, string to, DateTime requestTime, CancellationToken cancelToken)
        {
            try
            {
                // Check if a previously obtained session id cookie is still valid
                if ((DateTime.Now - sessionCookieTime).TotalMinutes > SeesionCookieValidTimeInMinutes)
                {
                    // Must load the search page in order to set the session id cookie
                    await client.GetAsync("http://ojp.nationalrail.co.uk/service/planjourney/search", cancelToken);

                    // Save the time that this session id was obtained
                    sessionCookieTime = DateTime.Now;
                }

                // Set up the variable parameters
                requestParameters["from.searchTerm"]               = TrainTrip.ToWebFormat(from);
                requestParameters["to.searchTerm"]                 = TrainTrip.ToWebFormat(to);
                requestParameters["timeOfOutwardJourney.hour"]     = requestTime.Hour.ToString();
                requestParameters["timeOfOutwardJourney.minute"]   = requestTime.Minute.ToString();
                requestParameters["timeOfOutwardJourney.monthDay"] = requestTime.ToString("dd/MM/yy");

                // Make the request
                HttpResponseMessage response = await client.PostAsync("http://ojp.nationalrail.co.uk/service/planjourney/plan",
                                                                      new FormUrlEncodedContent( requestParameters ), cancelToken);

                // Load the result of the request into an HtmlDocument
                HtmlDocument doc = new HtmlDocument();
                doc.LoadHtml(await response.Content.ReadAsStringAsync());

                // Extract the journey, changes and date change nodes
                // The journeys are in table rows that contain cells of class 'dep'. Grab the containing row.
                // The changes associated with a journey are not in the same row as the journey so look for a cell with class 'origin'.
                // Changes are stored in the containing table. The extracted changes are stored with the last journey.
                // Date changes between journeys are contained in table rows with class 'day-heading'.
                // If date of the first journey are in an H3 element with class 'outward top ctf-h3'.
                HtmlNodeCollection dormNodes = doc.DocumentNode.SelectNodes(
                    "//td[@class='dep']/..|//td[@class='origin']/..|//h3[@class='outward top ctf-h3']/.|//tr[@class='day-heading']/.");
                if (dormNodes != null)
                {
                    // Assume that the journeys found are initially for the same day as the request
                    DateTime responseDate = requestTime.Date;

                    TrainJourneys journeys = new TrainJourneys();

                    // Fill the journeys list with the results
                    foreach (HtmlNode journeyNode in dormNodes)
                    {
                        // Check if this is a train node
                        if (journeyNode.SelectSingleNode("./td[@class='dep']") != null)
                        {
                            TrainJourney newJourney = new TrainJourney {
                                ArrivalTime   = journeyNode.SelectSingleNode("./td[@class='arr']").InnerText.Substring(0, 5),
                                DepartureTime = journeyNode.SelectSingleNode("./td[@class='dep']").InnerText.Substring(0, 5),
                                Duration      = ReplaceWhitespace(journeyNode.SelectSingleNode("./td[@class='dur']").InnerText),
                                Status        = ReplaceWhitespace(journeyNode.SelectSingleNode("./td[@class='status']").InnerText)
                            };

                            // Set the full departure timestamp from the responseDate and the departure time
                            newJourney.DepartureDateTime = responseDate + TimeSpan.ParseExact(newJourney.DepartureTime, "h\\:mm", CultureInfo.InvariantCulture);

                            journeys.Journeys.Add(newJourney);
                        }
                        else if (journeyNode.SelectSingleNode("./td[@class='origin']") != null)
                        {
                            // Only proceed with processing changes if a journey has been found
                            if (journeys.Journeys.Count > 0)
                            {
                                // Get the change data ignoring any empty cells and whitespace
                                HtmlNodeCollection cells = journeyNode.SelectNodes("./td");

                                if (cells != null)
                                {
                                    // Somewhere to save the cell data
                                    List <string> cellContents = new List <string>();

                                    foreach (HtmlNode cell in cells)
                                    {
                                        string innerText = ReplaceWhitespace(cell.InnerText);
                                        if (innerText.Length > 0)
                                        {
                                            cellContents.Add(innerText);
                                        }
                                    }

                                    // There should be 4 entries for a journey leg
                                    if (cellContents.Count == 4)
                                    {
                                        JourneyLeg leg = new JourneyLeg {
                                            DepartureTime = cellContents[0], From = cellContents[1],
                                            ArrivalTime   = cellContents[2], To = cellContents[3]
                                        };

                                        journeys.Journeys[journeys.Journeys.Count - 1].Legs.Add(leg);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // If this is either the report header or a date change within the report.
                            // Extraxct the date
                            string headerDate = (journeyNode.Name == "h3") ?
                                                ReplaceWhitespace(journeyNode.InnerText).Replace("+", " ").Substring(17, 10) :
                                                ReplaceWhitespace(journeyNode.InnerText);

                            // Date is now of the format DDD nn MMM where nn could be one or two numeric digits
                            try
                            {
                                responseDate = DateTime.ParseExact(headerDate, new[] { "ddd dd MMM", "ddd d MMM" }, CultureInfo.InvariantCulture, DateTimeStyles.None);
                            }
                            catch (FormatException)
                            {
                            }
                        }
                    }

                    // Save the journeys so they can be accessed from outside the class
                    Journeys = journeys.Journeys;

                    JourneysAvailableEvent?.Invoke(this, new JourneysAvailableArgs {
                        JourneysAvailable = true
                    });
                }
                else
                {
                    JourneysAvailableEvent?.Invoke(this, new JourneysAvailableArgs {
                        JourneysAvailable = false
                    });
                }
            }
            catch (HttpRequestException)
            {
                JourneysAvailableEvent?.Invoke(this, new JourneysAvailableArgs {
                    JourneysAvailable = false, NetworkProblem = true
                });
            }
            catch (TaskCanceledException)
            {
                // This can be caused either from a user request or a network problem
                if (cancelToken.IsCancellationRequested == true)
                {
                    JourneysAvailableEvent?.Invoke(this, new JourneysAvailableArgs {
                        JourneysAvailable = false, RequestCancelled = true
                    });
                }
                else
                {
                    JourneysAvailableEvent?.Invoke(this, new JourneysAvailableArgs {
                        JourneysAvailable = false, NetworkProblem = true
                    });
                }
            }
            catch (OperationCanceledException)
            {
                JourneysAvailableEvent?.Invoke(this, new JourneysAvailableArgs {
                    JourneysAvailable = false, NetworkProblem = true
                });
            }
        }