diff --git a/Weather/Service/Controllers/ReadingsController.cs b/Weather/Service/Controllers/ReadingsController.cs index 9607973..3a383ef 100644 --- a/Weather/Service/Controllers/ReadingsController.cs +++ b/Weather/Service/Controllers/ReadingsController.cs @@ -32,6 +32,14 @@ namespace ChrisKaczor.HomeMonitor.Weather.Service.Controllers return (await _database.GetReadingHistory(start, end)).ToList(); } + [HttpGet("aggregate")] + public async Task> GetHistoryAggregate(DateTimeOffset start, DateTimeOffset end) + { + var readings = await _database.GetReadingHistory(start, end); + + return new WeatherAggregate(readings); + } + [HttpGet("value-history")] public async Task>> GetValueHistory(WeatherValueType weatherValueType, DateTimeOffset start, DateTimeOffset end) { diff --git a/Weather/Service/Extensions.cs b/Weather/Service/Extensions.cs index 40b09bb..693a2d1 100644 --- a/Weather/Service/Extensions.cs +++ b/Weather/Service/Extensions.cs @@ -1,4 +1,5 @@ using System; +using DecimalMath; namespace ChrisKaczor.HomeMonitor.Weather.Service { @@ -8,5 +9,10 @@ namespace ChrisKaczor.HomeMonitor.Weather.Service { return item.CompareTo(start) >= 0 && item.CompareTo(end) <= 0; } + + public static decimal Truncate(this decimal value, int decimalPlaces) + { + return decimal.Truncate(value * DecimalEx.Pow(10, decimalPlaces)) / DecimalEx.Pow(10, decimalPlaces); + } } } diff --git a/Weather/Service/Models/ReadingAggregate.cs b/Weather/Service/Models/ReadingAggregate.cs new file mode 100644 index 0000000..9699dc4 --- /dev/null +++ b/Weather/Service/Models/ReadingAggregate.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using ChrisKaczor.HomeMonitor.Weather.Models; +using JetBrains.Annotations; + +namespace ChrisKaczor.HomeMonitor.Weather.Service.Models +{ + [PublicAPI] + public class ReadingAggregate + { + public decimal Min { get; set; } + + public decimal Max { get; set; } + + public decimal Average { get; set; } + + public ReadingAggregate(IEnumerable readings, Func selector, int decimalPlaces) + { + Min = readings.Min(selector); + Max = readings.Max(selector); + Average = readings.Average(selector).Truncate(decimalPlaces); + } + } +} \ No newline at end of file diff --git a/Weather/Service/Models/WeatherAggregate.cs b/Weather/Service/Models/WeatherAggregate.cs new file mode 100644 index 0000000..f8c775d --- /dev/null +++ b/Weather/Service/Models/WeatherAggregate.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using ChrisKaczor.HomeMonitor.Weather.Models; +using JetBrains.Annotations; + +namespace ChrisKaczor.HomeMonitor.Weather.Service.Models +{ + [PublicAPI] + public class WeatherAggregate + { + public ReadingAggregate Humidity { get; set; } + + public ReadingAggregate Temperature { get; set; } + + public ReadingAggregate Pressure { get; set; } + + public ReadingAggregate Light { get; set; } + + public ReadingAggregate WindSpeed { get; set; } + + public WindDirection WindDirectionAverage { get; set; } + + public decimal RainTotal { get; set; } + + private readonly static List _windDirectionValues = ((WindDirection[])Enum.GetValues(typeof(WindDirection))).Select(e => (int)e).ToList(); + + public WeatherAggregate(IEnumerable readings) + { + if (!readings.Any()) + return; + + Humidity = new ReadingAggregate(readings, r => r.Humidity, 1); + + Temperature = new ReadingAggregate(readings, r => r.PressureTemperature, 1); + + Pressure = new ReadingAggregate(readings, r => r.Pressure, 2); + + Light = new ReadingAggregate(readings, r => (r.LightLevel / 3.3m * 100).Truncate(1), 1); + + WindSpeed = new ReadingAggregate(readings, r => r.WindSpeed, 1); + + var windDirectionAverage = readings.Average(r => (decimal)r.WindDirection); + WindDirectionAverage = (WindDirection)_windDirectionValues.Aggregate((x, y) => Math.Abs(x - windDirectionAverage) < Math.Abs(y - windDirectionAverage) ? x : y); + + RainTotal = readings.Sum(r => r.Rain); + } + } +} \ No newline at end of file