405 lines
18 KiB
C#
405 lines
18 KiB
C#
namespace MapoDataFiller.Filler
|
|
{
|
|
public class InterClays
|
|
{
|
|
#region Public Properties
|
|
|
|
public SimSetup currSetup { get; set; } = new SimSetup();
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Restituisce elenco righe da caricare sul DB dato periodo indicato
|
|
/// </summary>
|
|
/// <param name="CodIOB"></param>
|
|
/// <param name="currDay"></param>
|
|
/// <returns></returns>
|
|
public SimBlock GetDataRows(string CodIOB, DayConf currDay)
|
|
{
|
|
string fileConf = Path.Combine("Conf", $"{CodIOB}.json");
|
|
if (File.Exists(fileConf))
|
|
{
|
|
currSetup = SimSetup.readConf(fileConf);
|
|
}
|
|
|
|
SimBlock answ = new SimBlock();
|
|
int idxEv = 0;
|
|
int idxFl = 0;
|
|
bool doProd = false;
|
|
List<string> nextRowsFL = new List<string>();
|
|
List<string> nextRowsEV = new List<string>();
|
|
int valReq = 0;
|
|
int valCurr = 0;
|
|
// simulo periodi
|
|
int numPer = rnd.Next(10, numPerMax);
|
|
// calcolo durata media periodi in minuti
|
|
double avgDurPer = (currDay.dtEnd.Subtract(currDay.dtStart).TotalMinutes) / numPer;
|
|
double preDelay = avgDurPer / 2;
|
|
// imposto cursore
|
|
DateTime dtStart = currDay.dtStart.AddMinutes(preDelay);
|
|
DateTime dtEnd = dtStart;
|
|
// per prima cosa aggiungo start dopo un delay di max 1/2 periodo...
|
|
answ.FlList.Add($"{CodIOB};{dtStart:yyyy-MM-dd HH:mm:ss.fff};IOB-STATUS;IOB Started;{idxFl++}");
|
|
answ.EvList.Add($"{CodIOB};{dtStart:yyyy-MM-dd HH:mm:ss.fff};14;ND;[{idxEv++}] 00;0;-");
|
|
// calcolo durata successivi
|
|
while (dtEnd < currDay.dtEnd)
|
|
{
|
|
dtStart = dtEnd.AddSeconds(rnd.Next(25, 35));
|
|
dtEnd = dtStart.AddMinutes(avgDurPer * rnd.Next(600, 1400) / 1000);
|
|
// verifico il tipo di CodIOB
|
|
if (CodIOB == "INTERCL_01")
|
|
{
|
|
// tiro a dadi x decidere SE LAVORA periodo... 50% dei casi nel periodo TRACCIATO
|
|
doProd = (rnd.Next(0, 100) <= 40);
|
|
|
|
// FluxLOG: genero righe FL x periodo e sommo
|
|
nextRowsFL = IC_ESS_getFlRows(CodIOB, dtStart, dtEnd, doProd, ref idxFl);
|
|
|
|
// EvList: genero righe EV x periodo e sommo
|
|
nextRowsEV = IC_ESS_getEvRows(CodIOB, dtStart, dtEnd, doProd, ref idxEv);
|
|
}
|
|
else if (CodIOB == "INTERCL_02")
|
|
{
|
|
// verifico se DEVO finire caricamento...
|
|
if (valCurr < valReq)
|
|
{
|
|
doProd = true;
|
|
}
|
|
else
|
|
{
|
|
// tiro a dadi x decidere SE ho pesate nel periodo... 30% dei casi
|
|
doProd = (rnd.Next(0, 100) <= 30);
|
|
|
|
// FluxLOG: SE ho pesate --> genero target
|
|
valReq = doProd ? rnd.Next(valMin / valStep, valMax / valStep) * valStep : 0;
|
|
}
|
|
// FluxLOG: genero righe FL x periodo e sommo
|
|
nextRowsFL = IC_OX_getFlRows(CodIOB, dtStart, dtEnd, doProd, valReq, ref idxFl, ref valCurr);
|
|
|
|
// EvList: genero righe EV x periodo e sommo
|
|
nextRowsEV = IC_OX_getEvRows(CodIOB, dtStart, dtEnd, doProd, ref idxEv);
|
|
}
|
|
// accodo FL
|
|
answ.FlList.AddRange(nextRowsFL);
|
|
// accodo EV
|
|
answ.EvList.AddRange(nextRowsEV);
|
|
}
|
|
|
|
// aggiungo chiusura eventi...
|
|
dtStart = dtEnd.AddSeconds(rnd.Next(25, 35));
|
|
answ.EvList.Add($"{CodIOB};{dtStart:yyyy-MM-dd HH:mm:ss.fff};15;ND;[{idxEv++}] 01;0;-");
|
|
dtStart = dtEnd.AddSeconds(rnd.Next(80, 180));
|
|
answ.EvList.Add($"{CodIOB};{dtStart:yyyy-MM-dd HH:mm:ss.fff};14;ND;[{idxEv++}] 00;0;-");
|
|
|
|
// ritorno
|
|
return answ;
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Fields
|
|
|
|
protected int numPerMax = 50;
|
|
protected int numSec = 30;
|
|
protected Random rnd = new Random();
|
|
protected int stepMax = 150;
|
|
protected int stepMin = 50;
|
|
protected int valMax = 15000;
|
|
protected int valMin = 500;
|
|
protected int valStep = 10;
|
|
protected int waitMax = 240;
|
|
protected int waitMin = 10;
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Methods
|
|
|
|
/// <summary>
|
|
/// Simulo un blocco dati FL
|
|
/// </summary>
|
|
/// <param name="CodIOB"></param>
|
|
/// <param name="dtStart"></param>
|
|
/// <param name="dtEnd"></param>
|
|
/// <param name="doProd"></param>
|
|
/// <param name="idxCount"></param>
|
|
/// <returns></returns>
|
|
protected List<string> IC_OX_getEvRows(string CodIOB, DateTime dtStart, DateTime dtEnd, bool doProd, ref int idxCount)
|
|
{
|
|
List<string> rows = new List<string>();
|
|
DateTime dtCurs = dtStart.AddMilliseconds(rnd.Next(1000, 60000));
|
|
string currRow = "";
|
|
// reset counter
|
|
idxCount = idxCount <= 9999 ? idxCount : 0;
|
|
// se produce registro poweron...
|
|
if (doProd)
|
|
{
|
|
currRow = $"{CodIOB};{dtStart.AddSeconds(5):yyyy-MM-dd HH:mm:ss.fff};16;ND;[{idxCount++}] 23;0;-";
|
|
rows.Add(currRow);
|
|
currRow = $"{CodIOB};{dtEnd.AddSeconds(-5):yyyy-MM-dd HH:mm:ss.fff};15;ND;[{idxCount++}] 01;0;-";
|
|
rows.Add(currRow);
|
|
}
|
|
// se NON produce alterno valori spenta/accesa
|
|
else
|
|
{
|
|
// genera i dati secondo lo schema configurato... con periodo da 15" a 15 min di pausa
|
|
while (dtCurs < dtEnd)
|
|
{
|
|
currRow = $"{CodIOB};{dtCurs:yyyy-MM-dd HH:mm:ss.fff};15;ND;[{idxCount++}] 01;0;-";
|
|
rows.Add(currRow);
|
|
dtCurs = dtCurs.AddSeconds(rnd.Next(60 * 5, 60 * 15));
|
|
currRow = $"{CodIOB};{dtCurs:yyyy-MM-dd HH:mm:ss.fff};14;ND;[{idxCount++}] 00;0;-";
|
|
rows.Add(currRow);
|
|
dtCurs = dtCurs.AddMilliseconds(rnd.Next(500, 5000));
|
|
// reset counter
|
|
idxCount = idxCount <= 9999 ? idxCount : 0;
|
|
}
|
|
}
|
|
return rows;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Simulo un blocco dati FL
|
|
/// </summary>
|
|
/// <param name="CodIOB"></param>
|
|
/// <param name="dtStart"></param>
|
|
/// <param name="dtEnd"></param>
|
|
/// <param name="doProd"></param>
|
|
/// <param name="valReq"></param>
|
|
/// <param name="idxCount"></param>
|
|
/// <param name="valCurr"></param>
|
|
/// <returns></returns>
|
|
protected List<string> IC_OX_getFlRows(string CodIOB, DateTime dtStart, DateTime dtEnd, bool doProd, int valReq, ref int idxCount, ref int valCurr)
|
|
{
|
|
List<string> rows = new List<string>();
|
|
DateTime dtCurs = dtStart;
|
|
int valTo = doProd ? valReq + rnd.Next(0, valStep) * valStep : 0;
|
|
valCurr = valReq > 0 ? valCurr : 0;
|
|
string currRow = "";
|
|
// reset counter
|
|
idxCount = idxCount <= 9999 ? idxCount : 0;
|
|
// genera i dati secondo lo schema configurato...
|
|
while (dtCurs < dtEnd)
|
|
{
|
|
currRow = $"{CodIOB};{dtCurs:yyyy-MM-dd HH:mm:ss.fff};kgImp;{valReq};{idxCount++}";
|
|
rows.Add(currRow);
|
|
dtCurs = dtCurs.AddMilliseconds(rnd.Next(50, 300));
|
|
currRow = $"{CodIOB};{dtCurs:yyyy-MM-dd HH:mm:ss.fff};kgAct;{valCurr};{idxCount++}";
|
|
rows.Add(currRow);
|
|
dtCurs = dtCurs.AddMilliseconds(rnd.Next(27000, 33000));
|
|
// incremento peso... SE <= max...
|
|
if (valCurr < valTo)
|
|
{
|
|
valCurr += rnd.Next(stepMin / valStep, stepMax / valStep) * valStep;
|
|
}
|
|
// reset counter
|
|
idxCount = idxCount <= 9999 ? idxCount : 0;
|
|
}
|
|
return rows;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Simulo un blocco dati FL
|
|
/// </summary>
|
|
/// <param name="CodIOB"></param>
|
|
/// <param name="dtStart"></param>
|
|
/// <param name="dtEnd"></param>
|
|
/// <param name="doProd"></param>
|
|
/// <param name="idxCount"></param>
|
|
/// <returns></returns>
|
|
protected List<string> IC_ESS_getEvRows(string CodIOB, DateTime dtStart, DateTime dtEnd, bool doProd, ref int idxCount)
|
|
{
|
|
List<string> rows = new List<string>();
|
|
DateTime dtCurs = dtStart.AddMilliseconds(rnd.Next(1000, 60000));
|
|
string currRow = "";
|
|
// reset counter
|
|
idxCount = idxCount <= 9999 ? idxCount : 0;
|
|
var fullDuration = dtEnd.Subtract(dtStart).TotalMinutes;
|
|
// se produce registro riscaldamento + poweron...
|
|
if (doProd)
|
|
{
|
|
// calcolo 1/8 = 12.5% riscaldamento...
|
|
currRow = $"{CodIOB};{dtStart.AddSeconds(1):yyyy-MM-dd HH:mm:ss.fff};40;ND;[{idxCount++}] 34;0;-";
|
|
rows.Add(currRow);
|
|
// ...il resto lavoro... partendo a 1/8
|
|
currRow = $"{CodIOB};{dtStart.AddMinutes(fullDuration / 8):yyyy-MM-dd HH:mm:ss.fff};16;ND;[{idxCount++}] 13;0;-";
|
|
rows.Add(currRow);
|
|
currRow = $"{CodIOB};{dtEnd.AddSeconds(-1):yyyy-MM-dd HH:mm:ss.fff};15;ND;[{idxCount++}] 12;0;-";
|
|
rows.Add(currRow);
|
|
}
|
|
// se NON produce alterno valori spenta/accesa
|
|
else
|
|
{
|
|
/*
|
|
* genera i dati con durata secondo pareto standard...
|
|
* - 10% --> 24: manuale
|
|
* - 30% --> 15: fermo generico
|
|
* - 60% --> 14: spenta
|
|
*/
|
|
// manuale
|
|
currRow = $"{CodIOB};{dtStart.AddSeconds(1):yyyy-MM-dd HH:mm:ss.fff};24;ND;[{idxCount++}] 24;0;-";
|
|
rows.Add(currRow);
|
|
// fermo generico dopo 10%
|
|
currRow = $"{CodIOB};{dtStart.AddMinutes(fullDuration / 10):yyyy-MM-dd HH:mm:ss.fff};15;ND;[{idxCount++}] 12;0;-";
|
|
rows.Add(currRow);
|
|
// spenta dopo 40%
|
|
currRow = $"{CodIOB};{dtStart.AddMinutes(fullDuration * 4 / 10):yyyy-MM-dd HH:mm:ss.fff};15;ND;[{idxCount++}] 12;0;-";
|
|
rows.Add(currRow);
|
|
// reset counter
|
|
idxCount = idxCount <= 9999 ? idxCount : 0;
|
|
}
|
|
return rows;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Simulo un blocco dati FL
|
|
/// </summary>
|
|
/// <param name="CodIOB"></param>
|
|
/// <param name="dtStart"></param>
|
|
/// <param name="dtEnd"></param>
|
|
/// <param name="doProd"></param>
|
|
/// <param name="valReq"></param>
|
|
/// <param name="idxCount"></param>
|
|
/// <param name="valCurr"></param>
|
|
/// <returns></returns>
|
|
protected List<string> IC_ESS_getFlRows(string CodIOB, DateTime dtStart, DateTime dtEnd, bool doProd, ref int idxCount)
|
|
{
|
|
List<string> rows = new List<string>();
|
|
// inizio spostando di 5-10 sec avanti inizio
|
|
DateTime dtCurs = dtStart.AddSeconds(rnd.Next(5, 10));
|
|
int simInt = 0;
|
|
double simReal = 0;
|
|
double simDTime = 0;
|
|
// se è do prod --> simulo 50° percentile in su, altrimenti primi 50 percentili...
|
|
string currRow = "";
|
|
// reset counter
|
|
idxCount = idxCount <= 9999 ? idxCount : 0;
|
|
// genera i dati secondo lo schema configurato...
|
|
while (dtCurs < dtEnd)
|
|
{
|
|
// in primis genero gli items INT
|
|
if (currSetup.SetupSimInt.Count > 0)
|
|
{
|
|
foreach (var item in currSetup.SetupSimInt)
|
|
{
|
|
simInt = simValInt(doProd, item.Key, item.Value);
|
|
currRow = $"{CodIOB};{dtCurs:yyyy-MM-dd HH:mm:ss.fff};{item.Key};{simInt};{idxCount++}";
|
|
rows.Add(currRow);
|
|
dtCurs = dtCurs.AddMilliseconds(rnd.Next(10, 100));
|
|
idxCount = idxCount <= 9999 ? idxCount : 0;
|
|
}
|
|
}
|
|
// poi gli item REAL
|
|
if (currSetup.SetupSimReal.Count > 0)
|
|
{
|
|
foreach (var item in currSetup.SetupSimReal)
|
|
{
|
|
simReal = simValReal(doProd, item.Key, item.Value);
|
|
currRow = $"{CodIOB};{dtCurs:yyyy-MM-dd HH:mm:ss.fff};{item.Key};{simReal};{idxCount++}";
|
|
rows.Add(currRow);
|
|
dtCurs = dtCurs.AddMilliseconds(rnd.Next(10, 100));
|
|
idxCount = idxCount <= 9999 ? idxCount : 0;
|
|
}
|
|
}
|
|
// infine certo gli items basati su datetime
|
|
if (currSetup.SetupDtData.Count > 0 && doProd)
|
|
{
|
|
foreach (var item in currSetup.SetupDtData)
|
|
{
|
|
simDTime = simValData(dtCurs, item.Key, item.Value);
|
|
currRow = $"{CodIOB};{dtCurs:yyyy-MM-dd HH:mm:ss.fff};{item.Key};{simDTime};{idxCount++}";
|
|
rows.Add(currRow);
|
|
dtCurs = dtCurs.AddMilliseconds(rnd.Next(10, 100));
|
|
idxCount = idxCount <= 9999 ? idxCount : 0;
|
|
}
|
|
}
|
|
|
|
|
|
dtCurs = dtCurs.AddMilliseconds(rnd.Next(87000, 93000));
|
|
// reset counter
|
|
idxCount = idxCount <= 9999 ? idxCount : 0;
|
|
}
|
|
return rows;
|
|
}
|
|
/// <summary>
|
|
/// Simulazione valore int secondo tab transcodifica:
|
|
/// doProd=true --> simulo 50° percentile in su, altrimenti primi 50 percentili...
|
|
/// </summary>
|
|
/// <param name="doProd"></param>
|
|
/// <param name="codFlux"></param>
|
|
/// <param name="transcMap"></param>
|
|
/// <returns></returns>
|
|
protected int simValInt(bool doProd, string codFlux, Dictionary<int, int> transcMap)
|
|
{
|
|
int result = 0;
|
|
// se è in prod --> 50° perc in su...
|
|
int rawSim = rnd.Next(0, 50) + (doProd ? 50 : 0);
|
|
// transcodifico
|
|
var val0 = transcMap
|
|
.Where(x => x.Key <= rawSim)
|
|
.OrderByDescending(x => x.Value)
|
|
.FirstOrDefault();
|
|
var val1 = transcMap
|
|
.Where(x => x.Key >= rawSim)
|
|
.OrderBy(x => x.Value)
|
|
.FirstOrDefault();
|
|
result = val0.Value + (int)Math.Round((double)(val1.Value - val0.Value) * (rawSim - val0.Key) / (val1.Key - val0.Key), 0);
|
|
return result;
|
|
}
|
|
/// <summary>
|
|
/// Simulazione valore REAL secondo tab transcodifica:
|
|
/// doProd=true --> simulo 50° percentile in su, altrimenti primi 50 percentili...
|
|
/// </summary>
|
|
/// <param name="doProd"></param>
|
|
/// <param name="codFlux"></param>
|
|
/// <param name="transcMap"></param>
|
|
/// <returns></returns>
|
|
protected double simValReal(bool doProd, string codFlux, Dictionary<int, double> transcMap)
|
|
{
|
|
double result = 0;
|
|
// se è in prod --> 50° perc in su...
|
|
int rawSim = rnd.Next(0, 50) + (doProd ? 50 : 0);
|
|
// transcodifico
|
|
var val0 = transcMap
|
|
.Where(x => x.Key <= rawSim)
|
|
.OrderByDescending(x => x.Value)
|
|
.FirstOrDefault();
|
|
var val1 = transcMap
|
|
.Where(x => x.Key >= rawSim)
|
|
.OrderBy(x => x.Value)
|
|
.FirstOrDefault();
|
|
result = Math.Round(val0.Value + (val1.Value - val0.Value) * (rawSim - val0.Key) / (val1.Key - val0.Key), 2);
|
|
return result;
|
|
}
|
|
/// <summary>
|
|
/// Simulazione valore Real dt-based secondo tab transcodifica
|
|
/// </summary>
|
|
/// <param name="dtCurs"></param>
|
|
/// <param name="codFlux"></param>
|
|
/// <param name="transcMap"></param>
|
|
/// <returns></returns>
|
|
protected double simValData(DateTime dtCurs, string codFlux, Dictionary<DateTime, double> transcMap)
|
|
{
|
|
double result = 0;
|
|
int rawSim = rnd.Next(-5000, 5000);
|
|
// perturbo la data in ms per +/-5 sec
|
|
dtCurs = dtCurs.AddMilliseconds(rawSim);
|
|
// transcodifico
|
|
var val0 = transcMap
|
|
.Where(x => x.Key <= dtCurs)
|
|
.OrderByDescending(x => x.Value)
|
|
.FirstOrDefault();
|
|
var val1 = transcMap
|
|
.Where(x => x.Key >= dtCurs)
|
|
.OrderBy(x => x.Value)
|
|
.FirstOrDefault();
|
|
// prendo valore intervallo calcolato...
|
|
result = Math.Round(val0.Value + (val1.Value - val0.Value) * (dtCurs - val0.Key) / (val1.Key - val0.Key), 2);
|
|
return result;
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
}
|
|
} |