public List <GeohashRange> GetRanges(double latitude, double longitude, int rangeBitDepth = 16) // 156.5km { long geohash = GeoHash.EncodeInt(latitude, longitude, bitDepth: rangeBitDepth); long[] neighbours = GeoHash.NeighborsInt(geohash, bitDepth: rangeBitDepth); var ranges = new List <GeohashRange>(neighbours.Length); var rangeLength = geohash.ToString().Length; foreach (var neighbour in neighbours) { var latLong = GeoHash.DecodeInt(neighbour, bitDepth: rangeBitDepth); long geoHash = GeoHash.EncodeInt(latLong.Coordinates.Lat, latLong.Coordinates.Lon); var padAmount = geoHash.ToString().Length; // Now produce the min / max value of this based on the range length // So 21345 becomes 213450000000 to 21345999999 var leftPart = geoHash.ToString().Substring(0, rangeLength); var min = Convert.ToInt64(leftPart.PadRight(padAmount, '0')); var max = Convert.ToInt64(leftPart.PadRight(padAmount, '9')); ranges.Add(new GeohashRange { Min = min, Max = max }); } return(ranges); }
public Task <MessageHandlerResults> ProcessMessageAsync(Message msg, string pipelineName, int idx) { //TODO: Handle incorrect messages that doesn't have the required properties var lat = double.Parse(msg.Properties[InputLatProperty]); var lon = double.Parse(msg.Properties[InputLonProperty]); var precision = GeoHashPrecision; var geoHash = GeoHash.EncodeInt(lat, lon, precision); msg.Properties[GeoHashProperty] = geoHash.ToString(); msg.Properties[GeoHashProperty + "Precision"] = precision.ToString(); if (CalculateGeoHashCenterCoordinates) { var x = GeoHash.DecodeInt(geoHash, precision); msg.Properties[GeoHashCenterLatProperty] = x.Coordinates.Lat.ToString(); msg.Properties[GeoHashCenterLonProperty] = x.Coordinates.Lon.ToString(); var originCoordinates = new GeoCoordinate(lat, lon); var geoHashCenter = new GeoCoordinate(x.Coordinates.Lat, x.Coordinates.Lon); msg.Properties[GeoHashCenterDistProperty] = originCoordinates.GetDistanceTo(geoHashCenter).ToString("0"); } return(Task.FromResult(MessageHandlerResults.Success)); }
public async Task HandleLocationEventAsync(GameEventData data) { const int GeoHashBitPrecision = 32; //bits const int LocationLookupGeoHashBitPrecistion = 30; //bits var inEvent = JsonConvert.DeserializeObject <IncommingLocationEvent>(data.Data); var geoHash = GeoHash.EncodeInt(inEvent.Lat, inEvent.Lon, GeoHashBitPrecision); var geoHashCenterCoordinates = GeoHash.DecodeInt(geoHash, GeoHashBitPrecision).Coordinates; var locationLookupGeoHash = GeoHash.EncodeInt(inEvent.Lat, inEvent.Lon, LocationLookupGeoHashBitPrecistion); var l = new LocationEventHandler(_locationLookupProvider); var location = l.LookupGeoHash(locationLookupGeoHash, LocationLookupGeoHashBitPrecistion); var outEvent = new OutgoingLocationEvent { EnqueueTime = data.EnqueuedTime, DequeueTime = data.DequeuedTime, ClientUtcTime = inEvent.ClientUtcTime, GameSessionId = inEvent.GameSessionId, Lat = inEvent.Lat, Lon = inEvent.Lon, GeoHash = geoHash, GeoHashPrecision = GeoHashBitPrecision, GeoHashCenterLat = geoHashCenterCoordinates.Lat, GeoHashCenterLon = geoHashCenterCoordinates.Lon, Country = location.Country, District = location.District, City = location.City, Properties = inEvent.Properties }; //TODO: Optimize this so we don't serialize back to JSON first and then to CSV var jsonObject = JsonConvert.SerializeObject( outEvent, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); data.Data = jsonObject; var csvObject = data.ToCsv("gameSessionId", "lat", "lon", "geoHash", "geoHashPrecision", "geoHashCenterLat", "geoHashCenterLon", "country", "district", "city"); // Output CSV to BLOB Storage and JSON to StreamAnalytics (via EventHub) await _blobOutputManager.QueueAppendToBlobAsync(data, csvObject); await _eventHubOutputManager.SendToEventHubAsync(data, jsonObject); }
public async Task <MessageHandlerResults> ProcessMessageAsync(Message msg, string pipelineName, int idx) { //TODO: Replace all console logging of exceptions to generic log solution double lat; double lon; //TODO: Catch more specific error if property doesn't exist or use another method to get the properties try { lat = double.Parse(msg.Properties[_latProperty]); lon = double.Parse(msg.Properties[_lonProperty]); } catch (Exception) { Console.WriteLine($"Unable to find required properties: '{_latProperty}' and '{_lonProperty}' on message"); return(MessageHandlerResults.FailStopProcessing); } var geoHash = GeoHash.EncodeInt(lat, lon, _geoHashCacheProvider.Precision); BingResult bingParsingResult; //if we have the result in the cache, fetch it if (await _geoHashCacheProvider.ContainsGeoHashAsync(geoHash)) { bingParsingResult = await _geoHashCacheProvider.GetAsync(geoHash); Debug.WriteLine("Found in cache"); } //else, query bing directly else { Debug.WriteLine("Not found in cache"); double geoHashCenterLat, geoHashCenterLon; //get the center of the geoHash in order to call Bing API with this {lat,lon} var decodedGeoHash = GeoHash.DecodeInt(geoHash, _geoHashCacheProvider.Precision); geoHashCenterLat = decodedGeoHash.Coordinates.Lat; geoHashCenterLon = decodedGeoHash.Coordinates.Lon; var bingUrl = $"http://dev.virtualearth.net/REST/v1/Locations/{geoHashCenterLat},{geoHashCenterLon}?key={_bingMapsKey}"; string bingResult; try { var client = new HttpClient(); bingResult = await client.GetStringAsync(bingUrl); } catch (Exception ex) { Console.WriteLine("An exception occurred while calling Bing to Lookup coordinates"); Console.WriteLine(ex); return(MessageHandlerResults.FailStopProcessing); } try { var json = JObject.Parse(bingResult); var address = json["resourceSets"][0]["resources"][0]["address"]; //create a bing parsing result instance and cache it bingParsingResult = new BingResult() { City = (string)address["locality"], Country = (string)address["countryRegion"], District = (string)address["adminDistrict"] }; await _geoHashCacheProvider.AppendToCacheAsync(geoHash, bingParsingResult); } catch (Exception ex) { Console.WriteLine("An exception occurred while trying to parse Location Lookup results from Bing"); Console.WriteLine(ex); return(MessageHandlerResults.FailStopProcessing); } } //add values to msg msg.Properties.Add("country", bingParsingResult.Country); msg.Properties.Add("district", bingParsingResult.District); msg.Properties.Add("city", bingParsingResult.City); return(MessageHandlerResults.Success); }
public long Encode(double latitude, double longitude) { return(GeoHash.EncodeInt(latitude, longitude)); }
public void EncodeInt_WhenTheBitDepthIsProvided_ReturnsHashStringIntWithTheProvidedBitDepth() { var actualHashStringInt = GeoHash.EncodeInt(Latitude, Longitude, 26); Assert.Equal(60572995, actualHashStringInt); }
public void EncodeInt_WhenTheBitDepthIsNotProvided_ReturnsHashStringIntWithTheDefaultBitDepth() { var actualHashStringInt = GeoHash.EncodeInt(Latitude, Longitude); Assert.Equal(HashStringInt, actualHashStringInt); }
public void BboxesInt_ReturnsHashStringsIntBetweenCoordinates() { var bBoxes = GeoHash.BboxesInt(30, 120, 30.0001, 120.0001, 8); Assert.Equal(GeoHash.EncodeInt(30.0001, 120.0001, 8), bBoxes[bBoxes.Length - 1]); }