2025-04-15 12:10:19 +02:00

627 lines
19 KiB
C#

using System;
using System.Data;
using System.Configuration;
using System.Collections.Generic;
using System.Collections;
/// <summary>
/// Summary description for RischioRelativo
/// </summary>
public class RischioRelativo_PesoPercentuale
{
public RischioRelativo_PesoPercentuale()
{
//
// TODO: Add constructor logic here
//
}
public RischioRelativo_PesoPercentuale(string area, string nomeprogetto, decimal rischio, string rischiostring, decimal peso)
{
_area = area;
_rischio = rischio;
_rischiostring = rischiostring;
_peso = peso;
_nomeprogetto = nomeprogetto;
}
private string _area;
private string _nomeprogetto;
private decimal _rischio;
private string _rischiostring;
private decimal _peso;
//private TipoRitorno _tipodiritorno;
private DataTable _datasource;
/// <summary>
/// Datatable contenente i controvalori di tutte le aree bisogno / progetti per cui vanno calcolati Peso e Rischio.
/// </summary>
public DataTable DataSource
{
get { return _datasource; }
set { _datasource = value; }
}
public string Area
{
get { return _area; }
set { _area = value; }
}
public string NomeProgetto
{
get { return _nomeprogetto; }
set { _nomeprogetto = value; }
}
public decimal Rischio
{
get { return _rischio; }
set { _rischio = value; }
}
/// <summary>
/// Rappresentazione in stringa del Rischio relativo nel caso in cuiquesto non sia calcolabile (es VaR = n.d.)
/// </summary>
public string RischioString
{
get { return _rischiostring; }
set { _rischiostring = value; }
}
public decimal Peso
{
get { return _peso; }
set { _peso = value; }
}
/// <summary>
/// Rirorna un DataTable contenente con i valori del Peso Percentuale.
/// Il nome delle colonne :
/// AreaBisogno
/// NomeProgetto
/// PesoPercentuale
/// </summary>
/// <returns></returns>
public DataTable calcolaPeso()
{
DataTable dtResult = new DataTable("dtResult");
dtResult.Columns.Add("AreaBisogno");
dtResult.Columns.Add("NomeProgetto");
dtResult.Columns.Add("PesoPercentuale",typeof(decimal));
decimal dividendo = 0;
decimal divisore = 0;
decimal ctvArea = 0;
decimal pesopercentuale = 0;
List<RischioRelativo_PesoPercentuale> _itemsPesoPercentuale = new List<RischioRelativo_PesoPercentuale>();
DataView dwAreeBisogno = new DataView(_datasource);
DataTable dtAreeBisogno = dwAreeBisogno.ToTable(true, "need_area");
if (dtAreeBisogno.Rows.Count == 0)
return null;
foreach (DataRow drGlobale in dtAreeBisogno.Rows)
{
if (drGlobale["need_area"].ToString().ToLower() != "na") //escludo le risorse non allocate
{
//Recupero il dividendo (controvalore dell'area o del singolo progetto)
DataRow[] rowFilter;
rowFilter = _datasource.Select("need_area ='" + drGlobale["need_area"] + "'");
foreach (DataRow row in rowFilter)
{
ctvArea = Convert.ToDecimal(row["CONTROVALOREATTUALE"]);
dividendo = Math.Round(ctvArea, 2);
// Recupero il divisore
divisore = recuperaDivisorePeso(_datasource);
if (divisore == 0M)
pesopercentuale = 0M;
else
pesopercentuale = Math.Round((dividendo / divisore) * 100, 2);
_itemsPesoPercentuale.Add(new RischioRelativo_PesoPercentuale(row["NEED_AREA"].ToString(), row["nome_progetto"].ToString(), 0,string.Empty, pesopercentuale));
divisore = 0;
}
}
}
_itemsPesoPercentuale = ArrotondaLista(_itemsPesoPercentuale, TipoRitorno.PESO);
foreach (RischioRelativo_PesoPercentuale obj in _itemsPesoPercentuale)
{
DataRow rToAdd = dtResult.NewRow();
rToAdd["AreaBisogno"] = obj.Area;
rToAdd["NomeProgetto"] = obj.NomeProgetto;
rToAdd["PesoPercentuale"] = obj.Peso;
dtResult.Rows.Add(rToAdd);
}
return dtResult;
}
/// <summary>
/// Ritorna un DataTable contenente con i controvalori totali di ciascusa area/progetto.
/// I controvalori espressi qui sono già comprensivi di patrimonio non rappresentabile.
/// </summary>
/// <returns></returns>
public DataTable calcolaControvaloriAttuali()
{
DataTable dtResult = new DataTable("dtResult");
dtResult.Columns.Add("AreaBisogno");
dtResult.Columns.Add("NomeProgetto");
dtResult.Columns.Add("ControvaloreTotale", typeof(decimal));
dtResult.Columns.Add("Ordinamento_progetto", typeof(int));
foreach (DataRow dr in _datasource.Rows)
{
DataRow rToAdd = dtResult.NewRow();
rToAdd["AreaBisogno"] = dr["need_area"].ToString();
rToAdd["NomeProgetto"] = dr["nome_progetto"].ToString();
rToAdd["ControvaloreTotale"] = dr["ControvaloreAttuale"]== DBNull.Value ? 0 :Convert.ToDecimal(dr["ControvaloreAttuale"]);
rToAdd["Ordinamento_progetto"] = Convert.ToInt32(dr["ORDINAMENTO_PROGETTO"]);
dtResult.Rows.Add(rToAdd);
}
return dtResult;
}
/// <summary>
/// Ritorna un DataTable contenente con i valori del Rischio Relativo.
/// Il nome delle colonne :
/// AreaBisogno
/// NomeProgetto
/// RischioRelativo
///
///
/// Di seguito la formula utilizzata:
///
/// var area/progetto * ctv area/progetto
/// -------------------------------------
/// sommatoria ( var area/progetto * ctv area/progetto )
///
/// </summary>
/// <returns></returns>
public DataTable calcolaRischio()
{
DataTable dtResult = new DataTable("dtResult");
dtResult.Columns.Add("AreaBisogno");
dtResult.Columns.Add("NomeProgetto");
dtResult.Columns.Add("RischioRelativo",typeof(decimal));
dtResult.Columns.Add("RischioRelativoString");
decimal varpArea = 0;
decimal dividendo = 0;
decimal divisore = 0;
decimal ctvArea = 0;
decimal rischio = 0;
string rischiostring = string.Empty;
List<RischioRelativo_PesoPercentuale> _itemsRischioRelativo = new List<RischioRelativo_PesoPercentuale>();
List<Rischio> _itemsRischioRelativoAppoggio = new List<Rischio>();
if (_datasource.Rows.Count == 0)
return null;
foreach (DataRow dr in _datasource.Rows)
{
rischio = 0;
varpArea = dr["var_needarea"]==DBNull.Value? 0 : Convert.ToDecimal(dr["var_needarea"]);
ctvArea = Convert.ToDecimal(dr["controvaloreattuale"]);
rischiostring = string.Empty;
dividendo = varpArea * ctvArea;
if (dividendo != 0)
{
divisore = recuperaDivisoreRischio(_datasource);
rischio = Math.Round(dividendo * 100 / divisore, 2);
}
if (dr["var_needareastring"].ToString().ToLower() == "n.c.")
rischiostring = "n.c.";
_itemsRischioRelativo.Add(new RischioRelativo_PesoPercentuale(dr["NEED_AREA"].ToString(), dr["nome_progetto"].ToString(), rischio, rischiostring, 0));
}
_itemsRischioRelativo = ArrotondaLista(_itemsRischioRelativo, TipoRitorno.RISCHIO);
foreach (RischioRelativo_PesoPercentuale obj in _itemsRischioRelativo)
{
DataRow rToAdd = dtResult.NewRow();
rToAdd["AreaBisogno"] = obj.Area;
rToAdd["NomeProgetto"] = obj.NomeProgetto;
rToAdd["RischioRelativo"] = obj.Rischio;
rToAdd["RischioRelativoString"] = obj.RischioString;
dtResult.Rows.Add(rToAdd);
}
return dtResult;
}
/// <summary>
/// Ritorna la sommatoria di tutte i controvalori di area/progetto * il VaR di area/progetto di tutte le area/progetto.
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
private decimal recuperaDivisoreRischio(DataTable dt)
{
decimal returnValue = 0M;
decimal ctvA = 0;
decimal varA = 0;
DataRow[] drFilter;
object sumExt = dt.Compute("Sum(CONTROVALOREATTUALE)", "NEED_AREA='Ext'");
drFilter = dt.Select("NEED_AREA='Ext'");
if (sumExt.ToString() == string.Empty)
sumExt = 0M;
if (Convert.ToDecimal(sumExt) > 0)
{
ctvA = Convert.ToDecimal(sumExt);
varA = Convert.ToDecimal(drFilter[0]["var_needarea"]);
returnValue = (returnValue + Math.Round(ctvA * varA, 2));
}
object sumLiq = dt.Compute("Sum(CONTROVALOREATTUALE)", "NEED_AREA='Liq'");
drFilter = dt.Select("NEED_AREA='Liq'");
if (sumLiq.ToString() == string.Empty)
sumLiq = 0M;
if (Convert.ToDecimal(sumLiq) > 0)
{
ctvA = Convert.ToDecimal(sumLiq);
varA = Convert.ToDecimal(drFilter[0]["var_needarea"]);
returnValue = (returnValue + Math.Round(ctvA * varA, 2));
}
//object sumInv = dt.Compute("Sum(CONTROVALOREATTUALE)", "NEED_AREA='Inv'");
drFilter = dt.Select("NEED_AREA='Inv'");
//if (sumInv.ToString() == string.Empty) sumInv = 0M;
foreach (DataRow drInvestimento in drFilter)
{
varA = Convert.ToDecimal(drInvestimento["var_needarea"]);
ctvA = Convert.ToDecimal(drInvestimento["controvaloreattuale"]);
returnValue = (returnValue + Math.Round(ctvA * varA, 2));
}
object sumPre = dt.Compute("Sum(CONTROVALOREATTUALE)", "NEED_AREA='Pre'");
drFilter = dt.Select("NEED_AREA='Pre'");
if (sumPre.ToString() == string.Empty)
sumPre = 0M;
if (Convert.ToDecimal(sumPre) > 0)
{
ctvA = Convert.ToDecimal(sumPre);
varA = Convert.ToDecimal(drFilter[0]["var_needarea"]);
returnValue = (returnValue + Math.Round(ctvA * varA, 2));
}
object sumRis = dt.Compute("Sum(CONTROVALOREATTUALE)", "NEED_AREA='Ris'");
drFilter = dt.Select("NEED_AREA='Ris'");
if (sumRis.ToString() == string.Empty)
sumRis = 0M;
if (Convert.ToDecimal(sumRis) > 0)
{
ctvA = Convert.ToDecimal(sumRis);
varA = Convert.ToDecimal(drFilter[0]["var_needarea"]);
returnValue = (returnValue + Math.Round(ctvA * varA, 2));
}
return returnValue;
}
/// <summary>
/// Ritorna la sommatoria di tutte i controvalori di area/progetto di tutte le area/progetto.
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
private decimal recuperaDivisorePeso(DataTable dt)
{
decimal returnValue = 0M;
decimal ctvA = 0;
object sumExt = dt.Compute("Sum(CONTROVALOREATTUALE)", "NEED_AREA='Ext'");
if (sumExt.ToString() == string.Empty)
sumExt = 0M;
ctvA = Convert.ToDecimal(sumExt);
returnValue = (returnValue + ctvA);
object sumLiq = dt.Compute("Sum(CONTROVALOREATTUALE)", "NEED_AREA='Liq'");
if (sumLiq.ToString() == string.Empty)
sumLiq = 0M;
ctvA = Convert.ToDecimal(sumLiq);
returnValue = (returnValue + ctvA);
object sumInv = dt.Compute("Sum(CONTROVALOREATTUALE)", "NEED_AREA='Inv'");
if (sumInv.ToString() == string.Empty)
sumInv = 0M;
ctvA = Convert.ToDecimal(sumInv);
returnValue = (returnValue + ctvA);
object sumPre = dt.Compute("Sum(CONTROVALOREATTUALE)", "NEED_AREA='Pre'");
if (sumPre.ToString() == string.Empty)
sumPre = 0M;
ctvA = Convert.ToDecimal(sumPre);
returnValue = (returnValue +ctvA);
object sumRis = dt.Compute("Sum(CONTROVALOREATTUALE)", "NEED_AREA='Ris'");
if (sumRis.ToString() == string.Empty)
sumRis = 0M;
ctvA = Convert.ToDecimal(sumRis);
returnValue = (returnValue + ctvA);
return returnValue;
}
/// <summary>
/// Arrotonda, aggiungendo all'oggetto piu alto la differenza per arrivare al 100%, una lista di oggetti.
/// </summary>
/// <param name="listadaarrotondare"></param>
/// <returns></returns>
private List<RischioRelativo_PesoPercentuale> ArrotondaLista(List<RischioRelativo_PesoPercentuale> listadaarrotondare, TipoRitorno tiporitorno)
{
//-----------------------------------------------------------
// verifico se la somma di tutti i rischi relativi è 100.
decimal totale = 0M;
foreach (RischioRelativo_PesoPercentuale r in listadaarrotondare)
{
if (tiporitorno == TipoRitorno.RISCHIO)
totale += Math.Round(r.Rischio, 2);
else
totale += Math.Round(r.Peso, 2);
}
// se la somma non è 100 aggiungo o elimino la differenza all'area che ha il rischio piu alto.
if (totale != 100M)
{
RischioRelativo_PesoPercentuale robjMax; // è l'area/progetto con valore (rischio o peso) piu grande
MyItemCompare _compare = new MyItemCompare();
_compare.TipologiaRitorno = tiporitorno;
listadaarrotondare.Sort(_compare);
decimal diff = 0;
decimal rischio_pesoTotaleAreaInvestimento = 0; // somma del rischio o del peso (a seconda della richiesta) di tutti i progetti di investimento.
foreach (RischioRelativo_PesoPercentuale obj in listadaarrotondare)
{
if (obj.Area.ToLower() == "inv")
{
if (tiporitorno == TipoRitorno.RISCHIO)
rischio_pesoTotaleAreaInvestimento += obj.Rischio;
else if (tiporitorno == TipoRitorno.PESO)
rischio_pesoTotaleAreaInvestimento += obj.Peso;
}
}
robjMax = listadaarrotondare.ToArray()[listadaarrotondare.Count - 1];
if (tiporitorno == TipoRitorno.RISCHIO)
{
if (rischio_pesoTotaleAreaInvestimento > robjMax.Rischio)
{
List<RischioRelativo_PesoPercentuale> listadaarrotondare_appoggio = listadaarrotondare;
// devo prendere il progetto di investimento piu alto.
listadaarrotondare_appoggio = listadaarrotondare.FindAll(delegate(RischioRelativo_PesoPercentuale r) { return (r.Area.ToLower() == "inv"); });
listadaarrotondare_appoggio.Sort(_compare);
robjMax = listadaarrotondare_appoggio.ToArray()[listadaarrotondare_appoggio.Count - 1];
}
}
else if (tiporitorno == TipoRitorno.PESO)
{
if (rischio_pesoTotaleAreaInvestimento > robjMax.Peso)
{
List<RischioRelativo_PesoPercentuale> listadaarrotondare_appoggio = listadaarrotondare;
// devo prendere il progetto di investimento piu alto.
listadaarrotondare_appoggio = listadaarrotondare.FindAll(delegate(RischioRelativo_PesoPercentuale r) { return (r.Area.ToLower() == "inv"); });
listadaarrotondare_appoggio.Sort(_compare);
robjMax = listadaarrotondare_appoggio.ToArray()[listadaarrotondare_appoggio.Count - 1];
}
}
// ricavo la differenza
if (totale == 0)
diff = 0;
else
diff = 100 - totale;
foreach (RischioRelativo_PesoPercentuale objToUpdate in listadaarrotondare)
{
if (objToUpdate.Area == robjMax.Area && objToUpdate.NomeProgetto == robjMax.NomeProgetto)
{
if (tiporitorno == TipoRitorno.PESO)
objToUpdate.Peso += diff;
else
objToUpdate.Rischio += diff;
}
}
return listadaarrotondare;
}
else //== 100
{
return listadaarrotondare;
}
}
}
public class Rischio
{
private decimal _fattoreribasamento = 0;
private decimal _ribasamentototale = 0;
private string _area = string.Empty;
private string _nomeprogetto = string.Empty;
public Rischio(string Area, string NomeProgetto, decimal FattoreRibasamento)
{
_area = Area;
_nomeprogetto = NomeProgetto;
_fattoreribasamento = FattoreRibasamento;
}
public string Area
{
get { return _area; }
set { _area = value; }
}
public string NomeProgetto
{
get { return _nomeprogetto; }
set { _nomeprogetto = value; }
}
public decimal RibasamentoTotale
{
get { return _ribasamentototale; }
set { _ribasamentototale = value; }
}
public decimal FattoreRibasamento
{
get { return _fattoreribasamento; }
set { _fattoreribasamento = value; }
}
}
public enum TipoRitorno
{
RISCHIO,
PESO
}
public class MyItemCompare : IComparer<RischioRelativo_PesoPercentuale>
{
private TipoRitorno _tipologiaritorno;
public TipoRitorno TipologiaRitorno
{
get { return _tipologiaritorno; }
set { _tipologiaritorno = value; }
}
/// <summary>
/// Compara due struttire di tipo MyItem
/// </summary>
/// <param name="x">MyItem</param>
/// <param name="y">MyItem</param>
/// <returns>0 = sono uguali, -1 y è maggiore, 1 x è maggiore </returns>
public int Compare(RischioRelativo_PesoPercentuale x, RischioRelativo_PesoPercentuale y)
{
if (x == null)
{
if (y == null)
{
// Se x è null e y è null, sono uguali
return 0;
}
else
{
// Se x è null e y non è null, y è maggiore
return -1;
}
}
else
{
// Se x non è null...
if (y == null)
// ...e y è null, x è magiore.
{
return 1;
}
else
{
// ...e y non è null, confronto la categoria
int retval;
if (_tipologiaritorno == TipoRitorno.RISCHIO)
retval = (x.Rischio).CompareTo(y.Rischio);
else
retval = (x.Peso).CompareTo(y.Peso);
if (retval != 0)
{
// Se la categoria non è uguale ritorno il valore di retval
return retval;
}
else
{
// Se la categoria è la stessa, allora devo ordinare per la descrizione
return CheckNull(x.Area).CompareTo(CheckNull(y.Area));
}
}
}
}
private string CheckNull(string val)
{
if (val == null)
return "";
return val;
}
}