Files
2024-09-03 12:20:53 +02:00

1238 lines
39 KiB
C#

using MapoDb;
using MapoDb.DS_applicazioneTableAdapters;
using Newtonsoft.Json;
using SteamWare;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
/// <summary>
/// Summary description for resoconti
/// </summary>
public enum statoMacchina
{
Run = 1,
Setup,
Guasto,
Campionatura,
Disposizione,
Varie
}
/// <summary>
/// oggetto dati per grafico sequencer
/// </summary>
public struct jsonVisJS
{
#region Public Fields
/// <summary>
/// idx macchina
/// </summary>
public string idxMacchina;
/// <summary>
/// intervallo analisi
/// </summary>
public intervalloDate intervallo;
/// <summary>
/// serie dei dati già elaborati come json stream
/// </summary>
public string jsonDati;
#endregion Public Fields
}
/// <summary>
/// oggetto dati per grafico sequencer
/// </summary>
public struct objSequencer
{
#region Public Fields
/// <summary>
/// Macchina selezionata
/// </summary>
public string idxMacchina;
/// <summary>
/// Intervallo date
/// </summary>
public intervalloDate intervallo;
/// <summary>
/// serie dei dati da plottare
/// </summary>
public DataLayer_generic.serieDatiDataTable serieDati;
#endregion Public Fields
}
/// <summary>
/// oggetto dati per grafico TempiCiclo
/// </summary>
public struct objTempiCiclo
{
#region Public Fields
public intervalloDate intervallo;
public decimal maxVal;
public decimal minVal;
public bool palletChange;
/// <summary>
/// serie dei dati da plottare
/// </summary>
public DataLayer_generic.serieTimeValDataTable serieDati;
public decimal targetVal;
#endregion Public Fields
}
//public struct intervallo
//{
// public DateTime inizio;
// public DateTime fine;
//}
public class resoconti
{
#region Public Fields
/// <summary>
/// singleton accesso resoconti
/// </summary>
public static resoconti mngr = new resoconti();
#endregion Public Fields
#region Public Constructors
public resoconti()
{
AvviaTabAdapt();
setConnString();
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Restituisce colore da IdxStato
/// </summary>
/// <param name="idx"></param>
/// <returns></returns>
public string coloreDaIdx(int idx)
{
string _answ = "";
if (memLayer.ML.CRB("fastColorDecode"))
{
_answ = codColore[idx];
}
else
{
switch (Stati.FindByIdxStato(idx).Semaforo)
{
case "sGi": // giallo
_answ = "#ffec00";
break;
case "sRo": // rosso
_answ = "#e2001a";
break;
case "sGr": // grigio - spenta
_answ = "#bcbcbc";
break;
case "sVe": // verde
_answ = "#009036";
break;
case "sBl": // blu
_answ = "#3690FF";
break;
default:
break;
}
}
return _answ;
}
/// <summary>
/// Recupera commessa attiva al momento indicato
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="inizio"></param>
/// <param name="fine"></param>
/// <param name="dataRif"></param>
/// <returns></returns>
public string commessaAttiva(string idxMacchina, DateTime inizio, DateTime fine, DateTime dataRif)
{
string answ = "NA";
var tabOdl = OdlPeriodo(idxMacchina, inizio, fine);
if (tabOdl != null)
{
var currRow = tabOdl
.Where(x => x.DataInizio <= dataRif && (x.DataFine >= dataRif || x.DataFine == null))
.FirstOrDefault();
// 2023.05.17: se NON trovasse "sposto avanti" un sec...
if (currRow == null)
{
dataRif = dataRif.AddSeconds(1);
currRow = tabOdl
.Where(x => x.DataInizio <= dataRif && (x.DataFine >= dataRif || x.DataFine == null))
.FirstOrDefault();
}
if (currRow != null)
{
answ = currRow.KeyRichiesta;
}
}
return answ;
}
/// <summary>
/// oggetto GRUPPI x sequencer formato VisJS
/// </summary>
/// <param name="idxMacchina">IdxMacchina</param>
/// <returns></returns>
public List<visjsDsGroups> groupsVisJS(string idxMacchina)
{
List<visjsDsGroups> sequenza = new List<visjsDsGroups>();
// se idxMacchina = 0 --> ciclo su tutte con 1 / numMacch eventi ciascuna...
if (idxMacchina != "0")
{
sequenza.Add(new visjsDsGroups
{
id = idxMacchina,
content = idxMacchina,
className = ""
});
}
else
{
// ciclo su tutte le macchine
DataLayer DataLayerObj = new DataLayer();
var elMacchine = DataLayerObj.taSelMacc.getAttive();
foreach (var item in elMacchine)
{
sequenza.Add(new visjsDsGroups
{
id = item.value,
content = item.label,
className = ""
});
}
}
return sequenza;
}
public string idxDaLocazione(string locazione)
{
string answ = "";
DS_applicazione.MacchineRow riga = null;
try
{
riga = (DS_applicazione.MacchineRow)Macchine.Select(string.Format("locazione = '{0}'", locazione))[0];
answ = riga.IdxMacchina;
}
catch
{
}
return answ;
}
public string locazioneDaIdx(string idx)
{
string answ = "";
try
{
DS_applicazione.MacchineRow riga = Macchine.FindByIdxMacchina(idx);
if (riga != null)
{
answ = riga.locazione;
}
}
catch
{ }
return answ;
}
public string macchinaDaIdx(string idx)
{
string answ = "";
try
{
DS_applicazione.MacchineRow riga = Macchine.FindByIdxMacchina(idx);
answ = riga.CodMacchina;
}
catch
{ }
return answ;
}
public string nomeMacchina(string idx)
{
string answ = "";
DS_applicazione.MacchineRow riga = Macchine.FindByIdxMacchina(idx);
try
{
answ = string.Format("{0} ({1} - {2})", riga.Nome, riga.CodMacchina, riga.Descrizione);
}
catch
{ }
return answ;
}
/// <summary>
/// fornisce cod operatore data matricola
/// </summary>
/// <param name="matr"></param>
/// <returns></returns>
public string oprDaMatr(int matr)
{
string answ = "nd";
try
{
DS_applicazione.AnagraficaOperatoriRow riga = AnagOpr.FindByMatrOpr(matr);
answ = $"{riga.Cognome} {riga.Nome}";
}
catch
{ }
return answ;
}
/// <summary>
/// restituisce cod semaforo dato IdxStato
/// </summary>
/// <param name="idx"></param>
/// <returns></returns>
public string semaforoDaIdxStato(int idx)
{
string _answ = "";
// cerco in LUT...
if (SemapLUT.ContainsKey(idx))
{
_answ = SemapLUT[idx];
}
else
{
if (memLayer.ML.CRB("fastColorDecode"))
{
_answ = codSemaforo[idx];
}
else
{
_answ = Stati.FindByIdxStato(idx).Semaforo;
}
SemapLUT.Add(idx, _answ);
}
return _answ;
}
/// <summary>
/// oggetto sequenza dati x sequencer
/// </summary>
/// <param name="idxMacchina">IdxMacchina</param>
/// <param name="_intervallo"></param>
/// <returns></returns>
public objSequencer sequenzaDati(string idxMacchina, intervalloDate _intervallo)
{
DateTime start = DateTime.Now;
// leggo i dati e costituisco una collezione...
objSequencer _sequenza = new objSequencer();
if (idxMacchina != null && idxMacchina != "")
{
// verifico se ho i dati in cache REDIS...
double numGG = _intervallo.fine.Subtract(_intervallo.inizio).TotalDays;
logger.lg.scriviLog(string.Format("Richiesta dati legacySeq idxMacc {0} per {1} gg", idxMacchina, numGG));
string rKey = DataLayer.mHash(string.Format("legacySeq:spl_{0}:mac_{1}_{2}_{3}", 0, idxMacchina, _intervallo.inizio.ToString("yyyyMMdd_HHmmss"), _intervallo.fine.ToString("yyyyMMdd_HHmmss")).Replace(" ", "_"));
bool needRecalc = true;
string redJson = memLayer.ML.getRSV(rKey);
// controllo se ho già in sessione un oggetto seq...
if (redJson != null && redJson != "")
{
try
{
needRecalc = false;
// deserializzo
_sequenza = JsonConvert.DeserializeObject<objSequencer>(redJson);
logger.lg.scriviLog("Recuperato legacySeq " + idxMacchina + " " + rKey);
}
catch
{ }
}
if (needRecalc)
{
logger.lg.scriviLog(string.Format("INIZIO calcolo dati per {0} {1}", idxMacchina, rKey));
// altrimenti procedo come al solito...
_sequenza.idxMacchina = idxMacchina;
_sequenza.serieDati = new DataLayer_generic.serieDatiDataTable();
// seleziono i dati...
DS_applicazione.DiarioDiBordoDataTable tabSeq = taDiarioDiBordo.GetSequenza(idxMacchina, _intervallo.inizio, _intervallo.fine);
logger.lg.scriviLog(string.Format("Recuperate per {0} {1} righe da DB", idxMacchina, tabSeq.Count));
// processo
foreach (DS_applicazione.DiarioDiBordoRow riga in tabSeq.Rows)
{
_sequenza.serieDati.AddserieDatiRow(riga.DurataMinuti, semaforoDaIdxStato(riga.IdxStato), riga.CodArticolo, riga.InizioStato);
}
// SE HO ALMENO un evento
if (tabSeq.Count > 0)
{
// faccio trim x primo evento...
if (_sequenza.serieDati[0].timeData < _intervallo.inizio)
{
_sequenza.serieDati[0].valore -= _intervallo.inizio.Subtract(_sequenza.serieDati[0].timeData).TotalMinutes;
_sequenza.serieDati[0].timeData = _intervallo.inizio;
}
//...e ultimo evento...
int numValori = _sequenza.serieDati.Count - 1;
_sequenza.serieDati[numValori].valore = _intervallo.fine.Subtract(_sequenza.serieDati[numValori].timeData).TotalMinutes;
}
// salvo intervallo
_sequenza.intervallo = _intervallo;
logger.lg.scriviLog(string.Format("FINE calcolo dati per {0} {1}", idxMacchina, rKey));
// salvo sequenza in REDIS...
string rData = JsonConvert.SerializeObject(_sequenza);
// salvo in sessione l'oggetto... secondo durata impostata in web.config..
// moltiplicata x numero gg...
memLayer.ML.setRSV(rKey, rData, 60 * memLayer.ML.CRI("seqCacheDurMin") * (int)numGG);
logger.lg.scriviLog(string.Format("Salvato legacySeq in REDIS {0} {1}", idxMacchina, rKey));
}
}
return _sequenza;
}
/// <summary>
/// oggetto sequenza dati x sequencer formato VisJS
/// </summary>
/// <param name="idxMacchina">IdxMacchina</param>
/// <param name="_intervallo"></param>
/// <param name="numSplit">num massimo segmenti da restituire</param>
/// <returns></returns>
public List<visjsDsItem> sequenzaDatiVisJS(string idxMacchina, intervalloDate _intervallo, int numSplit)
{
List<visjsDsItem> sequenza = new List<visjsDsItem>();
// se idxMacchina = 0 --> ciclo su tutte con 1 / numMacch eventi ciascuna...
if (idxMacchina != "0")
{
sequenza.AddRange(seqSingleMachine(idxMacchina, _intervallo, numSplit, 0));
}
else
{
int index = 0;
// ciclo su tutte le macchine
DataLayer DataLayerObj = new DataLayer();
var elMacchine = DataLayerObj.taSelMacc.getAttive();
foreach (var item in elMacchine)
{
sequenza.AddRange(seqSingleMachine(item.value, _intervallo, numSplit, index));
index = sequenza.Count;
}
}
return sequenza;
}
/// <summary>
/// fornisce descrizione stato da IdxStato
/// </summary>
/// <param name="idx"></param>
/// <returns></returns>
public string statoDaIdx(int idx)
{
return user_std.UtSn.Traduci(Stati.FindByIdxStato(idx).Descrizione.Replace(" ", "_"));
}
/// <summary>
/// fornisce idxStato della macchina indicata
/// </summary>
/// <param name="idx"></param>
/// <returns></returns>
public int statoMacchina(string idx)
{
int answ = 0;
try
{
DataLayer DataLayerObj = new DataLayer();
if (memLayer.ML.CRB("RedEnab"))
{
// recupero SE IMPIEGATO REDIS i valori del Dictionary della macchina...
Dictionary<string, string> datiMacc = DataLayerObj.mDatiMacchine(idx);
answ = Convert.ToInt32(datiMacc["IdxStato"]);
}
if (answ == 0)
{
DS_ProdTempi.stp_repDonati_getLastStatoDurataMacchinaRow riga = DataLayerObj.taDatiStatoMacch.GetData(idx, 0)[0];
answ = riga.idxStato;
}
}
catch
{ }
return answ;
}
/// <summary>
/// oggetto sequenza tempi ciclo x visualizzatore
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="_intervallo"></param>
/// <param name="targetVal">tempo target di riferimento (se zero calcola la media...)</param>
/// <returns></returns>
public objTempiCiclo tempiCiclo(string idxMacchina, intervalloDate _intervallo, decimal targetVal)
{
// inizializzo
objTempiCiclo _serie = new objTempiCiclo();
if (idxMacchina != null && idxMacchina != "")
{
_serie.serieDati = new DataLayer_generic.serieTimeValDataTable();
// seleziono i dati
if (targetVal > 0)
{
_serie.targetVal = targetVal;
}
else
{
try
{
_serie.targetVal = taTempiCiclo.getMedByMacchinaPeriodo(idxMacchina, _intervallo.inizio, _intervallo.fine)[0].TCMedio;
}
catch
{ }
}
int TcMaxFactor = memLayer.ML.CRI("TcMaxFactor");
DS_ProdTempi.TempiCicloRilevatiDataTable tabTempi = taTempiCiclo.getByMacchinaPeriodoFiltMax(idxMacchina, _intervallo.inizio, _intervallo.fine, _serie.targetVal * TcMaxFactor);
// converto!
DateTime inizio;
foreach (MapoDb.DS_ProdTempi.TempiCicloRilevatiRow riga in tabTempi.Rows)
{
inizio = riga.DataOraRif.AddMinutes(Convert.ToDouble(-riga.TCMedio * riga.PzProd)); // tolgo il tempo necessario a produrre i pezzi indicati come inizio
_serie.serieDati.AddserieTimeValRow(inizio, riga.DataOraRif, riga.TCMedio, string.Format("Art: {0} - T.C. {1}'", riga.CodArticolo, riga.TCMedio), riga.CodArticolo);
}
// sistemo estremi x date e valori
try
{
_serie.maxVal = taTempiCiclo.getMaxByMacchinaPeriodo(idxMacchina, _intervallo.inizio, _intervallo.fine)[0].TCMedio;
if (_serie.maxVal > _serie.targetVal * TcMaxFactor)
{
_serie.maxVal = _serie.targetVal * TcMaxFactor;
}
}
catch
{ }
try
{
_serie.minVal = taTempiCiclo.getMinByMacchinaPeriodo(idxMacchina, _intervallo.inizio, _intervallo.fine)[0].TCMedio;
}
catch
{ }
_serie.intervallo = _intervallo;
// imposto se abbia cambio pallet
_serie.palletChange = false;
try
{
DataLayer DataLayerObj = new DataLayer();
_serie.palletChange = DataLayerObj.taDatiMacchine.getByIdx(idxMacchina)[0].palletChange;
}
catch
{ }
}
return _serie;
}
/// <summary>
/// tipo evento da Idx
/// </summary>
/// <param name="idx"></param>
/// <returns></returns>
public string tipoDaIdx(int idx)
{
return AnagraficaEventi.FindByIdxTipo(idx).Nome;
}
/// <summary>
/// fornisce una torta stati
/// </summary>
/// <param name="idx"></param>
/// <param name="_intervallo"></param>
/// <param name="minDurata"></param>
/// <param name="hideSpenta"></param>
/// <returns></returns>
public DataLayer_generic.serieDatiDataTable tortaStati(string idx, intervalloDate _intervallo, int minDurata, bool hideSpenta)
{
// leggo i dati e costituisco una collezione...
DataLayer_generic.serieDatiDataTable punti = new DataLayer_generic.serieDatiDataTable();
// seleziono i dati...
DS_applicazione.ParetoDurateDataTable tabPareto;
if (hideSpenta)
{
tabPareto = taParetoDurate.GetParetoDurateHideSpenta(idx, minDurata, _intervallo.fine, _intervallo.inizio);
}
else
{
tabPareto = taParetoDurate.GetParetoDurateFilt(idx, minDurata, _intervallo.fine, _intervallo.inizio);
}
double totale = 1;
try
{
totale = (double)tabPareto.Compute("SUM(DurataMinuti)", "");
}
catch
{
}
foreach (DS_applicazione.ParetoDurateRow riga in tabPareto.Rows)
{
punti.AddserieDatiRow((float)((Math.Round(((float)riga.DurataMinuti) / totale * 1000)) / 1000), coloreDaIdx(riga.IdxStato), statoDaIdx(riga.IdxStato), riga.InizioStato);
}
return punti;
}
public string urlMacchina(string idx)
{
string answ = "";
DS_applicazione.MacchineRow riga = null;
try
{
riga = Macchine.FindByIdxMacchina(idx);
answ = riga.url;
}
catch
{ }
return answ;
}
#endregion Public Methods
#region Protected Fields
protected DS_applicazione.AnagArticoliDataTable _AnagArt;
protected DS_applicazione.AnagraficaOperatoriDataTable _AnagOpr;
protected DS_applicazione.AnagraficaEventiDataTable _AnagraficaEventi;
protected DS_applicazione.DiarioDiBordoDataTable _DiarioDiBordo;
protected DS_applicazione.MacchineDataTable _Macchine;
protected DS_applicazione.AnagraficaStatiDataTable _Stati;
protected DS_applicazione.StatoMacchineDataTable _StatoMacchine;
protected Dictionary<int, string> SemapLUT = new Dictionary<int, string>();
protected MapoDb.DS_applicazioneTableAdapters.AnagArticoliTableAdapter taAnagArt;
protected MapoDb.DS_applicazioneTableAdapters.AnagraficaOperatoriTableAdapter taAnagOpr;
protected MapoDb.DS_applicazioneTableAdapters.AnagraficaEventiTableAdapter taAnagraficaEventi;
protected MapoDb.DS_applicazioneTableAdapters.DiarioDiBordoTableAdapter taDiarioDiBordo;
protected MapoDb.DS_applicazioneTableAdapters.MacchineTableAdapter taMacchine;
protected MapoDb.DS_ProdTempiTableAdapters.ODLTableAdapter taODL;
protected MapoDb.DS_applicazioneTableAdapters.ParetoDurateTableAdapter taParetoDurate;
protected MapoDb.DS_applicazioneTableAdapters.AnagraficaStatiTableAdapter taStati;
protected MapoDb.DS_applicazioneTableAdapters.StatoMacchineTableAdapter taStatoMacchine;
protected MapoDb.DS_ProdTempiTableAdapters.TempiCicloRilevatiTableAdapter taTempiCiclo;
#endregion Protected Fields
#region Protected Properties
protected DS_applicazione.AnagArticoliDataTable AnagArt
{
get
{
if (!memLayer.ML.isInCacheObject("AnagArt"))
{
_AnagArt = taAnagArt.GetData();
string serVal = JsonConvert.SerializeObject(_AnagArt);
memLayer.ML.setCacheVal("AnagArt", serVal, true);
}
else
{
string redKey = memLayer.ML.redHash("AnagArt");
string serVal = memLayer.ML.getRSV(redKey);
_AnagArt = JsonConvert.DeserializeObject<DS_applicazione.AnagArticoliDataTable>(serVal);
}
return _AnagArt;
}
}
protected DS_applicazione.AnagraficaOperatoriDataTable AnagOpr
{
get
{
string keyName = "AnagOpr";
if (!memLayer.ML.isInCacheObject(keyName))
{
_AnagOpr = taAnagOpr.GetData();
string serVal = JsonConvert.SerializeObject(_AnagOpr);
memLayer.ML.setCacheVal(keyName, serVal, true);
}
else
{
string redKey = memLayer.ML.redHash(keyName);
string serVal = memLayer.ML.getRSV(redKey);
_AnagOpr = JsonConvert.DeserializeObject<DS_applicazione.AnagraficaOperatoriDataTable>(serVal);
}
return _AnagOpr;
}
}
protected DS_applicazione.AnagraficaEventiDataTable AnagraficaEventi
{
get
{
if (!memLayer.ML.isInCacheObject("AnagraficaEventi"))
{
_AnagraficaEventi = taAnagraficaEventi.GetData();
string serVal = JsonConvert.SerializeObject(_AnagraficaEventi);
memLayer.ML.setCacheVal("AnagraficaEventi", serVal, true);
}
else
{
string redKey = memLayer.ML.redHash("AnagraficaEventi");
string serVal = memLayer.ML.getRSV(redKey);
_AnagraficaEventi = JsonConvert.DeserializeObject<DS_applicazione.AnagraficaEventiDataTable>(serVal);
}
return _AnagraficaEventi;
}
}
/// <summary>
/// Dizionario codici colore (chiave = idxStato), valore = codice colore
/// </summary>
protected Dictionary<int, string> codColore
{
get
{
Dictionary<int, string> answ = new Dictionary<int, string>();
if (memLayer.ML.isInCacheObject("codColore"))
{
string redKey = memLayer.ML.redHash("codColore");
string serVal = memLayer.ML.getRSV(redKey);
answ = JsonConvert.DeserializeObject<Dictionary<int, string>>(serVal);
}
else
{
string _colore = "";
foreach (DS_applicazione.AnagraficaStatiRow item in Stati)
{
switch (item.Semaforo)
{
case "sGi": // giallo
_colore = "#ffec00";
break;
case "sRo": // rosso
_colore = "#e2001a";
break;
case "sGr": // grigio - spenta
_colore = "#bcbcbc";
break;
case "sVe": // verde
_colore = "#009036";
break;
case "sBl": // blu
_colore = "#3690FF";
break;
default:
break;
}
answ.Add(item.IdxStato, _colore);
}
string serVal = JsonConvert.SerializeObject(answ);
memLayer.ML.setCacheVal("codColore", serVal, true);
}
return answ;
}
}
/// <summary>
/// Dizionario codici semaforo (chiave = idxStato), valore = codice semaforo
/// </summary>
protected Dictionary<int, string> codSemaforo
{
get
{
Dictionary<int, string> answ = new Dictionary<int, string>();
if (memLayer.ML.isInCacheObject("codSemaforo"))
{
string redKey = memLayer.ML.redHash("codSemaforo");
string serVal = memLayer.ML.getRSV(redKey);
answ = JsonConvert.DeserializeObject<Dictionary<int, string>>(serVal);
}
else
{
foreach (DS_applicazione.AnagraficaStatiRow item in Stati)
{
answ.Add(item.IdxStato, item.Semaforo);
}
string serVal = JsonConvert.SerializeObject(answ);
memLayer.ML.setCacheVal("codSemaforo", serVal, true);
}
return answ;
}
}
protected DS_applicazione.DiarioDiBordoDataTable DiarioDiBordo
{
get
{
if (_DiarioDiBordo == null)
{
_DiarioDiBordo = taDiarioDiBordo.GetData();
}
return _DiarioDiBordo;
}
}
protected DS_applicazione.MacchineDataTable Macchine
{
get
{
if (!memLayer.ML.isInCacheObject("Macchine"))
{
_Macchine = taMacchine.GetData();
string serVal = JsonConvert.SerializeObject(_Macchine);
memLayer.ML.setCacheVal("Macchine", serVal, true);
}
else
{
string redKey = memLayer.ML.redHash("Macchine");
string serVal = memLayer.ML.getRSV(redKey);
_Macchine = JsonConvert.DeserializeObject<DS_applicazione.MacchineDataTable>(serVal);
}
return _Macchine;
}
}
protected DS_applicazione.AnagraficaStatiDataTable Stati
{
get
{
if (!memLayer.ML.isInCacheObject("Stati"))
{
_Stati = taStati.GetData();
string serVal = JsonConvert.SerializeObject(_Stati);
memLayer.ML.setCacheVal("Stati", serVal, true);
}
else
{
string redKey = memLayer.ML.redHash("Stati");
string serVal = memLayer.ML.getRSV(redKey);
_Stati = JsonConvert.DeserializeObject<DS_applicazione.AnagraficaStatiDataTable>(serVal);
}
return _Stati;
}
}
protected DS_applicazione.StatoMacchineDataTable StatoMacchine
{
get
{
if (!memLayer.ML.isInCacheObject("StatoMacchine"))
{
_StatoMacchine = taStatoMacchine.GetData();
string serVal = JsonConvert.SerializeObject(_StatoMacchine);
memLayer.ML.setCacheVal("StatoMacchine", serVal, true);
}
else
{
string redKey = memLayer.ML.redHash("StatoMacchine");
string serVal = memLayer.ML.getRSV(redKey);
_StatoMacchine = JsonConvert.DeserializeObject<DS_applicazione.StatoMacchineDataTable>(serVal);
}
return _StatoMacchine;
}
}
#endregion Protected Properties
#region Protected Methods
/// <summary>
/// Recupera record odl al momento indicato
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="inizio"></param>
/// <param name="fine"></param>
/// <param name="dataRif"></param>
/// <returns></returns>
protected DS_ProdTempi.ODLRow currOdl(string idxMacchina, DateTime inizio, DateTime fine, DateTime dataRif)
{
DS_ProdTempi.ODLRow answ = null;
var tabOdl = OdlPeriodo(idxMacchina, inizio, fine);
if (tabOdl != null)
{
answ = tabOdl
.Where(x => x.DataInizio <= dataRif && (x.DataFine >= dataRif || x.DataFine == null))
.FirstOrDefault();
}
return answ;
}
/// <summary>
/// Recupera tab ODL per periodo e impianto indicati
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="inizio"></param>
/// <param name="fine"></param>
/// <returns></returns>
protected DS_ProdTempi.ODLDataTable OdlPeriodo(string idxMacchina, DateTime inizio, DateTime fine)
{
// cache redis di 5 minuti...
int cacheTtl = 300;
DS_ProdTempi.ODLDataTable odlReq = null;
string redKey = memLayer.ML.redHash($"OdlPeriodo:{idxMacchina}:{inizio:yyyy-MM-dd}:{inizio:HH:mm}");
string rawVal = memLayer.ML.getRSV(redKey);
if (string.IsNullOrEmpty(rawVal))
{
odlReq = taODL.getByMacchinaPeriodoNoNull(idxMacchina, inizio, fine);
rawVal = JsonConvert.SerializeObject(odlReq);
memLayer.ML.setRSV(redKey, rawVal, cacheTtl);
}
else
{
try
{
odlReq = JsonConvert.DeserializeObject<DS_ProdTempi.ODLDataTable>(rawVal);
}
catch
{ }
}
return odlReq;
}
/// <summary>
/// Effettua riduzione per accorpamento valori
/// </summary>
/// <param name="original"></param>
/// <returns></returns>
protected DS_applicazione.DiarioDiBordoDataTable riduciSeq(DS_applicazione.DiarioDiBordoDataTable original, double sogliaMin)
{
DS_applicazione.DiarioDiBordoDataTable copia = new DS_applicazione.DiarioDiBordoDataTable();
//DS_applicazione.DiarioDiBordoRow currRow;
// valori x setup
double minVerde = 0.5;
double minRosso = 0.5;
double minSpento = 0.5;
double valRigaCum = 0.0;
double valR = 0.0;
double valG = 0.0;
double valV = 0.0;
double valB = 0.0;
double valS = 0.0;
DateTime _t_0 = new DateTime(9999, 1, 1);
string _mostCodArticolo = "";
int _maxVal = 0;
foreach (var riga in original)
{
// salvo prima data...
if (riga.InizioStato < _t_0)
{
_t_0 = riga.InizioStato;
}
if (riga.DurataMinuti > _maxVal)
{
_maxVal = Convert.ToInt32(riga.DurataMinuti);
_mostCodArticolo = riga.CodArticolo;
}
valRigaCum = valRigaCum + riga.DurataMinuti;
// accumulo valori...
switch (semaforoDaIdxStato(riga.IdxStato))
{
case "sVe":
valV = valV + riga.DurataMinuti;
break;
case "sGi":
valG = valG + riga.DurataMinuti;
break;
case "sRo":
valR = valR + riga.DurataMinuti;
break;
case "sBl":
valB = valB + riga.DurataMinuti;
break;
case "sGr":
valS = valS + riga.DurataMinuti;
break;
}
// se è maggiore plotto...
if (valRigaCum >= sogliaMin)
{
// determino il colore...
if (valV / valRigaCum >= minVerde)
{
valV = 0.0;
}
else if (valR / valRigaCum >= minRosso)
{
valR = 0.0;
}
else if (valS / valRigaCum >= minSpento)
{
valS = 0.0;
}
else if (valB / valRigaCum >= minSpento)
{
valB = 0.0;
}
else
{
valG = 0.0;
}
// modifico riga corrente...
riga.DurataMinuti = valRigaCum;
riga.CodArticolo = _mostCodArticolo;
//riga.InizioStato = _t_0;
copia.ImportRow(riga);
// modifico inizio stato...
((DS_applicazione.DiarioDiBordoRow)copia.Rows[copia.Rows.Count - 1]).InizioStato = _t_0;
// reset dei contatori...
valRigaCum = 0.0;
_t_0 = new DateTime(9999, 1, 1);
_mostCodArticolo = "";
_maxVal = 0;
}
}
// restituisco valori "ridotti"
return copia;
}
#endregion Protected Methods
#region Private Methods
/// <summary>
/// avvio i table adapter della classe
/// </summary>
private void AvviaTabAdapt()
{
taMacchine = new MapoDb.DS_applicazioneTableAdapters.MacchineTableAdapter();
taStatoMacchine = new MapoDb.DS_applicazioneTableAdapters.StatoMacchineTableAdapter();
taStati = new MapoDb.DS_applicazioneTableAdapters.AnagraficaStatiTableAdapter();
taDiarioDiBordo = new MapoDb.DS_applicazioneTableAdapters.DiarioDiBordoTableAdapter();
taParetoDurate = new MapoDb.DS_applicazioneTableAdapters.ParetoDurateTableAdapter();
taAnagraficaEventi = new MapoDb.DS_applicazioneTableAdapters.AnagraficaEventiTableAdapter();
taAnagArt = new MapoDb.DS_applicazioneTableAdapters.AnagArticoliTableAdapter();
taAnagOpr = new MapoDb.DS_applicazioneTableAdapters.AnagraficaOperatoriTableAdapter();
taTempiCiclo = new MapoDb.DS_ProdTempiTableAdapters.TempiCicloRilevatiTableAdapter();
taODL = new MapoDb.DS_ProdTempiTableAdapters.ODLTableAdapter();
}
/// <summary>
/// recupera sequenza x una SINGOLA macchina
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="_intervallo"></param>
/// <param name="numSplit"></param>
/// <param name="index"></param>
/// <returns></returns>
private List<visjsDsItem> seqSingleMachine(string idxMacchina, intervalloDate _intervallo, int numSplit, int index)
{
List<visjsDsItem> sequenza = new List<visjsDsItem>();
Stopwatch stopwatch = new Stopwatch();
DateTime start = DateTime.Now;
// leggo i dati e costituisco una collezione...
int i = index;
if (idxMacchina != null && idxMacchina != "")
{
logger.lg.scriviLog("inizio WS");
stopwatch.Restart();
// seleziono i dati...
DS_applicazione.DiarioDiBordoDataTable tabSeq = taDiarioDiBordo.GetSequenza(idxMacchina, _intervallo.inizio, _intervallo.fine);
logger.lg.scriviLog(string.Format("Letta tabella: {0} rec, {1} msec", tabSeq.Rows.Count, stopwatch.ElapsedMilliseconds));
// se ho troppi dati faccio la riduzione dei dati, MAX numSplit...
if (tabSeq.Rows.Count > numSplit)
{
double sogliaMin = _intervallo.fine.Subtract(_intervallo.inizio).TotalMinutes / numSplit;
tabSeq = riduciSeq(tabSeq, sogliaMin);
}
logger.lg.scriviLog(string.Format("Riduzione seq fatta: {0} rec, {1} msec", tabSeq.Count, stopwatch.ElapsedMilliseconds));
// ora converto in oggetto definitivo x vis.js
sequenza = tabSeq.AsEnumerable().Select(riga => new visjsDsItem
{
//id = i,
content = "",//riga.CodArticolo,
start = riga.InizioStato.ToString("yyyy-MM-dd HH:mm:ss"),
end = riga.FineStato.ToString("yyyy-MM-dd HH:mm:ss"),
group = riga.IdxMacchina,// "1", // per mostrare multi macchine
type = "background", // importante x non vedere bordi...
className = semaforoDaIdxStato(riga.IdxStato)
}).ToList();
foreach (var item in sequenza)
{
//item.content = i.ToString();
item.id = i;
i++;
}
logger.lg.scriviLog(string.Format("Conversione oggetto eseguita: {0} rec, {1} msec", sequenza.Count, stopwatch.ElapsedMilliseconds));
}
return sequenza;
}
/// <summary>
/// forza la connString x i vari table adapters
/// </summary>
private void setConnString()
{
string _connectionString = memLayer.ML.confReadString("MoonProConnectionString");
taMacchine.Connection.ConnectionString = _connectionString;
taStatoMacchine.Connection.ConnectionString = _connectionString;
taStati.Connection.ConnectionString = _connectionString;
taDiarioDiBordo.Connection.ConnectionString = _connectionString;
taParetoDurate.Connection.ConnectionString = _connectionString;
taAnagraficaEventi.Connection.ConnectionString = _connectionString;
taAnagArt.Connection.ConnectionString = _connectionString;
taAnagOpr.Connection.ConnectionString = _connectionString;
taTempiCiclo.Connection.ConnectionString = _connectionString;
taODL.Connection.ConnectionString = _connectionString;
}
#endregion Private Methods
}
/// <summary>
/// Oggetto timeline vis.js con gruppi + items
/// </summary>
public class timelineVisJs
{
#region Public Fields
/// <summary>
/// Gruppi contenuti
/// </summary>
public List<visjsDsGroups> Groups;
/// <summary>
/// Valori
/// </summary>
public List<visjsDsItem> Items;
/// <summary>
/// Opzioni
/// </summary>
public visjsDsOptions Options;
#endregion Public Fields
}
/// <summary>
/// Groups Dataset di vis.js
/// </summary>
public class visjsDsGroups
{
#region Public Fields
/// <summary>
/// Classe css
/// </summary>
public string className;
/// <summary>
/// Testo descrittivo
/// </summary>
public string content;
/// <summary>
/// identificativo univoco
/// </summary>
public string id;
#endregion Public Fields
}
/// <summary>
/// Item Dataset di vis.js
/// </summary>
public class visjsDsItem
{
#region Public Fields
/// <summary>
/// Classe css
/// </summary>
public string className;
/// <summary>
/// Testo descrittivo
/// </summary>
public string content;
/// <summary>
/// Fine dell'evento
/// </summary>
public string end;
/// <summary>
/// Gruppo dell'item
/// </summary>
public string group;
/// <summary>
/// identificativo univoco
/// </summary>
public int id;
/// <summary>
/// Inizio dell'evento
/// </summary>
public string start;
/// <summary>
/// typo box/point/range/background
/// </summary>
public string type;
#endregion Public Fields
}
/// <summary>
/// Groups Dataset di vis.js
/// </summary>
public class visjsDsOptions
{
#region Public Fields
/// <summary>
/// Data End
/// </summary>
public string end;
/// <summary>
/// Abilita scroll orizzontale
/// </summary>
public bool horizontalScroll;
/// <summary>
/// Abilita spostamento
/// </summary>
public bool moveable;
/// <summary>
/// Indica se debba salvare come stacked i valori (false = in linea x gruppo)
/// </summary>
public bool stack;
/// <summary>
/// Data Start
/// </summary>
public string start;
/// <summary>
/// Abilita zoom
/// </summary>
public bool zoomable;
#endregion Public Fields
}