diff artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java @ 9620:26e113e8224f

Nachtrag Pos. 20: flood duration calculation for multiple infrastructure groups/types, local class FloodDurationCalculationResult.Infrastructure renamed and extracted into own class
author mschaefer
date Thu, 10 Oct 2019 17:11:54 +0200
parents d889ffe2fb05
children 07f02019065e
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java	Thu Oct 10 16:08:47 2019 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java	Thu Oct 10 17:11:54 2019 +0200
@@ -33,8 +33,6 @@
 import org.dive4elements.river.artifacts.model.river.RiverInfoProvider;
 import org.dive4elements.river.artifacts.sinfo.common.GaugeDurationValuesFinder;
 import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
-import org.dive4elements.river.artifacts.sinfo.flood_duration.FloodDurationCalculationResult.Infrastructure;
-import org.dive4elements.river.artifacts.sinfo.flood_duration.RiversideRadioChoice.RiversideChoiceKey;
 import org.dive4elements.river.exports.WaterlevelDescriptionBuilder;
 import org.dive4elements.river.model.Attribute.AttributeKey;
 import org.dive4elements.river.model.Gauge;
@@ -54,6 +52,7 @@
 
     private final RiverInfoProvider riverInfoProvider;
     private RiverInfoProvider riverInfoProvider2;
+    private final Map<Double, List<InfrastructureValue>> stationInfras;
 
     private final CallContext context;
 
@@ -61,18 +60,14 @@
         this.context = context;
         this.riverInfoProvider = riverInfoProvider;
         this.riverInfoProvider2 = null;
+        this.stationInfras = new HashMap<>();
     }
 
     /**
      * Calculate the infrastructures flood duration result rows
      */
-    public void execute(final Calculation problems, final String label, final DoubleRange calcRange, final RiversideChoiceKey riverside,
-            final Set<Infrastructure> infrastruktureKey, final boolean withWspl, final WINFOArtifact winfo, final FloodDurationCalculationResults results) {
-
-        // FIXME Schäfer:
-        // filter by infrastructureKey
-        // FIXME: Tironi: api gscheit benennen;
-        // Lösung finden für: Infrastructure enthält riverside, wird hier aber nicht benötigt (weil schon im choice)
+    public void execute(final Calculation problems, final String label, final DoubleRange calcRange, final AttributeKey riverside,
+            final Set<String> infrastructureChoices, final boolean withWspl, final WINFOArtifact winfo, final FloodDurationCalculationResults results) {
 
         // Find all gauges of the calc range, and create the duration finders
         final Map<Gauge, GaugeDurationValuesFinder> durFinders = new HashMap<>();
@@ -81,17 +76,18 @@
         }
 
         // Find all infrastructures within the calc range
-        final AttributeKey bankKey = riverside.getAttributeKey();
         final List<InfrastructureValue> infras = InfrastructureValue.getValues(this.riverInfoProvider.getRiver(), calcRange.getMinimumDouble(),
-                calcRange.getMaximumDouble(), bankKey);
+                calcRange.getMaximumDouble(), riverside, infrastructureChoices);
 
         // Merge all stations (range/step, borders of gauge ranges, infrastructures)
-        final Map<Double, InfrastructureValue> allStations = new HashMap<>();
-        final Map<Double, InfrastructureValue> secondBank = new HashMap<>(); // any second infrastructure in case of both-banks-option
-        addRangeStations(allStations, winfo);
-        addGaugeLimits(allStations, durFinders.keySet(), calcRange.getMinimumDouble(), calcRange.getMaximumDouble());
-        addInfrastructures(allStations, secondBank, infras);
-        final double[] stationsSorted = sortStations(allStations.keySet());
+        // final Map<Double, InfrastructureValue> allStations = new HashMap<>();
+        this.stationInfras.clear();
+        // final Map<Double, InfrastructureValue> secondBank = new HashMap<>(); // any second infrastructure in case of
+        // both-banks-option
+        addRangeStations(winfo);
+        addGaugeLimits(durFinders.keySet(), calcRange.getMinimumDouble(), calcRange.getMaximumDouble());
+        addInfrastructures(infras);
+        final double[] stationsSorted = sortStations(this.stationInfras.keySet());
 
         // Calculate W and Q for all stations and the selected discharge states/waterlevels
         final WQKms[] wqkmsArray = calculateWsts(winfo, withWspl, stationsSorted, problems);
@@ -111,22 +107,18 @@
         // (should be in cache since already used in calculateWaterlevels (winfo.computeWaterlevelData)
         final WstValueTable wst = WstValueTableFactory.getTable(this.riverInfoProvider2.getRiver());
 
-        final Set<FloodDurationCalculationResult.Infrastructure> infrastructures = new HashSet<>();
+        final Set<FloodDurationInfrastructureChoice> infrastructures = new HashSet<>();
 
         // Create the result rows, and calculate and add the flood durations etc.
         for (int i = 0; i <= stationsSorted.length - 1; i++) {
             final Gauge gauge = this.riverInfoProvider2.getGauge(stationsSorted[i], true);
-            final ResultRow row = createRow(stationsSorted[i], wqkmsArray, gaugeWstDurations.get(gauge), i);
-            if (allStations.containsKey(stationsSorted[i]) && (allStations.get(stationsSorted[i]) != null))
-                calculateInfrastructure(row, gauge, allStations.get(stationsSorted[i]), wst, durFinders, infrastructures);
-
-            this.rows.add(row);
-            if (secondBank.containsKey(stationsSorted[i])) {
-                final ResultRow row2 = ResultRow.create(row);
-                calculateInfrastructure(row2, gauge, secondBank.get(stationsSorted[i]), wst, durFinders, infrastructures);
-                this.rows.add(row2);
+            if (this.stationInfras.containsKey(stationsSorted[i])) {
+                for (final InfrastructureValue infra : this.stationInfras.get(stationsSorted[i])) {
+                    final ResultRow row = createRow(stationsSorted[i], wqkmsArray, gaugeWstDurations.get(gauge), i);
+                    calculateInfrastructure(row, gauge, infra, wst, durFinders, infrastructures);
+                    this.rows.add(row);
+                }
             }
-
         }
 
         // Get the labels of the selected waterlevels
@@ -158,36 +150,33 @@
     /**
      * Adds to a stations map all stations corresponding to the active range and step
      */
-    private void addRangeStations(final Map<Double, InfrastructureValue> allStations, final WINFOArtifact winfo) {
+    private void addRangeStations(final WINFOArtifact winfo) {
         for (final double station : new ComputationRangeAccess(winfo).getKms())
-            allStations.put(Double.valueOf(station), null);
+            this.stationInfras.put(Double.valueOf(station), new ArrayList<InfrastructureValue>());
     }
 
     /**
      * Adds to a stations map all range limits of the gauges within the calc range
      */
-    private void addGaugeLimits(final Map<Double, InfrastructureValue> allStations, final Set<Gauge> gauges, final double fromKm, final double toKm) {
+    private void addGaugeLimits(final Set<Gauge> gauges, final double fromKm, final double toKm) {
         for (final Gauge gauge : gauges) {
             final Double kmA = Double.valueOf(gauge.getRange().getA().doubleValue());
             final Double kmB = Double.valueOf(gauge.getRange().getB().doubleValue());
             if (kmA > fromKm - 0.0001)
-                allStations.put(kmA, null);
+                this.stationInfras.put(kmA, new ArrayList<InfrastructureValue>());
             if (kmB < toKm + 0.0001)
-                allStations.put(kmB, null);
+                this.stationInfras.put(kmB, new ArrayList<InfrastructureValue>());
         }
     }
 
     /**
-     * Adds to a stations map all (first) infrastructures of a station, and the second, if any, to another map
+     * Adds all infrastructures of a station to the station map
      */
-    private void addInfrastructures(final Map<Double, InfrastructureValue> allStations, final Map<Double, InfrastructureValue> secondBank,
-            final List<InfrastructureValue> infrastructures) {
+    private void addInfrastructures(final List<InfrastructureValue> infrastructures) {
         for (final InfrastructureValue infrastructure : infrastructures) {
             final Double station = infrastructure.getStation();
-            if (!allStations.containsKey(station) || !(allStations.get(station) instanceof InfrastructureValue))
-                allStations.put(station, infrastructure);
-            else
-                secondBank.put(station, infrastructure);
+            if (this.stationInfras.containsKey(station))
+                this.stationInfras.get(station).add(infrastructure);
         }
     }
 
@@ -312,7 +301,7 @@
      * Calculate the result row fields for one infrastructure
      */
     private void calculateInfrastructure(final ResultRow row, final Gauge gauge, final InfrastructureValue infrastructure, final WstValueTable wst,
-            final Map<Gauge, GaugeDurationValuesFinder> durFinders, final Set<Infrastructure> infrastructures) {
+            final Map<Gauge, GaugeDurationValuesFinder> durFinders, final Set<FloodDurationInfrastructureChoice> infrastructures) {
 
         // Interpolate the infrastructure height in the wst table to get the corresponding Q
         final Calculation problems = new Calculation();
@@ -328,16 +317,15 @@
 
         // Determine the relative column position of the Q of the infrastructure height
         final QPosition qPos = wst.getQPosition(infrastructure.getStation().doubleValue(), q);
-        if (qPos == null)
-            return;
-        // Get the Q for the found column position for the station of the gauge
-        final double qGauge = wst.getQ(qPos, gauge.getStation().doubleValue());
-        // Interpolate the Q-D-table of the gauge
-        final double dur = underflowDaysToOverflowDays(durFinders.get(gauge).getDuration(qGauge));
-        // Set D in the result row
-        row.putValue(SInfoResultType.floodDuration, dur);
-
-        final FloodDurationCalculationResult.Infrastructure groupType = new FloodDurationCalculationResult.Infrastructure(row);
+        if (qPos != null) {
+            // Get the Q for the found column position for the station of the gauge
+            final double qGauge = wst.getQ(qPos, gauge.getStation().doubleValue());
+            // Interpolate the Q-D-table of the gauge
+            final double dur = underflowDaysToOverflowDays(durFinders.get(gauge).getDuration(qGauge));
+            // Set D in the result row
+            row.putValue(SInfoResultType.floodDuration, dur);
+        }
+        final FloodDurationInfrastructureChoice groupType = new FloodDurationInfrastructureChoice(row);
         infrastructures.add(groupType);
     }
 

http://dive4elements.wald.intevation.org