diff --git a/src/FlightRecorder.Api/Controllers/ReportsController.cs b/src/FlightRecorder.Api/Controllers/ReportsController.cs
index 6f9deda..ebc0ccb 100644
--- a/src/FlightRecorder.Api/Controllers/ReportsController.cs
+++ b/src/FlightRecorder.Api/Controllers/ReportsController.cs
@@ -1,13 +1,9 @@
-using FlightRecorder.BusinessLogic.Factory;
+using FlightRecorder.Api.Entities;
+using FlightRecorder.BusinessLogic.Factory;
using FlightRecorder.Entities.Db;
using FlightRecorder.Entities.Reporting;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Linq.Expressions;
-using System.Threading.Tasks;
using System.Web;
namespace FlightRecorder.Api.Controllers
@@ -27,6 +23,34 @@ public ReportsController(FlightRecorderFactory factory)
_factory = factory;
}
+ ///
+ /// Generate the sighting statistics report
+ ///
+ ///
+ [HttpGet]
+ [Route("sightings")]
+ public async Task> GetSightingStatistics()
+ {
+ var aircraft = await _factory.Aircraft.CountAsync();
+ var manufacturers = await _factory.Manufacturers.CountAsync();
+ var models = await _factory.Models.CountAsync();
+ var airlines = await _factory.Airlines.CountAsync();
+ var flights = await _factory.Flights.CountAsync();
+ var sightings = await _factory.Sightings.CountAsync();
+ var locations = await _factory.Locations.CountAsync();
+
+ return new SightingStatisticsReport
+ (
+ aircraft,
+ manufacturers,
+ models,
+ airlines,
+ flights,
+ sightings,
+ locations
+ );
+ }
+
///
/// Generate the airline statistics report
///
diff --git a/src/FlightRecorder.Api/Entities/SightingStatisticsReport.cs b/src/FlightRecorder.Api/Entities/SightingStatisticsReport.cs
new file mode 100644
index 0000000..89696b1
--- /dev/null
+++ b/src/FlightRecorder.Api/Entities/SightingStatisticsReport.cs
@@ -0,0 +1,16 @@
+using System.Diagnostics.CodeAnalysis;
+
+namespace FlightRecorder.Api.Entities
+{
+ [ExcludeFromCodeCoverage]
+ public record SightingStatisticsReport
+ (
+ int Aircraft,
+ int Manufacturers,
+ int Models,
+ int Airlines,
+ int Flights,
+ int Sightings,
+ int Locations
+ );
+}
diff --git a/src/FlightRecorder.Api/FlightRecorder.Api.csproj b/src/FlightRecorder.Api/FlightRecorder.Api.csproj
index 86e2044..9e4610b 100644
--- a/src/FlightRecorder.Api/FlightRecorder.Api.csproj
+++ b/src/FlightRecorder.Api/FlightRecorder.Api.csproj
@@ -2,9 +2,9 @@
net8.0
- 1.10.0.0
- 1.10.0.0
- 1.10.0
+ 1.11.0.0
+ 1.11.0.0
+ 1.11.0
enable
false
diff --git a/src/FlightRecorder.BusinessLogic/Database/AircraftManager.cs b/src/FlightRecorder.BusinessLogic/Database/AircraftManager.cs
index 7c24834..cb881b7 100644
--- a/src/FlightRecorder.BusinessLogic/Database/AircraftManager.cs
+++ b/src/FlightRecorder.BusinessLogic/Database/AircraftManager.cs
@@ -67,6 +67,13 @@ public IAsyncEnumerable ListAsync(Expression> pre
return aircraft;
}
+ ///
+ /// Return the number of aircraft in the database
+ ///
+ ///
+ public async Task CountAsync()
+ => await _factory.Context.Aircraft.CountAsync();
+
///
/// Get the aircraft of a specified model
///
diff --git a/src/FlightRecorder.BusinessLogic/Database/AirlineManager.cs b/src/FlightRecorder.BusinessLogic/Database/AirlineManager.cs
index 2d9c7a9..2b363eb 100644
--- a/src/FlightRecorder.BusinessLogic/Database/AirlineManager.cs
+++ b/src/FlightRecorder.BusinessLogic/Database/AirlineManager.cs
@@ -56,6 +56,13 @@ public IAsyncEnumerable ListAsync(Expression> predi
return results;
}
+ ///
+ /// Return the number of airlines in the database
+ ///
+ ///
+ public async Task CountAsync()
+ => await _context.Airlines.CountAsync();
+
///
/// Add a named airline, if it doesn't already exist
///
diff --git a/src/FlightRecorder.BusinessLogic/Database/FlightManager.cs b/src/FlightRecorder.BusinessLogic/Database/FlightManager.cs
index 16fd66a..217ffc9 100644
--- a/src/FlightRecorder.BusinessLogic/Database/FlightManager.cs
+++ b/src/FlightRecorder.BusinessLogic/Database/FlightManager.cs
@@ -63,6 +63,13 @@ public IAsyncEnumerable ListAsync(Expression> predica
return flights;
}
+ ///
+ /// Return the number of flights in the database
+ ///
+ ///
+ public async Task CountAsync()
+ => await _factory.Context.Flights.CountAsync();
+
///
/// Get the flights for a named airline
///
diff --git a/src/FlightRecorder.BusinessLogic/Database/LocationManager.cs b/src/FlightRecorder.BusinessLogic/Database/LocationManager.cs
index 22f5e62..26aaae5 100644
--- a/src/FlightRecorder.BusinessLogic/Database/LocationManager.cs
+++ b/src/FlightRecorder.BusinessLogic/Database/LocationManager.cs
@@ -60,6 +60,13 @@ public virtual IAsyncEnumerable ListAsync(Expression
+ /// Return the number of locations in the database
+ ///
+ ///
+ public async Task CountAsync()
+ => await _context.Locations.CountAsync();
+
///
/// Add a named location, if it doesn't already exist
///
diff --git a/src/FlightRecorder.BusinessLogic/Database/ManufacturerManager.cs b/src/FlightRecorder.BusinessLogic/Database/ManufacturerManager.cs
index a7a1e58..aca6929 100644
--- a/src/FlightRecorder.BusinessLogic/Database/ManufacturerManager.cs
+++ b/src/FlightRecorder.BusinessLogic/Database/ManufacturerManager.cs
@@ -60,6 +60,13 @@ public IAsyncEnumerable ListAsync(Expression
+ /// Return the number of manufacturers in the database
+ ///
+ ///
+ public async Task CountAsync()
+ => await _context.Manufacturers.CountAsync();
+
///
/// Add a named manufacturer, if it doesn't already exist
///
diff --git a/src/FlightRecorder.BusinessLogic/Database/ModelManager.cs b/src/FlightRecorder.BusinessLogic/Database/ModelManager.cs
index 662cd84..e83a0a8 100644
--- a/src/FlightRecorder.BusinessLogic/Database/ModelManager.cs
+++ b/src/FlightRecorder.BusinessLogic/Database/ModelManager.cs
@@ -63,6 +63,13 @@ public IAsyncEnumerable ListAsync(Expression> predicate
return models;
}
+ ///
+ /// Return the number of aircraft models in the database
+ ///
+ ///
+ public async Task CountAsync()
+ => await _factory.Context.Models.CountAsync();
+
///
/// Get the models for a named manufacturer
///
diff --git a/src/FlightRecorder.BusinessLogic/Database/SightingManager.cs b/src/FlightRecorder.BusinessLogic/Database/SightingManager.cs
index 56c64d5..47760be 100644
--- a/src/FlightRecorder.BusinessLogic/Database/SightingManager.cs
+++ b/src/FlightRecorder.BusinessLogic/Database/SightingManager.cs
@@ -76,6 +76,13 @@ public IAsyncEnumerable ListAsync(Expression> pre
return sightings;
}
+ ///
+ /// Return the number of sightings in the database
+ ///
+ ///
+ public async Task CountAsync()
+ => await _factory.Context.Sightings.CountAsync();
+
///
/// Add a new sighting
///
diff --git a/src/FlightRecorder.Entities/Interfaces/IAircraftManager.cs b/src/FlightRecorder.Entities/Interfaces/IAircraftManager.cs
index f0772eb..513d51f 100644
--- a/src/FlightRecorder.Entities/Interfaces/IAircraftManager.cs
+++ b/src/FlightRecorder.Entities/Interfaces/IAircraftManager.cs
@@ -11,6 +11,7 @@ public interface IAircraftManager
Task AddAsync(string registration, string serialNumber, long? yearOfManufacture, string modelName, string manufacturerName);
Task GetAsync(Expression> predicate);
IAsyncEnumerable ListAsync(Expression> predicate, int pageNumber, int pageSize);
+ Task CountAsync();
Task> ListByModelAsync(string modelName, int pageNumber, int pageSize);
Task> ListByManufacturerAsync(string manufacturerName, int pageNumber, int pageSize);
}
diff --git a/src/FlightRecorder.Entities/Interfaces/IAirlineManager.cs b/src/FlightRecorder.Entities/Interfaces/IAirlineManager.cs
index 27e9c99..68bd0b2 100644
--- a/src/FlightRecorder.Entities/Interfaces/IAirlineManager.cs
+++ b/src/FlightRecorder.Entities/Interfaces/IAirlineManager.cs
@@ -10,6 +10,7 @@ public interface IAirlineManager
{
Task AddAsync(string name);
Task GetAsync(Expression> predicate);
- IAsyncEnumerable ListAsync(Expression> predicate, int pageNumber, int pageSize);
+ IAsyncEnumerable ListAsync(Expression> predicate, int pageNumber, int pageSize);
+ Task CountAsync();
}
}
\ No newline at end of file
diff --git a/src/FlightRecorder.Entities/Interfaces/IFlightManager.cs b/src/FlightRecorder.Entities/Interfaces/IFlightManager.cs
index d5b3206..e8166b3 100644
--- a/src/FlightRecorder.Entities/Interfaces/IFlightManager.cs
+++ b/src/FlightRecorder.Entities/Interfaces/IFlightManager.cs
@@ -11,6 +11,7 @@ public interface IFlightManager
Task AddAsync(string number, string embarkation, string destination, string airlineName);
Task GetAsync(Expression> predicate);
IAsyncEnumerable ListAsync(Expression> predicate, int pageNumber, int pageSize);
+ Task CountAsync();
Task> ListByAirlineAsync(string airlineName, int pageNumber, int pageSize);
}
}
\ No newline at end of file
diff --git a/src/FlightRecorder.Entities/Interfaces/ILocationManager.cs b/src/FlightRecorder.Entities/Interfaces/ILocationManager.cs
index 59a4e7b..25e273d 100644
--- a/src/FlightRecorder.Entities/Interfaces/ILocationManager.cs
+++ b/src/FlightRecorder.Entities/Interfaces/ILocationManager.cs
@@ -10,6 +10,7 @@ public interface ILocationManager
{
Task AddAsync(string name);
Task GetAsync(Expression> predicate);
- IAsyncEnumerable ListAsync(Expression> predicate, int pageNumber, int pageSize);
+ IAsyncEnumerable ListAsync(Expression> predicate, int pageNumber, int pageSize);
+ Task CountAsync();
}
}
\ No newline at end of file
diff --git a/src/FlightRecorder.Entities/Interfaces/IManufacturerManager.cs b/src/FlightRecorder.Entities/Interfaces/IManufacturerManager.cs
index 993196a..19144a7 100644
--- a/src/FlightRecorder.Entities/Interfaces/IManufacturerManager.cs
+++ b/src/FlightRecorder.Entities/Interfaces/IManufacturerManager.cs
@@ -10,6 +10,7 @@ public interface IManufacturerManager
{
Task AddAsync(string name);
Task GetAsync(Expression> predicate);
- IAsyncEnumerable ListAsync(Expression> predicate, int pageNumber, int pageSize);
+ IAsyncEnumerable ListAsync(Expression> predicate, int pageNumber, int pageSize);
+ Task CountAsync();
}
}
\ No newline at end of file
diff --git a/src/FlightRecorder.Entities/Interfaces/IModelManager.cs b/src/FlightRecorder.Entities/Interfaces/IModelManager.cs
index 4e53151..71558aa 100644
--- a/src/FlightRecorder.Entities/Interfaces/IModelManager.cs
+++ b/src/FlightRecorder.Entities/Interfaces/IModelManager.cs
@@ -11,6 +11,7 @@ public interface IModelManager
Task AddAsync(string name, string manufacturerName);
Task GetAsync(Expression> predicate);
IAsyncEnumerable ListAsync(Expression> predicate, int pageNumber, int pageSize);
+ Task CountAsync();
IAsyncEnumerable ListByManufacturerAsync(string manufacturerName, int pageNumber, int pageSize);
}
}
\ No newline at end of file
diff --git a/src/FlightRecorder.Entities/Interfaces/ISightingManager.cs b/src/FlightRecorder.Entities/Interfaces/ISightingManager.cs
index 0330fc7..a6e36ee 100644
--- a/src/FlightRecorder.Entities/Interfaces/ISightingManager.cs
+++ b/src/FlightRecorder.Entities/Interfaces/ISightingManager.cs
@@ -13,6 +13,7 @@ public interface ISightingManager
Task AddAsync(FlattenedSighting flattened);
Task GetAsync(Expression> predicate);
IAsyncEnumerable ListAsync(Expression> predicate, int pageNumber, int pageSize);
+ Task CountAsync();
Task> ListByAircraftAsync(string registration, int pageNumber, int pageSize);
Task> ListByRouteAsync(string embarkation, string destination, int pageNumber, int pageSize);
Task> ListByAirlineAsync(string airlineName, int pageNumber, int pageSize);
diff --git a/src/FlightRecorder.Mvc/FlightRecorder.Mvc.csproj b/src/FlightRecorder.Mvc/FlightRecorder.Mvc.csproj
index ee6f047..2d897f2 100644
--- a/src/FlightRecorder.Mvc/FlightRecorder.Mvc.csproj
+++ b/src/FlightRecorder.Mvc/FlightRecorder.Mvc.csproj
@@ -2,9 +2,9 @@
net8.0
- 1.10.0.0
- 1.10.0.0
- 1.10.0
+ 1.11.0.0
+ 1.11.0.0
+ 1.11.0
enable
false
diff --git a/src/FlightRecorder.Mvc/Views/Shared/_Layout.cshtml b/src/FlightRecorder.Mvc/Views/Shared/_Layout.cshtml
index 5db3aeb..13d01a8 100644
--- a/src/FlightRecorder.Mvc/Views/Shared/_Layout.cshtml
+++ b/src/FlightRecorder.Mvc/Views/Shared/_Layout.cshtml
@@ -109,7 +109,7 @@