using SteamWare; using System; using System.Web.UI; using System.Web.UI.DataVisualization.Charting; using System.Web.UI.WebControls; namespace MoonPro.WebUserControls { public partial class mod_sequencerTempiCiclo : System.Web.UI.UserControl { #region proprietà protected int _timeSplits = 10; protected double _minVal = 0.5; /// /// totale in minuti da plottare /// protected double totale = 1; /// /// valore minimo da plottare /// public double min2plot { get; set; } /// /// titolo del grafico /// public string titolo { get; set; } /// /// larghezza totale del grafico /// public int larghezza { get; set; } /// /// numero dei segmenti del grafico /// public int numSplit { get; set; } /// /// % minuma nel periodo per dire che sia verde /// public double minVal { get; set; } /// /// definisce se plottare "reversed" (ovvero i valori "minimi" sono con barre + alte dei massimi, come se vosse apssare da tempo a velocità...) /// public bool plotReversed { get; set; } /// /// altezza max grafico /// public int graphHeight { get; set; } #endregion /// /// caricamento pagina /// /// /// protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { // setup valori min2plot = 0.0; titolo = "TempiCiclo"; doUpdate(); } } /// /// disegna la tabella /// protected void plottaGrafico() { // a seconda del numero di eventi da plottare decido la procedura... DataLayer_generic.serieTimeValDataTable dati = _grafico.serieDati; try { // è la somma dei minuti totali dall'inizio alla fine... totale = ((TimeSpan)_grafico.intervallo.fine.Subtract(_grafico.intervallo.inizio)).TotalMinutes; } catch { } plottaDettaglio(dati); } /// /// popola il sequencer degli stati riportando tutti i singoli valori /// /// /// private void plottaDettaglio(DataLayer_generic.serieTimeValDataTable dati) { // definizioni x chart Chart1.Width = larghezza; Chart1.AntiAliasing = System.Web.UI.DataVisualization.Charting.AntiAliasingStyles.All; Chart1.Height = graphHeight; // definizione intervallo asse Y (che qui è anche asse X... Chart1.ChartAreas["TempiCiclo"].AxisX.Minimum = _grafico.intervallo.inizio.ToOADate(); Chart1.ChartAreas["TempiCiclo"].AxisX.Maximum = _grafico.intervallo.fine.ToOADate(); LabelStyle lbst = new LabelStyle(); lbst.Format = "HH:mm"; Chart1.ChartAreas["TempiCiclo"].AxisX.LabelStyle = lbst; // definizioni x chart area tempi ciclo Chart1.ChartAreas["TempiCiclo"].AxisY.Enabled = System.Web.UI.DataVisualization.Charting.AxisEnabled.False; Chart1.ChartAreas["TempiCiclo"].AxisY.IsLogarithmic = false; Chart1.ChartAreas["TempiCiclo"].AxisY.IsReversed = true; string tipo_A = ""; string tipo_B = ""; decimal ratioTC; decimal deltaValori = grafico.maxVal - grafico.minVal; foreach (DataLayer_generic.serieTimeValRow riga in _grafico.serieDati) { ratioTC = riga.valore; // a seconda del tipo aggiungo all'una o all'altra serie... if (grafico.palletChange) { // controllo per inizializzare i 2 tipi... if (tipo_A == "") { tipo_A = riga.tipo; if (Chart1.Series.Count < 1) { Chart1.Series.Add(tipo_A); } } else if (tipo_B == "" && riga.tipo != tipo_A) { tipo_B = riga.tipo; if (Chart1.Series.Count < 2) { // provo ad aggiungere nuova... try { Chart1.Series.Add(tipo_B); } // ... sennò aggiungo vecchia serie catch { Chart1.Series.Add(tipo_A); } } } // definisco colori if (riga.tipo == tipo_A) { try { Chart1.Series[tipo_A].Points.AddXY(riga.DataEnd, ratioTC); } catch { Chart1.Series[0].Points.AddXY(riga.DataEnd, ratioTC); } } else { try { Chart1.Series[tipo_B].Points.AddXY(riga.DataEnd, ratioTC); } catch { Chart1.Series[1].Points.AddXY(riga.DataEnd, ratioTC); } } } else // unica serie { if (tipo_A == "") { tipo_A = riga.tipo; if (Chart1.Series.Count < 1) { Chart1.Series.Add(tipo_A); } } Chart1.Series[tipo_A].Points.AddXY(riga.DataEnd, ratioTC); } } if (Chart1.Series.Count > 0) { // disegno plot nuovo... try { Chart1.Series[tipo_A].XValueType = ChartValueType.DateTime; Chart1.Series[tipo_A].ChartType = SeriesChartType.FastPoint; } catch { Chart1.Series[0].XValueType = ChartValueType.DateTime; Chart1.Series[0].ChartType = SeriesChartType.FastPoint; } if (Chart1.Series.Count > 1) { try { Chart1.Series[tipo_B].XValueType = ChartValueType.DateTime; Chart1.Series[tipo_B].ChartType = SeriesChartType.FastPoint; } catch { Chart1.Series[1].XValueType = ChartValueType.DateTime; Chart1.Series[1].ChartType = SeriesChartType.FastPoint; } } } } /// /// calcola il rapporto tr ail valore e le grandezze reali dato masismo, intervallo, apdding, plot regolare o reversed... /// /// /// /// /// /// protected decimal calcolaRatio(decimal valore, decimal maxVal, decimal deltaValori, bool plotReversed, decimal padding) { decimal answ = 0; if (plotReversed) { answ = (padding + ((1 - 2 * padding) * ((maxVal - valore) / (deltaValori)))); } else { answ = (padding + ((1 - 2 * padding) * ((valore - maxVal) / (deltaValori)))); } return answ; } /// /// intercetta richiesta di zoom e zoomma sul giorno in esame... /// /// /// void lnkb_Click(object sender, EventArgs e) { LinkButton lnk = (LinkButton)sender; // calcolo il giorno... Session["dataZoom"] = lnk.CommandArgument.ToString();//Convert.ToDateTime if (eh_richiestaZoom != null) { eh_richiestaZoom(this, new EventArgs()); } } /// /// popola il sequencer degli stati raggruppando perché troppi valori secondo MEDIA ARMONICA /// /// /// private void plottaGruppiMediaArmonica(DataLayer_generic.serieTimeValDataTable dati) { // creo oggetto x contenere i dati "mediati" DataLayer_generic.serieTimeValDataTable datiGrouped = new DataLayer_generic.serieTimeValDataTable(); // calcolo il val minimo da plottare (come ampiezza) decimal ampiezzaMin = (decimal)totale / numSplit; // setup valori iniziali decimal valoreCurr = (decimal)0.0; decimal valoreMedio = (decimal)1.0; DateTime timeRaggiunto = _grafico.intervallo.inizio; decimal ampiezzaCurr = (decimal)0.0; decimal ampiezzaMedia = (decimal)0.0; string label = ""; // ciclo x tutti i record foreach (DataLayer_generic.serieTimeValRow riga in dati) { // calcolo nuova ampiezza ampiezzaCurr = (decimal)((TimeSpan)riga.DataEnd.Subtract(riga.DataStart)).TotalMinutes; //...e calcolo nuovo valore medio... valoreCurr = riga.valore; // calcolo media armonica valoreMedio = ((ampiezzaCurr + ampiezzaMedia) / (ampiezzaMedia / valoreMedio + ampiezzaCurr / valoreCurr)); ampiezzaMedia = ampiezzaCurr + ampiezzaMedia; // se supero il limite aggiungo in tabella, sennò proseguo... if (ampiezzaMedia > ampiezzaMin) { label = string.Format("TC: {0} min/pz", valoreMedio); datiGrouped.AddserieTimeValRow(timeRaggiunto, riga.DataEnd, valoreMedio, label, "TC"); // resetto timeRaggiunto = riga.DataEnd; ampiezzaMedia = (decimal)0.0; valoreMedio = (decimal)1.0; } } _grafico.palletChange = false; plottaDettaglio(datiGrouped); } /// /// restituisce true se ci sono dati... /// /// protected bool datiPresenti() { bool answ = false; try { int numCelle = grafico.serieDati.Rows.Count; answ = (numCelle > 0); } catch { } return answ; } /// /// oggetto protected /// protected objTempiCiclo _grafico; /// /// elemento grafico da plottare /// public objTempiCiclo grafico { get { return _grafico; } set { _grafico = value; } } /// /// aggiorna il controllo /// public void doUpdate() { if (datiPresenti()) { plottaGrafico(); } else { // non plotto } } /// /// evento di richeista zoom sui dati /// public event EventHandler eh_richiestaZoom; /// /// evento di click x zoom /// /// /// protected void Chart1_Click(object sender, ImageMapEventArgs e) { // alzo evento if (eh_richiestaZoom != null) { eh_richiestaZoom(this, new EventArgs()); } } } }