Algoritmo bilanciamento vers 0.3

This commit is contained in:
Samuele Locatelli
2021-06-10 19:14:24 +02:00
parent dc4601ff7e
commit 5a570d6ad0
8 changed files with 350 additions and 37 deletions
+15 -12
View File
@@ -1411,23 +1411,26 @@ namespace AppData
/// </summary>
public static Dictionary<string, DS_App.OrderListDataTable> OrdersExtByBatch(int BatchId, string PlaceCod)
{
DataLayer DLMan = new DataLayer();
string redKey = $"{redOrders}:BYBATCH:{BatchId}";
string rawData = "";
Dictionary<string, DS_App.OrderListDataTable> answ = new Dictionary<string, DS_App.OrderListDataTable>();
// cerco in redis
if (memLayer.ML.redKeyPresent(redKey))
if (BatchId > 0)
{
rawData = memLayer.ML.getRSV(redKey);
if (!string.IsNullOrEmpty(rawData))
DataLayer DLMan = new DataLayer();
string redKey = $"{redOrders}:BYBATCH:{BatchId}";
string rawData = "";
// cerco in redis
if (memLayer.ML.redKeyPresent(redKey))
{
try
rawData = memLayer.ML.getRSV(redKey);
if (!string.IsNullOrEmpty(rawData))
{
answ = JsonConvert.DeserializeObject<Dictionary<string, DS_App.OrderListDataTable>>(rawData);
try
{
answ = JsonConvert.DeserializeObject<Dictionary<string, DS_App.OrderListDataTable>>(rawData);
}
catch
{ }
}
catch
{ }
}
// se vuoto rileggo
if (answ.Count == 0)
Vendored
+2 -2
View File
@@ -12,8 +12,8 @@ pipeline {
/* calcolo numero versione... diverso x branch MASTER/DEVELOP */
script {
withEnv(['NEXT_BUILD_NUMBER=393']) {
// env.versionNumber = VersionNumber(versionNumberString : '1.3.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2019-07-01', skipFailedBuilds: true)
env.versionNumber = VersionNumber(versionNumberString : '1.3.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2019-07-01', skipFailedBuilds: true, overrideBuildsAllTime: '${NEXT_BUILD_NUMBER}')
// env.versionNumber = VersionNumber(versionNumberString : '2.0.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2019-07-01', skipFailedBuilds: true)
env.versionNumber = VersionNumber(versionNumberString : '2.0.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2019-07-01', skipFailedBuilds: true, overrideBuildsAllTime: '${NEXT_BUILD_NUMBER}')
env.versionNumberBeta = VersionNumber(versionNumberString : '1.3.${BUILD_DATE_FORMATTED, "yyMM"}-beta.${BUILDS_ALL_TIME}', projectStartDate : '2019-07-01', skipFailedBuilds: true, overrideBuildsAllTime: '${NEXT_BUILD_NUMBER}')
env.APP_NAME = 'NKC'
}
+42
View File
@@ -604,6 +604,48 @@ namespace NKC_SDK
#endregion Public Properties
}
/// <summary>
/// Classe simulazione di un assegnazione di un set di ordini (compreso score)
/// </summary>
public class OrderSetSim
{
#region Public Properties
/// <summary>
/// Valore attuale (somma dei punteggi degli elementi)
/// </summary>
public double ActualValue
{
get
{
return OrderSet.Sum(x => x.Value);
}
}
/// <summary>
/// Valore score (scostamento target/actual)
/// </summary>
public double IndexScore
{
get
{
return Math.Abs(TargetValue - ActualValue);
}
}
/// <summary>
/// Vettore Ordini + durate
/// </summary>
public Dictionary<int, double> OrderSet { get; set; } = new Dictionary<int, double>();
/// <summary>
/// Valore target durate desiderate
/// </summary>
public double TargetValue { get; set; } = 0;
#endregion Public Properties
}
/// <summary>
/// Classe che rappresenta stato ordine ricevuto via REDIS da NESTING
/// </summary>
+10 -3
View File
@@ -106,15 +106,22 @@
<span class="btn btn-secondary disabled"><b>NE02</b>
<asp:Label runat="server" ID="lblRatio02" />%</span>
</div>
<div class="col-12">
<div class="col-1">
<asp:LinkButton runat="server" ID="lbtSave" CssClass="btn btn-sm btn-success" OnClick="lbtSave_Click"><i class="fa fa-floppy-o" aria-hidden="true"></i></asp:LinkButton>
</div>
<div class="col-10">
<asp:HiddenField runat="server" ID="hfNeedSave" />
<asp:TextBox runat="server" ID="txtRatio" TextMode="Range" CssClass="form-control-range" AutoPostBack="true" OnTextChanged="txtRatio_TextChanged" />
</div>
<div class="col-1">
<asp:LinkButton runat="server" ID="lbtCancel" CssClass="btn btn-sm btn-warning" OnClick="lbtCancel_Click"><i class="fa fa-ban" aria-hidden="true"></i></asp:LinkButton>
</div>
<div class="col-6">
ORD LIST NE01 - summary
<uc1:cmp_orderExtList runat="server" id="cmp_orderExtListNE01" />
<uc1:cmp_orderExtList runat="server" ID="cmp_orderExtListNE01" />
</div>
<div class="col-6">
ORD LIST NE02- summary
<uc1:cmp_orderExtList runat="server" id="cmp_orderExtListNE02" />
<uc1:cmp_orderExtList runat="server" ID="cmp_orderExtListNE02" />
</div>
</div>
+236 -18
View File
@@ -19,6 +19,20 @@ namespace NKC_WF.WebUserControls
#region Protected Properties
protected bool needSave
{
get
{
bool answ = true;
bool.TryParse(hfNeedSave.Value, out answ);
return answ;
}
set
{
hfNeedSave.Value = $"{value}";
}
}
/// <summary>
/// Tabella dei batch Descendant di quello corrente
/// </summary>
@@ -30,7 +44,7 @@ namespace NKC_WF.WebUserControls
}
}
protected Dictionary<string, DS_App.OrderListDataTable> TabOrders
protected Dictionary<string, DS_App.OrderListDataTable> TabOrdersFromDb
{
get
{
@@ -39,6 +53,19 @@ namespace NKC_WF.WebUserControls
}
}
protected int valRatio
{
get
{
int answ = 50;
if (!string.IsNullOrEmpty(txtRatio.Text))
{
int.TryParse(txtRatio.Text, out answ);
}
return answ;
}
}
#endregion Protected Properties
#region Public Properties
@@ -222,8 +249,11 @@ namespace NKC_WF.WebUserControls
lblTestJson.Text = "<hr/>" + sbDebug.Replace("\r\n", "<br/>").ToString();
}
}
checkCreateDescendant();
showBatchDescendant();
if (BatchId > 0)
{
checkCreateDescendant();
showBatchDescendant();
}
}
get
{
@@ -263,11 +293,110 @@ namespace NKC_WF.WebUserControls
}
}
/// <summary>
/// effettua ribilanciamento ordini partendo da elenco completo e poi assegnando a impianti
/// </summary>
private void rebalanceOrder()
{
// costruisco vettore durata ordini
OrderSetSim FullSet = new OrderSetSim();
OrderSetSim SetNe01 = new OrderSetSim();
OrderSetSim SetNe02 = new OrderSetSim();
// creo liste x i valori da processare...
Dictionary<int, double> RawList = new Dictionary<int, double>();
Dictionary<int, double> OrderedList = new Dictionary<int, double>();
Dictionary<string, DS_App.OrderListDataTable> TabOrders = new Dictionary<string, DS_App.OrderListDataTable>(TabOrdersFromDb);
if (TabOrders.ContainsKey("VIRTNE"))
{
foreach (var item in TabOrders["VIRTNE"])
{
RawList.Add(item.OrdID, item.EstProcTime);
}
}
if (TabOrders.ContainsKey("NE01"))
{
foreach (var item in TabOrders["NE01"])
{
RawList.Add(item.OrdID, item.EstProcTime);
}
}
if (TabOrders.ContainsKey("NE02"))
{
foreach (var item in TabOrders["NE02"])
{
RawList.Add(item.OrdID, item.EstProcTime);
}
}
// ordino la lista x processing successivo
OrderedList = RawList.OrderBy(x => x.Value).ToDictionary(t => t.Key, t => t.Value);
// salvo i set
FullSet.OrderSet = OrderedList;
// IndexScore = errore di stima corrente
double IScoreCurr = FullSet.ActualValue;
// lavoro sull'ottimizzare il MINORE
double ValRatio = (double)valRatio / 100;
if (ValRatio <= 0.5)
{
SetNe01.TargetValue = FullSet.ActualValue * ValRatio;
SetNe01.OrderSet = findLocalMin(OrderedList, SetNe01.TargetValue, IScoreCurr);
// l'altro è la differenza
SetNe02.OrderSet = OrderedList;
foreach (var item in SetNe01.OrderSet)
{
SetNe02.OrderSet.Remove(item.Key);
}
}
else
{
SetNe02.TargetValue = FullSet.ActualValue * (1 - ValRatio);
SetNe02.OrderSet = findLocalMin(OrderedList, SetNe02.TargetValue, IScoreCurr);
// l'altro è la differenza
SetNe01.OrderSet = OrderedList;
foreach (var item in SetNe02.OrderSet)
{
SetNe01.OrderSet.Remove(item.Key);
}
}
// riorganizzo tabOrders...
List<OrderPrev> OrdersNe01 = new List<OrderPrev>();
List<OrderPrev> OrdersNe02 = new List<OrderPrev>();
foreach (var groupItem in TabOrders)
{
// ora guardo gli ordini...
foreach (var orderItem in groupItem.Value)
{
if (SetNe01.OrderSet.ContainsKey(orderItem.OrdID))
{
OrdersNe01.Add(new OrderPrev() { OrderId = orderItem.OrdID, OrderExtCode = orderItem.OrderExtCode, NumBin = orderItem.EstNumBin, NumCart = orderItem.EstNumCart, TotTime = orderItem.EstProcTime });
}
else
{
OrdersNe02.Add(new OrderPrev() { OrderId = orderItem.OrdID, OrderExtCode = orderItem.OrderExtCode, NumBin = orderItem.EstNumBin, NumCart = orderItem.EstNumCart, TotTime = orderItem.EstProcTime });
}
}
}
// ...e poi mostro
cmp_orderExtListNE01.CurrOrders = OrdersNe01;
cmp_orderExtListNE02.CurrOrders = OrdersNe02;
// --> richiede salvataggio
needSave = true;
}
/// <summary>
/// Mostro dati dei Batch descendant
/// </summary>
private void showBatchDescendant()
{
Dictionary<string, DS_App.OrderListDataTable> TabOrders = new Dictionary<string, DS_App.OrderListDataTable>(TabOrdersFromDb);
// se ho qualcosa aggiorno visualizzazione...
if (TabOrders.Count > 0)
{
@@ -275,10 +404,14 @@ namespace NKC_WF.WebUserControls
if (TabOrders["VIRTNE"].Count > 0)
{
// suddivido
rebalanceOrder();
}
else
{
//// ...e poi mostro
//cmp_orderExtListNE01.CurrOrders = TabOrders["NE01"];
//cmp_orderExtListNE02.CurrOrders = TabOrders["NE02"];
}
// ...e poi mostro
cmp_orderExtListNE01.CurrOrders = TabOrders["NE01"];
cmp_orderExtListNE02.CurrOrders = TabOrders["NE02"];
}
}
@@ -286,6 +419,94 @@ namespace NKC_WF.WebUserControls
#region Protected Methods
/// <summary>
/// Cerca il set con lo score migliore calcolando x subset della lista ordinata
/// </summary>
/// <param name="OrderedList">Lista ordinata oggetti (INT) + valore</param>
/// <param name="TargetVal">Valore desiderato (comeSOMMA)</param>
/// <param name="CurrIndexScore">Indice score = errore minimo da migliorare</param>
/// <returns></returns>
protected Dictionary<int, double> findLocalMin(Dictionary<int, double> OrderedList, double TargetVal, double CurrIndexScore)
{
Dictionary<int, double> answ = new Dictionary<int, double>();
List<OrderSetSim> Candidates = new List<OrderSetSim>();
OrderSetSim CurrSimSet = new OrderSetSim();
// parte dal valore (singolo) più piccolo tra quelli maggiori del target... se c'è...
var OrdSup = OrderedList.Where(x => x.Value > TargetVal).OrderBy(x => x.Value);
if (OrdSup != null && OrdSup.Any())
{
var currOrder = OrdSup.FirstOrDefault();
CurrSimSet = new OrderSetSim();
CurrSimSet.TargetValue = TargetVal;
CurrSimSet.OrderSet.Add(currOrder.Key, currOrder.Value);
// se lo score è migliorativo...
if (CurrSimSet.IndexScore < CurrIndexScore)
{
Candidates.Add(CurrSimSet);
CurrIndexScore = CurrSimSet.IndexScore;
}
}
// ora guardo gli elementi restanti.. se ci sono
var OrdInf = OrderedList.Where(x => x.Value <= TargetVal).OrderByDescending(x => x.Value).ToDictionary(t => t.Key, t => t.Value);
if (OrdInf != null && OrdInf.Any())
{
var currOrder = OrdInf.FirstOrDefault();
CurrSimSet = new OrderSetSim();
CurrSimSet.TargetValue = TargetVal;
CurrSimSet.OrderSet.Add(currOrder.Key, currOrder.Value);
// se lo score è migliorativo...
if (CurrSimSet.IndexScore < CurrIndexScore)
{
Candidates.Add(CurrSimSet);
CurrIndexScore = CurrSimSet.IndexScore;
}
// prendo i restanti tranne il primo
OrdInf.Remove(currOrder.Key);
// se rimane qualcosa...
if (OrdInf != null && OrdInf.Any())
{
// calcolo il minimo locale nei 2 casi, da soli
Dictionary<int, double> TestOrderSet01 = findLocalMin(OrdInf, TargetVal, CurrIndexScore);
if (TestOrderSet01.Count > 0)
{
OrderSetSim CurrSet = new OrderSetSim();
CurrSet.TargetValue = TargetVal;
CurrSet.OrderSet = TestOrderSet01;
if (CurrSet.IndexScore < CurrIndexScore)
{
Candidates.Add(CurrSimSet);
CurrIndexScore = CurrSimSet.IndexScore;
}
}
// ...e con il primo valore...
Dictionary<int, double> TestOrderSet02 = findLocalMin(OrdInf, TargetVal - currOrder.Value, CurrIndexScore);
TestOrderSet02.Add(currOrder.Key, currOrder.Value);
// verifico se migliorativo...
if (TestOrderSet02.Count > 0)
{
OrderSetSim CurrSet = new OrderSetSim();
CurrSet.TargetValue = TargetVal - currOrder.Value;
CurrSet.OrderSet = TestOrderSet02;
if (CurrSet.IndexScore < CurrIndexScore)
{
Candidates.Add(CurrSimSet);
CurrIndexScore = CurrSimSet.IndexScore;
}
}
}
}
// cerco il minimo...
if (Candidates != null && Candidates.Count > 0)
{
answ = Candidates.OrderBy(x => x.IndexScore).FirstOrDefault().OrderSet;
}
// calcolo il minimo e lo restituisco...
return answ;
}
protected void lbtAccept_Click(object sender, EventArgs e)
{
// registro accettazione Nesting
@@ -293,6 +514,14 @@ namespace NKC_WF.WebUserControls
raiseEvent();
}
protected void lbtCancel_Click(object sender, EventArgs e)
{
}
protected void lbtSave_Click(object sender, EventArgs e)
{
}
protected void lbtSendEstim_Click(object sender, EventArgs e)
{
// invia a redis una richiesta...
@@ -358,20 +587,9 @@ namespace NKC_WF.WebUserControls
return num / den;
}
/// <summary>
/// Elenco ordini dato BatchID
/// </summary>
/// <param name="BatchId"></param>
/// <returns></returns>
protected DS_App.OrderListDataTable tabOrdersByBatch(int BatchId)
{
return ComLib.OrdersByBatch(BatchId);
}
protected void txtRatio_TextChanged(object sender, EventArgs e)
{
int valRatio = 0;
int.TryParse(txtRatio.Text, out valRatio);
rebalanceOrder();
lblRatio01.Text = $"{valRatio}";
lblRatio02.Text = $"{100 - valRatio}";
}
+27
View File
@@ -86,6 +86,24 @@ namespace NKC_WF.WebUserControls
/// </remarks>
protected global::System.Web.UI.WebControls.Label lblRatio02;
/// <summary>
/// lbtSave control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.LinkButton lbtSave;
/// <summary>
/// hfNeedSave control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.HiddenField hfNeedSave;
/// <summary>
/// txtRatio control.
/// </summary>
@@ -95,6 +113,15 @@ namespace NKC_WF.WebUserControls
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox txtRatio;
/// <summary>
/// lbtCancel control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.LinkButton lbtCancel;
/// <summary>
/// cmp_orderExtListNE01 control.
/// </summary>
+1 -1
View File
@@ -1,4 +1,4 @@
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="cmp_orderExtList.ascx.cs" Inherits="NKC_WF.WebUserControls.cmp_orderExtList" %>
<asp:GridView ID="grView" runat="server"></asp:GridView>
<asp:GridView ID="grView" runat="server" AutoGenerateColumns="true"></asp:GridView>
<asp:ObjectDataSource ID="ods" runat="server"></asp:ObjectDataSource>
@@ -1,6 +1,8 @@
using AppData;
using NKC_SDK;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
@@ -12,7 +14,21 @@ namespace NKC_WF.WebUserControls
{
#region Public Properties
public DS_App.OrderListDataTable CurrOrders { get; set; }
public List<OrderPrev> _CurrOrders { get; set; } = new List<OrderPrev>();
public List<OrderPrev> CurrOrders
{
get
{
return _CurrOrders;
}
set
{
_CurrOrders = value;
grView.DataSource = value;
grView.DataBind();
}
}
#endregion Public Properties