1238 lines
39 KiB
C#
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
|
|
} |