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 void DecodeInt_WhenHashStringIntHasDefaultBitDepth_ReturnsCoordinatesWithinStandardPrecision() { var geoHashDecodeResult = GeoHash.DecodeInt(HashStringInt); Assert.True(Math.Abs(Latitude - geoHashDecodeResult.Coordinates.Lat) < 0.0001, "(37.8324 - " + geoHashDecodeResult.Coordinates.Lat + " was >= 0.0001"); Assert.True(Math.Abs(Longitude - geoHashDecodeResult.Coordinates.Lon) < 0.0001, "(112.5584 - " + geoHashDecodeResult.Coordinates.Lon + " was >= 0.0001"); }
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); }
private string Print(DateTime startTime, TimeSpan time, GeoPosition pos) { const string type = "location"; const string version = "1.0.0"; var enqueueTime = startTime + time; var dequeueTime = enqueueTime.AddMilliseconds(_random.Next(500)); var clientUtcTime = enqueueTime.AddMilliseconds(-_random.Next(500)); // "yyyy-MM-dd HH:mm:ss" var hashPos = GeoHash.DecodeInt(pos.GeoHash, 32); var line = $"{type}|{version}|{enqueueTime:yyyy-MM-dd HH:mm:ss}|{dequeueTime:yyyy-MM-dd HH:mm:ss}|{clientUtcTime:yyyy-MM-dd HH:mm:ss}|{_gameSessionId}|{pos.Lat:0.############}|{pos.Lon:0.############}|{pos.GeoHash}|{pos.Precision}|{hashPos.Coordinates.Lat}|{hashPos.Coordinates.Lon}|Country N/A|District N/A|City N/A|prop1=tst;prop2=tmp"; return(line); }
public LocationLookupInfo LookupGeoHash(long geoHash, int precision) { if (s_cache.TryGetValue(geoHash, out LocationLookupInfo info)) { Console.WriteLine($"Cached geohash {geoHash}:{precision} is in {info.City}, {info.District}, {info.Country}"); return(info); } Console.WriteLine($"Looking up geohash {geoHash}:{precision}"); var geoHashCenter = GeoHash.DecodeInt(geoHash, precision).Coordinates; var l = _locationLookupProvider.Lookup(geoHashCenter.Lat, geoHashCenter.Lon); l.Wait(); var location = l.Result; Console.WriteLine($"Geohash {geoHash}:{precision} is in {location.City}, {location.District}, {location.Country} according to {_locationLookupProvider.GetType()}"); s_cache.TryAdd(geoHash, location); return(location); }
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); }