mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
Separate each statistics pie chart into an independent component, fixes rendering crashes.
This commit is contained in:
16
Aaru.Server.New/Components/Pages/Statistics/Commands.razor
Normal file
16
Aaru.Server.New/Components/Pages/Statistics/Commands.razor
Normal file
@@ -0,0 +1,16 @@
|
||||
@using Aaru.Server.Database
|
||||
@using Aaru.Server.Database.Models
|
||||
@using Blazorise.Charts
|
||||
@using Blazorise.DataGrid
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All Aaru commands...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_commandsChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@CommandsList" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="Command">
|
||||
<DataGridColumn Caption="Command" Field="@nameof(Command.Name)"/>
|
||||
<DataGridNumericColumn Caption="Times run" Field="@nameof(Command.Count)"/>
|
||||
</DataGrid>
|
||||
@@ -0,0 +1,54 @@
|
||||
using Aaru.Server.Database.Models;
|
||||
using Blazorise.Charts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages.Statistics;
|
||||
|
||||
public partial class Commands
|
||||
{
|
||||
PieChart<long>? _commandsChart;
|
||||
List<long> _commandsCounts = [];
|
||||
string[] _commandsLabels = [];
|
||||
List<Command> CommandsList { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
CommandsList = await ctx.Commands.OrderBy(static c => c.Name).ToListAsync();
|
||||
|
||||
_commandsLabels = await ctx.Commands.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_commandsCounts = await ctx.Commands.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_commandsLabels.Length >= 10)
|
||||
{
|
||||
_commandsLabels[9] = "Other";
|
||||
|
||||
_commandsCounts[9] = ctx.Commands.Sum(static o => o.Count) - _commandsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
await Common.HandleRedraw(_commandsChart, _commandsLabels, GetCommandsChartDataset);
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
}
|
||||
|
||||
PieChartDataset<long> GetCommandsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_commandsLabels.Length} used commands",
|
||||
Data = _commandsCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
}
|
||||
26
Aaru.Server.New/Components/Pages/Statistics/Common.cs
Normal file
26
Aaru.Server.New/Components/Pages/Statistics/Common.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Blazorise.Charts;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages.Statistics;
|
||||
|
||||
public static class Common
|
||||
{
|
||||
internal static readonly List<string> _backgroundColors =
|
||||
[
|
||||
ChartColor.FromHtmlColorCode("#006412"), ChartColor.FromHtmlColorCode("#0000D3"),
|
||||
ChartColor.FromHtmlColorCode("#FF6403"), ChartColor.FromHtmlColorCode("#562C05"),
|
||||
ChartColor.FromHtmlColorCode("#DD0907"), ChartColor.FromHtmlColorCode("#F20884"),
|
||||
ChartColor.FromHtmlColorCode("#4700A5"), ChartColor.FromHtmlColorCode("#90713A"),
|
||||
ChartColor.FromHtmlColorCode("#1FB714"), ChartColor.FromHtmlColorCode("#02ABEA"),
|
||||
ChartColor.FromHtmlColorCode("#FBF305")
|
||||
];
|
||||
internal static readonly List<string> _borderColors = [ChartColor.FromHtmlColorCode("#8b0000")];
|
||||
|
||||
internal static async Task HandleRedraw<TDataSet, TItem, TOptions, TModel>(
|
||||
BaseChart<TDataSet, TItem, TOptions, TModel> chart, string[] labels, Func<TDataSet> getDataSet)
|
||||
where TDataSet : ChartDataset<TItem> where TOptions : ChartOptions where TModel : ChartModel
|
||||
{
|
||||
await chart.Clear();
|
||||
|
||||
await chart.AddLabelsDatasetsAndUpdate(labels, getDataSet());
|
||||
}
|
||||
}
|
||||
46
Aaru.Server.New/Components/Pages/Statistics/Devices.razor
Normal file
46
Aaru.Server.New/Components/Pages/Statistics/Devices.razor
Normal file
@@ -0,0 +1,46 @@
|
||||
@using Aaru.Server.Database
|
||||
@using Aaru.Server.Database.Models
|
||||
@using Blazorise
|
||||
@using Blazorise.Charts
|
||||
@using Blazorise.DataGrid
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
@*
|
||||
TODO: Group by datagrid
|
||||
*@
|
||||
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All devices found...</p>
|
||||
</h1>
|
||||
<Carousel @ref="_devicesCarousel">
|
||||
<CarouselSlide Name="1">
|
||||
<PieChart @ref="_devicesByBusChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
<CarouselSlide Name="2">
|
||||
<PieChart @ref="_devicesByManufacturerChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
</Carousel>
|
||||
<DataGrid Data="@DevicesList" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="DeviceItem">
|
||||
<DataGridColumn Caption="Manufacturer" Field="@nameof(DeviceItem.Manufacturer)"/>
|
||||
<DataGridColumn Caption="Model" Field="@nameof(DeviceItem.Model)"/>
|
||||
<DataGridColumn Caption="Revision" Field="@nameof(DeviceItem.Revision)"/>
|
||||
<DataGridColumn Caption="Bus" Field="@nameof(DeviceItem.Bus)"/>
|
||||
<DataGridColumn Caption="Report" Field="@nameof(DeviceItem.ReportId)">
|
||||
<DisplayTemplate>
|
||||
@{
|
||||
int? reportId = context?.ReportId;
|
||||
|
||||
if(reportId > 0)
|
||||
{
|
||||
<a href="/report/@reportId.Value" target="_blank">Yes</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>No</span>
|
||||
}
|
||||
}
|
||||
</DisplayTemplate>
|
||||
</DataGridColumn>
|
||||
</DataGrid>
|
||||
116
Aaru.Server.New/Components/Pages/Statistics/Devices.razor.cs
Normal file
116
Aaru.Server.New/Components/Pages/Statistics/Devices.razor.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using Aaru.Server.Database.Models;
|
||||
using Blazorise;
|
||||
using Blazorise.Charts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages.Statistics;
|
||||
|
||||
public partial class Devices
|
||||
{
|
||||
PieChart<long>? _devicesByBusChart;
|
||||
List<long> _devicesByBusCounts = [];
|
||||
string[] _devicesByBusLabels = [];
|
||||
PieChart<long>? _devicesByManufacturerChart;
|
||||
List<long> _devicesByManufacturerCounts = [];
|
||||
string[] _devicesByManufacturerLabels = [];
|
||||
Carousel? _devicesCarousel;
|
||||
List<DeviceItem> DevicesList { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
DevicesList = DevicesList.OrderBy(static device => device.Manufacturer)
|
||||
.ThenBy(static device => device.Model)
|
||||
.ThenBy(static device => device.Revision)
|
||||
.ThenBy(static device => device.Bus)
|
||||
.ToList();
|
||||
|
||||
var data = await ctx.DeviceStats.Select(static d => d.Bus)
|
||||
.Distinct()
|
||||
.Select(deviceBus => new
|
||||
{
|
||||
deviceBus,
|
||||
deviceBusCount = ctx.DeviceStats.LongCount(d => d.Bus == deviceBus)
|
||||
})
|
||||
.Select(static t => new
|
||||
{
|
||||
Name = t.deviceBus,
|
||||
Count = t.deviceBusCount
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
_devicesByBusLabels = data.OrderByDescending(static o => o.Count).Take(10).Select(static v => v.Name).ToArray();
|
||||
_devicesByBusCounts = data.OrderByDescending(static o => o.Count).Take(10).Select(static x => x.Count).ToList();
|
||||
|
||||
if(_devicesByBusLabels.Length >= 10)
|
||||
{
|
||||
_devicesByBusLabels[9] = "Other";
|
||||
|
||||
_devicesByBusCounts[9] = data.Sum(static o => o.Count) - _devicesByBusCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
List<DeviceStat> devices = await ctx.DeviceStats
|
||||
.Where(static d => d.Manufacturer != null && d.Manufacturer != "")
|
||||
.ToListAsync();
|
||||
|
||||
data = devices.Select(static d => d.Manufacturer!.ToLowerInvariant())
|
||||
.Distinct()
|
||||
.Select(manufacturer => new
|
||||
{
|
||||
manufacturer,
|
||||
manufacturerCount =
|
||||
devices.LongCount(d => d.Manufacturer?.ToLowerInvariant() == manufacturer)
|
||||
})
|
||||
.Select(static t => new
|
||||
{
|
||||
Name = t.manufacturer,
|
||||
Count = t.manufacturerCount
|
||||
})
|
||||
.ToList();
|
||||
|
||||
_devicesByManufacturerLabels =
|
||||
data.OrderByDescending(static o => o.Count).Take(10).Select(static v => v.Name).ToArray();
|
||||
|
||||
_devicesByManufacturerCounts =
|
||||
data.OrderByDescending(static o => o.Count).Take(10).Select(static x => x.Count).ToList();
|
||||
|
||||
if(_devicesByManufacturerLabels.Length < 10) return;
|
||||
|
||||
_devicesByManufacturerLabels[9] = "Other";
|
||||
_devicesByManufacturerCounts[9] = data.Sum(static o => o.Count) - _devicesByManufacturerCounts.Take(9).Sum();
|
||||
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
await Common.HandleRedraw(_devicesByBusChart, _devicesByBusLabels, GetDevicesByBusChartDataset);
|
||||
|
||||
await Common.HandleRedraw(_devicesByManufacturerChart,
|
||||
_devicesByManufacturerLabels,
|
||||
GetDevicesByManufacturerChartDataset);
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
|
||||
// Upstream: https://github.com/Megabit/Blazorise/issues/5491
|
||||
_devicesCarousel.Interval = 5000;
|
||||
}
|
||||
|
||||
PieChartDataset<long> GetDevicesByBusChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_devicesByBusLabels.Length} devices by bus",
|
||||
Data = _devicesByBusCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetDevicesByManufacturerChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_devicesByManufacturerLabels.Length} devices by manufacturers",
|
||||
Data = _devicesByManufacturerCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
@using Aaru.Server.Database
|
||||
@using Aaru.Server.Database.Models
|
||||
@using Blazorise.Charts
|
||||
@using Blazorise.DataGrid
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All filesystems found...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_filesystemsChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@FilesystemsList" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="Filesystem">
|
||||
<DataGridColumn Caption="Filesystem name" Field="@nameof(Filesystem.Name)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(Filesystem.Count)"/>
|
||||
</DataGrid>
|
||||
@@ -0,0 +1,54 @@
|
||||
using Aaru.Server.Database.Models;
|
||||
using Blazorise.Charts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages.Statistics;
|
||||
|
||||
public partial class Filesystems
|
||||
{
|
||||
PieChart<long>? _filesystemsChart;
|
||||
List<long> _filesystemsCounts = [];
|
||||
string[] _filesystemsLabels = [];
|
||||
List<Filesystem> FilesystemsList { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
FilesystemsList = await ctx.Filesystems.OrderBy(static filesystem => filesystem.Name).ToListAsync();
|
||||
|
||||
_filesystemsLabels = await ctx.Filesystems.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_filesystemsCounts = await ctx.Filesystems.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_filesystemsLabels.Length >= 10)
|
||||
{
|
||||
_filesystemsLabels[9] = "Other";
|
||||
|
||||
_filesystemsCounts[9] = ctx.Filesystems.Sum(static o => o.Count) - _filesystemsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
await Common.HandleRedraw(_filesystemsChart, _filesystemsLabels, GetFilesystemsChartDataset);
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
}
|
||||
|
||||
PieChartDataset<long> GetFilesystemsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_filesystemsLabels.Length} filesystems found",
|
||||
Data = _filesystemsCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
}
|
||||
16
Aaru.Server.New/Components/Pages/Statistics/Filters.razor
Normal file
16
Aaru.Server.New/Components/Pages/Statistics/Filters.razor
Normal file
@@ -0,0 +1,16 @@
|
||||
@using Aaru.Server.Database
|
||||
@using Aaru.Server.Database.Models
|
||||
@using Blazorise.Charts
|
||||
@using Blazorise.DataGrid
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All filters found...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_filtersChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@FiltersList" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="Filter">
|
||||
<DataGridColumn Caption="Filter" Field="@nameof(Filter.Name)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(Filter.Count)"/>
|
||||
</DataGrid>
|
||||
55
Aaru.Server.New/Components/Pages/Statistics/Filters.razor.cs
Normal file
55
Aaru.Server.New/Components/Pages/Statistics/Filters.razor.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Aaru.Server.Database.Models;
|
||||
using Blazorise.Charts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages.Statistics;
|
||||
|
||||
public partial class Filters
|
||||
{
|
||||
PieChart<long>? _filtersChart;
|
||||
List<long> _filtersCounts = [];
|
||||
string[] _filtersLabels = [];
|
||||
List<Filter> FiltersList { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
FiltersList = await ctx.Filters.OrderBy(static filter => filter.Name).ToListAsync();
|
||||
|
||||
_filtersLabels = await ctx.Filters.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_filtersCounts = await ctx.Filters.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_filtersLabels.Length >= 10)
|
||||
{
|
||||
_filtersLabels[9] = "Other";
|
||||
|
||||
_filtersCounts[9] = ctx.Filters.Sum(static o => o.Count) - _filtersCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
await Common.HandleRedraw(_filtersChart, _filtersLabels, GetFiltersChartDataset);
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
}
|
||||
|
||||
|
||||
PieChartDataset<long> GetFiltersChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_filtersLabels.Length} filters found",
|
||||
Data = _filtersCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
}
|
||||
22
Aaru.Server.New/Components/Pages/Statistics/Formats.razor
Normal file
22
Aaru.Server.New/Components/Pages/Statistics/Formats.razor
Normal file
@@ -0,0 +1,22 @@
|
||||
@using Aaru.Server.Database
|
||||
@using Aaru.Server.Database.Models
|
||||
@using Blazorise.Charts
|
||||
@using Blazorise.DataGrid
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
<PageTitle>Aaru: Statistics</PageTitle>
|
||||
|
||||
@*
|
||||
TODO: Group by datagrid
|
||||
*@
|
||||
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All media image formats found...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_formatsChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@MediaImages" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="MediaFormat">
|
||||
<DataGridColumn Caption="Media image format" Field="@nameof(MediaFormat.Name)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(MediaFormat.Count)"/>
|
||||
</DataGrid>
|
||||
57
Aaru.Server.New/Components/Pages/Statistics/Formats.razor.cs
Normal file
57
Aaru.Server.New/Components/Pages/Statistics/Formats.razor.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using Aaru.Server.Database.Models;
|
||||
using Blazorise.Charts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages.Statistics;
|
||||
|
||||
public partial class Formats
|
||||
{
|
||||
PieChart<long>? _formatsChart;
|
||||
List<long> _formatsCounts = [];
|
||||
string[] _formatsLabels = [];
|
||||
List<MediaFormat> MediaImages { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
|
||||
MediaImages = await ctx.MediaFormats.OrderBy(static format => format.Name).ToListAsync();
|
||||
|
||||
_formatsLabels = await ctx.MediaFormats.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_formatsCounts = await ctx.MediaFormats.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_formatsLabels.Length >= 10)
|
||||
{
|
||||
_formatsLabels[9] = "Other";
|
||||
|
||||
_formatsCounts[9] = ctx.MediaFormats.Sum(static o => o.Count) - _formatsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
await Common.HandleRedraw(_formatsChart, _formatsLabels, GetFormatsChartDataset);
|
||||
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
}
|
||||
|
||||
PieChartDataset<long> GetFormatsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_formatsLabels.Length} media image formats found",
|
||||
Data = _formatsCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
@using Aaru.CommonTypes.Metadata
|
||||
@using Aaru.Server.Database
|
||||
@using Blazorise
|
||||
@using Blazorise.Charts
|
||||
@using Blazorise.DataGrid
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
@*
|
||||
TODO: Group by datagrid
|
||||
*@
|
||||
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All operating systems Aaru has run on...</p>
|
||||
</h1>
|
||||
<Carousel @ref="_operatingSystemsCarousel">
|
||||
<CarouselSlide Name="1">
|
||||
<PieChart @ref="_operatingSystemsChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
<CarouselSlide Name="2">
|
||||
<PieChart @ref="_linuxChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
<CarouselSlide Name="3">
|
||||
<PieChart @ref="_macosChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
<CarouselSlide Name="4">
|
||||
<PieChart @ref="_windowsChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
</Carousel>
|
||||
<DataGrid Data="@OperatingSystemsList" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="NameValueStats">
|
||||
<DataGridColumn Caption="Name" Field="@nameof(NameValueStats.name)"/>
|
||||
<DataGridNumericColumn Caption="Times" Field="@nameof(NameValueStats.Value)"/>
|
||||
</DataGrid>
|
||||
@@ -0,0 +1,190 @@
|
||||
using Aaru.CommonTypes.Interop;
|
||||
using Aaru.CommonTypes.Metadata;
|
||||
using Blazorise;
|
||||
using Blazorise.Charts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
using PlatformID = Aaru.CommonTypes.Interop.PlatformID;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages.Statistics;
|
||||
|
||||
public partial class OperatingSystems
|
||||
{
|
||||
PieChart<long>? _linuxChart;
|
||||
List<long> _linuxCounts = [];
|
||||
string[] _linuxLabels = [];
|
||||
PieChart<long>? _macosChart;
|
||||
List<long> _macosCounts = [];
|
||||
string[] _macosLabels = [];
|
||||
Carousel? _operatingSystemsCarousel;
|
||||
PieChart<long>? _operatingSystemsChart;
|
||||
List<long> _operatingSystemsCounts = [];
|
||||
string[] _operatingSystemsLabels = [];
|
||||
PieChart<long>? _windowsChart;
|
||||
List<long> _windowsCounts = [];
|
||||
string[] _windowsLabels = [];
|
||||
List<NameValueStats> OperatingSystemsList { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
// TODO: Cache real OS name in database, lookups would be much faster
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
OperatingSystemsList = (await ctx.OperatingSystems.OrderBy(static os => os.Name)
|
||||
.ThenBy(static os => os.Version)
|
||||
.Select(static nvs => new NameValueStats
|
||||
{
|
||||
name =
|
||||
$"{GetPlatformName(nvs.Name, nvs.Version)}{(string.IsNullOrEmpty(nvs.Version) ? "" : " ")}{nvs.Version}",
|
||||
Value = nvs.Count
|
||||
})
|
||||
.ToListAsync()).OrderBy(static os => os.name)
|
||||
.ToList();
|
||||
|
||||
var osQuery = ctx.OperatingSystems.GroupBy(static x => new
|
||||
{
|
||||
x.Name
|
||||
},
|
||||
static x => x.Count)
|
||||
.Select(static g => new
|
||||
{
|
||||
g.Key.Name,
|
||||
Count = g.Sum()
|
||||
});
|
||||
|
||||
_operatingSystemsLabels = await osQuery.Select(static x => x.Name).ToArrayAsync();
|
||||
_operatingSystemsCounts = await osQuery.Select(static x => x.Count).ToListAsync();
|
||||
|
||||
for(var i = 0; i < _operatingSystemsLabels.Length; i++)
|
||||
{
|
||||
_operatingSystemsLabels[i] =
|
||||
DetectOS.GetPlatformName((PlatformID)Enum.Parse(typeof(PlatformID), _operatingSystemsLabels[i]));
|
||||
}
|
||||
|
||||
_linuxLabels = await ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Linux.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x =>
|
||||
$"{DetectOS.GetPlatformName(PlatformID.Linux, x.Version)}{(string.IsNullOrEmpty(x.Version) ? "" : " ")}{x.Version}")
|
||||
.ToArrayAsync();
|
||||
|
||||
_linuxCounts = await ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Linux.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
|
||||
if(_linuxLabels.Length >= 10)
|
||||
{
|
||||
_linuxLabels[9] = "Other";
|
||||
|
||||
_linuxCounts[9] =
|
||||
ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Linux.ToString()).Sum(static o => o.Count) -
|
||||
_linuxCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
_macosLabels = await ctx.OperatingSystems.Where(static o => o.Name == PlatformID.MacOSX.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x =>
|
||||
$"{DetectOS.GetPlatformName(PlatformID.MacOSX, x.Version)}{(string.IsNullOrEmpty(x.Version) ? "" : " ")}{x.Version}")
|
||||
.ToArrayAsync();
|
||||
|
||||
_macosCounts = await ctx.OperatingSystems.Where(static o => o.Name == PlatformID.MacOSX.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
|
||||
if(_macosLabels.Length >= 10)
|
||||
{
|
||||
_macosLabels[9] = "Other";
|
||||
|
||||
_macosCounts[9] =
|
||||
ctx.OperatingSystems.Where(static o => o.Name == PlatformID.MacOSX.ToString())
|
||||
.Sum(static o => o.Count) -
|
||||
_macosCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
_windowsLabels = await ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Win32NT.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x =>
|
||||
$"{DetectOS.GetPlatformName(PlatformID.Win32NT, x.Version)}{(string.IsNullOrEmpty(x.Version) ? "" : " ")}{x.Version}")
|
||||
.ToArrayAsync();
|
||||
|
||||
_windowsCounts = await ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Win32NT.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
|
||||
if(_windowsLabels.Length >= 10)
|
||||
{
|
||||
_windowsLabels[9] = "Other";
|
||||
|
||||
_windowsCounts[9] =
|
||||
ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Win32NT.ToString())
|
||||
.Sum(static o => o.Count) -
|
||||
_windowsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
|
||||
await Task.WhenAll(Common.HandleRedraw(_operatingSystemsChart,
|
||||
_operatingSystemsLabels,
|
||||
GetOperatingSystemsChartDataset),
|
||||
Common.HandleRedraw(_linuxChart, _linuxLabels, GetLinuxChartDataset),
|
||||
Common.HandleRedraw(_macosChart, _macosLabels, GetMacosChartDataset),
|
||||
Common.HandleRedraw(_windowsChart, _windowsLabels, GetWindowsChartDataset));
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
|
||||
// Upstream: https://github.com/Megabit/Blazorise/issues/5491
|
||||
_operatingSystemsCarousel.Interval = 5000;
|
||||
}
|
||||
|
||||
PieChartDataset<long> GetOperatingSystemsChartDataset() => new()
|
||||
{
|
||||
Label = "Operating systems",
|
||||
Data = _operatingSystemsCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetLinuxChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_linuxLabels.Length} Linux versions",
|
||||
Data = _linuxCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetMacosChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_macosLabels.Length} macOS versions",
|
||||
Data = _macosCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetWindowsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_windowsLabels.Length} Windows versions",
|
||||
Data = _windowsCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
static string GetPlatformName(string name, string version) =>
|
||||
DetectOS.GetPlatformName((PlatformID)Enum.Parse(typeof(PlatformID), name), version);
|
||||
}
|
||||
16
Aaru.Server.New/Components/Pages/Statistics/Partitions.razor
Normal file
16
Aaru.Server.New/Components/Pages/Statistics/Partitions.razor
Normal file
@@ -0,0 +1,16 @@
|
||||
@using Aaru.Server.Database
|
||||
@using Aaru.Server.Database.Models
|
||||
@using Blazorise.Charts
|
||||
@using Blazorise.DataGrid
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All partitioning schemes found...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_partitionsChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@PartitionsList" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="Partition">
|
||||
<DataGridColumn Caption="Partitioning scheme" Field="@nameof(Partition.Name)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(Partition.Count)"/>
|
||||
</DataGrid>
|
||||
@@ -0,0 +1,54 @@
|
||||
using Aaru.Server.Database.Models;
|
||||
using Blazorise.Charts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages.Statistics;
|
||||
|
||||
public partial class Partitions
|
||||
{
|
||||
PieChart<long>? _partitionsChart;
|
||||
List<long> _partitionsCounts = [];
|
||||
string[] _partitionsLabels = [];
|
||||
List<Partition> PartitionsList { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
PartitionsList = await ctx.Partitions.OrderBy(static partition => partition.Name).ToListAsync();
|
||||
|
||||
_partitionsLabels = await ctx.Partitions.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_partitionsCounts = await ctx.Partitions.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_partitionsLabels.Length >= 10)
|
||||
{
|
||||
_partitionsLabels[9] = "Other";
|
||||
|
||||
_partitionsCounts[9] = ctx.Partitions.Sum(static o => o.Count) - _partitionsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
await Common.HandleRedraw(_partitionsChart, _partitionsLabels, GetPartitionsChartDataset);
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
}
|
||||
|
||||
PieChartDataset<long> GetPartitionsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_partitionsLabels.Length} partitioning schemes found",
|
||||
Data = _partitionsCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
}
|
||||
21
Aaru.Server.New/Components/Pages/Statistics/RealMedias.razor
Normal file
21
Aaru.Server.New/Components/Pages/Statistics/RealMedias.razor
Normal file
@@ -0,0 +1,21 @@
|
||||
@using Aaru.Server.Database
|
||||
@using Aaru.Server.Database.Models
|
||||
@using Blazorise.Charts
|
||||
@using Blazorise.DataGrid
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
@*
|
||||
TODO: Group by datagrid
|
||||
*@
|
||||
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All media types found in devices...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_realMediaChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@RealMedia" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="MediaItem">
|
||||
<DataGridColumn Caption="Physical type" Field="@nameof(MediaItem.Type)"/>
|
||||
<DataGridColumn Caption="Logical type" Field="@nameof(MediaItem.SubType)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(MediaItem.Count)"/>
|
||||
</DataGrid>
|
||||
@@ -0,0 +1,70 @@
|
||||
using Aaru.CommonTypes.Metadata;
|
||||
using Aaru.Server.Database.Models;
|
||||
using Blazorise.Charts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
using Media = Aaru.Server.Database.Models.Media;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages.Statistics;
|
||||
|
||||
public partial class RealMedias
|
||||
{
|
||||
PieChart<long>? _realMediaChart;
|
||||
List<long> _realMediaCounts = [];
|
||||
string[] _realMediaLabels = [];
|
||||
List<MediaItem> RealMedia { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
Media[] realMedias = await ctx.Medias.Where(static o => o.Real)
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.ToArrayAsync();
|
||||
|
||||
foreach(Media media in realMedias)
|
||||
{
|
||||
try
|
||||
{
|
||||
(string type, string subType) mediaType =
|
||||
MediaType.MediaTypeToString((CommonTypes.MediaType)Enum.Parse(typeof(CommonTypes.MediaType),
|
||||
media.Type));
|
||||
|
||||
media.Type = $"{mediaType.type} ({mediaType.subType})";
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Could not get media type/subtype pair from type, so just leave it as is
|
||||
}
|
||||
}
|
||||
|
||||
_realMediaLabels = realMedias.Select(static v => v.Type).ToArray();
|
||||
_realMediaCounts = realMedias.Select(static x => x.Count).ToList();
|
||||
|
||||
if(_realMediaLabels.Length >= 10)
|
||||
{
|
||||
_realMediaLabels[9] = "Other";
|
||||
|
||||
_realMediaCounts[9] = ctx.Medias.Where(static o => o.Real).Sum(static o => o.Count) -
|
||||
_realMediaCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
await Common.HandleRedraw(_realMediaChart, _realMediaLabels, GetRealMediaChartDataset);
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
}
|
||||
|
||||
PieChartDataset<long> GetRealMediaChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_realMediaLabels.Length} media types found in devices",
|
||||
Data = _realMediaCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
}
|
||||
16
Aaru.Server.New/Components/Pages/Statistics/Versions.razor
Normal file
16
Aaru.Server.New/Components/Pages/Statistics/Versions.razor
Normal file
@@ -0,0 +1,16 @@
|
||||
@using Aaru.CommonTypes.Metadata
|
||||
@using Aaru.Server.Database
|
||||
@using Blazorise.Charts
|
||||
@using Blazorise.DataGrid
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All Aaru versions...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_versionsChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@VersionsList" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="NameValueStats">
|
||||
<DataGridColumn Caption="Version" Field="@nameof(NameValueStats.name)"/>
|
||||
<DataGridNumericColumn Caption="Times run" Field="@nameof(NameValueStats.Value)"/>
|
||||
</DataGrid>
|
||||
@@ -0,0 +1,60 @@
|
||||
using Aaru.CommonTypes.Metadata;
|
||||
using Blazorise.Charts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages.Statistics;
|
||||
|
||||
public partial class Versions
|
||||
{
|
||||
PieChart<long>? _versionsChart;
|
||||
List<long> _versionsCounts = [];
|
||||
string[] _versionsLabels = [];
|
||||
List<NameValueStats> VersionsList { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
VersionsList = (await ctx.Versions.Select(static nvs => new NameValueStats
|
||||
{
|
||||
name = nvs.Name == "previous" ? "Previous than 3.4.99.0" : nvs.Name,
|
||||
Value = nvs.Count
|
||||
})
|
||||
.ToListAsync()).OrderBy(static version => version.name)
|
||||
.ToList();
|
||||
|
||||
_versionsLabels = await ctx.Versions.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name == "previous" ? "Previous than 3.4.99.0" : v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_versionsCounts = await ctx.Versions.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_versionsLabels.Length >= 10)
|
||||
{
|
||||
_versionsLabels[9] = "Other";
|
||||
|
||||
_versionsCounts[9] = ctx.Versions.Sum(static o => o.Count) - _versionsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
await Common.HandleRedraw(_versionsChart, _versionsLabels, GetVersionsChartDataset);
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
}
|
||||
|
||||
PieChartDataset<long> GetVersionsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_versionsLabels.Length} Aaru versions",
|
||||
Data = _versionsCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
@using Aaru.Server.Database
|
||||
@using Aaru.Server.Database.Models
|
||||
@using Blazorise.Charts
|
||||
@using Blazorise.DataGrid
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
@*
|
||||
TODO: Group by datagrid
|
||||
*@
|
||||
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All media types found in images...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_virtualMediaChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@VirtualMedia" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="MediaItem">
|
||||
<DataGridColumn Caption="Physical type" Field="@nameof(MediaItem.Type)"/>
|
||||
<DataGridColumn Caption="Logical type" Field="@nameof(MediaItem.SubType)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(MediaItem.Count)"/>
|
||||
</DataGrid>
|
||||
@@ -0,0 +1,69 @@
|
||||
using Aaru.CommonTypes.Metadata;
|
||||
using Aaru.Server.Database.Models;
|
||||
using Blazorise.Charts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
using Media = Aaru.Server.Database.Models.Media;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages.Statistics;
|
||||
|
||||
public partial class VirtualMedias
|
||||
{
|
||||
PieChart<long>? _virtualMediaChart;
|
||||
List<long> _virtualMediaCounts = [];
|
||||
string[] _virtualMediaLabels = [];
|
||||
List<MediaItem> VirtualMedia { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
Media[] virtualMedias = await ctx.Medias.Where(static o => !o.Real)
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.ToArrayAsync();
|
||||
|
||||
foreach(Media media in virtualMedias)
|
||||
{
|
||||
try
|
||||
{
|
||||
(string type, string subType) mediaType =
|
||||
MediaType.MediaTypeToString((CommonTypes.MediaType)Enum.Parse(typeof(CommonTypes.MediaType),
|
||||
media.Type));
|
||||
|
||||
media.Type = $"{mediaType.type} ({mediaType.subType})";
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Could not get media type/subtype pair from type, so just leave it as is
|
||||
}
|
||||
}
|
||||
|
||||
_virtualMediaLabels = virtualMedias.Select(static v => v.Type).ToArray();
|
||||
_virtualMediaCounts = virtualMedias.Select(static x => x.Count).ToList();
|
||||
|
||||
if(_virtualMediaLabels.Length >= 10)
|
||||
{
|
||||
_virtualMediaLabels[9] = "Other";
|
||||
|
||||
_virtualMediaCounts[9] = ctx.Medias.Where(static o => !o.Real).Sum(static o => o.Count) -
|
||||
_virtualMediaCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
await Common.HandleRedraw(_virtualMediaChart, _virtualMediaLabels, GetVirtualMediaChartDataset);
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
}
|
||||
|
||||
PieChartDataset<long> GetVirtualMediaChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_virtualMediaLabels.Length} media types found in images",
|
||||
Data = _virtualMediaCounts,
|
||||
BackgroundColor = Common._backgroundColors,
|
||||
BorderColor = Common._borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
}
|
||||
@@ -1,167 +1,70 @@
|
||||
@page "/Stats"
|
||||
@using Aaru.CommonTypes.Metadata
|
||||
@using Aaru.Server.Database
|
||||
@using Aaru.Server.Database.Models
|
||||
@using Aaru.Server.New.Components.Pages.Statistics
|
||||
@using Blazorise
|
||||
@using Blazorise.Charts
|
||||
@using Blazorise.DataGrid
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
<PageTitle>Aaru: Statistics</PageTitle>
|
||||
|
||||
@*
|
||||
TODO: Group by datagrid
|
||||
TODO: Sortable datagrid
|
||||
*@
|
||||
|
||||
<div class="stats-section">
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All operating systems Aaru has run on...</p>
|
||||
</h1>
|
||||
<Carousel @ref="_operatingSystemsCarousel">
|
||||
<CarouselSlide Name="1">
|
||||
<PieChart @ref="_operatingSystemsChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
<CarouselSlide Name="2">
|
||||
<PieChart @ref="_linuxChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
<CarouselSlide Name="3">
|
||||
<PieChart @ref="_macosChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
<CarouselSlide Name="4">
|
||||
<PieChart @ref="_windowsChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
</Carousel>
|
||||
<DataGrid Data="@OperatingSystems" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="NameValueStats">
|
||||
<DataGridColumn Caption="Name" Field="@nameof(NameValueStats.name)"/>
|
||||
<DataGridNumericColumn Caption="Times" Field="@nameof(NameValueStats.Value)"/>
|
||||
</DataGrid>
|
||||
<Tabs FullWidth Justified Pills @ref="_tabs" RenderMode="TabsRenderMode.LazyLoad">
|
||||
<Items>
|
||||
<Tab Name="oses">Operating systems</Tab>
|
||||
<Tab Name="versions">Versions</Tab>
|
||||
<Tab Name="commands">Commands</Tab>
|
||||
<Tab Name="filters">Filters</Tab>
|
||||
<Tab Name="formats">Media image formats</Tab>
|
||||
<Tab Name="partitions">Partitioning schemes</Tab>
|
||||
<Tab Name="filesystems">Filesystems</Tab>
|
||||
<Tab Name="virtualMedias">Media types (images)</Tab>
|
||||
<Tab Name="realMedias">Media types (devices)</Tab>
|
||||
<Tab Name="devices">Devices</Tab>
|
||||
</Items>
|
||||
<Content>
|
||||
<TabPanel Name="oses">
|
||||
<OperatingSystems/>
|
||||
</TabPanel>
|
||||
<TabPanel Name="versions">
|
||||
<Versions/>
|
||||
</TabPanel>
|
||||
<TabPanel Name="commands">
|
||||
<Commands/>
|
||||
</TabPanel>
|
||||
<TabPanel Name="filters">
|
||||
<Filters/>
|
||||
</TabPanel>
|
||||
<TabPanel Name="formats">
|
||||
<Formats/>
|
||||
</TabPanel>
|
||||
<TabPanel Name="partitions">
|
||||
<Partitions/>
|
||||
</TabPanel>
|
||||
<TabPanel Name="filesystems">
|
||||
<Filesystems/>
|
||||
</TabPanel>
|
||||
<TabPanel Name="virtualMedias">
|
||||
<VirtualMedias/>
|
||||
</TabPanel>
|
||||
<TabPanel Name="realMedias">
|
||||
<RealMedias/>
|
||||
</TabPanel>
|
||||
<TabPanel Name="devices">
|
||||
<Devices/>
|
||||
</TabPanel>
|
||||
</Content>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
<div class="stats-section">
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All Aaru versions...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_versionsChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@Versions" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="NameValueStats">
|
||||
<DataGridColumn Caption="Version" Field="@nameof(NameValueStats.name)"/>
|
||||
<DataGridNumericColumn Caption="Times run" Field="@nameof(NameValueStats.Value)"/>
|
||||
</DataGrid>
|
||||
</div>
|
||||
@code
|
||||
{
|
||||
Tabs _tabs;
|
||||
|
||||
<div class="stats-section">
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All Aaru commands...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_commandsChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@Commands" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="Command">
|
||||
<DataGridColumn Caption="Command" Field="@nameof(Command.Name)"/>
|
||||
<DataGridNumericColumn Caption="Times run" Field="@nameof(Command.Count)"/>
|
||||
</DataGrid>
|
||||
</div>
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
<div class="stats-section">
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All filters found...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_filtersChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@Filters" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="Filter">
|
||||
<DataGridColumn Caption="Filter" Field="@nameof(Filter.Name)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(Filter.Count)"/>
|
||||
</DataGrid>
|
||||
</div>
|
||||
if(!firstRender) return;
|
||||
|
||||
<div class="stats-section">
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All media image formats found...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_formatsChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@MediaImages" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="MediaFormat">
|
||||
<DataGridColumn Caption="Media image format" Field="@nameof(MediaFormat.Name)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(MediaFormat.Count)"/>
|
||||
</DataGrid>
|
||||
</div>
|
||||
|
||||
<div class="stats-section">
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All partitioning schemes found...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_partitionsChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@Partitions" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="Partition">
|
||||
<DataGridColumn Caption="Partitioning scheme" Field="@nameof(Partition.Name)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(Partition.Count)"/>
|
||||
</DataGrid>
|
||||
</div>
|
||||
|
||||
<div class="stats-section">
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All filesystems found...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_filesystemsChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@Filesystems" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="Filesystem">
|
||||
<DataGridColumn Caption="Filesystem name" Field="@nameof(Filesystem.Name)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(Filesystem.Count)"/>
|
||||
</DataGrid>
|
||||
</div>
|
||||
|
||||
<div class="stats-section">
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All media types found in images...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_virtualMediaChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@VirtualMedia" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="MediaItem">
|
||||
<DataGridColumn Caption="Physical type" Field="@nameof(MediaItem.Type)"/>
|
||||
<DataGridColumn Caption="Logical type" Field="@nameof(MediaItem.SubType)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(MediaItem.Count)"/>
|
||||
</DataGrid>
|
||||
</div>
|
||||
|
||||
<div class="stats-section">
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All media types found in devices...</p>
|
||||
</h1>
|
||||
<PieChart @ref="_realMediaChart" style="padding: 40px" TItem="long"/>
|
||||
<DataGrid Data="@RealMedia" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="MediaItem">
|
||||
<DataGridColumn Caption="Physical type" Field="@nameof(MediaItem.Type)"/>
|
||||
<DataGridColumn Caption="Logical type" Field="@nameof(MediaItem.SubType)"/>
|
||||
<DataGridNumericColumn Caption="Times found" Field="@nameof(MediaItem.Count)"/>
|
||||
</DataGrid>
|
||||
</div>
|
||||
|
||||
<div class="stats-section">
|
||||
<h1>
|
||||
<p class="text-center" style="color: deeppink;">All devices found...</p>
|
||||
</h1>
|
||||
<Carousel @ref="_devicesCarousel">
|
||||
<CarouselSlide Name="1">
|
||||
<PieChart @ref="_devicesByBusChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
<CarouselSlide Name="2">
|
||||
<PieChart @ref="_devicesByManufacturerChart" style="padding: 40px" TItem="long"/>
|
||||
</CarouselSlide>
|
||||
</Carousel>
|
||||
<DataGrid Data="@Devices" FixedHeader FixedHeaderDataGridMaxHeight="300px" PageSize="int.MaxValue" TItem="DeviceItem">
|
||||
<DataGridColumn Caption="Manufacturer" Field="@nameof(DeviceItem.Manufacturer)"/>
|
||||
<DataGridColumn Caption="Model" Field="@nameof(DeviceItem.Model)"/>
|
||||
<DataGridColumn Caption="Revision" Field="@nameof(DeviceItem.Revision)"/>
|
||||
<DataGridColumn Caption="Bus" Field="@nameof(DeviceItem.Bus)"/>
|
||||
<DataGridColumn Caption="Report" Field="@nameof(DeviceItem.ReportId)">
|
||||
<DisplayTemplate>
|
||||
@{
|
||||
int? reportId = context?.ReportId;
|
||||
|
||||
if(reportId > 0)
|
||||
{
|
||||
<a href="/report/@reportId.Value" target="_blank">Yes</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>No</span>
|
||||
}
|
||||
}
|
||||
</DisplayTemplate>
|
||||
</DataGridColumn>
|
||||
</DataGrid>
|
||||
</div>
|
||||
await _tabs.SelectTab("oses");
|
||||
}
|
||||
}
|
||||
@@ -1,665 +0,0 @@
|
||||
using Aaru.CommonTypes.Interop;
|
||||
using Aaru.CommonTypes.Metadata;
|
||||
using Aaru.Server.Database.Models;
|
||||
using Blazorise;
|
||||
using Blazorise.Charts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
using Media = Aaru.Server.Database.Models.Media;
|
||||
using PlatformID = Aaru.CommonTypes.Interop.PlatformID;
|
||||
|
||||
namespace Aaru.Server.New.Components.Pages;
|
||||
|
||||
public partial class Stats
|
||||
{
|
||||
readonly List<string> _backgroundColors =
|
||||
[
|
||||
ChartColor.FromHtmlColorCode("#006412"), ChartColor.FromHtmlColorCode("#0000D3"),
|
||||
ChartColor.FromHtmlColorCode("#FF6403"), ChartColor.FromHtmlColorCode("#562C05"),
|
||||
ChartColor.FromHtmlColorCode("#DD0907"), ChartColor.FromHtmlColorCode("#F20884"),
|
||||
ChartColor.FromHtmlColorCode("#4700A5"), ChartColor.FromHtmlColorCode("#90713A"),
|
||||
ChartColor.FromHtmlColorCode("#1FB714"), ChartColor.FromHtmlColorCode("#02ABEA"),
|
||||
ChartColor.FromHtmlColorCode("#FBF305")
|
||||
];
|
||||
readonly List<string> _borderColors = [ChartColor.FromHtmlColorCode("#8b0000")];
|
||||
PieChart<long>? _commandsChart;
|
||||
List<long> _commandsCounts = [];
|
||||
string[] _commandsLabels = [];
|
||||
PieChart<long>? _devicesByBusChart;
|
||||
List<long> _devicesByBusCounts = [];
|
||||
string[] _devicesByBusLabels = [];
|
||||
PieChart<long>? _devicesByManufacturerChart;
|
||||
List<long> _devicesByManufacturerCounts = [];
|
||||
string[] _devicesByManufacturerLabels = [];
|
||||
Carousel? _devicesCarousel;
|
||||
PieChart<long>? _filesystemsChart;
|
||||
List<long> _filesystemsCounts = [];
|
||||
string[] _filesystemsLabels = [];
|
||||
PieChart<long>? _filtersChart;
|
||||
List<long> _filtersCounts = [];
|
||||
string[] _filtersLabels = [];
|
||||
PieChart<long>? _formatsChart;
|
||||
List<long> _formatsCounts = [];
|
||||
string[] _formatsLabels = [];
|
||||
PieChart<long>? _linuxChart;
|
||||
List<long> _linuxCounts = [];
|
||||
string[] _linuxLabels = [];
|
||||
PieChart<long>? _macosChart;
|
||||
List<long> _macosCounts = [];
|
||||
string[] _macosLabels = [];
|
||||
Carousel? _operatingSystemsCarousel;
|
||||
PieChart<long>? _operatingSystemsChart;
|
||||
List<long> _operatingSystemsCounts = [];
|
||||
string[] _operatingSystemsLabels = [];
|
||||
PieChart<long>? _partitionsChart;
|
||||
List<long> _partitionsCounts = [];
|
||||
string[] _partitionsLabels = [];
|
||||
PieChart<long>? _realMediaChart;
|
||||
List<long> _realMediaCounts = [];
|
||||
string[] _realMediaLabels = [];
|
||||
PieChart<long>? _versionsChart;
|
||||
List<long> _versionsCounts = [];
|
||||
string[] _versionsLabels = [];
|
||||
PieChart<long>? _virtualMediaChart;
|
||||
List<long> _virtualMediaCounts = [];
|
||||
string[] _virtualMediaLabels = [];
|
||||
PieChart<long>? _windowsChart;
|
||||
List<long> _windowsCounts = [];
|
||||
string[] _windowsLabels = [];
|
||||
List<NameValueStats> OperatingSystems { get; set; } = [];
|
||||
List<NameValueStats> Versions { get; set; } = [];
|
||||
List<Command> Commands { get; set; } = [];
|
||||
List<Filter> Filters { get; set; } = [];
|
||||
List<MediaFormat> MediaImages { get; set; } = [];
|
||||
List<Partition> Partitions { get; set; } = [];
|
||||
List<Filesystem> Filesystems { get; set; } = [];
|
||||
List<MediaItem> RealMedia { get; set; } = [];
|
||||
List<MediaItem> VirtualMedia { get; set; } = [];
|
||||
List<DeviceItem> Devices { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
// TOOD: Cache real OS name in database, lookups would be much faster
|
||||
await using DbContext _ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
OperatingSystems = (await _ctx.OperatingSystems.OrderBy(static os => os.Name)
|
||||
.ThenBy(static os => os.Version)
|
||||
.Select(static nvs => new NameValueStats
|
||||
{
|
||||
name =
|
||||
$"{GetPlatformName(nvs.Name, nvs.Version)}{(string.IsNullOrEmpty(nvs.Version) ? "" : " ")}{nvs.Version}",
|
||||
Value = nvs.Count
|
||||
})
|
||||
.ToListAsync()).OrderBy(static os => os.name)
|
||||
.ToList();
|
||||
|
||||
var osQuery = _ctx.OperatingSystems.GroupBy(static x => new
|
||||
{
|
||||
x.Name
|
||||
},
|
||||
static x => x.Count)
|
||||
.Select(static g => new
|
||||
{
|
||||
g.Key.Name,
|
||||
Count = g.Sum()
|
||||
});
|
||||
|
||||
_operatingSystemsLabels = await osQuery.Select(static x => x.Name).ToArrayAsync();
|
||||
_operatingSystemsCounts = await osQuery.Select(static x => x.Count).ToListAsync();
|
||||
|
||||
for(var i = 0; i < _operatingSystemsLabels.Length; i++)
|
||||
{
|
||||
_operatingSystemsLabels[i] =
|
||||
DetectOS.GetPlatformName((PlatformID)Enum.Parse(typeof(PlatformID), _operatingSystemsLabels[i]));
|
||||
}
|
||||
|
||||
_linuxLabels = await _ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Linux.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x =>
|
||||
$"{DetectOS.GetPlatformName(PlatformID.Linux, x.Version)}{(string.IsNullOrEmpty(x.Version) ? "" : " ")}{x.Version}")
|
||||
.ToArrayAsync();
|
||||
|
||||
_linuxCounts = await _ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Linux.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
|
||||
if(_linuxLabels.Length >= 10)
|
||||
{
|
||||
_linuxLabels[9] = "Other";
|
||||
|
||||
_linuxCounts[9] =
|
||||
_ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Linux.ToString())
|
||||
.Sum(static o => o.Count) -
|
||||
_linuxCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
_macosLabels = await _ctx.OperatingSystems.Where(static o => o.Name == PlatformID.MacOSX.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x =>
|
||||
$"{DetectOS.GetPlatformName(PlatformID.MacOSX, x.Version)}{(string.IsNullOrEmpty(x.Version) ? "" : " ")}{x.Version}")
|
||||
.ToArrayAsync();
|
||||
|
||||
_macosCounts = await _ctx.OperatingSystems.Where(static o => o.Name == PlatformID.MacOSX.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
|
||||
if(_macosLabels.Length >= 10)
|
||||
{
|
||||
_macosLabels[9] = "Other";
|
||||
|
||||
_macosCounts[9] =
|
||||
_ctx.OperatingSystems.Where(static o => o.Name == PlatformID.MacOSX.ToString())
|
||||
.Sum(static o => o.Count) -
|
||||
_macosCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
_windowsLabels = await _ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Win32NT.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x =>
|
||||
$"{DetectOS.GetPlatformName(PlatformID.Win32NT, x.Version)}{(string.IsNullOrEmpty(x.Version) ? "" : " ")}{x.Version}")
|
||||
.ToArrayAsync();
|
||||
|
||||
_windowsCounts = await _ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Win32NT.ToString())
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
|
||||
if(_windowsLabels.Length >= 10)
|
||||
{
|
||||
_windowsLabels[9] = "Other";
|
||||
|
||||
_windowsCounts[9] =
|
||||
_ctx.OperatingSystems.Where(static o => o.Name == PlatformID.Win32NT.ToString())
|
||||
.Sum(static o => o.Count) -
|
||||
_windowsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
Versions = (await _ctx.Versions.Select(static nvs => new NameValueStats
|
||||
{
|
||||
name = nvs.Name == "previous" ? "Previous than 3.4.99.0" : nvs.Name,
|
||||
Value = nvs.Count
|
||||
})
|
||||
.ToListAsync()).OrderBy(static version => version.name)
|
||||
.ToList();
|
||||
|
||||
_versionsLabels = await _ctx.Versions.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name == "previous" ? "Previous than 3.4.99.0" : v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_versionsCounts = await _ctx.Versions.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_versionsLabels.Length >= 10)
|
||||
{
|
||||
_versionsLabels[9] = "Other";
|
||||
|
||||
_versionsCounts[9] = _ctx.Versions.Sum(static o => o.Count) - _versionsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
Commands = await _ctx.Commands.OrderBy(static c => c.Name).ToListAsync();
|
||||
|
||||
_commandsLabels = await _ctx.Commands.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_commandsCounts = await _ctx.Commands.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_commandsLabels.Length >= 10)
|
||||
{
|
||||
_commandsLabels[9] = "Other";
|
||||
|
||||
_commandsCounts[9] = _ctx.Commands.Sum(static o => o.Count) - _commandsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
Filters = await _ctx.Filters.OrderBy(static filter => filter.Name).ToListAsync();
|
||||
|
||||
_filtersLabels = await _ctx.Filters.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_filtersCounts = await _ctx.Filters.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_filtersLabels.Length >= 10)
|
||||
{
|
||||
_filtersLabels[9] = "Other";
|
||||
|
||||
_filtersCounts[9] = _ctx.Filters.Sum(static o => o.Count) - _filtersCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
MediaImages = await _ctx.MediaFormats.OrderBy(static format => format.Name).ToListAsync();
|
||||
|
||||
_formatsLabels = await _ctx.MediaFormats.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_formatsCounts = await _ctx.MediaFormats.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_formatsLabels.Length >= 10)
|
||||
{
|
||||
_formatsLabels[9] = "Other";
|
||||
|
||||
_formatsCounts[9] = _ctx.MediaFormats.Sum(static o => o.Count) - _formatsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
Partitions = await _ctx.Partitions.OrderBy(static partition => partition.Name).ToListAsync();
|
||||
|
||||
_partitionsLabels = await _ctx.Partitions.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_partitionsCounts = await _ctx.Partitions.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_partitionsLabels.Length >= 10)
|
||||
{
|
||||
_partitionsLabels[9] = "Other";
|
||||
|
||||
_partitionsCounts[9] = _ctx.Partitions.Sum(static o => o.Count) - _partitionsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
Filesystems = await _ctx.Filesystems.OrderBy(static filesystem => filesystem.Name).ToListAsync();
|
||||
|
||||
_filesystemsLabels = await _ctx.Filesystems.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static v => v.Name)
|
||||
.ToArrayAsync();
|
||||
|
||||
_filesystemsCounts = await _ctx.Filesystems.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.Select(static x => x.Count)
|
||||
.ToListAsync();
|
||||
|
||||
if(_filesystemsLabels.Length >= 10)
|
||||
{
|
||||
_filesystemsLabels[9] = "Other";
|
||||
|
||||
_filesystemsCounts[9] = _ctx.Filesystems.Sum(static o => o.Count) - _filesystemsCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
RealMedia = [];
|
||||
VirtualMedia = [];
|
||||
|
||||
await foreach(Media nvs in _ctx.Medias.AsAsyncEnumerable())
|
||||
{
|
||||
try
|
||||
{
|
||||
(string type, string subType) mediaType =
|
||||
MediaType.MediaTypeToString((CommonTypes.MediaType)Enum.Parse(typeof(CommonTypes.MediaType),
|
||||
nvs.Type));
|
||||
|
||||
if(nvs.Real)
|
||||
{
|
||||
RealMedia.Add(new MediaItem
|
||||
{
|
||||
Type = mediaType.type,
|
||||
SubType = mediaType.subType,
|
||||
Count = nvs.Count
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
VirtualMedia.Add(new MediaItem
|
||||
{
|
||||
Type = mediaType.type,
|
||||
SubType = mediaType.subType,
|
||||
Count = nvs.Count
|
||||
});
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if(nvs.Real)
|
||||
{
|
||||
RealMedia.Add(new MediaItem
|
||||
{
|
||||
Type = nvs.Type,
|
||||
SubType = null,
|
||||
Count = nvs.Count
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
VirtualMedia.Add(new MediaItem
|
||||
{
|
||||
Type = nvs.Type,
|
||||
SubType = null,
|
||||
Count = nvs.Count
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RealMedia = RealMedia.OrderBy(static media => media.Type).ThenBy(static media => media.SubType).ToList();
|
||||
VirtualMedia = VirtualMedia.OrderBy(static media => media.Type).ThenBy(static media => media.SubType).ToList();
|
||||
|
||||
Media[] virtualMedias = await _ctx.Medias.Where(static o => !o.Real)
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.ToArrayAsync();
|
||||
|
||||
foreach(Media media in virtualMedias)
|
||||
{
|
||||
try
|
||||
{
|
||||
(string type, string subType) mediaType =
|
||||
MediaType.MediaTypeToString((CommonTypes.MediaType)Enum.Parse(typeof(CommonTypes.MediaType),
|
||||
media.Type));
|
||||
|
||||
media.Type = $"{mediaType.type} ({mediaType.subType})";
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Could not get media type/subtype pair from type, so just leave it as is
|
||||
}
|
||||
}
|
||||
|
||||
_virtualMediaLabels = virtualMedias.Select(static v => v.Type).ToArray();
|
||||
_virtualMediaCounts = virtualMedias.Select(static x => x.Count).ToList();
|
||||
|
||||
if(_virtualMediaLabels.Length >= 10)
|
||||
{
|
||||
_virtualMediaLabels[9] = "Other";
|
||||
|
||||
_virtualMediaCounts[9] = _ctx.Medias.Where(static o => !o.Real).Sum(static o => o.Count) -
|
||||
_virtualMediaCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
Media[] realMedias = await _ctx.Medias.Where(static o => o.Real)
|
||||
.OrderByDescending(static o => o.Count)
|
||||
.Take(10)
|
||||
.ToArrayAsync();
|
||||
|
||||
foreach(Media media in realMedias)
|
||||
{
|
||||
try
|
||||
{
|
||||
(string type, string subType) mediaType =
|
||||
MediaType.MediaTypeToString((CommonTypes.MediaType)Enum.Parse(typeof(CommonTypes.MediaType),
|
||||
media.Type));
|
||||
|
||||
media.Type = $"{mediaType.type} ({mediaType.subType})";
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Could not get media type/subtype pair from type, so just leave it as is
|
||||
}
|
||||
}
|
||||
|
||||
_realMediaLabels = realMedias.Select(static v => v.Type).ToArray();
|
||||
_realMediaCounts = realMedias.Select(static x => x.Count).ToList();
|
||||
|
||||
if(_realMediaLabels.Length >= 10)
|
||||
{
|
||||
_realMediaLabels[9] = "Other";
|
||||
|
||||
_realMediaCounts[9] = _ctx.Medias.Where(static o => o.Real).Sum(static o => o.Count) -
|
||||
_realMediaCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
Devices = await _ctx.DeviceStats.Include(static deviceStat => deviceStat.Report)
|
||||
.Select(static device => new DeviceItem
|
||||
{
|
||||
Manufacturer = device.Manufacturer,
|
||||
Model = device.Model,
|
||||
Revision = device.Revision,
|
||||
Bus = device.Bus,
|
||||
ReportId = device.Report != null && device.Report.Id != 0 ? device.Report.Id : 0
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
Devices = Devices.OrderBy(static device => device.Manufacturer)
|
||||
.ThenBy(static device => device.Model)
|
||||
.ThenBy(static device => device.Revision)
|
||||
.ThenBy(static device => device.Bus)
|
||||
.ToList();
|
||||
|
||||
var data = await _ctx.DeviceStats.Select(static d => d.Bus)
|
||||
.Distinct()
|
||||
.Select(deviceBus => new
|
||||
{
|
||||
deviceBus,
|
||||
deviceBusCount = _ctx.DeviceStats.LongCount(d => d.Bus == deviceBus)
|
||||
})
|
||||
.Select(static t => new
|
||||
{
|
||||
Name = t.deviceBus,
|
||||
Count = t.deviceBusCount
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
_devicesByBusLabels = data.OrderByDescending(static o => o.Count).Take(10).Select(static v => v.Name).ToArray();
|
||||
_devicesByBusCounts = data.OrderByDescending(static o => o.Count).Take(10).Select(static x => x.Count).ToList();
|
||||
|
||||
if(_devicesByBusLabels.Length >= 10)
|
||||
{
|
||||
_devicesByBusLabels[9] = "Other";
|
||||
|
||||
_devicesByBusCounts[9] = data.Sum(static o => o.Count) - _devicesByBusCounts.Take(9).Sum();
|
||||
}
|
||||
|
||||
List<DeviceStat> devices = await _ctx.DeviceStats
|
||||
.Where(static d => d.Manufacturer != null && d.Manufacturer != "")
|
||||
.ToListAsync();
|
||||
|
||||
data = devices.Select(static d => d.Manufacturer!.ToLowerInvariant())
|
||||
.Distinct()
|
||||
.Select(manufacturer => new
|
||||
{
|
||||
manufacturer,
|
||||
manufacturerCount =
|
||||
devices.LongCount(d => d.Manufacturer?.ToLowerInvariant() == manufacturer)
|
||||
})
|
||||
.Select(static t => new
|
||||
{
|
||||
Name = t.manufacturer,
|
||||
Count = t.manufacturerCount
|
||||
})
|
||||
.ToList();
|
||||
|
||||
_devicesByManufacturerLabels =
|
||||
data.OrderByDescending(static o => o.Count).Take(10).Select(static v => v.Name).ToArray();
|
||||
|
||||
_devicesByManufacturerCounts =
|
||||
data.OrderByDescending(static o => o.Count).Take(10).Select(static x => x.Count).ToList();
|
||||
|
||||
if(_devicesByManufacturerLabels.Length < 10) return;
|
||||
|
||||
_devicesByManufacturerLabels[9] = "Other";
|
||||
_devicesByManufacturerCounts[9] = data.Sum(static o => o.Count) - _devicesByManufacturerCounts.Take(9).Sum();
|
||||
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
|
||||
await
|
||||
Task.WhenAll(HandleRedraw(_operatingSystemsChart, _operatingSystemsLabels, GetOperatingSystemsChartDataset),
|
||||
HandleRedraw(_linuxChart, _linuxLabels, GetLinuxChartDataset),
|
||||
HandleRedraw(_macosChart, _macosLabels, GetMacosChartDataset),
|
||||
HandleRedraw(_windowsChart, _windowsLabels, GetWindowsChartDataset),
|
||||
HandleRedraw(_versionsChart, _versionsLabels, GetVersionsChartDataset),
|
||||
HandleRedraw(_commandsChart, _commandsLabels, GetCommandsChartDataset),
|
||||
HandleRedraw(_filtersChart, _filtersLabels, GetFiltersChartDataset),
|
||||
HandleRedraw(_formatsChart, _formatsLabels, GetFormatsChartDataset),
|
||||
HandleRedraw(_partitionsChart, _partitionsLabels, GetPartitionsChartDataset),
|
||||
HandleRedraw(_filesystemsChart, _filesystemsLabels, GetFilesystemsChartDataset),
|
||||
HandleRedraw(_virtualMediaChart, _virtualMediaLabels, GetVirtualMediaChartDataset),
|
||||
HandleRedraw(_realMediaChart, _realMediaLabels, GetRealMediaChartDataset),
|
||||
HandleRedraw(_devicesByBusChart, _devicesByBusLabels, GetDevicesByBusChartDataset),
|
||||
HandleRedraw(_devicesByManufacturerChart,
|
||||
_devicesByManufacturerLabels,
|
||||
GetDevicesByManufacturerChartDataset));
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
|
||||
// Upstream: https://github.com/Megabit/Blazorise/issues/5491
|
||||
_operatingSystemsCarousel.Interval = 5000;
|
||||
_devicesCarousel.Interval = 5000;
|
||||
}
|
||||
|
||||
static async Task HandleRedraw<TDataSet, TItem, TOptions, TModel>(
|
||||
BaseChart<TDataSet, TItem, TOptions, TModel> chart, string[] labels, Func<TDataSet> getDataSet)
|
||||
where TDataSet : ChartDataset<TItem> where TOptions : ChartOptions where TModel : ChartModel
|
||||
{
|
||||
await chart.Clear();
|
||||
|
||||
await chart.AddLabelsDatasetsAndUpdate(labels, getDataSet());
|
||||
}
|
||||
|
||||
PieChartDataset<long> GetOperatingSystemsChartDataset() => new()
|
||||
{
|
||||
Label = "Operating systems",
|
||||
Data = _operatingSystemsCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetLinuxChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_linuxLabels.Length} Linux versions",
|
||||
Data = _linuxCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetMacosChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_macosLabels.Length} macOS versions",
|
||||
Data = _macosCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetWindowsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_windowsLabels.Length} Windows versions",
|
||||
Data = _windowsCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetVersionsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_versionsLabels.Length} Aaru versions",
|
||||
Data = _versionsCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetCommandsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_commandsLabels.Length} used commands",
|
||||
Data = _commandsCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetFiltersChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_filtersLabels.Length} filters found",
|
||||
Data = _filtersCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetFormatsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_formatsLabels.Length} media image formats found",
|
||||
Data = _formatsCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetPartitionsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_partitionsLabels.Length} partitioning schemes found",
|
||||
Data = _partitionsCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetFilesystemsChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_filesystemsLabels.Length} filesystems found",
|
||||
Data = _filesystemsCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetVirtualMediaChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_virtualMediaLabels.Length} media types found in images",
|
||||
Data = _virtualMediaCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetRealMediaChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_realMediaLabels.Length} media types found in devices",
|
||||
Data = _realMediaCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetDevicesByBusChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_devicesByBusLabels.Length} devices by bus",
|
||||
Data = _devicesByBusCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
PieChartDataset<long> GetDevicesByManufacturerChartDataset() => new()
|
||||
{
|
||||
Label = $"Top {_devicesByManufacturerLabels.Length} devices by manufacturers",
|
||||
Data = _devicesByManufacturerCounts,
|
||||
BackgroundColor = _backgroundColors,
|
||||
BorderColor = _borderColors,
|
||||
BorderWidth = 1
|
||||
};
|
||||
|
||||
static string GetPlatformName(string name, string version) =>
|
||||
DetectOS.GetPlatformName((PlatformID)Enum.Parse(typeof(PlatformID), name), version);
|
||||
}
|
||||
Reference in New Issue
Block a user