public async Task <IActionResult> Show( [FromRoute] string id ) { var cta = await Mongo.GetCallToAction(id); if (cta == null) { Logger.LogInformation("Call to action {0} not found", id); return(NotFound()); } var filter = (await Mongo.GetCallToActionFilters(id)).FirstOrDefault(); if (filter == null) { Logger.LogError("Call to action {0} has no filter", filter); return(NotFound()); } // HACK: shows huge Geohash var geohashBounds = Geohasher.GetBoundingBox(filter.CoveringGeohash[0].Substring(0, 1)); return(View("Show", new CallToActionViewModel { Id = cta.Id.ToString(), From = filter.TimeBegin, To = filter.TimeEnd, Description = cta.Description, BoundingBox = geohashBounds, PolygonCoordinates = filter.Geometry.ToRingArray() })); }
public async Task <IActionResult> UpdateFilter( [FromRoute] string id, [FromRoute] string filterId, [FromForm] DateTime?addedOn, [FromForm] DateTime from, [FromForm] DateTime to, [FromForm] string geojson ) { var filter = await Mongo.GetCallToActionFilter(filterId); if (filter == null || !filter.CallToActionId.ToString().Equals(id)) { return(NotFound()); } var geometry = geojson.PolygonFromGeoJson(); var geohashes = await Geohasher.GenerateCoveringGeohashes(geometry); Logger.LogInformation("Geometry converted to {HashCount} geohashes {Hashes}", geohashes.Count, string.Join(",", geohashes)); filter.AddedOn = addedOn ?? DateTime.UtcNow; filter.TimeBegin = from; filter.TimeEnd = to; filter.Geometry = geometry; filter.CoveringGeohash = geohashes.ToArray(); await Mongo.ReplaceCallToActionFilter(filter); return(RedirectToAction(nameof(ShowCall), "Dashboard", new { id = id })); }
public static RegisteredCredential From(EthEventDTO eventDto) { var ret = new RegisteredCredential() { IsRevoked = false, HashId = eventDto.IndexedParameters[0].Value, CitizenAddress = eventDto.NonIndexedParameters[0].Value, SubjectHashId = eventDto.NonIndexedParameters[1].Value, StartDate = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(eventDto.NonIndexedParameters[2].Value)).DateTime.ToUniversalTime(), CredentialCreation = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(eventDto.NonIndexedParameters[3].Value)).DateTime.ToUniversalTime(), Sex = Enum.Parse <Sex>(eventDto.NonIndexedParameters[4].Value), Age = short.Parse(eventDto.NonIndexedParameters[5].Value), CredentialType = Enum.Parse <CredentialType>(eventDto.NonIndexedParameters[7].Value), Reason = Enum.Parse <InterruptionReason>(eventDto.NonIndexedParameters[8].Value) }; var hasher = new Geohasher(); var hash = Hex.HexToString(eventDto.NonIndexedParameters[6].Value); var decoded = hasher.Decode(hash); ret.Location = new Point(decoded.Item2, decoded.Item1); ret.Lat = ret.Location.Coordinate.X; ret.Lon = ret.Location.Coordinate.Y; SetSymptoms(ret, eventDto.NonIndexedParameters[9].Value); return(ret); }
public async System.Threading.Tasks.Task Should_Get_Hashes_For_PolygonAsync() { var hasher = new Geohasher(); var geometryFactory = new GeometryFactory(); var p1 = new Coordinate() { X = 9.612350463867186, Y = 52.31141727938367 }; var p2 = new Coordinate() { X = 9.914474487304686, Y = 52.31141727938367 }; var p3 = new Coordinate() { X = 9.914474487304686, Y = 52.42252295423907 }; var p4 = new Coordinate() { X = 9.612350463867186, Y = 52.42252295423907 }; var polygon = geometryFactory.CreatePolygon(new[] { p1, p2, p3, p4, p1 }); var result = await hasher.GetHashesAsync(polygon, 6); Assert.AreEqual(486, result.Count); }
public void Should_Encode_WithDefaultPrecison() { var hasher = new Geohasher(); var hash = hasher.Encode(52.5174, 13.409); Assert.Equal("u33dc0", hash); }
public void Should_Give_Subhashes_1() { var hasher = new Geohasher(); var subhashes = hasher.GetSubhashes("u"); Assert.Equal(32, subhashes.Length); }
public void Should_Encode_WithGivenPrecision_11() { var hasher = new Geohasher(); var hash = hasher.Encode(52.517395, 13.408813, 11); Assert.Equal("u33dc07zzzz", hash); }
public void Should_Decode_Precision12() { var hasher = new Geohasher(); var hash = hasher.Decode("u33dc07zzzzx"); Assert.Equal(52.51739494, Math.Round(hash.Item1, 8)); Assert.Equal(13.40881297, Math.Round(hash.Item2, 8)); }
public void Should_Decode_Precision6() { var hasher = new Geohasher(); var hash = hasher.Decode("u33dc0"); Assert.Equal(52.5174, Math.Round(hash.Item1, 4)); Assert.Equal(13.409, Math.Round(hash.Item2, 3)); }
public static Task <List <string> > GenerateCoveringGeohashes(this Geohasher hasher, GeoJsonPolygon <GeoJson2DGeographicCoordinates> polygon, int precision = 4) { var outerRing = new NetTopologySuite.Geometries.LinearRing( (from coord in polygon.Coordinates.Exterior.Positions select new NetTopologySuite.Geometries.Coordinate(coord.Latitude, coord.Longitude)).ToArray() ); var p = new NetTopologySuite.Geometries.Polygon(outerRing); return(hasher.GetHashesAsync(p, precision, Mode.Intersect)); }
public void LargeCompressionTest() { var compressor = new GeohashCompressor(); var hasher = new Geohasher(); var compressed = compressor.Compress(GetHashes().ToArray()); Assert.AreEqual(152, compressed.Count); }
public void Should_Get_BoundingBox() { var hasher = new Geohasher(); var envelope = hasher.GetBoundingBox("u"); Assert.Equal(90, envelope.MaxX); Assert.Equal(45, envelope.MaxY); Assert.Equal(45, envelope.MinX); Assert.Equal(0, envelope.MinY); }
public void Should_Give_Neighbor() { var hasher = new Geohasher(); Assert.Equal("u33dc1", hasher.GetNeighbor("u33dc0", Direction.North)); Assert.Equal("u33dc3", hasher.GetNeighbor("u33dc0", Direction.NorthEast)); Assert.Equal("u33dc2", hasher.GetNeighbor("u33dc0", Direction.East)); Assert.Equal("u33d9r", hasher.GetNeighbor("u33dc0", Direction.SouthEast)); Assert.Equal("u33d9p", hasher.GetNeighbor("u33dc0", Direction.South)); Assert.Equal("u33d8z", hasher.GetNeighbor("u33dc0", Direction.SouthWest)); Assert.Equal("u33dbb", hasher.GetNeighbor("u33dc0", Direction.West)); Assert.Equal("u33dbc", hasher.GetNeighbor("u33dc0", Direction.NorthWest)); }
public async Task FullDump() { var lastAccess = await Mongo.GetLastDailyStats(); Response.Headers[HeaderNames.LastModified] = lastAccess.Date.ToUniversalTime().ToString("R"); Response.Headers[HeaderNames.ContentType] = "text/csv"; Response.StatusCode = (int)HttpStatusCode.OK; await Response.WriteAsync("Date,TotalMinutesTracked,CentroidGeohash,CentroidLat,CentroidLong,GeohashBoxJSON,LocationCount,VehicleCount,EventCount,SampleCount,DiscardedSampleCount,BoundingBoxDiagonal,MinAtHome,MinAtWork,MinAtSchool,MinAtLocations,MinElsewhere" + Environment.NewLine); var cursor = await Mongo.FetchAllDailyStats(); while (await cursor.MoveNextAsync()) { foreach (var stat in cursor.Current) { var centroid = stat.CentroidHash ?? Geohasher.Encode(stat.Centroid.Coordinates.Latitude, stat.Centroid.Coordinates.Longitude, 5); var bbox = Geohasher.GetBoundingBox(centroid); var polygon = new Polygon(new LineString[] { new LineString(new IPosition[] { new Position(bbox[0], bbox[2]), new Position(bbox[0], bbox[3]), new Position(bbox[1], bbox[3]), new Position(bbox[1], bbox[2]), new Position(bbox[0], bbox[2]) }) }); await Response.WriteAsync(string.Join(",", stat.Date.ToString("yyyy-MM-dd"), stat.TotalMinutesTracked, centroid, stat.Centroid.Coordinates.Latitude.ToString("F5"), stat.Centroid.Coordinates.Longitude.ToString("F5"), "\"" + JsonConvert.SerializeObject(polygon).Replace("\"", "\"\"") + "\"", stat.LocationCount, stat.VehicleCount, stat.EventCount, stat.SampleCount, stat.DiscardedSampleCount, stat.BoundingBoxDiagonal.ToString("F2"), stat.LocationTracking.MinutesAtHome, stat.LocationTracking.MinutesAtWork, stat.LocationTracking.MinutesAtSchool, stat.LocationTracking.MinutesAtOtherKnownLocations, stat.LocationTracking.MinutesElsewhere ) + Environment.NewLine); } } }
public void Should_Give_Neighbors() { var hasher = new Geohasher(); var subhashes = hasher.GetNeighbors("u33dc0"); Assert.Equal("u33dc1", subhashes[Direction.North]); Assert.Equal("u33dc3", subhashes[Direction.NorthEast]); Assert.Equal("u33dc2", subhashes[Direction.East]); Assert.Equal("u33d9r", subhashes[Direction.SouthEast]); Assert.Equal("u33d9p", subhashes[Direction.South]); Assert.Equal("u33d8z", subhashes[Direction.SouthWest]); Assert.Equal("u33dbb", subhashes[Direction.West]); Assert.Equal("u33dbc", subhashes[Direction.NorthWest]); }
public void Should_Give_Neighbors_EdgeWest() { var hasher = new Geohasher(); var subhashes = hasher.GetNeighbors("9"); Assert.Equal("c", subhashes[Direction.North]); Assert.Equal("b", subhashes[Direction.NorthWest]); Assert.Equal("f", subhashes[Direction.NorthEast]); Assert.Equal("d", subhashes[Direction.East]); Assert.Equal("3", subhashes[Direction.South]); Assert.Equal("2", subhashes[Direction.SouthWest]); Assert.Equal("6", subhashes[Direction.SouthEast]); Assert.Equal("8", subhashes[Direction.West]); }
public void Should_Give_Neighbors_EdgeNorth() { var hasher = new Geohasher(); var subhashes = hasher.GetNeighbors("u"); Assert.Equal("h", subhashes[Direction.North]); Assert.Equal("5", subhashes[Direction.NorthWest]); Assert.Equal("j", subhashes[Direction.NorthEast]); Assert.Equal("v", subhashes[Direction.East]); Assert.Equal("s", subhashes[Direction.South]); Assert.Equal("e", subhashes[Direction.SouthWest]); Assert.Equal("t", subhashes[Direction.SouthEast]); Assert.Equal("g", subhashes[Direction.West]); }
public bool Create(TrackingBinding binding) { using (var db = GetMainContext()) { var geohasher = new Geohasher(); var tracking = binding.ToEntity(); tracking.Geohash = geohasher.Encode((double)binding.Latitude, (double)binding.Longitude, 9); tracking.UserId = UserId; db.Trackings.Add(tracking); db.SaveChanges(); return(true); } }
public async Task Create(IEnumerable <TrackingBinding> binding) { var geohasher = new Geohasher(); using (var db = GetMainContext()) { await db.Trackings.AddRangeAsync(binding.Select(x => { var entity = x.ToEntity(); entity.Geohash = geohasher.Encode((double)x.Latitude, (double)x.Longitude, 9); entity.UserId = UserId; return(entity); })); await db.SaveChangesAsync(); } }
public async System.Threading.Tasks.Task Should_Get_Hashes_For_PolygonAsync_IntersectMode() { var hasher = new Geohasher(); var geometryFactory = new GeometryFactory(); var progess = new Progress <HashingProgress>(); progess.ProgressChanged += (e, hp) => { Debug.WriteLine($"Processed: {hp.HashesProcessed}, Queued: {hp.QueueSize}, Running Since: {hp.RunningSince}"); }; Polygon polygon = GetTestPolygon(geometryFactory); var result = await hasher.GetHashesAsync(polygon, 4, mode : Mode.Intersect, progress : progess); Assert.AreEqual(183, result.Count); }
private void btnGenerateGeohash_Click(object sender, EventArgs e) { var hasher = new Geohasher(); var geometryFactory = new GeometryFactory(); Polygon polygon = GetTestPolygon(geometryFactory); List <string> res = hasher.GetHashesAsync(polygon).Result; MessageBox.Show(res[0], "Test1"); //Task<List<string>> inner_polygon = Should_Get_Hashes_For_PolygonAsync_LongRunning(); //List<string> inner_polygon_Loaded = inner_polygon.Result; //string[] arr_result = inner_polygon_Loaded.ToArray(); //MessageBox.Show(arr_result[0], "sss"); int a = 3; }
public void SmallCompressionTest() { var compressor = new GeohashCompressor(); var hasher = new Geohasher(); var list = new List <string>(); list.AddRange(hasher.GetSubhashes("ABC")); list.AddRange(hasher.GetSubhashes("ABF")); list.AddRange(hasher.GetSubhashes("AFF")); list.AddRange(new List <string> { "KK", "F", "FKUVC", "FKUVX" }); var compressed = compressor.Compress(list.ToArray()); Assert.AreEqual(7, compressed.Count); }
public async System.Threading.Tasks.Task <List <string> > Should_Get_Hashes_For_PolygonAsync_LongRunning() { var hasher = new Geohasher(); var geometryFactory = new GeometryFactory(); var progess = new Progress <HashingProgress>(); progess.ProgressChanged += (e, hp) => { Debug.WriteLine($"Processed: {hp.HashesProcessed}, Queued: {hp.QueueSize}, Running Since: {hp.RunningSince}"); }; Polygon polygon = GetTestPolygon(geometryFactory); // var result = await hasher.GetHashesAsync(polygon, 4, mode: Mode.Contains, progress: progess); var result = await hasher.GetHashesAsync(polygon, 1, mode : Mode.Contains); //var result = await hasher.GetHashesAsync(polygon, 4, mode: Mode.Contains); return(result); //Assert.AreEqual(112, result.Count); }
public async Task <IEnumerable <string> > GetGeohashes(GeohashGetBinding binding) { var geohasher = new Geohasher(); using (var context = GetMainContext()) { var neighbours = binding.Geohash is null ? null : geohasher.GetNeighbors(binding.Geohash); return(await context.Trackings.WhereUser(UserId) .WhereTimestampInclusive(binding) .WhereIf(neighbours is not null, x => x.Geohash.StartsWith(binding.Geohash) || x.Geohash.StartsWith(neighbours[Direction.North]) || x.Geohash.StartsWith(neighbours[Direction.South]) || x.Geohash.StartsWith(neighbours[Direction.East]) || x.Geohash.StartsWith(neighbours[Direction.West]) || x.Geohash.StartsWith(neighbours[Direction.NorthEast]) || x.Geohash.StartsWith(neighbours[Direction.NorthWest]) || x.Geohash.StartsWith(neighbours[Direction.SouthEast]) || x.Geohash.StartsWith(neighbours[Direction.SouthWest])) .Select(x => x.Geohash.Substring(0, binding.Precision)) .Distinct() .ToListAsync()); } }
public async Task <IActionResult> AddFilter( [FromRoute] string id, [FromForm] DateTime?addedOn, [FromForm] DateTime from, [FromForm] DateTime to, [FromForm] string geojson ) { var geometry = geojson.PolygonFromGeoJson(); var geohashes = await Geohasher.GenerateCoveringGeohashes(geometry); Logger.LogInformation("Geometry converted to {HashCount} geohashes {Hashes}", geohashes.Count, string.Join(",", geohashes)); var filter = new CallToActionFilter { AddedOn = addedOn ?? DateTime.UtcNow, TimeBegin = from, TimeEnd = to, Geometry = geometry, CoveringGeohash = geohashes.ToArray() }; await Mongo.AddCallToActionFilter(id, filter); return(RedirectToAction(nameof(ShowCall), "Dashboard", new { id = id })); }
public void Should_Give_Parent() { var hasher = new Geohasher(); Assert.Equal("u33db", hasher.GetParent("u33dbc")); }
public void Should_Throw_Given_Incorrect_Lng() { var hasher = new Geohasher(); Assert.Throws <ArgumentException>(() => hasher.Encode(52.517395, 183.408813, 12)); }
public async Task <IActionResult> Upload( [FromBody] DailyStats stats ) { if (!ModelState.IsValid) { Logger.LogError("Failed to parse input data: {0}", ModelState); return(BadRequest(ModelState)); } Logger.LogInformation("Receiving daily stats from device {0} for {1}", stats.InstallationId, stats.Date.ToString("d", CultureInfo.InvariantCulture)); // Safety checks if (stats.Date < MinDate) { Logger.LogError("Daily statistics for unacceptable date {0}", stats.Date); return(UnprocessableEntity(ProblemDetailsFactory.CreateProblemDetails(HttpContext, title: "Unacceptable date (out of valid range)", type: "https://arianna.digit.srl/api/problems/invalid-date" ))); } if (stats.TotalMinutesTracked > MinutesADay) { Logger.LogError("Total minutes tracked ({0}) exceeds minutes in a day", stats.TotalMinutesTracked); return(UnprocessableEntity(ProblemDetailsFactory.CreateProblemDetails(HttpContext, title: "Total minutes tracked exceeds minutes in a day", type: "https://arianna.digit.srl/api/problems/invalid-data" ))); } if (stats.Date >= DateTime.UtcNow.Date) { Logger.LogError("Daily statistics for non-elapsed day {0}", stats.Date.Date); return(UnprocessableEntity(ProblemDetailsFactory.CreateProblemDetails(HttpContext, title: "Unacceptable date (future date)", type: "https://arianna.digit.srl/api/problems/invalid-date" ))); } GeoJsonPoint <GeoJson2DGeographicCoordinates> position; string geohash; try { geohash = stats.CentroidHash.Substring(0, 5); var decoded = Geohasher.Decode(geohash); position = new GeoJsonPoint <GeoJson2DGeographicCoordinates>(new GeoJson2DGeographicCoordinates(decoded.Item2, decoded.Item1)); Logger.LogInformation("GeoHash {0} decoded as {1:F5},{2:F5}", geohash, position.Coordinates.Latitude, position.Coordinates.Longitude); } catch (Exception ex) { return(UnprocessableEntity(ProblemDetailsFactory.CreateProblemDetails(HttpContext, title: "Cannot decode geohash", type: "https://arianna.digit.srl/api/problems/invalid-data", detail: ex.Message ))); } if (stats.LocationTracking == null) { Logger.LogError("Payload does not contain location tracking section"); return(UnprocessableEntity(ProblemDetailsFactory.CreateProblemDetails(HttpContext, title: "Payload does not contain location tracking section", type: "https://arianna.digit.srl/api/problems/invalid-data" ))); } if (stats.LocationTracking.MinutesAtHome < 0 || stats.LocationTracking.MinutesAtWork < 0 || stats.LocationTracking.MinutesAtSchool < 0 || stats.LocationTracking.MinutesAtOtherKnownLocations < 0 || stats.LocationTracking.MinutesElsewhere < 0) { Logger.LogError("Location tracking minutes cannot be negative"); return(UnprocessableEntity(ProblemDetailsFactory.CreateProblemDetails(HttpContext, title: "Negative location tracking value", type: "https://arianna.digit.srl/api/problems/invalid-data" ))); } if (stats.LocationTracking.MinutesAtHome > MinutesADay || stats.LocationTracking.MinutesAtWork > MinutesADay || stats.LocationTracking.MinutesAtSchool > MinutesADay || stats.LocationTracking.MinutesAtOtherKnownLocations > MinutesADay || stats.LocationTracking.MinutesElsewhere > MinutesADay) { Logger.LogError("One entry in the location tracking section exceeds minutes in a day"); return(UnprocessableEntity(ProblemDetailsFactory.CreateProblemDetails(HttpContext, title: "One entry in the location tracking section exceeds minutes in a day", type: "https://arianna.digit.srl/api/problems/invalid-data" ))); } // Check for duplicates var existingStats = await Mongo.GetDailyStats(stats.InstallationId, stats.Date); if (existingStats != null) { Logger.LogError("Duplicate statistics from device ID {0} for date {1}", stats.InstallationId, stats.Date.ToString("d", CultureInfo.InvariantCulture)); return(Conflict(ProblemDetailsFactory.CreateProblemDetails(HttpContext, title: "Duplicate statistics for date", type: "https://arianna.digit.srl/api/problems/duplicate" ))); } // Compute voucher amounts int stayAtHomeBonus = 0; int womCount = (int)Math.Ceiling(stats.TotalMinutesTracked / 60.0) + stayAtHomeBonus; Logger.LogInformation("Generating {0} WOM vouchers for {1} total minutes and {2} minutes at home ({3} stay at home bonus)", womCount, stats.TotalMinutesTracked, stats.LocationTracking.MinutesAtHome, stayAtHomeBonus); var voucherRequest = await Wom.Instrument.RequestVouchers(new VoucherCreatePayload.VoucherInfo[] { new VoucherCreatePayload.VoucherInfo { Aim = "P", Count = womCount, Latitude = position.Coordinates.Latitude, Longitude = position.Coordinates.Longitude, Timestamp = stats.Date.Date.AddHours(23.999) } }); // OK-dokey await Mongo.AddDailyStats(new DataModels.DailyStats { InstallationId = stats.InstallationId, Date = stats.Date.Date, TotalMinutesTracked = stats.TotalMinutesTracked, TotalWomVouchersEarned = womCount, Centroid = position, CentroidHash = geohash, LocationCount = stats.LocationCount, VehicleCount = stats.VehicleCount, EventCount = stats.EventCount, SampleCount = stats.SampleCount, DiscardedSampleCount = stats.DiscardedSampleCount, BoundingBoxDiagonal = stats.BoundingBoxDiagonal, LocationTracking = new DataModels.LocationTrackingStats { MinutesAtHome = stats.LocationTracking.MinutesAtHome, MinutesAtWork = stats.LocationTracking.MinutesAtWork, MinutesAtSchool = stats.LocationTracking.MinutesAtSchool, MinutesAtOtherKnownLocations = stats.LocationTracking.MinutesAtOtherKnownLocations, MinutesElsewhere = stats.LocationTracking.MinutesElsewhere } }); return(Ok(new UploadConfirmation { WomLink = voucherRequest.Link, WomPassword = voucherRequest.Password, WomCount = womCount })); }