240 lines
7.6 KiB
C#
240 lines
7.6 KiB
C#
using Microsoft.AspNetCore.Components;
|
|
using MP.Core.DTO;
|
|
using MP.Data;
|
|
using MP.Data.DbModels.Utils;
|
|
using MP.Data.DTO;
|
|
using MP.Data.Services.Utils;
|
|
|
|
namespace MP.IOC.Components.Pages
|
|
{
|
|
public partial class CallStats
|
|
{
|
|
#region Protected Methods
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
await ReloadData();
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
private List<StatDataDTO> currData = new();
|
|
|
|
private string currDetail = "";
|
|
|
|
private string currHistId = "";
|
|
|
|
private string currId = "";
|
|
|
|
private string currPieId = "";
|
|
|
|
private string currTitle = "";
|
|
|
|
private string currTsId = "";
|
|
|
|
private List<string> lineTitles = new List<string>();
|
|
|
|
private int numDays = 5;
|
|
|
|
private Dictionary<string, List<StatDataDTO>> ParetoDay = new();
|
|
|
|
private List<chartJsData.chartJsTSerie> tsData = new List<chartJsData.chartJsTSerie>();
|
|
|
|
private List<ChartSeriesDto> tsDataDetail = new();
|
|
|
|
private List<List<chartJsData.chartJsTSerie>> TSDataMulti = new();
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Properties
|
|
|
|
/// <summary>
|
|
/// Genera colori sfondo 33% rosso / arancione / giallo
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private List<string> bgColors
|
|
{
|
|
get => GetSemaforicColors(currData.Count, "0.3");
|
|
}
|
|
|
|
private List<string> bgColorsMLine
|
|
{
|
|
get => GetDistinctColors(tsDataDetail.Count, "0.3");
|
|
}
|
|
|
|
private List<double> DatiPareto
|
|
{
|
|
get => currData.OrderByDescending(x => x.Value).Take(ParetoTake).Select(x => x.Value).ToList();
|
|
}
|
|
|
|
private List<string> LabelPareto
|
|
{
|
|
get => currData.OrderByDescending(x => x.Value).Take(ParetoTake).Select(x => x.Label).ToList();
|
|
}
|
|
|
|
private List<string> LabelPlot
|
|
{
|
|
get => tsData.Select(r => $"{r.x:yyyy-MM-dd}").ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Genera colori sfondo 33% rosso / arancione / giallo
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private List<string> lineColors
|
|
{
|
|
get => GetSemaforicColors(currData.Count, "1");
|
|
}
|
|
|
|
private List<string> lineColorsMLine
|
|
{
|
|
get => GetDistinctColors(tsDataDetail.Count, "1");
|
|
}
|
|
|
|
private int ParetoTake
|
|
{
|
|
get => currData.Count() <= 25 ? currData.Count() : 25;
|
|
}
|
|
|
|
[Inject]
|
|
private IStatsDetailService SDetService { get; set; } = null!;
|
|
|
|
#endregion Private Properties
|
|
|
|
#region Private Methods
|
|
|
|
private string CheckSelect(string curKey)
|
|
{
|
|
return !string.IsNullOrEmpty(currId) && currId == curKey ? "active" : "";
|
|
}
|
|
|
|
private void DoReset()
|
|
{
|
|
currId = "";
|
|
currHistId = "";
|
|
currPieId = "";
|
|
currTsId = "";
|
|
currData = new();
|
|
}
|
|
|
|
private void DoSelect(string reqKey)
|
|
{
|
|
if (ParetoDay.ContainsKey(reqKey))
|
|
{
|
|
currId = reqKey;
|
|
currHistId = $"Bar_{reqKey}";
|
|
currPieId = $"Pie_{reqKey}";
|
|
currTsId = $"TS_{reqKey}";
|
|
currTitle = $"Pareto | {reqKey}";
|
|
currData = ParetoDay[reqKey];
|
|
tsDataDetail = new();
|
|
}
|
|
}
|
|
|
|
private List<string> GetDistinctColors(int numRecords, string alpha)
|
|
{
|
|
List<string> colors = new List<string>();
|
|
if (numRecords <= 0) return colors;
|
|
|
|
// Partiamo dal Blu (240°) invece che dal Rosso (0°)
|
|
double startHue = 240.0;
|
|
|
|
for (int i = 0; i < numRecords; i++)
|
|
{
|
|
// Distribuiamo la tonalità aggiungendo l'offset iniziale
|
|
// L'operatore % 360 assicura di rimanere nel cerchio se superiamo il rosso
|
|
double hue = (startHue + ((double)i * 360 / numRecords)) % 360;
|
|
|
|
// Strategia di distinzione (attiva sempre, ma più efficace sopra i 5 colori)
|
|
// Alterniamo i valori per i record pari/dispari
|
|
string saturation = "70%";
|
|
string lightness = "50%";
|
|
|
|
if (numRecords > 5)
|
|
{
|
|
// Se i colori sono molti, alterniamo luminosità e saturazione
|
|
// I record dispari saranno più chiari e saturi, i pari più scuri e tenui
|
|
lightness = (i % 2 == 0) ? "45%" : "65%";
|
|
saturation = (i % 2 == 0) ? "80%" : "60%";
|
|
}
|
|
|
|
colors.Add($"hsla({hue:0.##}, {saturation}, {lightness}, {alpha})");
|
|
}
|
|
|
|
return colors;
|
|
}
|
|
|
|
private List<string> GetSemaforicColors(int numRecords, string alpha)
|
|
{
|
|
List<string> colors = new List<string>();
|
|
if (numRecords <= 0) return colors;
|
|
if (numRecords == 1) { colors.Add($"rgba(54, 235, 82, {alpha})"); return colors; }
|
|
|
|
// Definiamo i punti chiave (R, G, B)
|
|
(int r, int g, int b) green = (54, 235, 82);
|
|
(int r, int g, int b) yellow = (255, 206, 86);
|
|
(int r, int g, int b) red = (255, 99, 132);
|
|
|
|
for (int i = 0; i < numRecords; i++)
|
|
{
|
|
// t va da 0.0 (primo record) a 1.0 (ultimo record)
|
|
double t = (double)i / (numRecords - 1);
|
|
int r, g, b;
|
|
|
|
if (t < 0.5)
|
|
{
|
|
// Da Verde a Giallo (mappiamo 0->0.5 su 0->1)
|
|
double localT = t * 2;
|
|
r = (int)(green.r + (yellow.r - green.r) * localT);
|
|
g = (int)(green.g + (yellow.g - green.g) * localT);
|
|
b = (int)(green.b + (yellow.b - green.b) * localT);
|
|
}
|
|
else
|
|
{
|
|
// Da Giallo a Rosso (mappiamo 0.5->1 su 0->1)
|
|
double localT = (t - 0.5) * 2;
|
|
r = (int)(yellow.r + (red.r - yellow.r) * localT);
|
|
g = (int)(yellow.g + (red.g - yellow.g) * localT);
|
|
b = (int)(yellow.b + (red.b - yellow.b) * localT);
|
|
}
|
|
|
|
colors.Add($"rgba({r}, {g}, {b}, {alpha})");
|
|
}
|
|
|
|
return colors;
|
|
}
|
|
|
|
private async Task OnDaysChangedAsync()
|
|
{
|
|
await ShowDetail(currDetail);
|
|
}
|
|
|
|
private async Task ReloadData()
|
|
{
|
|
ParetoDay = await SDetService.GetParetoStatsDayAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// abilita visualizzaione grafico dettagli x metodo indicato
|
|
/// </summary>
|
|
/// <param name="selDetail"></param>
|
|
private async Task ShowDetail(string selDetail)
|
|
{
|
|
currDetail = selDetail;
|
|
// recupero dettaglio 7gg...
|
|
DateTime adesso = DateTime.Now;
|
|
List<StatsDetailModel> rawData = await SDetService.GetFiltAsync(adesso.AddDays(-numDays), adesso, "", selDetail);
|
|
// conversione con grouping
|
|
tsData = rawData.Select(r => new chartJsData.chartJsTSerie() { x = r.Hour, y = (double)r.AvgDuration })
|
|
.OrderBy(o => o.x)
|
|
.ToList();
|
|
tsDataDetail = SDetService.GetTimeSeriesData(rawData);
|
|
lineTitles = tsDataDetail.Select(x => x.SeriesName).ToList();
|
|
TSDataMulti = tsDataDetail.Select(x => x.DataPoints).ToList();
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |