// Copyright (C) Stichting Deltares 2016. All rights reserved.
//
// This file is part of Ringtoets.
//
// Ringtoets 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.Collections.Generic;
using System.Globalization;
using System.Linq;
using Core.Common.Base.Data;
using log4net;
using Ringtoets.Common.Service;
using Ringtoets.HydraRing.Calculation.Data;
using Ringtoets.HydraRing.Calculation.Data.Input.WaveConditions;
using Ringtoets.HydraRing.Calculation.Data.Output;
using Ringtoets.HydraRing.Calculation.Parsers;
using Ringtoets.HydraRing.Calculation.Services;
using Ringtoets.HydraRing.Data;
using Ringtoets.HydraRing.IO;
using Ringtoets.Revetment.Data;
using Ringtoets.Revetment.Service.Properties;
using RingtoetsCommonServiceResources = Ringtoets.Common.Service.Properties.Resources;
using RingtoetsCommonFormsResources = Ringtoets.Common.Forms.Properties.Resources;
namespace Ringtoets.Revetment.Service
{
///
/// Service that provides methods for performing Hydra-Ring wave conditions calculations.
///
public class WaveConditionsCalculationService : IWaveConditionsCalculationService
{
private static readonly ILog log = LogManager.GetLogger(typeof(WaveConditionsCalculationService));
private static IWaveConditionsCalculationService instance;
private WaveConditionsCalculationService() {}
///
/// Gets or sets an instance of .
///
public static IWaveConditionsCalculationService Instance
{
get
{
return instance ?? (instance = new WaveConditionsCalculationService());
}
set
{
instance = value;
}
}
public bool Validate(WaveConditionsInput input, HydraulicBoundaryDatabase hydraulicBoundaryDatabase, string name)
{
return CalculationServiceHelper.PerformValidation(name,
() => ValidateAllInputs(hydraulicBoundaryDatabase, input));
}
public WaveConditionsOutput Calculate(RoundedDouble waterLevel,
double a,
double b,
double c,
int norm,
WaveConditionsInput input,
string hlcdDirectory,
string ringId,
string name)
{
WaveConditionsCosineCalculationInput calculationInput = CreateInput(waterLevel, a, b, c, norm, input);
var waveConditionsCalculationParser = new WaveConditionsCalculationParser();
HydraRingCalculationService.Instance.PerformCalculation(
hlcdDirectory,
ringId,
HydraRingUncertaintiesType.All,
calculationInput,
new IHydraRingFileParser[]
{
waveConditionsCalculationParser
});
VerifyWaveConditionsCalculationOutput(waveConditionsCalculationParser.Output, name, waterLevel);
return waveConditionsCalculationParser.Output != null
? new WaveConditionsOutput(waterLevel,
waveConditionsCalculationParser.Output.WaveHeight,
waveConditionsCalculationParser.Output.WavePeakPeriod,
waveConditionsCalculationParser.Output.WaveAngle) :
null;
}
private static void VerifyWaveConditionsCalculationOutput(WaveConditionsCalculationOutput output, string name, RoundedDouble waterLevel)
{
if (output == null)
{
log.ErrorFormat(CultureInfo.CurrentCulture, Resources.WaveConditionsCalculationService_VerifyWaveConditionsCalculationOutput_Error_in_wave_conditions_calculation_0_for_waterlevel_1, name, waterLevel);
}
}
private static WaveConditionsCosineCalculationInput CreateInput(double waterLevel,
double a,
double b,
double c,
double norm,
WaveConditionsInput input)
{
return new WaveConditionsCosineCalculationInput(1,
input.Orientation,
input.HydraulicBoundaryLocation.Id,
norm,
GetForeshore(input),
GetBreakWater(input),
waterLevel,
a,
b,
c);
}
private static HydraRingBreakWater GetBreakWater(WaveConditionsInput input)
{
return input.UseBreakWater ? new HydraRingBreakWater((int) input.BreakWater.Type, input.BreakWater.Height) : null;
}
private static IEnumerable GetForeshore(WaveConditionsInput input)
{
return input.UseForeshore ? input.ForeshoreGeometry.Select(c => new HydraRingForelandPoint(c.X, c.Y)) : new HydraRingForelandPoint[0];
}
private static string[] ValidateAllInputs(HydraulicBoundaryDatabase hydraulicBoundaryDatabase, WaveConditionsInput input)
{
string message = ValidateHydraulicBoundaryDatabase(hydraulicBoundaryDatabase);
if (!string.IsNullOrEmpty(message))
{
return new[]{message};
}
message = ValidateWaveConditionsInput(input);
if (!string.IsNullOrEmpty(message))
{
return new[]{message};
}
return new string[0];
}
private static string ValidateHydraulicBoundaryDatabase(HydraulicBoundaryDatabase hydraulicBoundaryDatabase)
{
if (hydraulicBoundaryDatabase == null)
{
return RingtoetsCommonFormsResources.Plugin_AllDataAvailable_No_hydraulic_boundary_database_imported;
}
string validationProblem = HydraulicDatabaseHelper.ValidatePathForCalculation(hydraulicBoundaryDatabase.FilePath);
if (!string.IsNullOrEmpty(validationProblem))
{
return string.Format(RingtoetsCommonServiceResources.Hydraulic_boundary_database_connection_failed_0_,
validationProblem);
}
return null;
}
private static string ValidateWaveConditionsInput(WaveConditionsInput input)
{
if (input.HydraulicBoundaryLocation == null)
{
return Resources.WaveConditionsCalculationService_ValidateInput_No_HydraulicBoundaryLocation_selected;
}
if (double.IsNaN(input.HydraulicBoundaryLocation.DesignWaterLevel))
{
return Resources.WaveConditionsCalculationService_ValidateInput_No_DesignWaterLevel_calculated;
}
if (!input.WaterLevels.Any())
{
return Resources.WaveConditionsCalculationService_ValidateInput_No_derived_WaterLevels;
}
if (input.UseBreakWater)
{
if (double.IsInfinity(input.BreakWater.Height) || double.IsNaN(input.BreakWater.Height))
{
return RingtoetsCommonServiceResources.ValidationService_ValidateInput_invalid_BreakWaterHeight_value;
}
}
return null;
}
}
}