228 lines
7.2 KiB
C#
228 lines
7.2 KiB
C#
using EgwCoreLib.Lux.Core.Stats;
|
|
|
|
namespace Lux.UI.Components.Compo.Stats
|
|
{
|
|
public partial class RealTimeStats : IDisposable
|
|
{
|
|
#region Public Methods
|
|
|
|
public void Dispose()
|
|
{
|
|
_cts?.Cancel();
|
|
_cts?.Dispose();
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Methods
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
if (firstRender)
|
|
{
|
|
_cts = new CancellationTokenSource();
|
|
_ = UpdateLoop(_cts.Token);
|
|
}
|
|
}
|
|
|
|
protected override Task OnInitializedAsync()
|
|
{
|
|
return ReloadStatsRT();
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
private CancellationTokenSource? _cts;
|
|
|
|
private Dictionary<string, string> BorderColors = new Dictionary<string, string>();
|
|
|
|
private Dictionary<string, double> DataseElapsed = new Dictionary<string, double>();
|
|
|
|
private Dictionary<string, double> DatasetCount = new Dictionary<string, double>();
|
|
|
|
private Dictionary<string, List<decimal>> DSBarCount = new Dictionary<string, List<decimal>>();
|
|
|
|
private Dictionary<string, List<decimal>> DSBarElapsed = new Dictionary<string, List<decimal>>();
|
|
|
|
private Dictionary<string, string> FillColors = new Dictionary<string, string>();
|
|
|
|
private DateTime lastUpdate = DateTime.Now;
|
|
|
|
private List<string> ListX = new List<string>();
|
|
|
|
private int numDay = 3;
|
|
|
|
private int refrPeriod = 5;
|
|
|
|
private List<RealtimeProcDto> rtProcStats = new List<RealtimeProcDto>();
|
|
|
|
private Enums.RuidGroupMode SelGroup = Enums.RuidGroupMode.Hour;
|
|
|
|
private Enums.RuidTagMode SelMode = Enums.RuidTagMode.Envir;
|
|
|
|
private StatsRealtimeDto? stats;
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Properties
|
|
|
|
[Inject]
|
|
private ICalcRuidService Calc { get; set; } = null!;
|
|
|
|
[Inject]
|
|
private IJSRuntime JSRuntime { get; set; } = null!;
|
|
|
|
private int NumDays
|
|
{
|
|
get => numDay;
|
|
set
|
|
{
|
|
if (numDay != value)
|
|
{
|
|
numDay = value > 1 ? value : 1;
|
|
_ = ReloadStatsRT();
|
|
}
|
|
}
|
|
}
|
|
|
|
private int RefPeriod
|
|
{
|
|
get => refrPeriod;
|
|
set
|
|
{
|
|
if (refrPeriod != value)
|
|
{
|
|
refrPeriod = value > 1 ? value : 1;
|
|
_ = ReloadStatsRT();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion Private Properties
|
|
|
|
#region Private Methods
|
|
|
|
private async Task OnGroupChanged(Enums.RuidGroupMode value)
|
|
{
|
|
if (SelGroup != value)
|
|
{
|
|
SelGroup = value;
|
|
await ReloadStatsRT();
|
|
}
|
|
}
|
|
|
|
private async Task OnTagChanged(Enums.RuidTagMode value)
|
|
{
|
|
if (SelMode != value)
|
|
{
|
|
SelMode = value;
|
|
await ReloadStatsRT();
|
|
}
|
|
}
|
|
|
|
private async Task ReloadStatsRT()
|
|
{
|
|
rtProcStats = await Calc.RealTimeDataStats(SelGroup, SelMode, DateTime.Today.AddDays(-numDay));
|
|
|
|
// calcolo i valori da mostrare...
|
|
if (rtProcStats != null && rtProcStats.Count > 0)
|
|
{
|
|
// Estrazione dei tag unici dalla lista dei dati
|
|
var uniqueTags = rtProcStats
|
|
.Select(x => x.TagClass)
|
|
.Distinct()
|
|
.OrderBy(x => x)
|
|
.ToList();
|
|
|
|
// Generazione Palette (ritorna hsla con alpha 0.6)
|
|
var palette = ColorHelper.GeneratePalette(uniqueTags.Count, 0.6);
|
|
|
|
for (int i = 0; i < uniqueTags.Count; i++)
|
|
{
|
|
string tag = uniqueTags[i];
|
|
string bgColor = palette[i]; // hsla(..., 0.6)
|
|
|
|
// Questo ora funziona anche su HSL!
|
|
string borderColor = ColorHelper.ToOpaque(bgColor); // hsla(..., 1.0)
|
|
|
|
FillColors[tag] = bgColor;
|
|
BorderColors[tag] = borderColor;
|
|
}
|
|
|
|
// generazione dei restanti dataset
|
|
DatasetCount = rtProcStats
|
|
.GroupBy(p => p.TagClass)
|
|
.ToDictionary(
|
|
g => g.Key,
|
|
g => (double)g.Sum(p => p.EventCount)
|
|
);
|
|
|
|
DataseElapsed = rtProcStats
|
|
.GroupBy(p => p.TagClass)
|
|
.ToDictionary(
|
|
g => g.Key,
|
|
g => g.Sum(p => p.Elapsed)
|
|
);
|
|
|
|
// 1. Definiamo le etichette dell'asse X (es. le ultime 24 ore o quelle presenti nei dati)
|
|
ListX = rtProcStats
|
|
.Select(p => p.Hour.ToString("yyyy-MM-dd HH:mm"))
|
|
.Distinct()
|
|
.OrderBy(t => t)
|
|
.ToList();
|
|
|
|
// 2. Identifichiamo tutti i TagClass unici (saranno i nostri dataset)
|
|
var allTags = rtProcStats.Select(p => p.TagClass).Distinct().ToList();
|
|
|
|
// 3. Costruiamo il DSBarCount: per ogni Tag, creiamo una lista di valori allineata a ListX
|
|
DSBarCount = allTags.ToDictionary(
|
|
tag => tag,
|
|
tag => ListX.Select(hour =>
|
|
{
|
|
// Cerchiamo il valore per quel tag in quell'ora specifica
|
|
return (decimal)(rtProcStats
|
|
.FirstOrDefault(p => p.TagClass == tag && p.Hour.ToString("yyyy-MM-dd HH:mm") == hour)
|
|
?.EventCount ?? 0); // Se non esiste, mettiamo 0
|
|
}).ToList()
|
|
);
|
|
|
|
// 4. Costruiamo il DSBarElapsed: per ogni Tag, creiamo una lista di valori allineata a ListX
|
|
DSBarElapsed = allTags.ToDictionary(
|
|
tag => tag,
|
|
tag => ListX.Select(hour =>
|
|
{
|
|
// Cerchiamo il valore per quel tag in quell'ora specifica
|
|
return (decimal)(rtProcStats
|
|
.FirstOrDefault(p => p.TagClass == tag && p.Hour.ToString("yyyy-MM-dd HH:mm") == hour)
|
|
?.Elapsed ?? 0); // Se non esiste, mettiamo 0
|
|
}).ToList()
|
|
);
|
|
|
|
lastUpdate = DateTime.Now;
|
|
// forzatura update
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
}
|
|
|
|
private async Task UpdateLoop(CancellationToken token)
|
|
{
|
|
try
|
|
{
|
|
while (!token.IsCancellationRequested)
|
|
{
|
|
await ReloadStatsRT();
|
|
// attesa RefPeriod secondi, rispettando il token
|
|
await Task.Delay(TimeSpan.FromSeconds(RefPeriod), token);
|
|
}
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
// loop fermato
|
|
}
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |