using Microsoft.AspNetCore.Components; using MongoDB.Driver.Linq; using MP.Data; using MP.Data.DbModels; using MP.Data.Services; using MP.Stats.Data; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading.Tasks; namespace MP.Stats.Components { public partial class ChartTrends { #region Public Properties [Parameter] public List CodFluxList { get; set; } [Parameter] public EventCallback EC_CodFluxSel { get; set; } [Parameter] public EventCallback EC_IdxMaccRem { get; set; } [Parameter] public bool ShowRem { get; set; } = false; [Parameter] public List RawData { get => _rawData; set { // salvo valori _rawData = value; if (value != null) { // ricalcolo charting data RecalcData(); } } } #endregion Public Properties private async Task RemoveMachine(string idxMacc) { await EC_IdxMaccRem.InvokeAsync(idxMacc); } #region Protected Enums protected enum PeriodoSel { Day, Week, Month, Year } #endregion Protected Enums #region Protected Properties protected List _rawData { get; set; } = new List(); /// /// Genera colori sfondo 33% rosso / arancione / giallo /// /// protected List bgColors { get => semaphColors(ParetoData.Count, "0.3"); } protected List bgColorsDet { get; set; } = new List(); protected string CodFluxSel { get => codFluxSel; set { if (codFluxSel != value) { codFluxSel = value; EC_CodFluxSel.InvokeAsync(value).ConfigureAwait(false); } } } /// /// Genera colori sfondo 33% rosso / arancione / giallo /// /// protected List lineColor { get => solidColors("0.9"); } /// /// Genera colori sfondo 33% rosso / arancione / giallo /// /// protected List lineColors { get => semaphColors(ParetoData.Count, "1"); } protected List lineColorsDet { get; set; } = new List(); [Inject] protected Data.MessageService MService { get; set; } [Inject] protected MpStatsService StatService { get; set; } [Inject] protected TranslateSrv TradService { get; set; } #endregion Protected Properties #region Protected Methods /// /// Genera colori sfondo alternat full / quasi grigi (x preious data) /// /// numero record CURRENT /// /// protected List cpColors(int numRecords, string alpha) { List answ = new List(); int r = 0; int g = 0; int b = 0; // ciclo x numRecords-1 for (int j = 0; j < numRecords; j++) { r = 54 + (180 - 54) * j / numRecords; g = 86 + (35 - 86) * j / numRecords; b = 254 + (180 - 254) * j / numRecords; answ.Add($"rgba({r}, {g}, {b}, {alpha}"); answ.Add($"rgba({(510 + r) / 3},{(510 + g) / 3},{(510 + b) / 3}, {alpha}"); } // chiude while (answ.Count < numRecords) { answ.Add($"rgba(180, 180, 35, {alpha})"); } return answ; } /// /// Genera colori sfondo 33% rosso / arancione / giallo /// /// /// /// protected List semaphColors(int numRecords, string alpha) { List answ = new List(); // ciclo x numRecords-1 for (int j = 0; j < numRecords; j++) { answ.Add($"rgba({54 + (180 - 54) * j / numRecords}, {86 + (35 - 86) * j / numRecords}, {254 + (180 - 254) * j / numRecords}, {alpha}"); } // chiude while (answ.Count < numRecords) { answ.Add($"rgba(180, 180, 35, {alpha})"); } return answ; } /// /// Colore azzurro + alpha /// /// /// protected List solidColors(string alpha) { List answ = new List(); answ.Add($"rgba(54, 162, 235, {alpha})"); return answ; } #endregion Protected Methods #region Private Fields private List lineTitles = new List() { "Consumo/UM" }; private List lineTitlesDet = new List() { "Consumo/UM" }; private List listMachine = new List(); #if false private string pieTitle = "Macchina"; #endif /// /// Modalità selezione /// private PeriodoSel pSel; #endregion Private Fields #region Private Properties private string codFluxSel { get; set; } private List DatiPareto { get => ParetoData.Select(x => x.value).ToList(); } private List DatiPlot { get => TSData; } private List LabelPareto { get => ParetoData.Select(x => x.label).ToList(); } private List LabelPlot { get => TSData.Select(r => $"{r.x:yyyy-MM-dd}").ToList(); } private List LabelPlotDet { get; set; } = new List(); private int numMachine { get => listMachine.Count; } private List ParetoData { get; set; } = new List(); private List TSData { get; set; } = new List(); private List> TSDataMulti { get; set; } = new List>(); /// /// TimeSeries su scala DAY /// private List> TSDataMultiDetail { get; set; } = new List>(); #endregion Private Properties #region Private Methods private double cDouble(string origValue) { double dblVal = 0; double.TryParse(origValue, NumberStyles.Any, CultureInfo.InvariantCulture, out dblVal); return dblVal; } private string CssBtn(PeriodoSel reqMode) { string answ = "btn-outline-primary"; if (reqMode == pSel) { answ = "btn-primary text-light"; } return answ; } private DateTime GetFirstDayOfWeek(DateTime date) { int offset = date.DayOfWeek - DayOfWeek.Sunday; return date.AddDays(-offset); } /// /// Ritorna dettaglio dato macchina e tipo (current o prev) /// /// Macchina richiesta /// Flusso richiesto /// Modo recap (se null --> intero periodo) /// Indica se iin caso di recap sia periodo corrente/precedente /// private List GetTSDetail(string idxMacc, string codFlux, PeriodoSel? recapMode, bool isCurrent = true) { List answ = new(); if (!recapMode.HasValue) { answ = RawData .Where(x => x.IdxMacchina == idxMacc) .Select(r => new chartJsData.chartJsTSerie() { x = r.dtEvento, y = cDouble(r.Valore) }) .OrderBy(o => o.x) .ToList(); } else { // fake fix: indietro 7 gg... DateTime dataRif = DateTime.Today;//.AddDays(-7); TimeSpan deltaOld = new TimeSpan(0); DateTime dtStart = dataRif; DateTime inizio = dataRif; DateTime fine = inizio.AddDays(1); double startVal = 0; switch (recapMode) { case PeriodoSel.Day: inizio = isCurrent ? dataRif : dataRif.AddDays(-1); fine = inizio.AddDays(1); deltaOld = TimeSpan.FromDays(1); break; case PeriodoSel.Week: inizio = isCurrent ? GetFirstDayOfWeek(dataRif) : GetFirstDayOfWeek(dataRif).AddDays(-7); fine = inizio.AddDays(7); deltaOld = TimeSpan.FromDays(7); break; case PeriodoSel.Month: inizio = isCurrent ? new DateTime(dataRif.Year, dataRif.Month, 1) : new DateTime(dataRif.Year, dataRif.Month, 1).AddMonths(-1); fine = inizio.AddMonths(1); deltaOld = inizio.AddMonths(1).Subtract(inizio); break; case PeriodoSel.Year: inizio = isCurrent ? new DateTime(dataRif.Year, 1, 1) : new DateTime(dataRif.Year, 1, 1).AddYears(-1); fine = inizio.AddYears(1); deltaOld = inizio.AddYears(1).Subtract(inizio); break; case null: default: break; } // calcolo il minimo... var listRaw = RawData .Where(x => x.IdxMacchina == idxMacc && x.dtEvento >= inizio && x.dtEvento < fine) .OrderBy(o => o.dtEvento) .ToList(); var firstRec = listRaw .FirstOrDefault(); if (firstRec != null) { startVal = cDouble(firstRec.Valore); dtStart = firstRec.dtEvento.Date; } answ = listRaw .Select(r => new chartJsData.chartJsTSerie() { x = isCurrent ? r.dtEvento : r.dtEvento.Add(deltaOld), y = cDouble(r.Valore) - startVal }) .OrderBy(o => o.x) .ToList(); } return answ; } private void RecalcData() { if (RawData != null) { // reset preliminare TSDataMulti.Clear(); TSDataMultiDetail.Clear(); lineTitles.Clear(); lineTitlesDet.Clear(); LabelPlotDet.Clear(); bgColorsDet.Clear(); lineColorsDet.Clear(); // calcolo i dati Pareto ParetoData = RawData //.GroupBy(p => new { p.IdxMacchina }) .GroupBy(p => new { p.IdxMacchina, p.CodFlux }) //.Select(y => new ChartKV() { label = y.First().IdxMacchina, value = y.Count() }) .Select(y => new ChartKV() { label = $"{y.First().IdxMacchina} {TradService.Traduci($"MP-STATS_{y.First().CodFlux}")}", value = y.Count() }) .OrderByDescending(x => x.value) .ToList(); // ciclo x ogni macchina listMachine = RawData .GroupBy(x => x.IdxMacchina) .Select(y => y.First().IdxMacchina) .ToList(); foreach (var idxMacc in listMachine) { lineTitles.Add($"{idxMacc} | {TradService.Traduci("MP-STATS_TotEn01")}"); lineTitlesDet.Add($"{idxMacc} | {TradService.Traduci("MP-STATS_TotEn01")} - CURR"); lineTitlesDet.Add($"{idxMacc} | {TradService.Traduci("MP-STATS_TotEn01")} - PREV"); // periodo completo TSDataMulti.Add(GetTSDetail(idxMacc, "", null)); // dettaglio richiesto... var currPlot = GetTSDetail(idxMacc, "", pSel, true); TSDataMultiDetail.Add(currPlot); TSDataMultiDetail.Add(GetTSDetail(idxMacc, "", pSel, false)); #if false if (LabelPlotDet.Count == 0) { switch (pSel) { //case PeriodoSel.Day: // LabelPlotDet = currPlot.Select(r => $"{r.x:HH}").ToList(); // break; //case PeriodoSel.Week: // LabelPlotDet = currPlot.Select(r => $"{r.x:dd}").ToList(); // break; //case PeriodoSel.Month: // LabelPlotDet = currPlot.Select(r => $"{r.x:dd}").ToList(); // break; //case PeriodoSel.Year: // LabelPlotDet = currPlot.Select(r => $"{r.x:MM-dd}").ToList(); // break; //default: // LabelPlotDet = currPlot.Select(r => $"{r.x:yyyy-MM-dd}").ToList(); // break; } } #endif } bgColorsDet = cpColors(ParetoData.Count, "0.3"); lineColorsDet = cpColors(ParetoData.Count, "1"); } } private void SetModo(PeriodoSel newModo) { pSel = newModo; // ricalcolo! RecalcData(); } #endregion Private Methods } }