// 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 } }