Index: DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/Translations.xml =================================================================== diff -u -r2440 -r2454 --- DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/Translations.xml (.../Translations.xml) (revision 2440) +++ DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/Translations.xml (.../Translations.xml) (revision 2454) @@ -280,6 +280,7 @@ + Index: DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/IO/CombineImportedData.cs =================================================================== diff -u -r2422 -r2454 --- DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/IO/CombineImportedData.cs (.../CombineImportedData.cs) (revision 2422) +++ DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/IO/CombineImportedData.cs (.../CombineImportedData.cs) (revision 2454) @@ -148,6 +148,7 @@ if (ScenarioRecords != null) { TransferScenarios(dike); + RemoveLocationsWithoutWaterHeight(dike); } } } @@ -592,6 +593,29 @@ return charCheck; } + private void RemoveLocationsWithoutWaterHeight(Dike dike) + { + for (int i = dike.Locations.Count - 1; i > -1; i--) + { + bool WaterHeightSpecified = false; + var location = dike.Locations[i]; + foreach (var scenario in location.Scenarios) + { + if (scenario.RiverLevel != null) + { + WaterHeightSpecified = true; + } + } + if (!WaterHeightSpecified) + { + LogMessage logmessage = new LogMessage(LogMessageType.Error, null, + string.Format(LocalizationManager.GetTranslatedText(GetType(), "NoWaterHeightLocationNotAdded"), location.Name)); + ErrorMessages.Add(logmessage); + dike.Locations.RemoveAt(dike.Locations.IndexOf(location)); + } + } + } + private void TransferScenarios(Dike dike) { if (ScenarioRecords == null) Index: DamClients/DamUI/trunk/src/Dam/Tests/DataPluginImporterTests.cs =================================================================== diff -u -r2421 -r2454 --- DamClients/DamUI/trunk/src/Dam/Tests/DataPluginImporterTests.cs (.../DataPluginImporterTests.cs) (revision 2421) +++ DamClients/DamUI/trunk/src/Dam/Tests/DataPluginImporterTests.cs (.../DataPluginImporterTests.cs) (revision 2454) @@ -19,14 +19,13 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. -using System.CodeDom.Compiler; using System.Collections.Generic; +using System.IO; using System.Linq; using Deltares.Dam.Data; using Deltares.Dam.Data.DataPlugins; using Deltares.Dam.Data.DataPlugins.Configuration; using Deltares.Dam.Data.Importers; -using Deltares.Dam.Data.Properties; using Deltares.Standard.Language; using Deltares.Standard.TestUtils; @@ -210,5 +209,329 @@ Assert.AreEqual("-3.632", scenarioDetails.First(x => x.ParameterName.Equals("HeadPL3")).ParameterValue); } + private void CreateBasicDataFiles(string importFolder) + { + var importFile = importFolder + "\\characteristicpoints.csv"; + if (File.Exists(importFile)) + File.Delete(importFile); + using (var writer = File.CreateText(importFile)) + { + writer.WriteLine("LOCATIONID;X_Maaiveld binnenwaarts;Y_Maaiveld binnenwaarts;Z_Maaiveld binnenwaarts;X_Insteek sloot polderzijde;Y_Insteek sloot polderzijde;Z_Insteek sloot polderzijde;X_Slootbodem polderzijde;Y_Slootbodem polderzijde;Z_Slootbodem polderzijde;X_Slootbodem dijkzijde;Y_Slootbodem dijkzijde;Z_Slootbodem dijkzijde;X_Insteek sloot dijkzijde;Y_Insteek_sloot dijkzijde;Z_Insteek sloot dijkzijde;X_Teen dijk binnenwaarts;Y_Teen dijk binnenwaarts;Z_Teen dijk binnenwaarts;X_Kruin binnenberm;Y_Kruin binnenberm;Z_Kruin binnenberm;X_Insteek binnenberm;Y_Insteek binnenberm;Z_Insteek binnenberm;X_Kruin binnentalud;Y_Kruin binnentalud;Z_Kruin binnentalud;X_Verkeersbelasting kant binnenwaarts;Y_Verkeersbelasting kant binnenwaarts;Z_Verkeersbelasting kant binnenwaarts;X_Verkeersbelasting kant buitenwaarts;Y_Verkeersbelasting kant buitenwaarts;Z_Verkeersbelasting kant buitenwaarts;X_Kruin buitentalud;Y_Kruin buitentalud;Z_Kruin buitentalud;X_Insteek buitenberm;Y_Insteek buitenberm;Z_Insteek buitenberm;X_Kruin buitenberm;Y_Kruin buitenberm;Z_Kruin buitenberm;X_Teen dijk buitenwaarts;Y_Teen dijk buitenwaarts;Z_Teen dijk buitenwaarts;X_Insteek geul;Y_Insteek geul;Z_Insteek geul;X_Teen geul;Y_Teen geul;Z_Teen geul;X_Maaiveld buitenwaarts;Y_Maaiveld buitenwaarts;Z_Maaiveld buitenwaarts"); + } + importFile = importFolder + "\\segments.csv"; + if (File.Exists(importFile)) + File.Delete(importFile); + using (var writer = File.CreateText(importFile)) + { + writer.WriteLine("segment_id;soilprofile_id;probability;calculation_type"); + } + importFile = importFolder + "\\soilprofiles.csv"; + if (File.Exists(importFile)) + File.Delete(importFile); + using (var writer = File.CreateText(importFile)) + { + writer.WriteLine("soilprofile_id;top_level;soil_name"); + } + importFile = importFolder + "\\surfacelines.csv"; + if (File.Exists(importFile)) + File.Delete(importFile); + using (var writer = File.CreateText(importFile)) + { + writer.WriteLine("LOCATIONID;X1;Y1;Z1;.....;Xn;Yn;Zn;(Profiel)"); + } + } + + private void CreateLocationsFileWithWaterHeight(string importFile) + { + // A valid locations.csv has at least 4 columns. + // Required are location_id, surfaceline_id, segment_id. + // For the test we need dikering_id as well. + // Include column for WaterHeight + if (File.Exists(importFile)) + File.Delete(importFile); + using (var writer = File.CreateText(importFile)) + { + writer.WriteLine("location_id;dikering_id;surfaceline_id;segment_id;water_height"); + writer.WriteLine("RK210-560;Actualisatie;RK210-560;1;1.2"); + writer.WriteLine("RK210-570;Actualisatie;RK210-570;1;2.2"); + } + } + + private void CreateLocationsFileWithoutWaterHeight(string importFile) + { + // A valid locations.csv has at least 4 columns + // Do NOT include column for WaterHeight + if (File.Exists(importFile)) + File.Delete(importFile); + using (var writer = File.CreateText(importFile)) + { + writer.WriteLine("location_id;surfaceline_id;segment_id;polderlevel"); + writer.WriteLine("RK210-560;Actualisatie;1;1.2"); + writer.WriteLine("RK210-570;Actualisatie;1;2.2"); + } + } + + private void CreateScenariosFileWithWaterHeight(string importFile) + { + // A valid scenarios.csv has at least 4 columns + // Required are location_id, location_scenario_id, water_height and dike_table_height. + // Include column for WaterHeight + if (File.Exists(importFile)) + File.Delete(importFile); + using (var writer = File.CreateText(importFile)) + { + writer.WriteLine("location_id;location_scenario_id;water_height;dike_table_height"); + writer.WriteLine("RK210-560;1;0.1;0.680"); + writer.WriteLine("RK210-570;1;0.2;1.680"); + } + } + + private void CreateScenariosFileWithoutWaterHeight(string importFile) + { + // A valid scenarios.csv has at least 4 columns + // Required are location_id, location_scenario_id, water_height and dike_table_height. + // Include column for WaterHeight + if (File.Exists(importFile)) + File.Delete(importFile); + using (var writer = File.CreateText(importFile)) + { + writer.WriteLine("location_id;location_scenario_id;HeadPL3;dike_table_height"); + writer.WriteLine("RK210-560;1;0.1;0.680"); + writer.WriteLine("RK210-570;1;0.2;1.680"); + } + } + +// [Test] +// // WaterHeight must be specified in locations.csv, shapefile or scenarios.csv +// // If not specified in each of them, do not add the location and add message to log +// // In this test reading from shapefile is skipped +// public void WaterHeightIsRequired() +// { +// const double tolerance = 0.001; +// +// // Setup folder for situation where WaterHeight is specified +// var importFolder = Path.Combine(Directory.GetCurrentDirectory(), "TmpImportFilesWithWaterHeight"); +// if (!Directory.Exists(importFolder)) +// Directory.CreateDirectory(importFolder); +// srcDataSources = new List +// { +// new DataSource +// { +// DataSourceType = DataSourceType.CsvFiles, +// DataLocation = importFolder +// }, +// }; +// +// // To call ImportDataForDikeRings we need also inputfiles for segments, characteristic points etc. +// // To simplify the test we only import locations and scenario csv files +// // and then call AddScenarioDataToDikes like in ImportData +// +// // Create locations.csv that includes waterheight +// string importLocationsFile = importFolder + "\\locations.csv"; +// CreateLocationsFileWithWaterHeight(importLocationsFile); +// var csvImporterLocations = new CsvImporterLocations(importLocationsFile); +// var locationRecords = csvImporterLocations.ImportedItems; +// Assert.AreEqual(2, locationRecords.Count); +// Assert.AreEqual("RK210-560", locationRecords[0].LocationId); +// Assert.AreEqual("RK210-570", locationRecords[1].LocationId); +// // Expected: The locations include values for WaterHeight +// Assert.AreEqual(1.2, locationRecords[0].WaterHeight, tolerance); +// Assert.AreEqual(2.2, locationRecords[1].WaterHeight, tolerance); +// +// // Create scenarios.csv that does NOT include waterheight +// var importScenarioFile = importFolder + "\\scenarios.csv"; +// CreateScenariosFileWithoutWaterHeight(importScenarioFile); +// var csvImporterScenarios = new CsvImporterScenarios(importScenarioFile); +// var scenarioRecords = csvImporterScenarios.ImportedItems; +// Assert.AreEqual(2, scenarioRecords.Count); +// // Expected: Null because WaterHeight is not specified in scenarios +// Assert.AreEqual(null, scenarioRecords[0].WaterHeight); +// Assert.AreEqual(null, scenarioRecords[1].WaterHeight); +// // Combine the locations and scenario data +// var csvImporter = new CsvImporter(); +// csvImporter.LocationRecords = locationRecords; +// dataPluginImporter = new DataPluginImporter(); +// dataPluginImporter.SetDataSources("", srcDataSources); +// string dikeRingId = dataPluginImporter.GetDikeRingIdList().FirstOrDefault(); +// +// dataPluginImporter.AddCsvDataToDikes(csvImporter); +// dataPluginImporter.AddScenarioDataToDikes(csvImporter.ScenariosRecords); +// // Expected: The values of location are used for scenario +// string scenarioId = dataPluginImporter.GetScenarioList(dikeRingId, "RK210-560").FirstOrDefault(); +// IEnumerable scenarioDetails = dataPluginImporter.GetScenarioDetails(dikeRingId, "RK210-560", scenarioId); +// var nameValueParameters = scenarioDetails as NameValueParameter[] ?? scenarioDetails.ToArray(); +// Assert.AreEqual("1.2", nameValueParameters.FirstOrDefault(x => x.ParameterName.Equals("WaterHeight")).ParameterValue); +// scenarioId = dataPluginImporter.GetScenarioList(dikeRingId, "RK210-570").FirstOrDefault(); +// scenarioDetails = dataPluginImporter.GetScenarioDetails(dikeRingId, "RK210-570", scenarioId); +// nameValueParameters = scenarioDetails as NameValueParameter[] ?? scenarioDetails.ToArray(); +// Assert.AreEqual("2.2", nameValueParameters.FirstOrDefault(x => x.ParameterName.Equals("WaterHeight")).ParameterValue); +// +// // Create scenarios.csv that includes waterheight +// importScenarioFile = importFolder + "\\scenarios.csv"; +// CreateScenariosFileWithWaterHeight(importScenarioFile); +// csvImporterScenarios = new CsvImporterScenarios(importScenarioFile); +// scenarioRecords = csvImporterScenarios.ImportedItems; +// Assert.AreEqual(2, scenarioRecords.Count); +// // Expected: The value from scenarios are read +// Assert.AreEqual(0.1, scenarioRecords[0].WaterHeight, tolerance); +// Assert.AreEqual(0.2, scenarioRecords[1].WaterHeight, tolerance); +// // Combine the locations and scenario data +// csvImporter = new CsvImporter(); +// csvImporter.LocationRecords = locationRecords; +// dataPluginImporter = new DataPluginImporter(); +// dataPluginImporter.SetDataSources("", srcDataSources); +// dataPluginImporter.AddCsvDataToDikes(csvImporter); +// dataPluginImporter.AddScenarioDataToDikes(csvImporter.ScenariosRecords); +// // Expected: The values of scenarios are not overwritten by values from locations +//// Assert.AreEqual(0.1, scenarioRecords[0].WaterHeight, tolerance); +//// Assert.AreEqual(0.2, scenarioRecords[1].WaterHeight, tolerance); +// +// +// // // Read a locations.csv that does NOT include waterheight +// // importFile = importFolder + "\\locationsWithoutWaterheight.csv"; +// // CreateLocationsFileWithoutWaterHeight(importFile); +// // csvImporterLocations = new CsvImporterLocations(importFile); +// // locationRecords = csvImporterLocations.ImportedItems; +// // Assert.AreEqual(2, locationRecords.Count); +// // Assert.AreEqual("25-2-2-A-1-A", locationRecords[1].LocationId); +// // Assert.AreEqual(1.2, locationRecords[0].WaterHeight, tolerance); +// // Assert.AreEqual(2.2, locationRecords[1].WaterHeight, tolerance); +// // // Read a scenarios.csv that does NOT include waterheight +// // importFile = importFolder + "\\scenariosWithoutWaterheight.csv"; +// // CreateLocationsFileWithoutWaterHeight(importFile); +// // csvImporterLocations = new CsvImporterLocations(importFile); +// // locationRecords = csvImporterLocations.ImportedItems; +// // Assert.AreEqual(2, locationRecords.Count); +// } + + [Test] + // WaterHeight must be specified in locations.csv, shapefile or scenarios.csv + // In this test reading from shapefile is skipped, WaterHeight is defined in locations, not in scenarios + public void ImportWaterHeightFromLocationsTest() + { + // Setup folder for situation where WaterHeight is specified in locations + var importFolder = Path.Combine(Directory.GetCurrentDirectory(), "TmpImportFilesWaterHeightFromLocations"); + if (!Directory.Exists(importFolder)) + Directory.CreateDirectory(importFolder); + srcDataSources = new List + { + new DataSource + { + DataSourceType = DataSourceType.CsvFiles, + DataLocation = importFolder + }, + }; + // Create basic datafiles that are needed to succeed the import method + CreateBasicDataFiles(importFolder); + // Create locations.csv that includes waterheight + string importLocationsFile = importFolder + "\\locations.csv"; + CreateLocationsFileWithWaterHeight(importLocationsFile); + // Create scenarios.csv that does NOT include waterheight + var importScenarioFile = importFolder + "\\scenarios.csv"; + CreateScenariosFileWithoutWaterHeight(importScenarioFile); + + dataPluginImporter = new DataPluginImporter(); + dataPluginImporter.SetDataSources("", srcDataSources); + string dikeRingId = dataPluginImporter.GetDikeRingIdList().FirstOrDefault(); + dataPluginImporter.ImportDataForDikeRings(new List { dikeRingId }, null); + + // Expected: The values of location are used for scenario, because it was not specified in scenarios.csv + string scenarioId = dataPluginImporter.GetScenarioList(dikeRingId, "RK210-560").FirstOrDefault(); + IEnumerable scenarioDetails = dataPluginImporter.GetScenarioDetails(dikeRingId, "RK210-560", scenarioId); + var nameValueParameters = scenarioDetails as NameValueParameter[] ?? scenarioDetails.ToArray(); + Assert.AreEqual("1.2", nameValueParameters.FirstOrDefault(x => x.ParameterName.Equals("RiverLevel")).ParameterValue); + scenarioId = dataPluginImporter.GetScenarioList(dikeRingId, "RK210-570").FirstOrDefault(); + scenarioDetails = dataPluginImporter.GetScenarioDetails(dikeRingId, "RK210-570", scenarioId); + nameValueParameters = scenarioDetails as NameValueParameter[] ?? scenarioDetails.ToArray(); + Assert.AreEqual("2.2", nameValueParameters.FirstOrDefault(x => x.ParameterName.Equals("RiverLevel")).ParameterValue); + // Expected: no error messages + Assert.AreEqual(0, dataPluginImporter.ImportLogMessages.Count); + } + + [Test] + // WaterHeight must be specified in locations.csv, shapefile or scenarios.csv + // In this test reading from shapefile is skipped, WaterHeight is defined in locations and in scenarios + public void ImportWaterHeightFromScenariosTest() + { + // Setup folder for situation where WaterHeight is specified in locations and scenarios + var importFolder = Path.Combine(Directory.GetCurrentDirectory(), "TmpImportFilesWaterHeightFromScenarios"); + if (!Directory.Exists(importFolder)) + Directory.CreateDirectory(importFolder); + srcDataSources = new List + { + new DataSource + { + DataSourceType = DataSourceType.CsvFiles, + DataLocation = importFolder + }, + }; + // Create basic datafiles that are needed to succeed the import method + CreateBasicDataFiles(importFolder); + // Create locations.csv that includes waterheight + string importLocationsFile = importFolder + "\\locations.csv"; + CreateLocationsFileWithWaterHeight(importLocationsFile); + // Create scenarios.csv that includes waterheight + var importScenarioFile = importFolder + "\\scenarios.csv"; + CreateScenariosFileWithWaterHeight(importScenarioFile); + + dataPluginImporter = new DataPluginImporter(); + dataPluginImporter.SetDataSources("", srcDataSources); + string dikeRingId = dataPluginImporter.GetDikeRingIdList().FirstOrDefault(); + dataPluginImporter.ImportDataForDikeRings(new List { dikeRingId }, null); + + // Expected: The values of scenarios are used for scenario + string scenarioId = dataPluginImporter.GetScenarioList(dikeRingId, "RK210-560").FirstOrDefault(); + IEnumerable scenarioDetails = dataPluginImporter.GetScenarioDetails(dikeRingId, "RK210-560", scenarioId); + var nameValueParameters = scenarioDetails as NameValueParameter[] ?? scenarioDetails.ToArray(); + Assert.AreEqual("0.1", nameValueParameters.FirstOrDefault(x => x.ParameterName.Equals("RiverLevel")).ParameterValue); + scenarioId = dataPluginImporter.GetScenarioList(dikeRingId, "RK210-570").FirstOrDefault(); + scenarioDetails = dataPluginImporter.GetScenarioDetails(dikeRingId, "RK210-570", scenarioId); + nameValueParameters = scenarioDetails as NameValueParameter[] ?? scenarioDetails.ToArray(); + Assert.AreEqual("0.2", nameValueParameters.FirstOrDefault(x => x.ParameterName.Equals("RiverLevel")).ParameterValue); + // Expected: no error messages + Assert.AreEqual(0, dataPluginImporter.ImportLogMessages.Count); + } + + [Test] + // WaterHeight must be specified in locations.csv, shapefile or scenarios.csv + // In this test reading from shapefile is skipped, WaterHeight is NOT defined in locations or scenarios + public void ImportWaterHeightNotSpecifiedTest() + { + // Setup folder for situation where WaterHeight is NOT specified in locations and scenarios + var importFolder = Path.Combine(Directory.GetCurrentDirectory(), "TmpImportFilesWaterHeightNotSpecified"); + if (!Directory.Exists(importFolder)) + Directory.CreateDirectory(importFolder); + srcDataSources = new List + { + new DataSource + { + DataSourceType = DataSourceType.CsvFiles, + DataLocation = importFolder + }, + }; + // Create basic datafiles that are needed to succeed the import method + CreateBasicDataFiles(importFolder); + // Create locations.csv that includes waterheight + string importLocationsFile = importFolder + "\\locations.csv"; + CreateLocationsFileWithoutWaterHeight(importLocationsFile); + // Create scenarios.csv that includes waterheight + var importScenarioFile = importFolder + "\\scenarios.csv"; + CreateScenariosFileWithoutWaterHeight(importScenarioFile); + + dataPluginImporter = new DataPluginImporter(); + dataPluginImporter.SetDataSources("", srcDataSources); + string dikeRingId = dataPluginImporter.GetDikeRingIdList().FirstOrDefault(); + dataPluginImporter.ImportDataForDikeRings(new List { dikeRingId }, null); + + // Expected: The values are null, the locations are deleted, error message for each location + string locations = dataPluginImporter.GetLocationIdList(dikeRingId).FirstOrDefault(); + Assert.AreEqual(null, locations); + // Expected: error message for each location, NB. messages start with last added locations first + Assert.AreEqual(2, dataPluginImporter.ImportLogMessages.Count); + Assert.AreEqual("Location 'RK210-570' not added, because water height is missing.", + dataPluginImporter.ImportLogMessages[0].Message); + Assert.AreEqual("Location 'RK210-560' not added, because water height is missing.", + dataPluginImporter.ImportLogMessages[1].Message); + } } } Index: DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/CsvImporters/CsvImporterScenarios.cs =================================================================== diff -u -r2422 -r2454 --- DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/CsvImporters/CsvImporterScenarios.cs (.../CsvImporterScenarios.cs) (revision 2422) +++ DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/CsvImporters/CsvImporterScenarios.cs (.../CsvImporterScenarios.cs) (revision 2454) @@ -148,7 +148,6 @@ const string fieldWaterHeight = "water_height"; int colIndexWaterHeight = CsvReaderUtilities.GetHeaderIndexByString(headers, fieldWaterHeight); - CheckColumn(colIndexWaterHeight, fileName, fieldWaterHeight); const string fieldWaterHeightLow = "water_height_low"; int colIndexWaterHeightLow = CsvReaderUtilities.GetHeaderIndexByString(headers, fieldWaterHeightLow); @@ -209,8 +208,11 @@ string value = csv[colIndexLocationScenarioId]; scenario.LocationScenarioId = string.IsNullOrWhiteSpace(value) ? null : value; - colIndex = colIndexWaterHeight; - scenario.WaterHeight = Convert.ToDouble(csv[colIndexWaterHeight]); + if (colIndexWaterHeight > -1) + { + colIndex = colIndexWaterHeight; + scenario.WaterHeight = Convert.ToDouble(csv[colIndexWaterHeight]); + } if (colIndexWaterHeightLow > -1) { colIndex = colIndexWaterHeightLow; Index: DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/DataPlugins/DataPluginImporter.cs =================================================================== diff -u -r2421 -r2454 --- DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/DataPlugins/DataPluginImporter.cs (.../DataPluginImporter.cs) (revision 2421) +++ DamClients/DamUI/trunk/src/DamClientsLibrary/Deltares.Dam.Data/DataPlugins/DataPluginImporter.cs (.../DataPluginImporter.cs) (revision 2454) @@ -1108,7 +1108,6 @@ { ImportDikeRingAndLocationData(dataSource, ref csvImporter); } - AddScenarioDataToDikes(csvImporter); isDikeRingAndLocationDataImported = true; } @@ -1315,6 +1314,7 @@ ScenarioRecords = csvImporter.ScenariosRecords, }; combineImportedData.AddScenarioDataToDikes(); + importLogMessages.AddRange(combineImportedData.ErrorMessages); Debug.Assert(ReferenceEquals(waterBoard, combineImportedData.WaterBoard)); waterBoard = combineImportedData.WaterBoard; }