// Copyright (C) Stichting Deltares 2025. All rights reserved.
//
// This file is part of the application DAM - UI.
//
// DAM - UI is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
// All names, logos, and references to "Deltares" are registered trademarks of
// Stichting Deltares and remain full property of Stichting Deltares at all times.
// All rights reserved.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using Deltares.Dam.Data.Importers;
using Deltares.Standard.IO;
using Deltares.Standard.Language;
using LumenWorks.Framework.IO.Csv;
namespace Deltares.Dam.Data.CsvImporters;
public class CsvImporterScenariosException : Exception
{
public CsvImporterScenariosException(string message)
: base(message) {}
}
public class CsvImporterScenarios
{
private int currentColIndex = -1; // Keep track of column for error message
public CsvImporterScenarios(string fileName)
{
ErrorMessages.Clear();
ThrowHelper.ThrowIfStringArgumentNullOrEmpty(fileName, StringResourceNames.CsvFileNotValid);
ThrowHelper.ThrowIfFileNotExist(fileName, StringResourceNames.CsvFileNotFound);
CultureInfo oldcur = Thread.CurrentThread.CurrentCulture;
try
{
Thread.CurrentThread.CurrentCulture = CsvReaderUtilities.DetermineCultureForFile(fileName);
using (var csv = new CsvReader(new StreamReader(fileName), true, ';'))
{
string[] headers = CsvImporterHelper.GetFieldHeaders(this, csv);
if (headers.Count() < 2)
{
string csvHeaderError = LocalizationManager.GetTranslatedText(GetType(), "csvHeaderError");
throw new CsvImporterSegmentsException($"{fileName} : {csvHeaderError}");
}
const string fieldLocationId = CsvColumnNames.LocationColumnName;
int colIndexLocationId = CsvReaderUtilities.GetHeaderIndexByString(headers, fieldLocationId);
CheckColumn(colIndexLocationId, fileName, fieldLocationId);
const string fieldLocationScenarioId = CsvColumnNames.LocationScenarioColumnName;
int colIndexLocationScenarioId = CsvReaderUtilities.GetHeaderIndexByString(headers, fieldLocationScenarioId);
CheckColumn(colIndexLocationScenarioId, fileName, fieldLocationScenarioId);
int colIndexRiverLevel = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.RiverLevelColumnName);
int colIndexRiverLevelLow = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.RiverLevelLowColumnName);
int colIndexDikeTableHeight = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.DikeTableHeightColumnName);
int colIndexSafetyFactorPiping = CsvReaderUtilities.GetHeaderIndexByString(headers, ModelFactorCsvIdentifiers.SafetyFactorPiping);
int colIndexSafetyFactorStabilityInnerSlope = CsvReaderUtilities.GetHeaderIndexByString(headers, ModelFactorCsvIdentifiers.SafetyFactorStabilityInnerslope);
int colIndexSafetyFactorStabilityOuterSlope = CsvReaderUtilities.GetHeaderIndexByString(headers, ModelFactorCsvIdentifiers.SafetyFactorStabilityOuterslope);
int colIndexUpliftCriterionPiping = CsvReaderUtilities.GetHeaderIndexByString(headers, ModelFactorCsvIdentifiers.UpliftCriterionPiping);
int colIndexUpliftCriterionStability = CsvReaderUtilities.GetHeaderIndexByString(headers, ModelFactorCsvIdentifiers.UpliftCriterionStability);
int colIndexPlLineOffsetBelowDikeTopAtRiver = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.PlLineOffsetBelowDikeTopAtRiverColumnName);
int colIndexPlLineOffsetBelowDikeTopAtPolder = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.PlLineOffsetBelowDikeTopAtPolderColumnName);
int colIndexPlLineOffsetBelowShoulderBaseInside = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.PlLineOffsetBelowShoulderBaseInsideColumnName);
int colIndexPlLineOffsetBelowDikeToeAtPolder = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.PlLineOffsetBelowDikeToeAtPolderColumnName);
int colIndexPlLineOffsetBelowDikeCrestMiddle = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.PlLineOffsetBelowDikeCrestMiddleColumnName);
int colIndexPlLineOffsetFactorBelowShoulderCrest = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.PlLineOffsetFactorBelowShoulderCrestColumnName);
int colIndexUsePlLineOffsetBelowDikeCrestMiddle = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.UsePlLineOffsetBelowDikeCrestMiddleColumnName);
int colIndexUsePlLineOffsetFactorBelowShoulderCrest = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.UsePlLineOffsetFactorBelowShoulderCrestColumnName);
int colIndexHeadPl3 = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.HeadPl3ColumnName);
int colIndexHeadPl4 = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.HeadPl4ColumnName);
int colIndexHeadPl3OldFormat = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.HeadPl3OldFormatColumnName);
int colIndexHeadPl4OldFormat = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.HeadPl4OldFormatColumnName);
int colIndexPolderLevel = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.PolderLevelColumnName);
int colIndexHeadPl2 = CsvReaderUtilities.GetHeaderIndexByString(headers, CsvColumnNames.HeadPl2ColumnName);
var index = 1;
while (csv.ReadNextRecord())
{
var scenario = new ScenarioRecord();
try
{
scenario.ScenarioRecordId = index;
index++;
scenario.LocationId = csv[colIndexLocationId];
// faassen: changed location scenario id type from int to string (default value was -1 now null is used)
string value = csv[colIndexLocationScenarioId];
scenario.LocationScenarioId = string.IsNullOrWhiteSpace(value) ? null : value;
scenario.RiverLevel = FetchOptionalColumnToDouble(colIndexRiverLevel, csv);
scenario.RiverLevelLow = FetchOptionalColumnToDouble(colIndexRiverLevelLow, csv);
scenario.DikeTableHeight = FetchOptionalColumnToDouble(colIndexDikeTableHeight, csv);
scenario.RequiredSafetyFactorPiping = FetchOptionalColumnToDouble(colIndexSafetyFactorPiping, csv);
scenario.RequiredSafetyFactorStabilityInnerSlope = FetchOptionalColumnToDouble(colIndexSafetyFactorStabilityInnerSlope, csv);
scenario.RequiredSafetyFactorStabilityOuterSlope = FetchOptionalColumnToDouble(colIndexSafetyFactorStabilityOuterSlope, csv);
scenario.UpliftCriterionPiping = FetchOptionalColumnToDouble(colIndexUpliftCriterionPiping, csv);
scenario.UpliftCriterionStability = FetchOptionalColumnToDouble(colIndexUpliftCriterionStability, csv);
scenario.PlLineOffsetBelowDikeTopAtRiver = FetchOptionalColumnToDouble(colIndexPlLineOffsetBelowDikeTopAtRiver, csv);
scenario.PlLineOffsetBelowDikeTopAtPolder = FetchOptionalColumnToDouble(colIndexPlLineOffsetBelowDikeTopAtPolder, csv);
scenario.PlLineOffsetBelowShoulderBaseInside = FetchOptionalColumnToDouble(colIndexPlLineOffsetBelowShoulderBaseInside, csv);
scenario.PlLineOffsetBelowDikeToeAtPolder = FetchOptionalColumnToDouble(colIndexPlLineOffsetBelowDikeToeAtPolder, csv);
scenario.PlLineOffsetBelowDikeCrestMiddle = FetchOptionalColumnToDouble(colIndexPlLineOffsetBelowDikeCrestMiddle, csv);
scenario.PlLineOffsetFactorBelowShoulderCrest = FetchOptionalColumnToDouble(colIndexPlLineOffsetFactorBelowShoulderCrest, csv);
scenario.UsePlLineOffsetBelowDikeCrestMiddle = FetchOptionalColumnToBoolean(colIndexUsePlLineOffsetBelowDikeCrestMiddle, csv);
scenario.UsePlLineOffsetFactorBelowShoulderCrest = FetchOptionalColumnToBoolean(colIndexUsePlLineOffsetFactorBelowShoulderCrest, csv);
scenario.HeadPl3 = FetchOptionalColumnToDouble(colIndexHeadPl3, csv) ?? FetchOptionalColumnToDouble(colIndexHeadPl3OldFormat, csv);
scenario.HeadPl4 = FetchOptionalColumnToDouble(colIndexHeadPl4, csv) ?? FetchOptionalColumnToDouble(colIndexHeadPl4OldFormat, csv);
scenario.PolderLevel = FetchOptionalColumnToDouble(colIndexPolderLevel, csv);
scenario.HeadPl2 = FetchOptionalColumnToDouble(colIndexHeadPl2, csv);
ImportedItems.Add(scenario);
}
catch (Exception e)
{
string csvScenarioError = string.Format(LocalizationManager.GetTranslatedText(GetType(), "csvScenarioError"), scenario.LocationId, currentColIndex + 1);
ErrorMessages.Add(csvScenarioError + e.Message);
}
}
}
}
finally
{
Thread.CurrentThread.CurrentCulture = oldcur;
}
}
public List ImportedItems { get; } = new();
public List ErrorMessages { get; set; } = new();
private double? FetchOptionalColumnToDouble(int colIndex, CsvReader csv)
{
if (colIndex > -1)
{
currentColIndex = colIndex;
return Convert.ToDouble(csv[colIndex]);
}
return null;
}
private bool? FetchOptionalColumnToBoolean(int colIndex, CsvReader csv)
{
if (colIndex > -1)
{
currentColIndex = colIndex;
return Convert.ToBoolean(csv[colIndex]);
}
return null;
}
private void CheckColumn(int index, string fileName, string fieldName)
{
if (index < 0)
{
string csvHeaderFieldError = LocalizationManager.GetTranslatedText(GetType(), "csvHeaderFieldError");
throw new CsvImporterScenariosException($"{fileName} : {csvHeaderFieldError} {fieldName}");
}
}
public class ScenarioRecord
{
public ScenarioRecord()
{
LocationScenarioId = null;
}
public int ScenarioRecordId { get; set; }
public string LocationId { get; set; } //required
public string LocationScenarioId { get; set; } //required
public double? RiverLevel { get; set; } //optional
public double? RiverLevelLow { get; set; } //optional
public double? DikeTableHeight { get; set; } //optional
public double? PlLineOffsetBelowDikeTopAtRiver { get; set; } //optional
public double? PlLineOffsetBelowDikeTopAtPolder { get; set; } //optional
public double? PlLineOffsetBelowShoulderBaseInside { get; set; } //optional
public double? PlLineOffsetBelowDikeToeAtPolder { get; set; } //optional
public double? PlLineOffsetBelowDikeCrestMiddle { get; set; } //optional
public double? PlLineOffsetFactorBelowShoulderCrest { get; set; } //optional
public bool? UsePlLineOffsetBelowDikeCrestMiddle { get; set; } //optional
public bool? UsePlLineOffsetFactorBelowShoulderCrest { get; set; } //optional
public double? HeadPl3 { get; set; } //optional
public double? HeadPl4 { get; set; } //optional
public double? PolderLevel { get; set; } // optional
public double? HeadPl2 { get; set; } // Optional
public double? UpliftCriterionPiping { get; set; } //optional
public double? UpliftCriterionStability { get; set; } //optional
public double? RequiredSafetyFactorPiping { get; set; } //optional
public double? RequiredSafetyFactorStabilityInnerSlope { get; set; } //optional
public double? RequiredSafetyFactorStabilityOuterSlope { get; set; } //optional
}
}