- Spostamento metodo da pagina a controller/servizio

- check su SM In2Ev
This commit is contained in:
Samuele Locatelli
2023-08-01 16:57:23 +02:00
parent 3f1c488685
commit 329fd4b099
9 changed files with 484 additions and 130 deletions
+27 -9
View File
@@ -1,15 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SMGen.Data.Data
namespace SMGen.Data.Data
{
public class FilesClass
{
public string provFileName { get; set; } = "";
#region Public Properties
/// <summary>
/// Indica che è in esecuzione il processing del file (quando è in una lista di file da processare)
/// </summary>
public bool calcRunning { get; set; } = false;
/// <summary>
/// File name x download finale file csv
/// </summary>
public string DLoadFileName { get; set; } = "";
/// <summary>
/// Boolean indica che è stato processato e salvato (DB/File)
/// </summary>
public bool isOk { get; set; } = false;
/// <summary>
/// File name temporaneo (autogenerato scrambled)
/// </summary>
public string tempFileName { get; set; } = "";
/// <summary>
/// File name originale (caricato)
/// </summary>
public string origFileName { get; set; } = "";
#endregion Public Properties
}
}
}
+9 -1
View File
@@ -30,11 +30,19 @@
<ItemGroup>
<Folder Include="Controllers\" />
<Folder Include="DTO\" />
<Folder Include="SqlScripts\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SMGen.Core\SMGen.Core.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="dto\.placeholder">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SqlScripts\.placeholder">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
+375 -68
View File
@@ -2,49 +2,25 @@
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using NLog;
using Org.BouncyCastle.Asn1.Pkcs;
using SMGen.Core;
using SMGen;
using SMGen.Data.Controllers;
using SMGen.Data.Data;
using SMGen.Data.DbModels;
using StackExchange.Redis;
using System.Diagnostics;
using SMGen.Data;
using SMGen.Data.Data;
using System.Text;
namespace SMGen.Data.Services
{
public class SMGDataService
{
#region Public Fields
public static SMGenController dbController = null!;
private static IConfiguration _configuration = null!;
#endregion Public Fields
private static JsonSerializerSettings? JSSettings;
private static Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
/// Durata cache lunga IN SECONDI
/// </summary>
private int cacheTtlLong = 60 * 5;
/// <summary>
/// Durata cache breve IN SECONDI
/// </summary>
private int cacheTtlShort = 60 * 1;
/// <summary>
/// Oggetto per connessione a REDIS
/// </summary>
private IConnectionMultiplexer redisConn;
/// <summary>
/// Oggetto DB redis da impiegare x chiamate R/W
/// </summary>
private IDatabase redisDb = null!;
private Random rnd = new Random();
#region Public Constructors
public SMGDataService(IConfiguration configuration, IConnectionMultiplexer redisConnMult)
{
@@ -75,54 +51,24 @@ namespace SMGen.Data.Services
// chiudo log
Log.Info("Avviata classe WebDoorCreatorService");
}
#endregion Public Constructors
#region Public Properties
public string CodApp { get; set; } = "";
#endregion Public Properties
#region Public Methods
public async Task<bool> TranInInsert(List<TransizioneIngressiModelTemp> newTIList, int currIdxFamiglia)
{
var dbResult = await dbController.TranInInsert(newTIList, currIdxFamiglia);
return dbResult;
}
public async Task<bool> AnagEventinInsert(List<AnagEventiModelTemp> newEvList)
{
var dbResult = await dbController.AnagEventinInsert(newEvList);
return dbResult;
}
public async Task<bool> FilesLoadRedis(Dictionary<string, FilesClass> filesDict)
{
bool fatto = false;
string currKey = $"{Constants.FILES_TO_PROC}";
await ExecFlushRedisPattern(currKey);
foreach (var item in filesDict)
{
string valSer = JsonConvert.SerializeObject(item.Value, JSSettings);
await RedHashUpsert(currKey, item.Key, valSer);
}
fatto = true;
return fatto;
}
public async Task<bool> FileUpdate(string origFileName, FilesClass fileNewInfo)
{
bool fatto = false;
string currKey = $"{Constants.FILES_TO_PROC}";
//await ExecFlushRedisPattern(currKey);
string valSer = JsonConvert.SerializeObject(fileNewInfo, JSSettings);
await RedHashUpsert(currKey, origFileName, valSer);
fatto = true;
return fatto;
}
/// <summary>
///
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
@@ -162,6 +108,332 @@ namespace SMGen.Data.Services
return dbResult;
}
public async Task<bool> FilesLoadRedis(Dictionary<string, FilesClass> filesDict)
{
bool fatto = false;
string currKey = $"{Constants.FILES_TO_PROC}";
await ExecFlushRedisPattern(currKey);
foreach (var item in filesDict)
{
string valSer = JsonConvert.SerializeObject(item.Value, JSSettings);
await RedHashUpsert(currKey, item.Key, valSer);
}
fatto = true;
return fatto;
}
public async Task<bool> FileUpdate(string origFileName, FilesClass fileNewInfo)
{
bool fatto = false;
string currKey = $"{Constants.FILES_TO_PROC}";
//await ExecFlushRedisPattern(currKey);
string valSer = JsonConvert.SerializeObject(fileNewInfo, JSSettings);
await RedHashUpsert(currKey, origFileName, valSer);
fatto = true;
return fatto;
}
public async Task<bool> TranInInsert(List<TransizioneIngressiModelTemp> newTIList, int currIdxFamiglia)
{
var dbResult = await dbController.TranInInsert(newTIList, currIdxFamiglia);
return dbResult;
}
#endregion Public Methods
private List<TransizioneIngressiModelTemp> TranInList2add { get; set; } = new List<TransizioneIngressiModelTemp>();
private int n_states = 0;
private bool b_rules_definition = false;
private int n_bits = 0;
private string sz_state_machine_name = "";
private string n_state_machine_index = "";
private List<RuleClass> Rules { get; set; } = new List<RuleClass>();
private List<string> Bits { get; set; } = new List<string>();
private List<string> Events_to_send { get; set; } = new List<string>();
private List<AnagEventiModelTemp> events2Add { get; set; } = new List<AnagEventiModelTemp>();
private List<string> States { get; set; } = new List<string>();
/// <summary>
/// Valuta un file di ruoles x ingressi 2 eventi e restituisce esito
/// </summary>
/// <param name="currFile">Path file *.rul da processare</param>
/// <param name="saveToDb">Indica se salvare sul DB</param>
/// <returns></returns>
public async Task<FilesClass> EvalIn2EvRuleFile(FilesClass currFile, bool saveToDb)
{
await Task.Delay(1);
sz_state_machine_name = "";
n_state_machine_index = "";
n_states = 0;
n_bits = 0;
States.Clear();
Bits.Clear();
Events_to_send.Clear();
Rules.Clear();
// recupero nome file x partire
string filePath = currFile.tempFileName;
// stream lettura file
using (StreamReader sr = new StreamReader(filePath))
{
string line = "";
while ((line = await sr.ReadLineAsync().ConfigureAwait(false)) != null)
{
if (!line.StartsWith("#") && !string.IsNullOrEmpty(line))
{
if (line.Contains("#"))
{
var lineSplit = line.Split("#");
line = lineSplit[0];
}
var sz_tokens = line.Split(":");
var sz_temp = sz_tokens[0].Trim();
switch (sz_temp)
{
case "$DEFINITIONS":
b_rules_definition = false;
break;
case "$NAME":
sz_state_machine_name = sz_tokens[1].Trim();
break;
case "$IDX":
n_state_machine_index = sz_tokens[1].Trim();
break;
case "$N_STATES":
n_states = int.Parse(sz_tokens[1].Trim());
break;
case "$N_BITS":
n_bits = int.Parse(sz_tokens[1].Trim());
break;
case "$BIT":
Bits.Add(sz_tokens[2].Trim().ToUpper());
break;
case "$STATE":
States.Add(sz_tokens[2].Trim().ToUpper());
break;
case "$EVENT":
Events_to_send.Add(sz_tokens[2].Trim().ToUpper());
var newEvent = new AnagEventiModelTemp()
{
IdxTipo = int.Parse(sz_tokens[1].Trim().ToUpper()),
Nome = sz_tokens[2].Trim().ToUpper()
};
events2Add.Add(newEvent);
break;
case "$RULES":
b_rules_definition = true;
break;
case "$DO":
b_rules_definition = false;
var isOk = checkDirExist(procRootDir);
if (isOk)
{
var fileName = $"{currFile.origFileName.Split(".")[0]}.csv";
currFile.DLoadFileName = $"{Path.Combine(procRootDir, bitCsvPath, fileName)}";
currFile = await evalIn2Ev_transitions(currFile);
if (saveToDb)
{
await AnagEventinInsert(events2Add);
await Task.Delay(1);
await TranInInsert(TranInList2add, int.Parse(n_state_machine_index));
}
}
break;
default:
if (b_rules_definition)
{
var temp_rule = new RuleClass()
{
state = sz_temp.Trim().ToUpper(),
expression = sz_tokens[1].Trim().ToUpper(),
next_state = sz_tokens[2].Trim().ToUpper(),
event_to_send = sz_tokens[3].Trim().ToUpper()
};
Rules.Add(temp_rule);
}
break;
}
}
}
}
return currFile;
}
/// <summary>
/// Valutazione schema macchina a stati x Ingressi --> Eventi
/// </summary>
/// <param name="sz_file2Write"></param>
/// <param name="origFileName"></param>
/// <returns></returns>
protected async Task<FilesClass> evalIn2Ev_transitions(FilesClass currFile)
{
await Task.Delay(1);
StringBuilder sb = new StringBuilder();
TranInList2add.Clear();
if (File.Exists(currFile.DLoadFileName))
{
File.Delete(currFile.DLoadFileName);
}
sb.AppendLine("IdxFamigliaIngresso;IdxMicroStato;ValoreIngresso;IdxTipoEvento;next_IdxMicroStato");
string sz_actual_state = "";
string sz_actual_bit = "";
string sz_line = "";
//int i = 0;
int n_input = 0;
//int n = 0;
int n_mask = 0;
int n_bit = 0;
bool[] b_bit = new bool[20];
bool b_invert = false;
//ciclo negli stati
try
{
for (var i = 0; i <= n_states - 1; i++)
{
sz_actual_state = States.ToArray()[i];
//ciclo negli ingressi
for (n_input = 0; n_input <= (Math.Pow(2, n_bits) - 1); n_input++)
{
n_mask = 1;
for (var n = 0; n <= n_bits - 1; n++)
{
b_bit[n] = Convert.ToBoolean(n_input & n_mask);
n_mask = n_mask << 1;
}
var exitFor = false;
foreach (var act_rule in Rules)
{
n_bit = -1;
if ((act_rule.state == "ALL_STATES") || (act_rule.state == sz_actual_state))
{
//DA RESETTARE A FALSE (errore da principianti...)
b_invert = false;
sz_actual_bit = act_rule.expression;
//controllo se la riga contiene l'istruzione per negare il bit
if (sz_actual_bit.Trim().StartsWith("NOT"))
{
//inverto il bit
b_invert = true;
sz_actual_bit = sz_actual_bit.Replace("NOT ", "").Trim();
}
//cerca il nome del bit e ne trova l' indice da 0
n_bit = Bits.FindIndex(x => x == sz_actual_bit);
if (n_bit == -1)
{
exitFor = true;
}
int nextState = States.IndexOf(act_rule.next_state);
if (!exitFor)
{
if (((!b_invert) && b_bit[n_bit]) || (b_invert && (!b_bit[n_bit])))
{
sz_line = "";
//eseguo solo se diverso dallo stato corrente
if (States.IndexOf(act_rule.next_state) != i)
{
if (nextState < 0)
{
nextState = 0;
}
sz_line = $"{n_state_machine_index}" +
$";" +
$"{i}" +
$";" +
$"{n_input}" +
$";" +
$"{Events_to_send.IndexOf(act_rule.event_to_send)}" +
$";" +
$"{nextState}";
sb.AppendLine(sz_line);
var newTranIn = new TransizioneIngressiModelTemp()
{
IdxFamigliaIngresso = int.Parse(n_state_machine_index),
IdxMicroStato = i,
ValoreIngresso = n_input,
IdxTipoEvento = Events_to_send.IndexOf(act_rule.event_to_send),
next_IdxMicroStato = States.IndexOf(act_rule.next_state)
};
TranInList2add.Add(newTranIn);
}
exitFor = true;
}
}
}
}
}
}
using (StreamWriter sw = new StreamWriter(currFile.DLoadFileName))
{
sw.Write(sb.ToString());
}
await Task.Delay(1);
currFile.isOk = true;
await FileUpdate(currFile.origFileName, currFile);
}
catch (Exception exc)
{
Log.Error($"Eccezione in evalIn2Ev_transitions{Environment.NewLine}{exc}");
}
return currFile;
}
protected string bitCsvPath
{
get => _configuration.GetValue<string>("ServerConf:BitCsvPath");
}
protected string procRootDir
{
get => _configuration.GetValue<string>("ServerConf:ProcCsvRootPath");
}
private bool checkDirExist(string dir)
{
bool answ = Directory.Exists(dir);
if (!answ)
{
var dirCreate = Directory.CreateDirectory(dir);
answ = (dirCreate != null);
}
return answ;
}
#region Protected Methods
/// <summary>
/// Effettua upsert in HasList redis
/// </summary>
@@ -181,6 +453,41 @@ namespace SMGen.Data.Services
Log.Trace($"RedHashUpsert | {currKey} | in: {ts.TotalMilliseconds} ms");
return numReq;
}
#endregion Protected Methods
#region Private Fields
private static IConfiguration _configuration = null!;
private static JsonSerializerSettings? JSSettings;
private static Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
/// Durata cache lunga IN SECONDI
/// </summary>
private int cacheTtlLong = 60 * 5;
/// <summary>
/// Durata cache breve IN SECONDI
/// </summary>
private int cacheTtlShort = 60 * 1;
/// <summary>
/// Oggetto per connessione a REDIS
/// </summary>
private IConnectionMultiplexer redisConn;
/// <summary>
/// Oggetto DB redis da impiegare x chiamate R/W
/// </summary>
private IDatabase redisDb = null!;
private Random rnd = new Random();
#endregion Private Fields
#region Private Properties
/// <summary>
View File
View File
+17 -3
View File
@@ -4,7 +4,12 @@
<tr>
<th scope="col">Rul file</th>
<th scope="col">Status</th>
<th scope="col"></th>
<th scope="col">
@if(Files!=null && Files.Count>0)
{
<button @onclick="()=>Read_rule_file_transitions()">Process</button>
}
</th>
</tr>
</thead>
<tbody>
@@ -22,9 +27,18 @@
}
else
{
<td class="text-danger"><i class="fa-solid fa-circle-xmark"></i></td>
<td class="text-danger">
<i class="fa-solid fa-circle-xmark"></i>
</td>
<td>
<a class="btn btn-sm text-decoration-none" disabled><i class="fa-solid fa-download text-secondary"></i></a>
@if (item.Value.calcRunning)
{
<LoadingData DisplaySize="LoadingData.CtrlSize.Small" DisplayMode="LoadingData.SpinMode.BounceLine"></LoadingData>
}
else
{
<a class="btn btn-sm text-decoration-none" disabled><i class="fa-solid fa-download text-secondary"></i></a>
}
</td>
}
+17
View File
@@ -17,6 +17,7 @@ using SMGen.Components;
using SMGen.Data;
using SMGen.Data.Data;
using SMGen.Data.Services;
using SMGen.Data.DbModels;
namespace SMGen.Components
{
@@ -87,5 +88,21 @@ namespace SMGen.Components
Files = FilesTemp.Skip(numRecord * (currPage - 1)).Take(numRecord).ToDictionary(x => x.Key, y => y.Value);
await InvokeAsync(() => StateHasChanged());
}
protected async Task Read_rule_file_transitions()
{
Files = await SMGDService.FilesGetAll();
foreach (var item in Files)
{
item.Value.calcRunning = true;
await InvokeAsync(() => StateHasChanged());
await Task.Delay(1);
// chiamo esecuzione 1:1...
await SMGDService.EvalIn2EvRuleFile(item.Value, true);
item.Value.calcRunning = false;
await InvokeAsync(() => StateHasChanged());
}
}
}
}
+2 -10
View File
@@ -247,7 +247,7 @@ namespace SMGen.Pages
foreach (var item in Files)
{
sz_file2Read = item.Value.provFileName;
sz_file2Read = item.Value.tempFileName;
using (StreamReader sr = new StreamReader(sz_file2Read))
{
@@ -280,12 +280,6 @@ namespace SMGen.Pages
case "$IDX":
n_state_machine_index = sz_tokens[1].Trim();
break;
#if false
case "$N_STATES":
n_states = int.Parse(sz_tokens[1].Trim());
break;
#endif
case "$STATE":
StatesAll.Add(sz_tokens[2].Trim().ToUpper(), int.Parse(sz_tokens[1].Trim().ToUpper()));
@@ -334,8 +328,6 @@ namespace SMGen.Pages
}
break;
}
//fileLines.Add(lineSplit[0]);
}
}
}
@@ -460,7 +452,7 @@ namespace SMGen.Pages
var newFIle = new FilesClass()
{
provFileName = pathFile,
tempFileName = pathFile,
isOk = false
};
+37 -39
View File
@@ -15,13 +15,13 @@ namespace SMGen.Pages
{
#region Protected Fields
protected static Logger Log = LogManager.GetCurrentClassLogger();
protected SelectSMIn2EvParams currFilter = new SelectSMIn2EvParams();
protected DataPager? pagerSMIn2Ev = null!;
#endregion Protected Fields
protected Dictionary<string, FilesClass> Files { get; set; } = new Dictionary<string, FilesClass>();
#region Protected Properties
protected bool b_rules_definition { get; set; } = false;
@@ -33,6 +33,27 @@ namespace SMGen.Pages
protected List<string> Bits { get; set; } = new List<string>();
protected string circleCssColor
{
get
{
string answ = "";
if ((Files.Count() >= (Files.Count() / 100) * 60) && (Files.Count() <= (Files.Count() / 100) * 90))
{
answ = "#F1C40F";
}
else if ((Files.Count() >= (Files.Count() / 100) * 90))
{
answ = "#C0392B";
}
else
{
answ = "#27AE60";
}
return answ;
}
}
[Inject]
protected IConfiguration conf { get; set; } = null!;
@@ -40,13 +61,12 @@ namespace SMGen.Pages
protected IWebHostEnvironment env { get; set; } = null!;
protected List<string> Events_to_send { get; set; } = new List<string>();
protected List<AnagEventiModelTemp> events2Add { get; set; } = new List<AnagEventiModelTemp>();
protected List<string> fileLines { get; set; } = new List<string>();
protected Dictionary<string, FilesClass> Files { get; set; } = new Dictionary<string, FilesClass>();
protected Dictionary<string, string> files2Read { get; set; } = new Dictionary<string, string>();
protected int maxAllowedFiles { get; set; } = 100;
protected int n_bits { get; set; } = 0;
protected string n_state_machine_index { get; set; } = "";
@@ -77,38 +97,12 @@ namespace SMGen.Pages
protected string sz_file2Write { get; set; } = "prova.csv";
protected string sz_state_machine_name { get; set; } = "";
protected string circleCssColor
{
get
{
string answ = "";
if ((Files.Count() >= (Files.Count() / 100) * 60) && (Files.Count() <= (Files.Count() / 100) * 90))
{
answ = "#F1C40F";
}
else if ((Files.Count() >= (Files.Count() / 100) * 90))
{
answ = "#C0392B";
}
else
{
answ = "#27AE60";
}
return answ;
}
}
protected List<TransizioneIngressiModelTemp> TranInList2add { get; set; } = new List<TransizioneIngressiModelTemp>();
#endregion Protected Properties
#region Protected Methods
protected override async Task OnInitializedAsync()
{
await Task.Delay(1);
await SMGDService.ExecFlushRedisPattern(Constants.FILES_TO_PROC);
}
protected bool checkDirExist(string dir)
{
bool answ = false;
@@ -277,6 +271,12 @@ namespace SMGen.Pages
currPage = newNum;
}
protected override async Task OnInitializedAsync()
{
await Task.Delay(1);
await SMGDService.ExecFlushRedisPattern(Constants.FILES_TO_PROC);
}
protected async Task pgResetReq(bool doReset)
{
if (doReset)
@@ -303,7 +303,7 @@ namespace SMGen.Pages
Bits.Clear();
Events_to_send.Clear();
Rules.Clear();
sz_file2Read = item.Value.provFileName;
sz_file2Read = item.Value.tempFileName;
using (StreamReader sr = new StreamReader(sz_file2Read))
{
@@ -480,8 +480,6 @@ namespace SMGen.Pages
}
}
protected int maxAllowedFiles { get; set; } = 100;
//// va dopo
//private StreamWriter objWriter { get; set; };
private async Task LoadFiles(InputFileChangeEventArgs e)
@@ -527,11 +525,13 @@ namespace SMGen.Pages
if (file.Name.Contains(".rul"))
{
var newFIle = new FilesClass()
{
provFileName = pathFile,
isOk = false
tempFileName = pathFile,
isOk = false,
origFileName = file.Name,
calcRunning = false,
DLoadFileName = ""
};
Files.Add(file.Name, newFIle);
@@ -541,7 +541,6 @@ namespace SMGen.Pages
{
Log.Error($"Errore durante salvataggio file temp {file.Name}: {exc}{Environment.NewLine}");
}
}
if (Files != null && Files.Count > 0)
{
@@ -549,7 +548,6 @@ namespace SMGen.Pages
}
await InvokeAsync(() => StateHasChanged());
}
protected static Logger Log = LogManager.GetCurrentClassLogger();
#endregion Private Methods
}