public void StoreRentals(Rental[] rentals)
            {
                var savedRentals = string.Empty;

                if (rentals != null)
                {
                    try {
                        var root = new XElement("rentals");
                        root.Add(rentals.Select(r => {
                            return(new XElement("rental",
                                                new XAttribute("Id", r.Id),
                                                new XAttribute("FromStationName", r.FromStationName),
                                                new XAttribute("ToStationName", r.ToStationName),
                                                new XAttribute("Price", r.Price),
                                                new XAttribute("DepartureTime", r.DepartureTime),
                                                new XAttribute("ArrivalTime", r.ArrivalTime),
                                                new XAttribute("Duration", r.Duration)));
                        }));
                        savedRentals = root.ToString();
                    } catch (Exception e) {
                        AnalyticsHelper.LogException("PreferencesRentalStorage", e);
                        Log.Error("PreferencesRentalStorage", "Couldn't serialize existing rental: {0}", e.ToString());
                    }
                }

                using (var editor = prefs.Edit()) {
                    editor.PutString(Key, savedRentals);
                    editor.Commit();
                }
            }
Example #2
0
        public async void FillUpMap(bool forceRefresh)
        {
            if (loading)
            {
                return;
            }
            loading = true;
            if (pane != null && pane.Opened)
            {
                pane.SetState(InfoPane.State.Closed, animated: false);
            }
            flashBar.ShowLoading();

            try {
                var stations = await hubway.GetStations(forceRefresh);
                await SetMapStationPins(stations);

                lastUpdateText.Text = "Last refreshed: " + DateTime.Now.ToShortTimeString();
            } catch (Exception e) {
                AnalyticsHelper.LogException("DataFetcher", e);
                Android.Util.Log.Debug("DataFetcher", e.ToString());
            }

            flashBar.ShowLoaded();
            showedStale = false;
            if (pendingSearchTerm != null)
            {
                OpenStationWithTerm(pendingSearchTerm);
                pendingSearchTerm = null;
            }
            loading = false;
        }
Example #3
0
        async Task <Asset> CreateWearAssetFrom(Station station)
        {
            var cacheDir = CacheDir.AbsolutePath;
            var file     = Path.Combine(cacheDir, "StationBackgrounds", station.Id.ToString());

            byte[] content = null;
            var    url     = GoogleApis.MakeStreetViewUrl(station.Location, 640, 400);

            try {
                if (!File.Exists(file))
                {
                    if (client == null)
                    {
                        client = new HttpClient();
                    }
                    content = await client.GetByteArrayAsync(url);

                    Directory.CreateDirectory(Path.GetDirectoryName(file));
                    File.WriteAllBytes(file, content);
                }
                else
                {
                    content = File.ReadAllBytes(file);
                }
            } catch (Exception e) {
                e.Data ["URL"] = url;
                Android.Util.Log.Error("StreetViewBackground", e.ToString());
                AnalyticsHelper.LogException("StreetViewBackground", e);
            }

            return(content == null ? null : Asset.CreateFromBytes(content));
        }
            public Rental[] GetStoredRentals()
            {
                var savedRentals = prefs.GetString(Key, null);

                if (string.IsNullOrEmpty(savedRentals))
                {
                    return(new Rental[0]);
                }
                try {
                    var root = XElement.Parse(savedRentals);
                    return(root.Elements("rental").Select(e => new Rental {
                        Id = (long)e.Attribute("Id"),
                        FromStationName = (string)e.Attribute("FromStationName"),
                        ToStationName = (string)e.Attribute("ToStationName"),
                        Price = (double)e.Attribute("Price"),
                        DepartureTime = (DateTime)e.Attribute("DepartureTime"),
                        ArrivalTime = (DateTime)e.Attribute("ArrivalTime"),
                        Duration = (TimeSpan)e.Attribute("Duration")
                    }).ToArray());
                } catch (Exception e) {
                    AnalyticsHelper.LogException("PreferencesRentalStorage", e);
                    Log.Error("PreferencesRentalStorage", "Couldn't deserialize existing rental: {0}", e.ToString());
                }

                return(null);
            }
        public override ICursor Query(Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder)
        {
            var query = uri.LastPathSegment.ToLowerInvariant();

            IList <Address> addresses = null;

            try {
                addresses = geocoder.GetFromLocationName(query,
                                                         SuggestionCount,
                                                         LowerLeftLat,
                                                         LowerLeftLon,
                                                         UpperRightLat,
                                                         UpperRightLon);
            } catch (Exception e) {
                AnalyticsHelper.LogException("SuggestionsFetcher", e);
                Android.Util.Log.Warn("SuggestionsFetcher", e.ToString());
                addresses = new Address[0];
            }

            var cursor = new MatrixCursor(new string[] {
                BaseColumns.Id,
                SearchManager.SuggestColumnText1,
                SearchManager.SuggestColumnText2,
                SearchManager.SuggestColumnIntentExtraData
            }, addresses.Count);

            long id = 0;

            foreach (var address in addresses)
            {
                int dummy;
                if (int.TryParse(address.Thoroughfare, out dummy))
                {
                    continue;
                }

                var options1 = new string[] { address.FeatureName, address.Thoroughfare };
                var options2 = new string[] { address.Locality, address.AdminArea };

                var line1 = string.Join(", ", options1.Where(s => !string.IsNullOrEmpty(s)).Distinct());
                var line2 = string.Join(", ", options2.Where(s => !string.IsNullOrEmpty(s)));

                if (string.IsNullOrEmpty(line1) || string.IsNullOrEmpty(line2))
                {
                    continue;
                }

                cursor.AddRow(new Java.Lang.Object[] {
                    id++,
                    line1,
                    line2,
                    address.Latitude.ToSafeString() + "|" + address.Longitude.ToSafeString()
                });
            }

            return(cursor);
        }
Example #6
0
 async void LoadStationHistory(int stationID)
 {
     try {
         using (var scope = ActivityScope.Of(Activity))
             await DoLoadStationHistory(scope, stationID);
     } catch (Exception e) {
         AnalyticsHelper.LogException("HistoryFetcher", e);
         Android.Util.Log.Debug("HistoryFetcher", e.ToString());
     }
 }
Example #7
0
        async ActivityTask DoFillUpMap(ActivityScope scope, bool forceRefresh)
        {
            try {
                var stations = await hubway.GetStations(forceRefresh);
                await SetMapStationPins(stations);

                lastUpdateText.Text = "Last refreshed: " + DateTime.Now.ToShortTimeString();
            } catch (Exception e) {
                AnalyticsHelper.LogException("DataFetcher", e);
                Android.Util.Log.Debug("DataFetcher", e.ToString());
            }
        }
Example #8
0
        void LaunchPlaceSearch()
        {
            const double LowerLeftLat  = 42.343828;
            const double LowerLeftLon  = -71.169777;
            const double UpperRightLat = 42.401150;
            const double UpperRightLon = -71.017685;

            try {
                var intent = new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.ModeFullscreen)
                             .SetBoundsBias(new LatLngBounds(new LatLng(LowerLeftLat, LowerLeftLon),
                                                             new LatLng(UpperRightLat, UpperRightLon)))
                             .Build(Activity);
                StartActivityForResult(intent, SearchRequestID);
            } catch (Exception e) {
                AnalyticsHelper.LogException("PlaceSearch", e);
                Android.Util.Log.Debug("PlaceSearch", e.ToString());
            }
        }
Example #9
0
        public async Task <Station[]> GetStations(bool forceRefresh = false, Action <string> dataCacher = null)
        {
            string data = null;

            if (HasCachedData && !forceRefresh)
            {
                return(LastStations);
            }

            if (stationDescriptions == null)
            {
                stationDescriptions = await GetStationDescriptions().ConfigureAwait(false);
            }

            while (data == null)
            {
                try {
                    data = await client.GetStringAsync(HubwayStationStatusUrl).ConfigureAwait(false);
                } catch (Exception e) {
                    AnalyticsHelper.LogException("HubwayDownloader", e);
                    Android.Util.Log.Error("HubwayDownloader", e.ToString());
                }
                if (data == null)
                {
                    await Task.Delay(500);
                }
            }

            if (dataCacher != null)
            {
                dataCacher(data);
            }

            var stations = ParseStationsFromContent(data);

            if (subscribers.Any())
            {
                foreach (var sub in subscribers)
                {
                    sub.Observer.OnNext(stations);
                }
            }
            return(stations);
        }
Example #10
0
 public async void SetStationIds(HashSet <int> ids)
 {
     while (true)
     {
         try {
             var hubway      = Hubway.Instance;
             var stationList = hubway.HasCachedData ? hubway.LastStations : (await hubway.GetStations());
             stations = stationList
                        .Where(s => ids.Contains(s.Id))
                        .OrderBy(s => s.Name)
                        .ToList();
         } catch (Exception e) {
             AnalyticsHelper.LogException("Favorite", e);
             Android.Util.Log.Error("Favorites", e.ToString());
         }
         NotifyDataSetChanged();
         break;
     }
 }
Example #11
0
        async void OpenStationWithTerm(string term)
        {
            try {
                var stations = await hubway.GetStations();

                var bestResult = stations
                                 .Select(s => new { Station = s, Score = FuzzyStringMatch(term, s.Name) })
                                 .Where(s => s.Score > 0.5f)
                                 .OrderByDescending(s => s.Score)
                                 .FirstOrDefault();
                if (bestResult == null)
                {
                    Toast.MakeText(Activity, "No station found for '" + term + "'", ToastLength.Short).Show();
                    return;
                }
                CenterAndOpenStationOnMap(bestResult.Station.Id);
            } catch (Exception e) {
                e.Data ["Term"] = term;
                AnalyticsHelper.LogException("TermStationSearch", e);
            }
        }
Example #12
0
        async Task FetchData()
        {
            historyCache = new Dictionary <int, IEnumerable <KeyValuePair <DateTime, int> > > ();

            for (int i = 0; i < 3; i++)
            {
                try {
                    var data = await client.GetStringAsync(HistoryApiEndpoint);

                    // If another update was done in the meantime, no need to process it
                    if (!NeedFetching)
                    {
                        return;
                    }

                    var    reader = new StringReader(data);
                    string line   = reader.ReadLine();
                    var    times  = line.Split('|').Select(t => DateTime.FromBinary(long.Parse(t))).ToArray();
                    while ((line = reader.ReadLine()) != null)
                    {
                        var split      = line.Split('|');
                        var id         = int.Parse(split[0]);
                        var datapoints = split.Skip(1).Select((v, index) => {
                            var time = times[index];
                            var num  = int.Parse(v);

                            return(new KeyValuePair <DateTime, int> (time, num));
                        }).ToArray();
                        historyCache[id] = datapoints;
                    }
                    lastFetch = DateTime.UtcNow;
                } catch (Exception e) {
                    AnalyticsHelper.LogException("HistoryDownloader", e);
                    Android.Util.Log.Error("HistoryDownloader", e.ToString());
                }
            }
        }
        public async Task <Rental[]> GetRentals(int page)
        {
            bool needsAuth = false;

            for (int i = 0; i < 4; i++)
            {
                try {
                    if (needsAuth)
                    {
                        if (await LoginToHubway().ConfigureAwait(false))
                        {
                            needsAuth = false;
                        }
                        else
                        {
                            continue;
                        }
                    }

                    if (string.IsNullOrEmpty(credentials.UserId))
                    {
                        credentials.UserId = await GetHubwayUserId().ConfigureAwait(false);

                        if (string.IsNullOrEmpty(credentials.UserId))
                        {
                            needsAuth = true;
                            continue;
                        }
                    }

                    var rentalsUrl = HubwayRentalsUrl + credentials.UserId;
                    if (page > 0)
                    {
                        rentalsUrl += "?pageNumber=" + page;
                    }
                    var answer = await Client.GetStringAsync(rentalsUrl).ConfigureAwait(false);

                    var parser = new SimpleHtmlParser();
                    var doc    = parser.ParseString(answer);
                    var div    = doc.GetElementsByTagName("section")
                                 .OfType <XmlElement> ()
                                 .First(s => s.GetAttribute("class") == "ed-profile-page__content");
                    var rows = div.GetElementsByTagName("div")
                               .OfType <XmlElement> ()
                               .Where(n => n.ContainsClass("ed-table__item_trip"));
                    return(rows.Select(row => {
                        var cells = row.GetElementsByTagName("div").OfType <XmlElement> ().ToList();

                        /* 0 <div>
                         * 1   <div>time start
                         * 2   <div>station start
                         *   </div>
                         * 3 <div>
                         * 4   <div>time end
                         * 5   <div>station end
                         *   </div>
                         * 6 <div>duration
                         * 7 <div>billed
                         */
                        var rental = new Rental {
                            FromStationName = cells[2].InnerText.Trim(),
                            ToStationName = cells[5].InnerText.Trim(),
                            Duration = ParseRentalDuration(cells[6].InnerText.Trim()),
                            Price = ParseRentalPrice(cells[7].InnerText.Trim()),
                            DepartureTime = DateTime.Parse(cells[1].InnerText,
                                                           System.Globalization.CultureInfo.InvariantCulture),
                            ArrivalTime = DateTime.Parse(cells[4].InnerText,
                                                         System.Globalization.CultureInfo.InvariantCulture)
                        };
                        rental.Id = ((long)rental.DepartureTime.GetHashCode()) << 32;
                        rental.Id |= (uint)rental.ArrivalTime.GetHashCode();
                        return rental;
                    }).ToArray());
                } catch (HttpRequestException htmlException) {
                    // Super hacky but oh well
                    if (!needsAuth)
                    {
                        needsAuth = htmlException.Message.Contains("302");
                    }
                    continue;
                } catch (Exception e) {
                    AnalyticsHelper.LogException("RentalsGenericError", e);
                    Log.Error("RentalsGenericError", e.ToString());
                    break;
                }
            }

            return(null);
        }
Example #14
0
        public async Task <Rental[]> GetRentals(int page)
        {
            bool needsAuth  = false;
            var  rentalsUrl = HubwayRentalsUrl;

            if (page > 0)
            {
                rentalsUrl += "/" + (page * 20);
            }

            for (int i = 0; i < 4; i++)
            {
                try {
                    if (needsAuth)
                    {
                        var content = new FormUrlEncodedContent(new Dictionary <string, string> {
                            { "username", credentials.Username },
                            { "password", credentials.Password }
                        });
                        var login = await Client.PostAsync(HubwayLoginUrl, content).ConfigureAwait(false);

                        if (login.StatusCode == HttpStatusCode.Found)
                        {
                            needsAuth = false;
                        }
                        else
                        {
                            continue;
                        }
                    }

                    var answer = await Client.GetStringAsync(rentalsUrl).ConfigureAwait(false);

                    var doc = new HtmlDocument();
                    doc.LoadHtml(answer);
                    var div   = doc.GetElementById("content");
                    var table = div.Element("table");
                    return(table.Element("tbody").Elements("tr").Select(row => {
                        var items = row.Elements("td").ToArray();
                        return new Rental {
                            Id = long.Parse(items[0].InnerText.Trim()),
                            FromStationName = items [1].InnerText.Trim(),
                            ToStationName = items [3].InnerText.Trim(),
                            Duration = ParseRentalDuration(items [5].InnerText.Trim()),
                            Price = ParseRentalPrice(items [6].InnerText.Trim()),
                            DepartureTime = DateTime.Parse(items[2].InnerText,
                                                           System.Globalization.CultureInfo.InvariantCulture),
                            ArrivalTime = DateTime.Parse(items[4].InnerText,
                                                         System.Globalization.CultureInfo.InvariantCulture)
                        };
                    }).ToArray());
                } catch (HttpRequestException htmlException) {
                    // Super hacky but oh well
                    if (!needsAuth)
                    {
                        needsAuth = htmlException.Message.Contains("302");
                    }
                    continue;
                } catch (Exception e) {
                    AnalyticsHelper.LogException("RentalsGenericError", e);
                    Log.Error("RentalsGenericError", e.ToString());
                    break;
                }
            }

            return(null);
        }
Example #15
0
        async void HandleMessage(IMessageEvent message)
        {
            try {
                Android.Util.Log.Info("WearIntegration", "Received Message");
                var client = new GoogleApiClientBuilder(this)
                             .AddApi(LocationServices.API)
                             .AddApi(WearableClass.API)
                             .Build();

                var result = client.BlockingConnect(30, Java.Util.Concurrent.TimeUnit.Seconds);
                if (!result.IsSuccess)
                {
                    return;
                }

                var path = message.Path;

                try {
                    var stations = Hubway.Instance.LastStations;
                    if (stations == null)
                    {
                        stations = await Hubway.Instance.GetStations();
                    }

                    if (path.StartsWith(SearchStationPath))
                    {
                        var lastLocation = LocationServices.FusedLocationApi.GetLastLocation(client);
                        if (lastLocation == null)
                        {
                            return;
                        }

                        var currentPoint = new GeoPoint {
                            Lat = lastLocation.Latitude,
                            Lon = lastLocation.Longitude
                        };
                        var nearestStations = Hubway.GetStationsAround(stations, currentPoint, maxItems: 6, minDistance: double.MaxValue);
                        var favManager      = FavoriteManager.Obtain(this);
                        var favorites       = await favManager.GetFavoriteStationIdsAsync();

                        var request = PutDataMapRequest.Create(SearchStationPath + "/Answer");
                        var map     = request.DataMap;

                        var stationMap = new List <DataMap> ();
                        foreach (var station in nearestStations)
                        {
                            var itemMap = new DataMap();

                            itemMap.PutInt("Id", station.Id);

                            var asset = await CreateWearAssetFrom(station);

                            itemMap.PutAsset("Background", asset);

                            string secondary;
                            string primary = StationUtils.CutStationName(station.Name, out secondary);
                            itemMap.PutString("Primary", primary);
                            itemMap.PutString("Secondary", secondary);

                            var distance = GeoUtils.Distance(currentPoint, station.Location);
                            itemMap.PutDouble("Distance", distance);
                            itemMap.PutDouble("Lat", station.Location.Lat);
                            itemMap.PutDouble("Lon", station.Location.Lon);

                            itemMap.PutInt("Bikes", station.BikeCount);
                            itemMap.PutInt("Racks", station.EmptySlotCount);

                            itemMap.PutBoolean("IsFavorite", favorites.Contains(station.Id));

                            stationMap.Add(itemMap);
                        }
                        map.PutDataMapArrayList("Stations", stationMap);
                        map.PutLong("UpdatedAt", DateTime.UtcNow.Ticks);

                        await WearableClass.DataApi.PutDataItem(client, request.AsPutDataRequest());
                    }
                    else
                    {
                        var uri   = new Uri("wear://watch" + path);
                        var query = uri.GetComponents(UriComponents.Query, UriFormat.Unescaped);
                        var parts = uri.GetComponents(UriComponents.Path, UriFormat.Unescaped).Split('/');

                        var action = parts[parts.Length - 2];
                        var id     = int.Parse(parts.Last());

                        if (action == FavoriteAction)
                        {
                            var favorites = FavoriteManager.Obtain(this);
                            handler.Post(() => {
                                if (query == "add")
                                {
                                    favorites.AddToFavorite(id);
                                }
                                else
                                {
                                    favorites.RemoveFromFavorite(id);
                                }
                            });
                        }
                    }
                } finally {
                    client.Disconnect();
                }
            } catch (Exception e) {
                Android.Util.Log.Error("WearIntegration", e.ToString());
                AnalyticsHelper.LogException("WearIntegration", e);
            }
        }