// 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.Linq;
using Deltares.Dam.Data.CsvImporters;
using Deltares.Geometry;
using Deltares.Geotechnics.Exception;
using Deltares.Geotechnics.GeotechnicalGeometry;
using Deltares.Geotechnics.Soils;
using Deltares.Geotechnics.SurfaceLines;
using Deltares.Standard.EventPublisher;
using Deltares.Standard.Language;
using Deltares.Standard.Logging;
namespace Deltares.Dam.Data.IO;
///
/// Exception class for the class.
///
public class CombineImportedDataException : Exception
{
public CombineImportedDataException(string message)
: base(message) {}
}
///
/// Class for combining imported data from CSV files.
///
public class CombineImportedData
{
///
/// The WaterBoard to which the imported data will be added.
///
public WaterBoard WaterBoard { get; set; }
///
/// The Location records.
///
public IEnumerable LocationRecords { get; set; }
///
/// The Segment records.
///
public IEnumerable SegmentRecords { get; set; }
///
/// The SoilProfile records.
///
public IEnumerable SoilProfilerecords { get; set; }
///
/// The Aquifer records.
///
public IEnumerable AquiferRecords { get; set; }
///
/// The SurfaceLine records.
///
public IEnumerable SurfaceLineRecords { get; set; }
///
/// The Soil records.
///
public IEnumerable SoilRecords { get; set; }
///
/// The CharacteristicPoints records.
///
public IEnumerable CharacteristicPointsRecords { get; set; }
///
/// The Scenario records.
///
public IEnumerable ScenarioRecords { get; set; }
///
/// The SigmaTauCurve records.
///
public IEnumerable SigmaTauCurveRecords { get; set; }
///
/// The SigmaTauCurve records.
///
public IEnumerable SuTableRecords { get; set; }
///
/// The error messages.
///
public IList ErrorMessages { get; } = new List();
///
/// Adds the imported CSV data to dikes.
///
public void AddCsvDataToDikes()
{
if (WaterBoard == null)
{
string damProjectDataNotAssignedForImport = LocalizationManager.GetTranslatedText(GetType(), "damProjectDataNotAssignedForImport");
throw new CombineImportedDataException(damProjectDataNotAssignedForImport);
}
AddDikesFromLocationsToWaterBoard(WaterBoard);
foreach (Dike dike in WaterBoard.Dikes)
{
TransferLocationsData(dike);
TransferSoilProfilesData(dike);
TransferAquifersData(dike);
TransferSegmentData(dike);
TransferSigmaTauCurveData(dike); // Should be done before TransferSoilData(), because the SigmaTauCurveData is used there
TransferSuTableData(dike); // Should be done before TransferSoilData(), because the SuTableCurveData is used there
TransferSoilData(dike);
// Use InvokeWithoutPublishingEvents for performance reasons after introducing SurfaceLine2
DataEventPublisher.InvokeWithoutPublishingEvents(() => { TransferSurfaceLines(dike); });
}
}
public void AddScenarioDataToDikes()
{
foreach (Dike dike in WaterBoard.Dikes)
{
if (ScenarioRecords != null)
{
TransferScenarios(dike);
}
}
}
internal bool CheckCharacteristicPointsForCoincidingLocations(SurfaceLine2 surfaceLine2,
out CharacteristicPointType type1, out CharacteristicPointType type2)
{
var doubleFound = false;
type1 = CharacteristicPointType.None;
type2 = CharacteristicPointType.None;
CharacteristicPointSet points = surfaceLine2.CharacteristicPoints;
foreach (CharacteristicPoint characteristicPoint in surfaceLine2.CharacteristicPoints)
{
if (!doubleFound)
{
// Find the coinciding points
IEnumerable doublePoints = points.Where(x =>
Math.Abs(x.X - characteristicPoint.X) < 1e-4 && Math.Abs(x.Y - characteristicPoint.Y) < 1e-4 &&
Math.Abs(x.Z - characteristicPoint.Z) < 1e-4);
if (doublePoints.Count() > 1)
{
// if there are coinciding points, see if the types clash. Only valid coinciding points are traffic loads
// which may coincide with any other type of point
CharacteristicPointType firstType = doublePoints.First().CharacteristicPointType;
var skip = 0;
foreach (CharacteristicPoint doublePoint in doublePoints)
{
if (skip > 0 && !doubleFound && firstType != CharacteristicPointType.TrafficLoadInside &&
firstType != CharacteristicPointType.TrafficLoadOutside)
{
if (doublePoint.CharacteristicPointType != CharacteristicPointType.TrafficLoadInside &&
doublePoint.CharacteristicPointType != CharacteristicPointType.TrafficLoadOutside)
{
doubleFound = doublePoint.CharacteristicPointType != firstType;
if (doubleFound)
{
type1 = firstType;
type2 = doublePoint.CharacteristicPointType;
}
}
}
firstType = doublePoint.CharacteristicPointType;
skip++;
}
}
}
}
return !doubleFound;
}
internal bool CheckOnCoincidingPoints(SurfaceLine2 surfaceLine)
{
bool charCheck;
CharacteristicPointType firstType;
CharacteristicPointType secondType;
charCheck = CheckCharacteristicPointsForCoincidingLocations(surfaceLine, out firstType, out secondType);
if (!charCheck)
{
string coincidingCharPointsFoundForSurfaceError =
LocalizationManager.GetTranslatedText(GetType(), "CoincidingCharPointsFoundForSurfaceError");
var logmessage = new LogMessage(LogMessageType.Error, null, $"{surfaceLine.Name} : {coincidingCharPointsFoundForSurfaceError} : {firstType.ToString()} : {secondType.ToString()}");
ErrorMessages.Add(logmessage);
}
return charCheck;
}
///
/// Adds the dikes from locations to water board.
///
/// The water board.
private void AddDikesFromLocationsToWaterBoard(WaterBoard targetWaterBoard)
{
if (LocationRecords == null)
{
return;
}
// Create list of unique dikering ids
var dikeRingIdList = new List();
foreach (CsvImporterLocations.LocationRecord locationRecord in LocationRecords)
{
if (!String.IsNullOrEmpty(locationRecord.DikeRingId))
{
if (!dikeRingIdList.Contains(locationRecord.DikeRingId))
{
dikeRingIdList.Add(locationRecord.DikeRingId);
}
}
}
// if no dikeringIds assigned, then use default dike and assign it to the locations (if there are any)
if ((dikeRingIdList.Count <= 0) && LocationRecords.Any())
{
var defaultDikeRingId = "Dike from CSV";
if (targetWaterBoard.Dikes.Count > 0)
{
defaultDikeRingId = targetWaterBoard.Dikes[0].Name;
}
foreach (CsvImporterLocations.LocationRecord locationRecord in LocationRecords)
{
locationRecord.DikeRingId = defaultDikeRingId;
}
dikeRingIdList.Add(defaultDikeRingId);
}
// Add dikeringids if not yet in waterboard
foreach (string dikeRingId in dikeRingIdList)
{
Dike dike = targetWaterBoard.Dikes.FirstOrDefault(d => d.Name.Equals(dikeRingId));
if (dike == null)
{
targetWaterBoard.Dikes.Add(new Dike
{
Name = dikeRingId
});
}
}
}
private bool CheckForValidSegmentId(int segmentRecordId, string segmentId)
{
if (String.IsNullOrEmpty(segmentId))
{
string segmentRecordHasNoId = LocalizationManager.GetTranslatedText(GetType(), "segmentRecordHasNoId");
var logmessage = new LogMessage(LogMessageType.Error, null,
$"Record {segmentRecordId} : {segmentRecordHasNoId}");
ErrorMessages.Add(logmessage);
return false;
}
return true;
}
///
/// Check if either a 1D-geometry or a 2D-geometry is specified
///
///
///
///
private bool CheckForAnySoilGeometry(string segmentId, string soilProfileId, string soilGeometry2DName)
{
if ((String.IsNullOrEmpty(soilProfileId)) && (String.IsNullOrEmpty(soilGeometry2DName)))
{
string segmentHasNoProfileOrGeometry = LocalizationManager.GetTranslatedText(GetType(), "segmentHasNoProfileOrGeometry");
var logmessage = new LogMessage(LogMessageType.Error, null,
$"{segmentId} : {segmentHasNoProfileOrGeometry}");
ErrorMessages.Add(logmessage);
return false;
}
return true;
}
///
/// Check if both a 1D-geometry or a 2D-geometry is specified (which is not allowed)
///
///
///
///
private bool CheckForDoubleSoilGeometry(string segmentId, string soilProfileId, string soilGeometry2DName)
{
if ((!String.IsNullOrEmpty(soilProfileId)) && (!String.IsNullOrEmpty(soilGeometry2DName)))
{
string segmentHasProfileAndGeometry = LocalizationManager.GetTranslatedText(GetType(), "segmentHasProfileAndGeometry");
var logmessage = new LogMessage(LogMessageType.Error, null,
$"{segmentId} : {segmentHasProfileAndGeometry}");
ErrorMessages.Add(logmessage);
return false;
}
return true;
}
// Before using this, the Locations and (for 1D profiles) SoilProfiles must be known!?
private void TransferSegmentData(Dike dike)
{
if (SegmentRecords == null)
{
return;
}
if (WaterBoard.Segments.Count > 0)
{
foreach (CsvImporterSegments.SegmentRecord segmentRecord in SegmentRecords)
{
// look for existing segments by Id. If found, remove them from the waterboard as they are to be (re)read here.
List oldSegments = WaterBoard.Segments.Where(s => s.Name == segmentRecord.SegmentId).ToList();
foreach (Segment oldSegment in oldSegments)
{
WaterBoard.Segments.Remove(oldSegment);
}
}
}
Dictionary soilProfileLookup = dike.SoilProfiles != null ? dike.SoilProfiles.ToDictionary(sp => sp.Name, sp => sp) : null;
foreach (CsvImporterSegments.SegmentRecord segmentRecord in SegmentRecords)
{
if (CheckForValidSegmentId(segmentRecord.SegmentRecordId, segmentRecord.SegmentId) &&
(CheckForDoubleSoilGeometry(segmentRecord.SegmentId, segmentRecord.SoilProfileId,
segmentRecord.SoilGeometry2DName)) &&
(CheckForAnySoilGeometry(segmentRecord.SegmentId, segmentRecord.SoilProfileId,
segmentRecord.SoilGeometry2DName)))
{
var newSegment = false;
//check if new segment is needed
Segment segment = WaterBoard.GetSegmentByName(segmentRecord.SegmentId);
if (segment == null)
{
newSegment = true;
segment = new Segment();
}
segment.Name = segmentRecord.SegmentId;
if (!String.IsNullOrEmpty(segmentRecord.SoilGeometry2DName))
{
segment.AddSoilGeometry2DProbability(segmentRecord.SoilGeometry2DName,
segmentRecord.Probability,
segmentRecord.SegmentFailureMechanismType);
}
if (!String.IsNullOrEmpty(segmentRecord.SoilProfileId))
{
if (soilProfileLookup == null)
{
string dikeHasNoSoilProfiles = LocalizationManager.GetTranslatedText(GetType(), "dikeHasNoSoilProfiles");
var logmessage = new LogMessage(LogMessageType.Error, null,
$"{dike.Name} : {dikeHasNoSoilProfiles}");
ErrorMessages.Add(logmessage);
}
else
{
string soilProfileName = segmentRecord.SoilProfileId;
SoilProfile1D soilProfile = soilProfileLookup.ContainsKey(soilProfileName) ? soilProfileLookup[soilProfileName] : null;
if (soilProfile == null)
{
//#Bka: do not give message here as it might be that an old project is being loaded which does not have a full
// dataset (such as old HHNK projects by Irene), leading to a very large list with non relevant errors as the locations
// for which this check is performed are not all used.
// var soilProfileForSegmentDoesNotExist =
// LocalizationManager.GetTranslatedText(this.GetType(),
// "soilProfileForSegmentDoesNotExist");
// LogMessage logmessage = new LogMessage(LogMessageType.Error, null,
// String.Format("{0} : {1}:{2}",
// segmentRecord.SegmentId,
// soilProfileForSegmentDoesNotExist,
// segmentRecord.SoilProfileId));
// ErrorMessages.Add(logmessage);
}
else
{
segment.AddSoilProfileProbability(soilProfile, segmentRecord.Probability,
segmentRecord.SegmentFailureMechanismType);
}
}
}
// Note Bka: coupling of segment to location still needs to be done. But can only be achieved when location has info on segment or segment id
//segment.Locations.AddRange(dike.Locations.Where(l => l.Segment.Name == segmentRecord.SegmentId));
// var segId = dike.Locations[0].SegmentId;
// if (segId == segmentRecord.SegmentId)
// dike.Locations[0].Segment = segment;
if (newSegment)
{
WaterBoard.Segments.Add(segment);
string segmentId = segmentRecord.SegmentId;
IEnumerable locationsWithSegmentId = WaterBoard.Locations.Where(x => x.SegmentId == segmentId);
foreach (Location location in locationsWithSegmentId)
{
location.Segment = segment;
}
}
}
}
}
private void TransferSoilData(Dike dike)
{
dike.FillImportedCsvSoilsFromCsvFile(SoilRecords);
dike.AssignImportedCsvSoilsPropertiesToSoilListSoils();
dike.FillTrafficLoadDegreeOfConsolidationFromCsvFile(SoilRecords);
}
private void TransferSigmaTauCurveData(Dike dike)
{
dike.FillImportedSigmaTauCurvesFromCsvFile(SigmaTauCurveRecords);
}
private void TransferSuTableData(Dike dike)
{
dike.FillImportedSuTablesFromCsvFile(SuTableRecords);
}
private void TransferSoilProfilesData(Dike dike)
{
if (SoilProfilerecords == null)
{
return;
}
var newSoilProfile = false;
var orgId = "";
SoilProfile1D soilProfile = null;
var layerIndex = 0;
foreach (CsvImporterSoilProfiles.SoilProfileRecord soilProfileRecord in SoilProfilerecords)
{
if (string.IsNullOrEmpty(soilProfileRecord.SoilProfileId) || string.IsNullOrEmpty(soilProfileRecord.SoilName))
{
string noIdForSoilProfileRecordError = LocalizationManager.GetTranslatedText(GetType(), "noIdOrSoilForSoilProfileRecordError");
var logMessage = new LogMessage(LogMessageType.Error, this,
$"Record {soilProfileRecord.SoilProfileRecordId} : {noIdForSoilProfileRecordError}");
ErrorMessages.Add(logMessage);
AddErrorMessage("noIdOrSoilForSoilProfileRecordError", soilProfileRecord);
}
else
{
// see if a next profile is to be converted from the csv data. If not, layer needs to be added to the current profile
if (orgId != soilProfileRecord.SoilProfileId)
{
// first add current profile (if it exists) to dike.
if (soilProfile != null)
{
if (newSoilProfile)
{
try
{
soilProfile.ValidateDirect();
dike.SoilProfiles.Add(soilProfile);
}
catch (SoilProfileLayersNotSortedDescendingException e)
{
var logMessage = new LogMessage(LogMessageType.Error, null, e.Message);
ErrorMessages.Add(logMessage);
}
layerIndex = 0;
}
newSoilProfile = false;
}
// determine the next profile (existing or new)
soilProfile = dike.SoilProfiles.FirstOrDefault(s => s.Name == soilProfileRecord.SoilProfileId);
if (soilProfile == null)
{
soilProfile = new SoilProfile1D();
newSoilProfile = true;
}
// clear layers of existing profile
if (soilProfile.Layers != null)
{
soilProfile.Layers.Clear();
}
else
{
string existingSoilProfileHasNoLayers = LocalizationManager.GetTranslatedText(GetType(), "existingSoilProfileHasNoLayers");
var logMessage = new LogMessage(LogMessageType.Error, null,
$"{soilProfileRecord.SoilProfileId} : {existingSoilProfileHasNoLayers}");
ErrorMessages.Add(logMessage);
}
soilProfile.Name = soilProfileRecord.SoilProfileId;
orgId = soilProfileRecord.SoilProfileId;
}
// if this is a dummy layer to set the bottom level for the entire profile, then do so
if (soilProfileRecord.SoilName == SoilProfile1D.SoilProfileBottomLevelId)
{
soilProfile.BottomLevel = soilProfileRecord.TopLevel;
}
else
{
// else set the layer
var layer = new SoilLayer1D
{
TopLevel = soilProfileRecord.TopLevel,
IsAquifer = soilProfileRecord.IsAquifer
};
int soilIndex = dike.SoilList.GetSoilIndexByName(soilProfileRecord.SoilName);
if (soilIndex == -1)
{
var soil = new Soil
{
Name = soilProfileRecord.SoilName
};
dike.SoilList.Soils.Add(soil);
soilIndex = dike.SoilList.Soils.Count - 1;
}
layer.Soil = dike.SoilList.Soils[soilIndex];
layer.Name = "Layer" + layerIndex;
layerIndex++;
soilProfile.Layers.Add(layer);
}
}
}
// finally add last current profile to dike.
if ((soilProfile != null) && newSoilProfile)
{
try
{
if ((soilProfile.Layers == null) || (soilProfile.Layers.Count == 0))
{
throw new SoilProfileLayersNotSortedDescendingException($"Soilprofile '{soilProfile.Name}' has no layers");
}
soilProfile.ValidateDirect();
dike.SoilProfiles.Add(soilProfile);
}
catch (SoilProfileLayersNotSortedDescendingException e)
{
var logmessage = new LogMessage(LogMessageType.Error, null, e.Message);
ErrorMessages.Add(logmessage);
}
}
// Make sure all soilprofiles last layer have a height
foreach (SoilProfile1D soilProfile1 in dike.SoilProfiles)
{
try
{
soilProfile1.EnsureLastLayerHasHeight();
}
catch (Exception e)
{
//var error = new StringBuilder();
var error = $"Error postprocessing soilprofile '{soilProfile1.Name}': {e.Message}";
var logmessage = new LogMessage(LogMessageType.Error, null, error);
ErrorMessages.Add(logmessage);
}
}
}
private void TransferAquifersData(Dike dike)
{
dike.FillImportedAquifersFromCsvFile(AquiferRecords);
}
private void TransferSurfaceLines(Dike dike)
{
if (SurfaceLineRecords == null)
{
return;
}
foreach (CsvImporterSurfaceLines.SurfaceLineRecord surfaceLineRecord in SurfaceLineRecords)
{
if (String.IsNullOrEmpty(surfaceLineRecord.SurfaceLineId))
{
string noIdForSurfaceLineRecordError = LocalizationManager.GetTranslatedText(GetType(), "noIdSurfaceLineRecordError");
var logmessage = new LogMessage(LogMessageType.Error, null,
$"Record {surfaceLineRecord.SurfaceLineRecordId} : {noIdForSurfaceLineRecordError}");
ErrorMessages.Add(logmessage);
}
else
{
var newSurfaceLine = false;
SurfaceLine2 surfaceLine =
dike.SurfaceLines2.FirstOrDefault(s => s.Name == surfaceLineRecord.SurfaceLineId);
if (surfaceLine == null)
{
surfaceLine = new SurfaceLine2
{
Geometry = new LocalizedGeometryPointString(),
CharacteristicPoints =
{
GeometryMustContainPoint = true
}
};
newSurfaceLine = true;
}
surfaceLine.Name = surfaceLineRecord.SurfaceLineId;
// first add all points from the surface line csv
for (var i = 0; i < surfaceLineRecord.Xcoors.Count; i++)
{
// empty points will not be added
if (surfaceLineRecord.Xcoors[i] != -1 || surfaceLineRecord.Ycoors[i] != -1 || surfaceLineRecord.Zcoors[i] != -1)
{
surfaceLine.EnsurePointOfType(surfaceLineRecord.Xcoors[i], surfaceLineRecord.Ycoors[i], surfaceLineRecord.Zcoors[i], null);
}
}
// Add the surface line to the dike
if (newSurfaceLine)
{
dike.SurfaceLines2.Add(surfaceLine);
}
// now see if all characteristic points belonging to this surface line are part of the surface line
CsvImporterCharacteristicPoints.CharacteristicPointsRecord characteristicPointsRecord =
CharacteristicPointsRecords.FirstOrDefault(s => s.SurfaceLineId == surfaceLine.Name);
var charCheck = true;
if (characteristicPointsRecord != null)
{
foreach (CsvImporterCharacteristicPoints.CharPoint point in characteristicPointsRecord.Points)
{
// ignore unset points
if (!((point.X == -1) && (point.Y == -1) && (point.Z == -1)))
{
GeometryPoint tppoint = surfaceLine.Geometry.GetPointAt(point.X, point.Y, point.Z);
if (tppoint != null)
{
surfaceLine.EnsurePointOfType(point.X, point.Y, point.Z, point.Type);
}
else
{
string charPointNotFoundInSurfaceError =
LocalizationManager.GetTranslatedText(GetType(), "charPointNotFoundInSurfaceError");
var logmessage = new LogMessage(LogMessageType.Error, null, $"{surfaceLine.Name} : {charPointNotFoundInSurfaceError} {point.Type}");
ErrorMessages.Add(logmessage);
charCheck = false;
}
}
}
}
else
{
string noCharPointsFoundForSurfaceError = LocalizationManager.GetTranslatedText(GetType(), "noCharPointsFoundForSurfaceError");
var logmessage = new LogMessage(LogMessageType.Error, null,
$"{surfaceLine.Name} : {noCharPointsFoundForSurfaceError}");
ErrorMessages.Add(logmessage);
charCheck = false;
}
// Check on illegal coinciding characteristic points
if (charCheck)
{
charCheck = CheckOnCoincidingPoints(surfaceLine);
}
if (!charCheck)
{
surfaceLine.Dispose();
dike.SurfaceLines2.Remove(surfaceLine);
}
}
}
}
private void TransferScenarios(Dike dike)
{
if (ScenarioRecords == null)
{
return;
}
Dictionary dikeLocationLookup = dike.Locations.ToDictionary(l => l.Name, l => l);
foreach (CsvImporterScenarios.ScenarioRecord scenarioRecord in ScenarioRecords)
{
var recordError = false;
if (string.IsNullOrEmpty(scenarioRecord.LocationId))
{
string noLocationIdForScenarioRecordError = LocalizationManager.GetTranslatedText(GetType(),
"noLocationIdForScenarioRecordError");
var logmessage = new LogMessage(LogMessageType.Error, null,
$"Record {scenarioRecord.ScenarioRecordId} : {noLocationIdForScenarioRecordError}");
ErrorMessages.Add(logmessage);
recordError = true;
}
// faassen: location id was of type int with default value -1 if empty. Now it is string and null as the default value
if (scenarioRecord.LocationScenarioId == null)
{
string invalidLocationScenarioIdForScenarioRecordError =
LocalizationManager.GetTranslatedText(GetType(), "invalidLocationScenarioIdForScenarioRecordError");
var logmessage = new LogMessage(LogMessageType.Error, null, $"Record {scenarioRecord.ScenarioRecordId} : {invalidLocationScenarioIdForScenarioRecordError}");
ErrorMessages.Add(logmessage);
recordError = true;
}
Location dikeLocation = dikeLocationLookup.ContainsKey(scenarioRecord.LocationId) ? dikeLocationLookup[scenarioRecord.LocationId] : null;
if (dikeLocation == null)
{
string locationNotFoundForScenarioRecordError = LocalizationManager.GetTranslatedText(GetType(), "locationNotFoundForScenarioRecordError");
var logmessage = new LogMessage(LogMessageType.Error, this, $"Record {scenarioRecord.ScenarioRecordId} : {locationNotFoundForScenarioRecordError}");
ErrorMessages.Add(logmessage);
recordError = true;
}
if (!recordError)
{
// Add to location scenario list
Scenario dikeScenario = dikeLocation.Scenarios.FirstOrDefault(s => s.Location.Name == scenarioRecord.LocationId &&
s.LocationScenarioID == scenarioRecord.LocationScenarioId);
if (dikeScenario != null)
{
string duplicateScenarioRecordError = LocalizationManager.GetTranslatedText(GetType(), "duplicateScenarioRecordError");
string errorMessage = string.Format(duplicateScenarioRecordError, dikeLocation.Name, dikeScenario.LocationScenarioID);
var logmessage = new LogMessage(LogMessageType.Error, null, $"Record {scenarioRecord.ScenarioRecordId} : {errorMessage}");
ErrorMessages.Add(logmessage);
}
else
{
CsvImporterLocations.LocationRecord locationRecord = LocationRecords.FirstOrDefault(l => l.LocationId == scenarioRecord.LocationId);
// Check if polder is present in either the location or the scenario record. This
// value is mandatory and must be present in either one.
if (locationRecord?.PolderLevel == null && scenarioRecord.PolderLevel == null)
{
string missingPolderLevelError = LocalizationManager.GetTranslatedText(GetType(), "missingPolderLevel");
var logmessage = new LogMessage(LogMessageType.Error, null, $"Record {scenarioRecord.ScenarioRecordId} : {missingPolderLevelError}");
ErrorMessages.Add(logmessage);
}
else
{
Scenario scenario = CreateScenario(dikeLocation, scenarioRecord, locationRecord);
dikeLocation.Scenarios.Add(scenario);
}
}
}
}
}
///
/// Creates a based on its input arguments.
///
/// The that belongs to the .
/// The to retrieve the data from.
/// The to retrieve the data from.
/// A .
private static Scenario CreateScenario(Location dikeLocation, CsvImporterScenarios.ScenarioRecord scenarioRecord,
CsvImporterLocations.LocationRecord locationRecord)
{
// set values in scenario (1 from scenariorecord, 2 from locationrecord, 3 default)
var modelFactors = new ModelFactors();
modelFactors.RequiredSafetyFactorStabilityInnerSlope = scenarioRecord.RequiredSafetyFactorStabilityInnerSlope ??
(locationRecord.RequiredSafetyFactorStabilityInnerSlope ?? modelFactors.RequiredSafetyFactorStabilityInnerSlope);
modelFactors.RequiredSafetyFactorStabilityOuterSlope = scenarioRecord.RequiredSafetyFactorStabilityOuterSlope ??
(locationRecord.RequiredSafetyFactorStabilityOuterSlope ?? modelFactors.RequiredSafetyFactorStabilityOuterSlope);
modelFactors.RequiredSafetyFactorPiping = scenarioRecord.RequiredSafetyFactorPiping ??
(locationRecord.RequiredSafetyFactorPiping ?? modelFactors.RequiredSafetyFactorPiping);
modelFactors.UpliftCriterionStability = scenarioRecord.UpliftCriterionStability ??
(locationRecord.UpliftCriterionStability ?? modelFactors.UpliftCriterionStability);
modelFactors.UpliftCriterionPiping = scenarioRecord.UpliftCriterionPiping ??
(locationRecord.UpliftCriterionPiping ?? modelFactors.UpliftCriterionPiping);
var scenario = new Scenario
{
Location = dikeLocation,
LocationScenarioID = scenarioRecord.LocationScenarioId,
ModelFactors = modelFactors
};
scenario.PlLineOffsetBelowDikeToeAtPolder = scenarioRecord.PlLineOffsetBelowDikeToeAtPolder ??
(locationRecord.PlLineOffsetBelowDikeToeAtPolder ?? scenario.PlLineOffsetBelowDikeToeAtPolder);
scenario.PlLineOffsetBelowDikeTopAtPolder = scenarioRecord.PlLineOffsetBelowDikeTopAtPolder ??
(locationRecord.PlLineOffsetBelowDikeTopAtPolder ?? scenario.PlLineOffsetBelowDikeTopAtPolder);
scenario.PlLineOffsetBelowDikeTopAtRiver = scenarioRecord.PlLineOffsetBelowDikeTopAtRiver ??
(locationRecord.PlLineOffsetBelowDikeTopAtRiver ?? scenario.PlLineOffsetBelowDikeTopAtRiver);
scenario.PlLineOffsetBelowShoulderBaseInside = scenarioRecord.PlLineOffsetBelowShoulderBaseInside ??
(locationRecord.PlLineOffsetBelowShoulderBaseInside ?? scenario.PlLineOffsetBelowShoulderBaseInside);
// set values in scenario (1 from scenariorecord, 2 from locationrecord, 3 stays null)
scenario.PlLineOffsetBelowDikeCrestMiddle = scenarioRecord.PlLineOffsetBelowDikeCrestMiddle ??
locationRecord.PlLineOffsetBelowDikeCrestMiddle;
scenario.PlLineOffsetFactorBelowShoulderCrest = scenarioRecord.PlLineOffsetFactorBelowShoulderCrest ??
locationRecord.PlLineOffsetFactorBelowShoulderCrest;
scenario.UsePlLineOffsetBelowDikeCrestMiddle = scenarioRecord.UsePlLineOffsetBelowDikeCrestMiddle ??
locationRecord.UsePlLineOffsetBelowDikeCrestMiddle;
scenario.UsePlLineOffsetFactorBelowShoulderCrest = scenarioRecord.UsePlLineOffsetFactorBelowShoulderCrest ??
locationRecord.UsePlLineOffsetFactorBelowShoulderCrest;
scenario.HeadPl3 = scenarioRecord.HeadPl3 ?? locationRecord.HeadPl3;
scenario.HeadPl4 = scenarioRecord.HeadPl4 ?? locationRecord.HeadPl4;
scenario.PolderLevel = scenarioRecord.PolderLevel ?? locationRecord.PolderLevel.Value;
scenario.HeadPl2 = scenarioRecord.HeadPl2 ?? locationRecord.HeadPl2;
scenario.DikeTableHeight = scenarioRecord.DikeTableHeight ?? locationRecord.DikeTableHeight;
scenario.RiverLevel = scenarioRecord.RiverLevel ?? locationRecord.RiverLevel;
scenario.RiverLevelLow = scenarioRecord.RiverLevelLow ?? locationRecord.RiverLevelLow;
return scenario;
}
///
/// Transfers the locations data.
///
/// The dike.
private void TransferLocationsData(Dike dike)
{
if (LocationRecords == null)
{
return;
}
foreach (CsvImporterLocations.LocationRecord locationRecord in LocationRecords)
{
if (locationRecord.DikeRingId.Equals(dike.Name))
{
// Check if id is defined
if (String.IsNullOrEmpty(locationRecord.LocationId))
{
AddErrorMessage("noIdLocationRecordError", locationRecord);
continue;
}
// See if location already exist; else create one and add it to the dike
Location location = dike.Locations.FirstOrDefault(s => s.Name == locationRecord.LocationId);
if (location == null)
{
var errorInrecord = false;
location = new Location();
location.Name = locationRecord.LocationId;
location.SurfaceLineId = locationRecord.SurfaceLineId;
location.SegmentId = locationRecord.SegmentId;
if (locationRecord.DikeRingId != null)
{
location.DikeRingId = locationRecord.DikeRingId;
}
if (location.DampingFactorPL3 < 0 || location.DampingFactorPL3 > 1)
{
AddErrorMessage("DampingFactorPl3BeyondLimits", locationRecord);
errorInrecord = true;
}
if (location.DampingFactorPL4 < 0 || location.DampingFactorPL4 > 1)
{
AddErrorMessage("DampingFactorPl4BeyondLimits", locationRecord);
errorInrecord = true;
}
if (null != locationRecord.DikeEmbankmentMaterial)
{
location.DikeEmbankmentMaterial = locationRecord.DikeEmbankmentMaterial;
}
if (null != locationRecord.ShoulderEmbankmentMaterial)
{
location.ShoulderEmbankmentMaterial = locationRecord.ShoulderEmbankmentMaterial;
}
location.XRd = locationRecord.GeoX.GetValueOrDefault(location.XRd);
location.YRd = locationRecord.GeoY.GetValueOrDefault(location.YRd);
location.XSoilGeometry2DOrigin = locationRecord.XSoilGeometry2DOrigin.GetValueOrDefault(location.XSoilGeometry2DOrigin);
location.DampingFactorPL3 = locationRecord.DampingFactorPl3.GetValueOrDefault(location.DampingFactorPL3);
location.DampingFactorPL4 = locationRecord.DampingFactorPl4.GetValueOrDefault(location.DampingFactorPL4);
location.PenetrationLength = locationRecord.PenetrationLength.GetValueOrDefault(location.PenetrationLength);
location.TrafficLoad = locationRecord.TrafficLoad.GetValueOrDefault(location.TrafficLoad);
location.TL_DegreeOfConsolidation = locationRecord.TL_DegreeOfConsolidation;
location.PLLineCreationMethod = locationRecord.PLLineCreationMethod.GetValueOrDefault(location.PLLineCreationMethod);
if (locationRecord.IntrusionVerticalWaterPressure.HasValue)
{
location.IntrusionVerticalWaterPressure = locationRecord.IntrusionVerticalWaterPressure.Value;
}
location.StabilityShoulderGrowSlope = locationRecord.StabilityShoulderGrowSlope.GetValueOrDefault(location.StabilityShoulderGrowSlope);
location.StabilityShoulderGrowDeltaX = locationRecord.StabilityShoulderGrowDeltaX.GetValueOrDefault(location.StabilityShoulderGrowDeltaX);
location.StabilitySlopeAdaptionDeltaX = locationRecord.StabilitySlopeAdaptionDeltaX.GetValueOrDefault(location.StabilitySlopeAdaptionDeltaX);
location.MinimalCircleDepth = locationRecord.MinimalCircleDepth.GetValueOrDefault(location.MinimalCircleDepth);
location.DistanceToEntryPoint = locationRecord.DistanceToEntryPoint.GetValueOrDefault(location.DistanceToEntryPoint);
location.SlopeDampingPiezometricHeightPolderSide = locationRecord.SlopeDampingPiezometricHeightPolderSide.GetValueOrDefault(location.SlopeDampingPiezometricHeightPolderSide);
location.StabilityDesignMethod = locationRecord.StabilityDesignMethod.GetValueOrDefault(location.StabilityDesignMethod);
location.SlopeAdaptionStartCotangent = locationRecord.SlopeAdaptionStartCotangent.GetValueOrDefault(location.SlopeAdaptionStartCotangent);
location.SlopeAdaptionEndCotangent = locationRecord.SlopeAdaptionEndCotangent.GetValueOrDefault(location.SlopeAdaptionEndCotangent);
location.SlopeAdaptionStepCotangent = locationRecord.SlopeAdaptionStepCotangent.GetValueOrDefault(location.SlopeAdaptionStepCotangent);
location.StabilityZoneType = locationRecord.StabilityZoneType.GetValueOrDefault(location.StabilityZoneType);
location.ForbiddenZoneFactor = locationRecord.ForbiddenZoneFactor.GetValueOrDefault(location.ForbiddenZoneFactor);
location.NewDepthDitch = locationRecord.NewDepthDitch.GetValueOrDefault(location.NewDepthDitch);
location.NewDikeSlopeInside = locationRecord.NewDikeSlopeInside.GetValueOrDefault(location.NewDikeSlopeInside);
location.NewDikeSlopeOutside = locationRecord.NewDikeSlopeOutside.GetValueOrDefault(location.NewDikeSlopeOutside);
location.NewDikeTopWidth = locationRecord.NewDikeTopWidth.GetValueOrDefault(location.NewDikeTopWidth);
location.NewMaxHeightShoulderAsFraction = locationRecord.NewMaxHeightShoulderAsFraction.GetValueOrDefault(location.NewMaxHeightShoulderAsFraction);
location.NewMinDistanceDikeToeStartDitch = locationRecord.NewMinDistanceDikeToeStartDitch.GetValueOrDefault(location.NewMinDistanceDikeToeStartDitch);
location.NewShoulderBaseSlope = locationRecord.NewShoulderBaseSlope.GetValueOrDefault(location.NewShoulderBaseSlope);
location.NewShoulderTopSlope = locationRecord.NewShoulderTopSlope.GetValueOrDefault(location.NewShoulderTopSlope);
location.NewSlopeAngleDitch = locationRecord.NewSlopeAngleDitch.GetValueOrDefault(location.NewSlopeAngleDitch);
location.NewWidthDitchBottom = locationRecord.NewWidthDitchBottom.GetValueOrDefault(location.NewWidthDitchBottom);
location.UseNewDikeSlopeInside = locationRecord.UseNewDikeSlopeInside.GetValueOrDefault(location.UseNewDikeSlopeInside);
location.UseNewDikeSlopeOutside = locationRecord.UseNewDikeSlopeOutside.GetValueOrDefault(location.UseNewDikeSlopeOutside);
location.UseNewDikeTopWidth = locationRecord.UseNewDikeTopWidth.GetValueOrDefault(location.UseNewDikeTopWidth);
location.UseNewDitchDefinition = locationRecord.UseNewDitchDefinition.GetValueOrDefault(location.UseNewDitchDefinition);
location.UseNewMaxHeightShoulderAsFraction = locationRecord.UseNewMaxHeightShoulderAsFraction.GetValueOrDefault(location.UseNewMaxHeightShoulderAsFraction);
location.UseNewMinDistanceDikeToeStartDitch = locationRecord.UseNewMinDistanceDikeToeStartDitch.GetValueOrDefault(location.UseNewMinDistanceDikeToeStartDitch);
location.UseNewShoulderBaseSlope = locationRecord.UseNewShoulderBaseSlope.GetValueOrDefault(location.UseNewShoulderBaseSlope);
location.UseNewShoulderTopSlope = locationRecord.UseNewShoulderTopSlope.GetValueOrDefault(location.UseNewShoulderTopSlope);
if (!errorInrecord)
{
dike.Locations.Add(location);
}
else
{
location.Dispose();
}
}
}
}
}
private void AddErrorMessage(string errorMessageTranslationId, CsvImporterLocations.LocationRecord locationRecord)
{
AddErrorMessage(errorMessageTranslationId, locationRecord.LocationRecordId);
}
private void AddErrorMessage(string errorMessageTranslationId, CsvImporterSoilProfiles.SoilProfileRecord soilProfileRecord)
{
AddErrorMessage(errorMessageTranslationId, soilProfileRecord.SoilProfileRecordId);
}
private void AddErrorMessage(string errorMessageTranslationId, int id)
{
string noIdForSoilProfileRecordError = LocalizationManager.GetTranslatedText(GetType(), errorMessageTranslationId);
var logmessage = new LogMessage(
LogMessageType.Error, this,
$"Record {id} : {noIdForSoilProfileRecordError}"
);
ErrorMessages.Add(logmessage);
}
}