update x conf simulatore avanzato x interclays01

This commit is contained in:
Samuele Locatelli
2023-05-05 19:15:48 +02:00
parent 742bd6637f
commit 81e45e9b8c
8 changed files with 458 additions and 140 deletions
+113
View File
@@ -0,0 +1,113 @@
---
SetupSimInt: {
Temp_Filtro:
{
0: 0.1,
1: 5.6,
25: 89.1,
50: 103.7,
75: 108.3,
99: 118.1,
100: 135.6
},
T_Attuale_Cil:
{
0: 0.01,
1: 0.65,
25: 10.36,
50: 11.46,
75: 11.98,
99: 13.99,
100: 327.67
},
Flowrate:
{
0: 0.01,
1: 0.06,
25: 5.34,
50: 8.22,
75: 9.48,
99: 12.86,
100: 262.8
},
Ampere_Cil:
{
0: 10.6,
1: 14.1,
25: 14.4,
50: 14.6,
75: 15.0,
99: 16.4,
100: 79.1
},
Ampere_Asp:
{
0: 12.1,
1: 14.8,
25: 15.9,
50: 17.2,
75: 22.1,
99: 32.4,
100: 87.3
},
Ampere_Dosat:
{
0: 0.1,
1: 1.8,
25: 2,
50: 2,
75: 2.1,
99: 2.4,
100: 3.3
}
}
SetupSimFloat: {
Dep_Cil_mmH2O:
{
0: 1,
1: 1,
25: 5,
50: 10,
75: 15,
99: 26,
100: 52
},
Bruc_0_100:
{
0: 1,
1: 17,
25: 24,
50: 33,
75: 47,
99: 71,
100: 100
},
Asp_0_100:
{
0: 3,
1: 36,
25: 52,
50: 59,
75: 77,
99: 100,
100: 100
}
}
SetupDtData: {
Tot_Parz_Dosatore:
{
2020-06-30 19:56:21: 1225.481,
2020-11-16 13:01:33: 5419.626,
2022-03-14 11:33:21: 20782.475,
2022-11-21 08:48:21: 27770.447,
2023-03-07 15:40:44: 30951.118
},
Tot_Dosatore:
{
2020-06-30 19:56:21: 9053.072,
2020-11-16 13:01:33: 13247.217,
2022-03-14 11:33:21: 28610.066,
2022-11-21 08:48:21: 35598.038,
2023-03-07 15:40:44: 38778.709
}
}
+88
View File
@@ -0,0 +1,88 @@
---
SetupSimInt:
Temp_Filtro:
"0": 0.1
"1": 5.6
"25": 89.1
"50": 103.7
"75": 108.3
"99": 118.1
"100": 135.6
T_Attuale_Cil:
"0": 0.01
"1": 0.65
"25": 10.36
"50": 11.46
"75": 11.98
"99": 13.99
"100": 327.67
Flowrate:
"0": 0.01
"1": 0.06
"25": 5.34
"50": 8.22
"75": 9.48
"99": 12.86
"100": 262.8
Ampere_Cil:
"0": 10.6
"1": 14.1
"25": 14.4
"50": 14.6
"75": 15
"99": 16.4
"100": 79.1
Ampere_Asp:
"0": 12.1
"1": 14.8
"25": 15.9
"50": 17.2
"75": 22.1
"99": 32.4
"100": 87.3
Ampere_Dosat:
"0": 0.1
"1": 1.8
"25": 2
"50": 2
"75": 2.1
"99": 2.4
"100": 3.3
SetupSimFloat:
Dep_Cil_mmH2O:
"0": 1
"1": 1
"25": 5
"50": 10
"75": 15
"99": 26
"100": 52
Bruc_0_100:
"0": 1
"1": 17
"25": 24
"50": 33
"75": 47
"99": 71
"100": 100
Asp_0_100:
"0": 3
"1": 36
"25": 52
"50": 59
"75": 77
"99": 100
"100": 100
SetupDtData:
Tot_Parz_Dosatore:
2020-06-30 19:56:21: 1225.481
2020-11-16 13:01:33: 5419.626
2022-03-14 11:33:21: 20782.475
2022-11-21 08:48:21: 27770.447
2023-03-07 15:40:44: 30951.118
Tot_Dosatore:
2020-06-30 19:56:21: 9053.072
2020-11-16 13:01:33: 13247.217
2022-03-14 11:33:21: 28610.066
2022-11-21 08:48:21: 35598.038
2023-03-07 15:40:44: 38778.709
+125 -83
View File
@@ -1,35 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MapoDataFiller.Filler
namespace MapoDataFiller.Filler
{
public class InterClays
{
protected int valStep = 10;
protected int valMin = 500;
protected int valMax = 15000;
protected int numSec = 30;
protected int stepMin = 50;
protected int stepMax = 150;
#region Public Properties
protected int waitMin = 10;
protected int waitMax = 240;
public SimSetup currSetup { get; set; } = new SimSetup();
protected int numPerMax = 50;
#endregion Public Properties
protected Random rnd = new Random();
#region Public Methods
/// <summary>
/// Restituisce elenco righe da caricare sul DB dato periodo indicato
/// </summary>
/// <param name="fillMode"></param>
/// <param name="CodIOB"></param>
/// <param name="currDay"></param>
/// <returns></returns>
public SimBlock GetDataRows(string fillMode, DayConf currDay)
public SimBlock GetDataRows(string CodIOB, DayConf currDay)
{
string fileConf = Path.Combine("Conf", $"{CodIOB}.yaml");
if (File.Exists(fileConf))
{
currSetup = SimSetup.readConf(fileConf);
}
SimBlock answ = new SimBlock();
int idxEv = 0;
int idxFl = 0;
@@ -38,7 +32,7 @@ namespace MapoDataFiller.Filler
List<string> nextRowsEV = new List<string>();
int valReq = 0;
int valCurr = 0;
// simulo periodi
// simulo periodi
int numPer = rnd.Next(10, numPerMax);
// calcolo durata media periodi in minuti
double avgDurPer = (currDay.dtEnd.Subtract(currDay.dtStart).TotalMinutes) / numPer;
@@ -47,46 +41,133 @@ namespace MapoDataFiller.Filler
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($"INTERCL_02;{dtStart:yyyy-MM-dd HH:mm:ss.fff};IOB-STATUS;IOB Started;{idxFl++}");
answ.EvList.Add($"INTERCL_02;{dtStart:yyyy-MM-dd HH:mm:ss.fff};14;ND;[{idxEv++}] 00;0;-");
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));
dtStart = dtEnd.AddSeconds(rnd.Next(25, 35));
dtEnd = dtStart.AddMinutes(avgDurPer * rnd.Next(600, 1400) / 1000);
// verifico se DEVO finire caricamento...
if (valCurr < valReq)
// verifico il tipo di CodIOB
if (CodIOB == "INTERCL_01")
{
doProd = true;
}
else
{
// tiro a dadi x decidere SE ho pesate nel periodo... 5% dei casi
doProd = (rnd.Next(0, 100) <= 5);
// 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: 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(dtStart, dtEnd, doProd, valReq, ref idxFl, ref valCurr);
// EvList: genero righe FL x periodo e sommo
nextRowsEV = IC_OX_getEvRows(dtStart, dtEnd, doProd, ref idxEv);
}
// FluxLOG: genero righe FL x periodo e sommo
nextRowsFL = IC_OX_getFlRows(dtStart, dtEnd, doProd, valReq, ref idxFl, ref valCurr);
// accodo
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(dtStart, dtEnd, doProd, valReq, ref idxFl, ref valCurr);
// EvList: genero righe FL x periodo e sommo
nextRowsEV = IC_OX_getEvRows(dtStart, dtEnd, doProd, ref idxEv);
}
// accodo FL
answ.FlList.AddRange(nextRowsFL);
// EvList: genero righe FL x periodo e sommo
nextRowsEV = IC_OX_getEvRows(dtStart, dtEnd, doProd, ref idxEv);
// accodo
// accodo EV
answ.EvList.AddRange(nextRowsEV);
}
// aggiungo chiusura eventi...
dtStart = dtEnd.AddSeconds(rnd.Next(25, 35));
answ.EvList.Add($"INTERCL_02;{dtStart:yyyy-MM-dd HH:mm:ss.fff};15;ND;[{idxEv++}] 01;0;-");
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($"INTERCL_02;{dtStart:yyyy-MM-dd HH:mm:ss.fff};14;ND;[{idxEv++}] 00;0;-");
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="dtStart"></param>
/// <param name="dtEnd"></param>
/// <param name="doProd"></param>
/// <param name="idxCount"></param>
/// <returns></returns>
protected List<string> IC_OX_getEvRows(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 = $"INTERCL_02;{dtStart.AddSeconds(5):yyyy-MM-dd HH:mm:ss.fff};16;ND;[{idxCount++}] 23;0;-";
rows.Add(currRow);
currRow = $"INTERCL_02;{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 = $"INTERCL_02;{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 = $"INTERCL_02;{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>
@@ -126,45 +207,6 @@ namespace MapoDataFiller.Filler
return rows;
}
/// <summary>
/// Simulo un blocco dati FL
/// </summary>
/// <param name="dtStart"></param>
/// <param name="dtEnd"></param>
/// <param name="doProd"></param>
/// <param name="idxCount"></param>
/// <returns></returns>
protected List<string> IC_OX_getEvRows(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 = $"INTERCL_02;{dtStart:yyyy-MM-dd HH:mm:ss.fff};16;ND;[{idxCount++}] 23;0;-";
currRow = $"INTERCL_02;{dtEnd:yyyy-MM-dd HH:mm:ss.fff};15;ND;[{idxCount++}] 01;0;-";
}
// 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 = $"INTERCL_02;{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 = $"INTERCL_02;{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;
}
#endregion Protected Methods
}
}
}
+33
View File
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization;
namespace MapoDataFiller
{
public class SimSetup
{
public Dictionary<string, Dictionary<int, int>> SetupSimInt { get; set; } = new Dictionary<string, Dictionary<int, int>>();
public Dictionary<string, Dictionary<int, float>> SetupSimFloat { get; set; } = new Dictionary<string, Dictionary<int, float>>();
public Dictionary<string, Dictionary<DateTime, float>> SetupDtData { get; set; } = new Dictionary<string, Dictionary<DateTime, float>>();
public static SimSetup readConf(string filePath)
{
SimSetup retObj = new SimSetup();
if (File.Exists(filePath))
{
var deserializer = new DeserializerBuilder()
.WithNamingConvention(new PascalCaseNamingConvention())
.Build();
string rawData = File.ReadAllText(filePath);
var input = new StringReader(rawData);
retObj = deserializer.Deserialize<SimSetup>(input);
}
return retObj;
}
}
}
+2 -2
View File
@@ -13,7 +13,7 @@ namespace MapoDataFiller
public class MConf
{
public string ConfDir { get; set; } = "";
public string FillMode { get; set; } = "";
public string CodIOB { get; set; } = "";
public bool HasHeader { get; set; } = false;
public string TimeTable { get; set; } = "";
public string OutFolder { get; set; } = "";
@@ -21,7 +21,7 @@ namespace MapoDataFiller
public MConf()
{
ConfDir = @"C:\temp\Interclays\";
FillMode = "NONE";
CodIOB = "NONE";
HasHeader = false;
TimeTable = "Demo.csv";
OutFolder = @"C:\temp\Interclays\Out";
+6
View File
@@ -16,6 +16,12 @@
<None Update="conf.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Conf\INTERCL_02.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Conf\INTERCL_01.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
+90 -54
View File
@@ -29,67 +29,103 @@ while (!pathOk)
pathOk = AnsiConsole.Confirm("Confermi ConfDir?");
}
AnsiConsole.MarkupLineInterpolated($"Conf FillMode: [yellow]{currConf.FillMode}[/]");
var fillOK = AnsiConsole.Confirm("Confermi FillMode?");
while (!fillOK)
// ora leggo i file di conf yaml e presento opzione...
if (!Directory.Exists(currConf.ConfDir))
{
currConf.FillMode = AnsiConsole.Ask<string>("Inserisci il modo desiderato:");
AnsiConsole.WriteLine(currConf.FillMode);
fillOK = AnsiConsole.Confirm("Confermi FillMode?");
// segnalo errore, credo directory
AnsiConsole.WriteLine("Conf directory not found! exiting...");
Directory.CreateDirectory(currConf.ConfDir);
}
AnsiConsole.MarkupLineInterpolated($"Conf HasHeader: [yellow]{currConf.HasHeader}[/]");
var headOK = AnsiConsole.Confirm("Confermi HasHeader?");
while (!headOK)
else
{
currConf.HasHeader = AnsiConsole.Ask<bool>("HasHeader (true/false)?");
AnsiConsole.WriteLine(currConf.HasHeader);
headOK = AnsiConsole.Confirm("Confermi HasHeader?");
}
// leggo timetable
string filePath = Path.Combine(currConf.ConfDir, currConf.TimeTable);
if (File.Exists(filePath))
{
var righe = File.ReadAllLines(filePath).ToList();
// se devo saltare
if (currConf.HasHeader)
// leggo elenco file yaml e presento alternativa
var fileOpt = Directory.GetFiles(currConf.ConfDir, "*.yaml");
if (fileOpt.Length == 0)
{
righe = righe.Skip(1).ToList();
AnsiConsole.WriteLine("Sim Conf file not found, exiting!");
}
// svuoto cartella output
if (!Directory.Exists(currConf.OutFolder))
else
{
Directory.CreateDirectory(currConf.OutFolder);
}
var fileList = Directory.GetFiles(currConf.OutFolder);
foreach (var file in fileList)
{
File.Delete(file);
}
var fileSel = AnsiConsole.Prompt(
new SelectionPrompt<string>()
.Title("Quale file vuoi [green]processare[/]?")
.PageSize(10)
.MoreChoicesText("[grey](Usare up/down per scorrere)[/]")
.AddChoices(fileOpt));
// verifico quale oggetto sim avviare... x ora SOLO interclays
InterClays currSim = new InterClays();
// ciclo su ogni record
foreach (var riga in righe)
{
// recupero dati del giorno corrente
var giornata = new DayConf("CsvDateDur", riga);
var simDataBlock = currSim.GetDataRows(currConf.FillMode, giornata);
// scrivo sul file mensile i dati del singolo giorno...
string pathFileFL = Path.Combine(currConf.OutFolder, $"{currConf.FillMode}_FL_{giornata.dtStart:yyyy-MM}.csv");
if (!File.Exists(pathFileFL))
// leggo la conf del file selezionato...
if (!string.IsNullOrEmpty(fileSel))
{
File.WriteAllText(pathFileFL,"");
currConf = CMan.readConf(fileSel);
#if false
// procedo come prima
AnsiConsole.MarkupLineInterpolated($"Conf FillMode: [yellow]{currConf.FillMode}[/]");
var fillOK = AnsiConsole.Confirm("Confermi FillMode?");
while (!fillOK)
{
currConf.FillMode = AnsiConsole.Ask<string>("Inserisci il modo desiderato:");
AnsiConsole.WriteLine(currConf.FillMode);
fillOK = AnsiConsole.Confirm("Confermi FillMode?");
}
AnsiConsole.MarkupLineInterpolated($"Conf HasHeader: [yellow]{currConf.HasHeader}[/]");
var headOK = AnsiConsole.Confirm("Confermi HasHeader?");
while (!headOK)
{
currConf.HasHeader = AnsiConsole.Ask<bool>("HasHeader (true/false)?");
AnsiConsole.WriteLine(currConf.HasHeader);
headOK = AnsiConsole.Confirm("Confermi HasHeader?");
}
#endif
// leggo timetable
string filePath = Path.Combine(currConf.ConfDir, currConf.TimeTable);
if (File.Exists(filePath))
{
var righe = File.ReadAllLines(filePath).ToList();
// se devo saltare
if (currConf.HasHeader)
{
righe = righe.Skip(1).ToList();
}
// svuoto cartella output
if (!Directory.Exists(currConf.OutFolder))
{
Directory.CreateDirectory(currConf.OutFolder);
}
var fileList = Directory.GetFiles(currConf.OutFolder);
foreach (var file in fileList)
{
File.Delete(file);
}
// verifico quale oggetto sim avviare... x ora SOLO interclays
InterClays currSim = new InterClays();
// ciclo su ogni record
foreach (var riga in righe)
{
// recupero dati del giorno corrente
var giornata = new DayConf("CsvDateDur", riga);
var simDataBlock = currSim.GetDataRows(currConf.CodIOB, giornata);
// scrivo sul file annuale i dati del singolo giorno...
string pathFileFL = Path.Combine(currConf.OutFolder, $"{currConf.CodIOB}_FL_{giornata.dtStart:yyyy}.csv");
if (!File.Exists(pathFileFL))
{
File.WriteAllText(pathFileFL, "");
}
string pathFileEL = Path.Combine(currConf.OutFolder, $"{currConf.CodIOB}_EL_{giornata.dtStart:yyyy}.csv");
if (!File.Exists(pathFileEL))
{
File.WriteAllText(pathFileEL, "");
}
// vado in append...
File.AppendAllLines(pathFileFL, simDataBlock.FlList);
File.AppendAllLines(pathFileEL, simDataBlock.EvList);
}
}
}
string pathFileEL = Path.Combine(currConf.OutFolder, $"{currConf.FillMode}_EL_{giornata.dtStart:yyyy-MM}.csv");
if (!File.Exists(pathFileEL))
{
File.WriteAllText(pathFileEL, "");
}
// vado in append...
File.AppendAllLines(pathFileFL, simDataBlock.FlList);
File.AppendAllLines(pathFileEL, simDataBlock.EvList);
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
---
ConfDir: C:\temp\Interclays
FillMode: Interclays02
CodIOB: INTERCL_02
HasHeader: true
TimeTable: Interclays02.csv
OutFolder: C:\temp\Interclays\Out