diff --git a/koswat/configuration/io/koswat_run_settings_importer.py b/koswat/configuration/io/koswat_run_settings_importer.py index 5ac66333..352e6fe6 100644 --- a/koswat/configuration/io/koswat_run_settings_importer.py +++ b/koswat/configuration/io/koswat_run_settings_importer.py @@ -1,7 +1,6 @@ import logging import math from pathlib import Path -from typing import Any from koswat.configuration.io.ini import KoswatGeneralIniFom from koswat.configuration.io.ini.koswat_general_ini_fom import ( diff --git a/koswat/configuration/settings/costs/dike_profile_costs_settings.py b/koswat/configuration/settings/costs/dike_profile_costs_settings.py index 2d46839c..7d3a8894 100644 --- a/koswat/configuration/settings/costs/dike_profile_costs_settings.py +++ b/koswat/configuration/settings/costs/dike_profile_costs_settings.py @@ -1,4 +1,5 @@ import math +from dataclasses import dataclass from koswat.configuration.koswat_config_protocol import KoswatConfigProtocol @@ -7,29 +8,18 @@ def _valid_float_prop(config_property: float) -> bool: return config_property is not None and not math.isnan(config_property) +@dataclass class DikeProfileCostsSettings(KoswatConfigProtocol): - added_layer_grass_m3: float - added_layer_clay_m3: float - added_layer_sand_m3: float - reused_layer_grass_m3: float - reused_layer_core_m3: float - disposed_material_m3: float - profiling_layer_grass_m2: float - profiling_layer_clay_m2: float - profiling_layer_sand_m2: float - bewerken_maaiveld_m2: float - - def __init__(self) -> None: - self.added_layer_grass_m3 = math.nan - self.added_layer_clay_m3 = math.nan - self.added_layer_sand_m3 = math.nan - self.reused_layer_grass_m3 = math.nan - self.reused_layer_core_m3 = math.nan - self.disposed_material_m3 = math.nan - self.profiling_layer_grass_m2 = math.nan - self.profiling_layer_clay_m2 = math.nan - self.profiling_layer_sand_m2 = math.nan - self.bewerken_maaiveld_m2 = math.nan + added_layer_grass_m3: float = math.nan + added_layer_clay_m3: float = math.nan + added_layer_sand_m3: float = math.nan + reused_layer_grass_m3: float = math.nan + reused_layer_core_m3: float = math.nan + disposed_material_m3: float = math.nan + profiling_layer_grass_m2: float = math.nan + profiling_layer_clay_m2: float = math.nan + profiling_layer_sand_m2: float = math.nan + bewerken_maaiveld_m2: float = math.nan def is_valid(self) -> bool: return all(_valid_float_prop(_prop) for _prop in self.__dict__.values()) diff --git a/koswat/configuration/settings/costs/koswat_costs_settings.py b/koswat/configuration/settings/costs/koswat_costs_settings.py index 48fd9448..cf03bf2f 100644 --- a/koswat/configuration/settings/costs/koswat_costs_settings.py +++ b/koswat/configuration/settings/costs/koswat_costs_settings.py @@ -1,4 +1,5 @@ import math +from dataclasses import dataclass from koswat.configuration.koswat_config_protocol import KoswatConfigProtocol from koswat.configuration.settings.costs.construction_costs_settings import ( @@ -15,19 +16,13 @@ ) +@dataclass class KoswatCostsSettings(KoswatConfigProtocol): - price_year: int - dike_profile_costs: DikeProfileCostsSettings - infrastructure_costs: InfrastructureCostsSettings - surtax_costs: SurtaxCostsSettings - construction_costs: ConstructionCostsSettings - - def __init__(self) -> None: - self.price_year = math.nan - self.dike_profile_costs = None - self.infrastructure_costs = None - self.surtax_costs = None - self.construction_costs = None + price_year: int = math.nan + dike_profile_costs: DikeProfileCostsSettings = None + infrastructure_costs: InfrastructureCostsSettings = None + surtax_costs: SurtaxCostsSettings = None + construction_costs: ConstructionCostsSettings = None def is_valid(self) -> bool: return ( diff --git a/koswat/configuration/settings/koswat_run_scenario_settings.py b/koswat/configuration/settings/koswat_run_scenario_settings.py index 449637f7..e4659d1a 100644 --- a/koswat/configuration/settings/koswat_run_scenario_settings.py +++ b/koswat/configuration/settings/koswat_run_scenario_settings.py @@ -1,3 +1,4 @@ +from dataclasses import dataclass from pathlib import Path from koswat.configuration.koswat_config_protocol import KoswatConfigProtocol @@ -12,13 +13,14 @@ from koswat.dike.surroundings.wrapper.surroundings_wrapper import SurroundingsWrapper +@dataclass class KoswatRunScenarioSettings(KoswatConfigProtocol): - scenario: KoswatScenario - reinforcement_settings: KoswatReinforcementSettings - surroundings: SurroundingsWrapper - costs_setting: KoswatCostsSettings - output_dir: Path - input_profile_case: KoswatProfileBase + scenario: KoswatScenario = None + reinforcement_settings: KoswatReinforcementSettings = None + surroundings: SurroundingsWrapper = None + costs_setting: KoswatCostsSettings = None + output_dir: Path = None + input_profile_case: KoswatProfileBase = None @property def name(self) -> str: diff --git a/koswat/core/io/ini/koswat_ini_reader.py b/koswat/core/io/ini/koswat_ini_reader.py index f971c023..c59fdf3e 100644 --- a/koswat/core/io/ini/koswat_ini_reader.py +++ b/koswat/core/io/ini/koswat_ini_reader.py @@ -1,4 +1,5 @@ import configparser +from dataclasses import dataclass from pathlib import Path from typing import Type @@ -6,12 +7,10 @@ from koswat.core.io.koswat_reader_protocol import KoswatReaderProtocol +@dataclass class KoswatIniReader(KoswatReaderProtocol): - koswat_ini_fom_type: Type[KoswatIniFomProtocol] - - def __init__(self) -> None: - self.koswat_ini_fom_type = None + koswat_ini_fom_type: Type[KoswatIniFomProtocol] = None def supports_file(self, file_path: Path) -> bool: return isinstance(file_path, Path) and file_path.suffix == ".ini" diff --git a/koswat/cost_report/infrastructure/infrastructure_location_costs.py b/koswat/cost_report/infrastructure/infrastructure_location_costs.py index 7829a1dc..41ab83ce 100644 --- a/koswat/cost_report/infrastructure/infrastructure_location_costs.py +++ b/koswat/cost_report/infrastructure/infrastructure_location_costs.py @@ -18,13 +18,18 @@ class InfrastructureLocationCosts: infrastructure: SurroundingsInfrastructure = None location: PointSurroundings = None - zone_a: float = math.nan - zone_a_costs: float = math.nan + zone_a: float = 0 + zone_a_costs: float = 0 - zone_b: float = math.nan - zone_b_costs: float = math.nan - surtax: float = math.nan + zone_b: float = 0 + zone_b_costs: float = 0 + surtax: float = 0 @property def total_cost(self) -> float: - return self.zone_a_costs + self.zone_b_costs + def valid_cost(cost: float) -> float: + if math.isnan(cost): + return 0 + return cost + + return valid_cost(self.zone_a_costs) + valid_cost(self.zone_b_costs) diff --git a/koswat/cost_report/infrastructure/infrastructure_location_profile_cost_report.py b/koswat/cost_report/infrastructure/infrastructure_location_profile_cost_report.py index 7eea84a0..c5398211 100644 --- a/koswat/cost_report/infrastructure/infrastructure_location_profile_cost_report.py +++ b/koswat/cost_report/infrastructure/infrastructure_location_profile_cost_report.py @@ -1,4 +1,3 @@ -import math from dataclasses import dataclass from koswat.cost_report.cost_report_protocol import CostReportProtocol @@ -32,7 +31,7 @@ def location(self) -> PointSurroundings | None: @property def total_cost(self) -> float: if not self.infrastructure_location_costs: - return math.nan + return 0 return ( self.infrastructure_location_costs.zone_a_costs + self.infrastructure_location_costs.zone_b_costs @@ -41,5 +40,5 @@ def total_cost(self) -> float: @property def total_cost_with_surtax(self) -> float: if not self.infrastructure_location_costs: - return math.nan + return 0 return self.total_cost * self.infrastructure_location_costs.surtax diff --git a/koswat/cost_report/infrastructure/infrastructure_profile_costs_calculator.py b/koswat/cost_report/infrastructure/infrastructure_profile_costs_calculator.py index b5f5bf90..23396801 100644 --- a/koswat/cost_report/infrastructure/infrastructure_profile_costs_calculator.py +++ b/koswat/cost_report/infrastructure/infrastructure_profile_costs_calculator.py @@ -24,8 +24,8 @@ class InfrastructureProfileCostsCalculator: infrastructure: SurroundingsInfrastructure = None surtax: float = math.nan - zone_a_costs: float = math.nan - zone_b_costs: float = math.nan + zone_a_costs: float = 0 + zone_b_costs: float = 0 def calculate( self, zone_a_width: float, zone_b_width: float @@ -49,6 +49,7 @@ def calculate( location=_location, ) for _location in self.infrastructure.points + if any(_location.surroundings_matrix.items()) ] def _calculate_at_location( diff --git a/koswat/cost_report/infrastructure/profile_zone_calculator.py b/koswat/cost_report/infrastructure/profile_zone_calculator.py index 2c14c24c..1e0cc0ad 100644 --- a/koswat/cost_report/infrastructure/profile_zone_calculator.py +++ b/koswat/cost_report/infrastructure/profile_zone_calculator.py @@ -38,7 +38,7 @@ def _calculate_zone_b(self) -> tuple[float, float]: self.reinforced_profile.old_profile ) _zone_b = self.reinforced_profile.points[-1].x - _left_limit - return (math.nan, _zone_b) + return (0, _zone_b) def calculate(self) -> tuple[float, float]: """ diff --git a/koswat/cost_report/summary/koswat_summary_builder.py b/koswat/cost_report/summary/koswat_summary_builder.py index 4da90e4a..ba46fe35 100644 --- a/koswat/cost_report/summary/koswat_summary_builder.py +++ b/koswat/cost_report/summary/koswat_summary_builder.py @@ -1,5 +1,6 @@ import logging import math +from dataclasses import dataclass from koswat.configuration.settings.koswat_run_scenario_settings import ( KoswatRunScenarioSettings, @@ -29,11 +30,9 @@ from koswat.strategies.strategy_input import StrategyInput +@dataclass class KoswatSummaryBuilder(BuilderProtocol): - run_scenario_settings: KoswatRunScenarioSettings - - def __init__(self) -> None: - self.run_scenario_settings = None + run_scenario_settings: KoswatRunScenarioSettings = None @staticmethod def _get_corrected_koswat_scenario( diff --git a/koswat/dike/surroundings/wrapper/obstacle_surroundings_wrapper.py b/koswat/dike/surroundings/wrapper/obstacle_surroundings_wrapper.py index bd3bfb69..8fbb57f5 100644 --- a/koswat/dike/surroundings/wrapper/obstacle_surroundings_wrapper.py +++ b/koswat/dike/surroundings/wrapper/obstacle_surroundings_wrapper.py @@ -16,7 +16,6 @@ class ObstacleSurroundingsWrapper(BaseSurroundingsWrapper): apply_buildings: bool = False apply_railways: bool = False apply_waters: bool = False - apply_infrastructure: bool = True reinforcement_min_separation: float = math.nan reinforcement_min_buffer: float = math.nan diff --git a/tests/__init__.py b/tests/__init__.py index 7aecae3d..52646482 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -3,8 +3,9 @@ from pytest import FixtureRequest -test_data = Path(__file__).parent / "test_data" -test_results = Path(__file__).parent / "test_results" +test_data = Path(__file__).parent.joinpath("test_data") +test_data_acceptance = test_data.joinpath("acceptance") +test_results = Path(__file__).parent.joinpath("test_results") if not test_results.is_dir(): test_results.mkdir(parents=True) diff --git a/tests/cost_report/infrastructure/test_infrastructure_location_costs.py b/tests/cost_report/infrastructure/test_infrastructure_location_costs.py new file mode 100644 index 00000000..155d40c1 --- /dev/null +++ b/tests/cost_report/infrastructure/test_infrastructure_location_costs.py @@ -0,0 +1,23 @@ +from koswat.cost_report.infrastructure.infrastructure_location_costs import ( + InfrastructureLocationCosts, +) + + +class TestInfrastructureLocationCosts: + def test_initialization(self): + # 1. Initialize class + _infra_location_costs = InfrastructureLocationCosts() + + # 2. Verify expectations. + assert isinstance(_infra_location_costs, InfrastructureLocationCosts) + assert not _infra_location_costs.infrastructure + assert not _infra_location_costs.location + + # Verify default values are not `math.nan``. + # (Otherwise the `.csv` files could become invalid) + assert _infra_location_costs.zone_a == 0 + assert _infra_location_costs.zone_b == 0 + assert _infra_location_costs.zone_a_costs == 0 + assert _infra_location_costs.zone_b_costs == 0 + assert _infra_location_costs.surtax == 0 + assert _infra_location_costs.total_cost == 0 diff --git a/tests/cost_report/infrastructure/test_infrastructure_location_profile_cost_report.py b/tests/cost_report/infrastructure/test_infrastructure_location_profile_cost_report.py new file mode 100644 index 00000000..2da80213 --- /dev/null +++ b/tests/cost_report/infrastructure/test_infrastructure_location_profile_cost_report.py @@ -0,0 +1,23 @@ +from koswat.cost_report.cost_report_protocol import CostReportProtocol +from koswat.cost_report.infrastructure.infrastructure_location_profile_cost_report import ( + InfrastructureLocationProfileCostReport, +) + + +class TestInfrastructureLocationProfileCostReport: + def test_initialize(self): + # 1. Define test data. + _report = InfrastructureLocationProfileCostReport( + reinforced_profile=None, + infrastructure=None, + infrastructure_location_costs=None, + ) + + # 2. Verify expectations. + assert isinstance(_report, InfrastructureLocationProfileCostReport) + assert isinstance(_report, CostReportProtocol) + + # Verify fallback values. + assert not _report.location + assert _report.total_cost == 0 + assert _report.total_cost_with_surtax == 0 diff --git a/tests/cost_report/infrastructure/test_infrastructure_profile_costs_calculator.py b/tests/cost_report/infrastructure/test_infrastructure_profile_costs_calculator.py index e92a703a..9ff31e4d 100644 --- a/tests/cost_report/infrastructure/test_infrastructure_profile_costs_calculator.py +++ b/tests/cost_report/infrastructure/test_infrastructure_profile_costs_calculator.py @@ -23,8 +23,8 @@ def test_initialize(self): assert isinstance(_calculator, InfrastructureProfileCostsCalculator) assert not _calculator.infrastructure assert math.isnan(_calculator.surtax) - assert math.isnan(_calculator.zone_a_costs) - assert math.isnan(_calculator.zone_b_costs) + assert _calculator.zone_a_costs == 0 + assert _calculator.zone_b_costs == 0 def test_given_infrastructure_fixture_calculates_costs( self, diff --git a/tests/cost_report/infrastructure/test_profile_zone_calculator.py b/tests/cost_report/infrastructure/test_profile_zone_calculator.py index a47b3b3e..09597ed0 100644 --- a/tests/cost_report/infrastructure/test_profile_zone_calculator.py +++ b/tests/cost_report/infrastructure/test_profile_zone_calculator.py @@ -87,31 +87,31 @@ def test_given_no_base_profile_calculate_returns_nan_tuple( pytest.param( _waterside_reinforced_points + [(3, 7), (13, 7), (40.87, -0.6), (68.87, -0.6), (74, -2)], - (math.nan, 74), + (0, 74), id="With dh0 increase to 1 - Soil reinforcement", ), pytest.param( _waterside_reinforced_points + [(3, 7), (13, 7), (44.17, -1.5), (54.17, -1.5), (56, -2)], - (math.nan, 56), + (0, 56), id="With dh0 increase to 1 - Vertical Piping Solution", ), pytest.param( _waterside_reinforced_points + [(3, 7), (13, 7), (46, -2), (46, -2), (46, -2)], - (math.nan, 46), + (0, 46), id="With dh0 increase to 1 - Piping Wall reinforcement", ), pytest.param( _waterside_reinforced_points + [(3, 7), (13, 7), (34, -2), (34, -2), (34, -2)], - (math.nan, 34), + (0, 34), id="With dh0 increase to 1 - Stability Wall reinforcement", ), pytest.param( _waterside_reinforced_points + [(0, 7), (10, 7), (34, -2), (34, -2), (34, -2)], - (math.nan, 34), + (0, 34), id="With dh0 increase to 1- Cofferdam reinforcement", ), ], diff --git a/tests/test_acceptance.py b/tests/test_acceptance.py index d600a761..ed1945ac 100644 --- a/tests/test_acceptance.py +++ b/tests/test_acceptance.py @@ -2,6 +2,7 @@ import shutil from pathlib import Path +from typing import Callable, Iterable, Iterator import cv2 import numpy as np @@ -9,8 +10,10 @@ from koswat.configuration.io.ini.koswat_general_ini_fom import ( InfrastructureSectionFom, + KoswatGeneralIniFom, SurroundingsSectionFom, ) +from koswat.configuration.io.koswat_costs_importer import KoswatCostsImporter from koswat.configuration.io.surroundings_wrapper_collection_importer import ( SurroundingsWrapperCollectionImporter, ) @@ -38,7 +41,11 @@ from koswat.configuration.settings.reinforcements.koswat_reinforcement_settings import ( KoswatReinforcementSettings, ) +from koswat.core.io.ini.koswat_ini_reader import KoswatIniReader from koswat.cost_report.cost_report_protocol import CostReportProtocol +from koswat.cost_report.infrastructure.infrastructure_location_profile_cost_report import ( + InfrastructureLocationProfileCostReport, +) from koswat.cost_report.io.plots.multi_location_profile_comparison_plot_exporter import ( MultiLocationProfileComparisonPlotExporter, ) @@ -55,6 +62,7 @@ get_fixturerequest_case_name, get_testcase_results_dir, test_data, + test_data_acceptance, test_results, ) from tests.acceptance_scenarios.acceptance_test_scenario_cases import ( @@ -81,6 +89,172 @@ def test_koswat_package_can_be_imported(self): except ImportError as exc_err: pytest.fail(f"It was not possible to import required packages {exc_err}") + @pytest.fixture(name="koswat_acceptance_settings") + def _get_koswat_acceptance_settings_fixtures( + self, + ) -> Iterator[Callable[[], tuple[KoswatGeneralIniFom, KoswatCostsSettings]]]: + # Config parser to map the settings to a real case + _koswat_general_settings: KoswatGeneralIniFom = KoswatIniReader( + koswat_ini_fom_type=KoswatGeneralIniFom + ).read(test_data_acceptance.joinpath("koswat_general.ini")) + + # It is easier returning the costs directly than the FOM, + # as there's no direct converter from `KoswatCostsIniFom` to `KoswatCosts` + _costs_importer = KoswatCostsImporter() + _costs_importer.include_taxes = True + _koswat_costs = _costs_importer.import_from( + test_data_acceptance.joinpath("koswat_costs.ini") + ) + + yield lambda: (_koswat_general_settings, _koswat_costs) + + @pytest.fixture( + name="t_10_3_surroundings_wrapper_fixture", + params=[(False, False), (False, True), (True, False), (True, True)], + ids=[ + "Without ANY surrounding", + "With Infrastructure", + "With Obstacles", + "With Infrastructure and Obstacles", + ], + ) + def _get_surroundings_wrapper_fixture( + self, + koswat_acceptance_settings: Callable[ + [], tuple[KoswatGeneralIniFom, KoswatCostsSettings] + ], + request: pytest.FixtureRequest, + ) -> Iterable[tuple[SurroundingsWrapper, KoswatCostsSettings, Path]]: + _traject = "10_3" + # Shp locations file + _shp_file = test_data.joinpath( + "shp_reader", + "Dijkvak", + "Dijkringlijnen_KOSWAT_Totaal_2017_10_3_Dijkvak.shp", + ) + assert _shp_file.is_file() + + # Surroundings directory + _surroundings_analysis_path = test_data_acceptance.joinpath( + "surroundings_analysis", _traject + ) + assert _surroundings_analysis_path.is_dir() + + # Create a dummy dir to avoid importing unnecessary data. + _dir_name = get_testcase_results_dir(request) + _temp_dir = test_results.joinpath(_dir_name, _traject) + if _temp_dir.exists(): + shutil.rmtree(_temp_dir) + shutil.copytree(_surroundings_analysis_path, _temp_dir) + + # Set surroundings (obstacles / infras) + _include_obstacles, _include_infras = request.param + + # Generate surroundings section File Object Model. + _koswat_general_settings, _koswat_costs = koswat_acceptance_settings() + _surroundings_settings = _koswat_general_settings.surroundings_section + _surroundings_settings.surroundings_database_dir = _temp_dir.parent + _surroundings_settings.bebouwing = _include_obstacles + + # Generate Infrastructures section file model + _infrastructure_settings = _koswat_general_settings.infrastructuur_section + _infrastructure_settings.infrastructuur = _include_infras + + # Generate wrapper + _importer = SurroundingsWrapperCollectionImporter( + infrastructure_section_fom=_infrastructure_settings, + surroundings_section_fom=_surroundings_settings, + selected_locations=[], + traject_loc_shp_file=_shp_file, + ) + _surroundings_wrapper_list = _importer.build() + assert any(_surroundings_wrapper_list) + + # Yield result + yield _surroundings_wrapper_list[0], _koswat_costs, _temp_dir + + if not _include_infras: + # Do not keep analysis results when no infrastructures are included. + shutil.rmtree(_temp_dir) + + @pytest.mark.parametrize("input_profile_case", InputProfileCases.cases) + @pytest.mark.parametrize("scenario_case", ScenarioCases.cases) + @pytest.mark.parametrize( + "layers_case", + LayersCases.cases, + ) + @pytest.mark.slow + def test_koswat_run_as_sandbox_with_obstacles_and_infrastructures( + self, + input_profile_case, + scenario_case: KoswatProfileBase, + layers_case, + t_10_3_surroundings_wrapper_fixture: tuple[ + SurroundingsWrapper, KoswatCostsSettings, Path + ], + ): + # 1. Define test data. + ( + _surroundings_wrapper, + _cost_settings, + _test_dir, + ) = t_10_3_surroundings_wrapper_fixture + + assert _test_dir.exists() + assert isinstance(_surroundings_wrapper, SurroundingsWrapper) + + # Define scenario settings. + _run_settings = KoswatRunScenarioSettings( + scenario=scenario_case, + surroundings=_surroundings_wrapper, + costs_setting=_cost_settings, + reinforcement_settings=KoswatReinforcementSettings(), + input_profile_case=KoswatProfileBuilder.with_data( + dict( + input_profile_data=input_profile_case, + layers_data=layers_case, + profile_type=KoswatProfileBase, + ) + ).build(), + ) + + # 2. Run test. + _summary = KoswatSummaryBuilder(run_scenario_settings=_run_settings).build() + assert isinstance(_summary, KoswatSummary) + + # 3. Verify expectations. + # TODO: These checks take extremely long time when infrastructures are present + assert any(_summary.locations_profile_report_list) + + KoswatSummaryExporter().export(_summary, _test_dir) + assert _test_dir.joinpath("summary_costs.csv").exists() + + # Validate obstacles. + if _surroundings_wrapper.obstacle_surroundings_wrapper.apply_buildings: + assert _test_dir.joinpath("summary_locations.csv").exists() + + # Validate infrastructures. + if ( + not _surroundings_wrapper.infrastructure_surroundings_wrapper.infrastructures_considered + ): + return + assert _test_dir.joinpath("summary_infrastructure_costs.csv").exists() + + def check_valid_infra_reports( + mlpc_report: MultiLocationProfileCostReport, + ) -> bool: + assert isinstance(mlpc_report, MultiLocationProfileCostReport) + assert any(mlpc_report.infra_multilocation_profile_cost_report) + assert all( + isinstance(_infra_report, InfrastructureLocationProfileCostReport) + for _infra_report in mlpc_report.infra_multilocation_profile_cost_report + ) + return True + + assert all( + map(check_valid_infra_reports, _summary.locations_profile_report_list) + ) + @pytest.mark.parametrize("input_profile_case", InputProfileCases.cases) @pytest.mark.parametrize("scenario_case", ScenarioCases.cases) @pytest.mark.parametrize( @@ -152,38 +326,42 @@ def test_koswat_run_as_sandbox_with_surroundings( ) ).build() - _run_settings = KoswatRunScenarioSettings() - _run_settings.scenario = scenario_case - _run_settings.reinforcement_settings = _reinforcement_settings - _run_settings.surroundings = _surroundings - _run_settings.input_profile_case = _base_koswat_profile - _costs_settings = KoswatCostsSettings() - _run_settings.costs_setting = _costs_settings - # Set default dike profile costs_setting. - _costs_settings.dike_profile_costs = DikeProfileCostsSettings() - _costs_settings.dike_profile_costs.added_layer_grass_m3 = 12.44 - _costs_settings.dike_profile_costs.added_layer_clay_m3 = 18.05 - _costs_settings.dike_profile_costs.added_layer_sand_m3 = 10.98 - _costs_settings.dike_profile_costs.reused_layer_grass_m3 = 6.04 - _costs_settings.dike_profile_costs.reused_layer_core_m3 = 4.67 - _costs_settings.dike_profile_costs.disposed_material_m3 = 7.07 - _costs_settings.dike_profile_costs.profiling_layer_grass_m2 = 0.88 - _costs_settings.dike_profile_costs.profiling_layer_clay_m2 = 0.65 - _costs_settings.dike_profile_costs.profiling_layer_sand_m2 = 0.60 - _costs_settings.dike_profile_costs.bewerken_maaiveld_m2 = 0.25 - _costs_settings.construction_costs = ConstructionCostsSettings() - _costs_settings.construction_costs.cb_damwand = ConstructionFactors() - _costs_settings.construction_costs.cb_damwand.c_factor = 0 - _costs_settings.construction_costs.cb_damwand.d_factor = 0 - _costs_settings.construction_costs.cb_damwand.z_factor = 999 - _costs_settings.construction_costs.cb_damwand.f_factor = 0 - _costs_settings.construction_costs.cb_damwand.g_factor = 0 - _costs_settings.surtax_costs = SurtaxCostsSettings() + # IMPORTANT!!! + # These are not (entirely) the values from the acceptance `.ini` files! + _run_settings = KoswatRunScenarioSettings( + scenario=scenario_case, + reinforcement_settings=_reinforcement_settings, + surroundings=_surroundings, + input_profile_case=_base_koswat_profile, + costs_setting=KoswatCostsSettings( + # Set default dike profile costs_setting. + dike_profile_costs=DikeProfileCostsSettings( + added_layer_grass_m3=12.44, + added_layer_clay_m3=18.05, + added_layer_sand_m3=10.98, + reused_layer_grass_m3=6.04, + reused_layer_core_m3=4.67, + disposed_material_m3=7.07, + profiling_layer_grass_m2=0.88, + profiling_layer_clay_m2=0.65, + profiling_layer_sand_m2=0.60, + bewerken_maaiveld_m2=0.25, + ), + construction_costs=ConstructionCostsSettings( + cb_damwand=ConstructionFactors( + c_factor=0, + d_factor=0, + z_factor=999, + f_factor=0, + g_factor=0, + ), + ), + surtax_costs=SurtaxCostsSettings(), + ), + ) # 2. Run test - _multi_loc_multi_prof_cost_builder = KoswatSummaryBuilder() - _multi_loc_multi_prof_cost_builder.run_scenario_settings = _run_settings - _summary = _multi_loc_multi_prof_cost_builder.build() + _summary = KoswatSummaryBuilder(run_scenario_settings=_run_settings).build() assert isinstance(_summary, KoswatSummary) KoswatSummaryExporter().export(_summary, _test_dir)