541 lines
24 KiB
C#

using System;
using System.Linq;
using Consulenza.ReportWriter.Business;
using Consulenza.ReportWriter.Business.OBJ_PDF;
using ceTe.DynamicPDF;
using System.Data;
using Consulenza.ReportCommon;
using Consulenza.ReportWriter.Manager.Integration;
using System.Collections.Generic;
using Consulenza.ExternalServices;
namespace Consulenza.ReportWriter.Manager.Section.Immobiliare.Diagnosi.Nucleo
{
/// <summary>
/// Scheda di stima parametrica del valore (id 39)
/// </summary>
public class S7 : Entity.Section
{
//private bool _assenzaTipologiaDiritto;
//private bool _assenzaQuotaDiritto;
public S7(EnvironmentFacade environmentFacade, int idSection)
: base(environmentFacade, idSection)
{
try
{
Draw();
}
catch (Exception ex)
{
SectionLogger.Write("S7", ex.Message, SectionLoggerMessageLevel.E, EnvironmentFacade.ReportEnvironment);
}
}
public S7(EnvironmentFacade environmentFacade, int idSection, IntegrationLayout integrationlayout)
: base(environmentFacade, idSection)
{
try
{
IntegrationLayout = integrationlayout;
Draw();
}
catch (Exception ex)
{
SectionLogger.Write("S7", ex.Message, SectionLoggerMessageLevel.E, EnvironmentFacade.ReportEnvironment);
}
}
/// <summary>
/// Scheda7. Scheda di stima parametrica del valore (Dettaglio dei dati sintetici, localizzazione geografica e stima del valore delle abitazioni selezionate) --> DUPLICATO PER OGNI IMMOBILE
/// </summary>
protected override sealed void Draw()
{
var dati = GetDataSet();
var testi = GetText();
if (dati == null) return;
var integrationlayout = ((DuplicazioneIdImmobileCatasto)IntegrationLayout);
//il validator si aspetta chiavecliente legata a idimmobile. con chiavenucleo, può esserci più volte lo stesso immobile per clienti diversi. la scelta di quale stampare viene demandata al front end, da cui arriva anche la chiaveclientepb associata in modo da avere una stampa coerente e non duplicata
#region recupera chiavecliente scelto per idimmobile in lista
int indexchiaveclientepbperimmobile = EnvironmentFacade.ReportEnvironment.NucleoImmobiliare.IdImmobileCatasto.IndexOf(integrationlayout.IdImmobileCatasto);
long chiaveclientepbcorrente = EnvironmentFacade.ReportEnvironment.NucleoImmobiliare.ChiaviClientiPBImmobili[indexchiaveclientepbperimmobile];
var cliente = EnvironmentFacade.ReportEnvironment.NucleoImmobiliare.ListaClientiNucleo.FirstOrDefault(l => l.Chiave == chiaveclientepbcorrente);
#endregion
#region SottoTitolo
//sottoTitolo = provincia - indirizzo
var comune = dati.Tables["DatiCatastali"].Select("Descrizione='Comune'").FirstOrDefault()["Valore"];
var indirizzo = dati.Tables["DatiCatastali"].Select("Descrizione='Indirizzo'").FirstOrDefault()["Valore"];
var formattazione = "{0}";
if (!string.IsNullOrEmpty(indirizzo.ToString()))
formattazione = "{0} - {1}";
var sottoTitolo = string.Format(formattazione, comune, indirizzo);
AddElement(new FormattedTextAreaPDF(sottoTitolo, EnvironmentFacade.RendererFacade.XLeftLimit + 30, 500) { FontSize = 14 });
#endregion
#region Dati sintetici
AddElement(new ResetterYPDF());
AddElement(new SpacePDF(50));
var icona = new ImagePDF(EnvironmentFacade.RendererFacade.XLeftLimit, 0.20F, "DatiSintetici.png") { AutoIncrementYWritable = false };
var titolo = new FormattedTextAreaPDF("Dati sintetici", 82) { FontSize = 10, DeltaY = 3, FontColor = ColorPDF.Immobiliare_Grigio_TitoloGrande };
#region Tabella
var tabella = new TablePDF(EnvironmentFacade.RendererFacade.XLeftLimit + 30, dati.Tables["DatiCatastali"])
{
Style = Style.Immobiliare,
Footer = false,
RowsPadding = 0,
ShowBorderLastLine = true,
HeaderHeight = 15
};
tabella.Columns.Add(new ColumnPDF("descrizione", 100, HorizontalAlignmentType.Sinistra, false, false, 8, ColumnType.Testo, "descrizione", "Dati catastali"));
tabella.Columns.Add(new ColumnPDF("valore", 160, HorizontalAlignmentType.Sinistra, false, false, 8, ColumnType.Testo, "valore", ""));
#endregion
AddElement(icona);
AddElement(titolo);
AddElement(new SpacePDF(20));
AddElement(tabella);
#endregion
#region Localizzazione geografica
var xLocalizzazioneGeografica = EnvironmentFacade.RendererFacade.XLeftLimit + 300;
AddElement(new ResetterYPDF());
AddElement(new SpacePDF(50));
icona = new ImagePDF(xLocalizzazioneGeografica, 0.20F, "LocGeografica.png") { AutoIncrementYWritable = false };
titolo = new FormattedTextAreaPDF("Localizzazione geografica", xLocalizzazioneGeografica + 30) { FontSize = 10, DeltaY = 3, FontColor = ColorPDF.Immobiliare_Grigio_TitoloGrande };
ImagePDF cartina1 = null;
ImagePDF cartina2 = null;
try
{
cartina1 = new ImagePDF(xLocalizzazioneGeografica + 30, new Prometeia().GetImageFromValidator(
integrationlayout.IdImmobileCatasto,
cliente.Tipo == ClienteType.Fisico ? cliente.CodiceFiscale : cliente.PartitaIva,
//EnvironmentFacade.ReportEnvironment.Cliente.Tipo == ClienteType.Fisico ? EnvironmentFacade.ReportEnvironment.Cliente.CodiceFiscale : EnvironmentFacade.ReportEnvironment.Cliente.PartitaIva,
EnvironmentFacade.ReportEnvironment.PrivateBanker.Codice, 1), 130, 205, 120) { AutoIncrementYWritable = false };
cartina2 = new ImagePDF(xLocalizzazioneGeografica + 30 + 210, new Prometeia().GetImageFromValidator(
integrationlayout.IdImmobileCatasto,
cliente.Tipo == ClienteType.Fisico ? cliente.CodiceFiscale : cliente.PartitaIva,
//EnvironmentFacade.ReportEnvironment.Cliente.Tipo == ClienteType.Fisico ? EnvironmentFacade.ReportEnvironment.Cliente.CodiceFiscale : EnvironmentFacade.ReportEnvironment.Cliente.PartitaIva,
EnvironmentFacade.ReportEnvironment.PrivateBanker.Codice, 2), 130, 205, 120) { AutoIncrementYWritable = true };
}
catch (Exception ex)
{
var cartinar = new RectanglePDF(xLocalizzazioneGeografica + 30, 120, 130, 205, ColorPDF.Bianco) { AutoIncrementYWritable = false };
var cartinar2 = new RectanglePDF(xLocalizzazioneGeografica + 30 + 210, 120, 130, 205, ColorPDF.Bianco) { AutoIncrementYWritable = true };
AddElement(cartinar);
AddElement(cartinar2);
//throw new Exception();
}
AddElement(icona);
AddElement(titolo);
AddElement(new SpacePDF(30));
if(cartina1 != null)
AddElement(cartina1);
if (cartina2 != null)
AddElement(cartina2);
#endregion
//---------------------------------//
if (dati.Tables["Tipologia"].Rows.Count <= 0 || dati.Tables["StimaValore"].Rows.Count <= 0) return;
#region Linea orizzontale
var lineaOrizzonataleSeparazione = new LinePDF(EnvironmentFacade.RendererFacade.XLeftLimit, EnvironmentFacade.RendererFacade.XRightLimit, 1F, ColorPDF.Immobiliare_Grigio_TitoloPiccolo);
AddElement(new SpacePDF(10));
AddElement(lineaOrizzonataleSeparazione);
#endregion
//---------------------------------//
#region Stima del valore
AddElement(new SpacePDF(10));
icona = new ImagePDF(EnvironmentFacade.RendererFacade.XLeftLimit, 0.20F, "StimaValore.png") { AutoIncrementYWritable = false };
titolo = new FormattedTextAreaPDF("Stima del valore", 82) { FontSize = 10, DeltaY = 3, FontColor = ColorPDF.Immobiliare_Grigio_TitoloGrande, AutoIncrementYWritable = false };
AddElement(icona);
AddElement(titolo);
AddElement(new SpacePDF(9));
#region Tabella Tipologia
tabella = new TablePDF(EnvironmentFacade.RendererFacade.XLeftLimit + 30, dati.Tables["Tipologia"])
{
Style = Style.Immobiliare,
Footer = false,
ShowBorderLastLine = true,
RowsPadding = 6,
HeaderMargin = 3
};
tabella.Columns.Add(new ColumnPDF("descrizione", 150, HorizontalAlignmentType.Sinistra, false, false, 8, ColumnType.Testo, "descrizione", "Tipologia"));
tabella.Columns.Add(new ColumnPDF("valoreMinimo", 55, HorizontalAlignmentType.Destra, false, false, 8, ColumnType.Intero, "valoreMinimo", "Min")
{
HeaderGroupText = new List<string> { string.Format("{0}Valori €/mq", string.Concat(Enumerable.Repeat("&nbsp;", 5))) },
HeaderGroupWidth = 110,
HeaderGroupTextDeltaX = 30,
HeaderGroupTextDeltaY = -15,
HeaderVerticalAlignment = VerticalAlignmentType.Basso
});
tabella.Columns.Add(new ColumnPDF("valoreMassimo", 55, HorizontalAlignmentType.Destra, false, false, 8, ColumnType.Intero, "valoreMassimo", "Max") { HeaderVerticalAlignment = VerticalAlignmentType.Basso });
AddElement(new SpacePDF(15));
AddElement(tabella);
#endregion
#region Tabella Stima del valore
tabella = new TablePDF(EnvironmentFacade.RendererFacade.XLeftLimit + 30, dati.Tables["StimaValore"])
{
Style = Style.Immobiliare,
Footer = false,
ShowBorderLastLine = true,
PageBreak = false,
RowsPadding = 6,
HeaderMargin = 3
};
tabella.Columns.Add(new ColumnPDF("descrizione", 185, HorizontalAlignmentType.Sinistra, false, false, 8, ColumnType.Testo, "descrizione", "Stima del valore"));
tabella.Columns.Add(new ColumnPDF("valore", 75, HorizontalAlignmentType.Destra, false, false, 8, ColumnType.Decimale, "valore", "") { FontColor = ColorPDF.Nero, FontBold = true, BackgroundColor = new ColorPDF(237, 237, 234) }); // BackgroundColor = Grigio
// Ultima cella marrone con testo bianco.
tabella.Cells[1, 2] = new Cell { FontBold = true, BackgroundColor = ColorPDF.Immobiliare_Marrone, FontColor = ColorPDF.Bianco }; // marrone
//AddElement(new SpacePDF(5));
if (dati.Tables["Tipologia"].Rows.Count == 3)
AddElement(new SpacePDF(5));
else
AddElement(new SpacePDF(38));
AddElement(tabella);
#endregion
#region Matrice
AddElement(new ResetterYPDF(305));
//Recupero il passo e superficieStimata
var superficieStimata = Convert.ToInt32(dati.Tables["StimaValore"].Select("Indice=1").FirstOrDefault()["Valore"]);
var passo = (from r in dati.Tables["Passo"].AsEnumerable()
where superficieStimata >= r.Field<Int32>("damq") && superficieStimata <= r.Field<Int32>("amq")
select r.Field<Int32>("passo"));
//Recupero il limite minimo e massimo della superficieStimata
var limiteMinimoSuperficieStimata = Helper.RoundDown(superficieStimata);
if (limiteMinimoSuperficieStimata.Equals(superficieStimata))
limiteMinimoSuperficieStimata -= passo.First();
var limiteMassimoSuperficieStimata = Helper.RoundUp(superficieStimata);
var valoriMq = new List<Int32>();
var valoriEuro = new List<decimal>();
//Recupero i 4 valori inferiori alla superficieStimata
for (var i = 3; i >= 0; i--)
valoriMq.Add(limiteMinimoSuperficieStimata - (passo.First() * i));
valoriMq.Add(superficieStimata);
//Recupero i 4 valori superiori alla superficieStimata
for (var i = 0; i < 4; i++)
valoriMq.Add(limiteMassimoSuperficieStimata + (passo.First() * i));
#region Rettangolo orizzontale
AddElement(new RectanglePDF(440, 20, 350, new ColorPDF(226, 226, 221)) { AutoIncrementYWritable = false }); // Rettangolo grigio
AddElement(new FormattedTextAreaPDF("€/mq", 615, 50) { FontBold = true, AutoIncrementYWritable = true, FixedHeight = 20 });
AddElement(new LinePDF(440, 790) { Width = 0.5F }); //Linea verticale
#endregion
#region Tabella
#region Recupero i valori di al mq minimi e massimi della categoria dell'immobile e delle categorie similari.
//Recupero i valori di € al mq minimi e massimi della categoria dell'immobile e delle categorie similari.
//#1 dalle categorie similari
foreach (DataRow row in dati.Tables["Tipologia"].Rows)
{
valoriEuro.Add(Convert.ToDecimal(row["ValoreMinimo"]));
valoriEuro.Add(Convert.ToDecimal(row["ValoreMassimo"]));
}
//#2 dell'immobile
valoriEuro.Add(Convert.ToDecimal(dati.Tables["StimaValore"].Select("Indice=2").FirstOrDefault()["Valore"]));
//Distinct e ordinamento.
valoriEuro = valoriEuro.Distinct().OrderBy(x => x).ToList();
#endregion
#region Tabella (matrice)
#region Recupero Dati
var datiTabellaMatrice = new DataTable();
//Definisco le colonne
for (int i = 0; i < valoriEuro.Count; i++)
datiTabellaMatrice.Columns.Add(string.Format("{0}", valoriEuro[i]), typeof(Int32));
//Popolo i dati per la matrice
var valori = new List<object>();
for (int r = 0; r < valoriMq.Count; r++)
{
for (int c = 0; c < valoriEuro.Count; c++)
valori.Add(valoriMq[r] * valoriEuro[c]);
datiTabellaMatrice.Rows.Add(valori.ToArray());
valori.Clear();
}
#endregion
#region Disegno Tabella
int larghezzaColonna = 350 / datiTabellaMatrice.Columns.Count;
double UltimaColonna = 0;
UltimaColonna = 350 - (350 / (datiTabellaMatrice.Columns.Count) * datiTabellaMatrice.Columns.Count);
larghezzaColonna = (350 / datiTabellaMatrice.Columns.Count);
tabella = new TablePDF(440, datiTabellaMatrice)
{
Style = Style.Immobiliare,
Footer = false,
ShowBorderLastLine = true,
RowsPadding = 3,
HeaderHeight = 15,
MinimumRowHeight = 10,
RowHeight = 10
};
var indiceColonnaSelezionata = 0;
var indiceColonna = 0;
foreach (DataColumn item in datiTabellaMatrice.Columns)
{
var colonnaSelezionata = Convert.ToDecimal(item.ColumnName).Equals(Convert.ToDecimal(dati.Tables["StimaValore"].Select("Indice=2").FirstOrDefault()["Valore"]));
if (colonnaSelezionata)
indiceColonnaSelezionata = indiceColonna;
if (indiceColonna == datiTabellaMatrice.Columns.Count - 1)
larghezzaColonna = larghezzaColonna + Convert.ToInt16(UltimaColonna);
tabella.Columns.Add(new ColumnPDF(item.ColumnName, larghezzaColonna, HorizontalAlignmentType.Destra, false, false, 7, ColumnType.Intero, item.ColumnName, item.ColumnName.EndsWith(",00") ? Helper.FormatInteger(item.ColumnName) : Helper.FormatCurrency(item.ColumnName))
{
HeaderBackgroundColor = new ColorPDF(226, 226, 221),
BackgroundColor = colonnaSelezionata ? new ColorPDF(237, 237, 234) : null,
FontColor = ColorPDF.Immobiliare_Grigio_TestoStandard,
PaddingRight = 5,
HeaderPaddingRight = 5
});
indiceColonna++;
}
//Evidenziazione Riga
tabella.Row[4].BackgroundColor = new ColorPDF(237, 237, 234); //Sarà sempre selezionata la riga centrale quindi l'indice è fisso!
tabella.Cells[indiceColonnaSelezionata, 4] = new Cell() { FontBold = true, BackgroundColor = ColorPDF.Immobiliare_Marrone, FontColor = ColorPDF.Bianco }; // sfondo marrone ; testo bianco
AddElement(tabella);
#endregion
#endregion
#endregion
#region Rettangolo verticale
float yInizialeRettangolo = 327 + tabella.HeaderHeight;
const float xInizialeRettangolo = 360;
AddElement(new ResetterYPDF(yInizialeRettangolo));
AddElement(new RectanglePDF(xInizialeRettangolo, tabella.Height - tabella.HeaderHeight, 80, new ColorPDF(226, 226, 221)) { AutoIncrementYWritable = false }); // Rettangolo grigio
AddElement(new LinePDF(xInizialeRettangolo + 40, yInizialeRettangolo, xInizialeRettangolo + 40, yInizialeRettangolo + tabella.Height - tabella.HeaderHeight) { Width = 0.5F }); //Linea verticale
AddElement(new FormattedTextAreaPDF("mq", xInizialeRettangolo, 40) { FontSize = 7, TextHorizontalAlign = TextAlign.Center, Y = yInizialeRettangolo + ((tabella.Height - tabella.HeaderHeight) / 2) - 3.5F, FontBold = true });
var yEtichettaMq = yInizialeRettangolo + tabella.HeaderMargin;
for (int i = 0; i < valoriMq.Count; i++)
{
var valoreGrassetto = valoriMq[i] == superficieStimata;
AddElement(new FormattedTextAreaPDF(valoriMq[i].ToString(), xInizialeRettangolo + 40, 40) { TextHorizontalAlign = TextAlign.Center, FontSize = 7, Y = yEtichettaMq, FontBold = valoreGrassetto, FixedHeight = tabella.RowHeight });
yEtichettaMq += tabella.RowHeight + tabella.RowsPadding;
}
#endregion
#endregion
// Nota a fine pagina
AddElement(new FormattedTextAreaPDF(testi.Rows[0]["testo1"].ToString(), base.EnvironmentFacade.RendererFacade.XLeftLimit, 780) { AbsolutePosition = true, Y = base.EnvironmentFacade.RendererFacade.YLowerLimit, FontSize = 7 });
#endregion
}
/// <summary>
/// Recupera i dati necessari alla Section restituendo un DataTable.
/// </summary>
/// <returns></returns>
protected sealed override DataTable GetDataTable()
{
return null;
}
/// <summary>
/// Recupera i dati necessari alla Section restituendo un DataSet.
/// </summary>
/// <returns></returns>
protected sealed override DataSet GetDataSet()
{
var integrationlayout = ((DuplicazioneIdImmobileCatasto)IntegrationLayout);
int indexchiaveclientepbperimmobile = EnvironmentFacade.ReportEnvironment.NucleoImmobiliare.IdImmobileCatasto.IndexOf(integrationlayout.IdImmobileCatasto);
long chiaveclientepbcorrente = EnvironmentFacade.ReportEnvironment.NucleoImmobiliare.ChiaviClientiPBImmobili[indexchiaveclientepbperimmobile];
DataSet dsResult = null;
#region Definizione dei parametri
var parametri = new List<Parametro>
{
new Parametro
{
Direction = ParameterDirection.Input,
DbType = DbType.Int64,
ParameterName = "ChiaveNucleo",
Value = EnvironmentFacade.ReportEnvironment.NucleoImmobiliare.ChiaveNucleo
},
new Parametro
{
Direction = ParameterDirection.Input,
DbType = DbType.Int64,
ParameterName = "ChiaveClientePB",
Value = Convert.ToInt64(chiaveclientepbcorrente)
},
new Parametro
{
Direction = ParameterDirection.Input,
DbType = DbType.AnsiString,
ParameterName = "IdCatasto",
Value = integrationlayout.IdImmobileCatasto
}
};
#endregion
//var dsOriginal = EnvironmentFacade.ReportEnvironment.NucleoImmobiliare.ImmobiliareCEUnica ? DataAccess.ExecuteDataSetStoredProcedure(DBProvider.SqlServerConsulenzaUnica, "REP_Nucleo_Immobiliare_S7_StimaParametricaValore", parametri)
// : DataAccess.ExecuteDataSetStoredProcedure(DBProvider.SqlServerConsulenzaEvoluta, "REP_Nucleo_Immobiliare_S7_StimaParametricaValore", parametri);
var dsOriginal = DataAccess.ExecuteDataSetStoredProcedure(DBProvider.SqlServerConsulenzaUnica, "REP_Nucleo_Immobiliare_S7_StimaParametricaValore", parametri);
if (dsOriginal.Tables[0].Rows.Count == 0) return null;
dsResult = new DataSet();
//_assenzaTipologiaDiritto = dsOriginal.Tables[0].AsEnumerable().All(r => r.Field<string>("TipologiaDiritto") == string.Empty);
//_assenzaQuotaDiritto = dsOriginal.Tables[0].AsEnumerable().All(r => r.Field<decimal>("QuotaDiritto") < 0);
#region DatiCatastali
//var quotaDiritto = string.Join(" / ", dsOriginal.Tables[0].AsEnumerable()
// .Select(o => o.Field<decimal>("QuotaDiritto"))
// .Select(p => Helper.FormatPercentage(p, 0)));
//var tipologiaDiritto = String.Join(" / ", dsOriginal.Tables[0].AsEnumerable().Select(o => o.Field<string>("TipologiaDiritto")));
var dt1 = new DataTable { TableName = "DatiCatastali" };
dt1.Columns.Add("Descrizione", typeof(string));
dt1.Columns.Add("Valore", typeof(string));
dt1.Rows.Add("Provincia", dsOriginal.Tables[0].Rows[0]["Provincia"].ToString());
dt1.Rows.Add("Comune", dsOriginal.Tables[0].Rows[0]["Comune"].ToString());
dt1.Rows.Add("Indirizzo", dsOriginal.Tables[0].Rows[0]["Indirizzo"].ToString());
dt1.Rows.Add("Tipologia", dsOriginal.Tables[0].Rows[0]["Tipologia"].ToString());
dt1.Rows.Add("Foglio", dsOriginal.Tables[0].Rows[0]["Foglio"].ToString());
dt1.Rows.Add("Particella", dsOriginal.Tables[0].Rows[0]["Particella"].ToString());
dt1.Rows.Add("Subalterno", dsOriginal.Tables[0].Rows[0]["Subalterno"].ToString());
dt1.Rows.Add("Rendita Catastale", Helper.FormatCurrency(dsOriginal.Tables[0].Rows[0]["RenditaCatastale"].ToString()));
dt1.Rows.Add("Nr. Vani catastali", dsOriginal.Tables[0].Rows[0]["VaniCatastali"].ToString());
//dt1.Rows.Add("Tipologia di diritto", tipologiaDiritto);
//dt1.Rows.Add("Quota di diritto", quotaDiritto);
dsResult.Tables.Add(dt1);
#endregion
#region Tipologia
var dt2 = dsOriginal.Tables[1];
dt2.TableName = "Tipologia";
dsResult.Tables.Add(dt2.Copy());
#endregion
#region StimaValore
var dt3 = new DataTable { TableName = "StimaValore" };
dt3.Columns.Add("Indice", typeof(Int32));
dt3.Columns.Add("Descrizione", typeof(string));
dt3.Columns.Add("Valore", typeof(decimal));
if (dsOriginal.Tables[2].Rows.Count > 0)
{
dt3.Rows.Add(1, "Superficie stimata (mq)", dsOriginal.Tables[2].Rows[0]["SuperficieStimata"].ToString());
dt3.Rows.Add(2, "Valore mercato (€/mq)", dsOriginal.Tables[2].Rows[0]["ValoreMercato"].ToString());
dt3.Rows.Add(3, "Valore stimato (€)", dsOriginal.Tables[2].Rows[0]["ValoreStimato"].ToString());
}
dsResult.Tables.Add(dt3.Copy());
#endregion
#region Passo
//var dt4 = DataAccess.ExecuteDataTableStoredProcedure(DBProvider.SqlServerConsulenzaEvoluta, "REP_Nucleo_Immobiliare_PassoStimeValori", null);
var dt4 = DataAccess.ExecuteDataTableStoredProcedure(DBProvider.SqlServerConsulenzaUnica, "REP_Nucleo_Immobiliare_PassoStimeValori", null);
dt4.TableName = "Passo";
dsResult.Tables.Add(dt4.Copy());
#endregion
return dsResult;
}
}
}