diff artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculation.java @ 8946:5d5d482da3e9

Implementing SINFO - FlowDepthMinMax calculation
author gernotbelger
date Tue, 13 Mar 2018 18:49:33 +0100
parents d9dbf0b74bc2
children 322b0e6298ea
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculation.java	Tue Mar 13 09:55:53 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculation.java	Tue Mar 13 18:49:33 2018 +0100
@@ -13,16 +13,15 @@
 
 import org.apache.commons.lang.math.DoubleRange;
 import org.dive4elements.artifacts.CallContext;
-import org.dive4elements.river.artifacts.BedHeightsArtifact;
 import org.dive4elements.river.artifacts.model.Calculation;
 import org.dive4elements.river.artifacts.model.CalculationResult;
 import org.dive4elements.river.artifacts.model.WKms;
 import org.dive4elements.river.artifacts.resources.Resources;
 import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
 import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
-import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthAccess.DifferencesPair;
 import org.dive4elements.river.artifacts.sinfo.tkhcalculation.DischargeValuesFinder;
 import org.dive4elements.river.artifacts.sinfo.tkhcalculation.TkhCalculator;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.WaterlevelValuesFinder;
 import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder;
 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
@@ -30,7 +29,6 @@
 import org.dive4elements.river.artifacts.states.WaterlevelData;
 import org.dive4elements.river.artifacts.states.WaterlevelFetcher;
 import org.dive4elements.river.model.River;
-import org.dive4elements.river.utils.RiverUtils;
 
 class FlowDepthCalculation {
 
@@ -51,7 +49,7 @@
         final River river = access.getRiver();
         final RiverInfo riverInfo = new RiverInfo(river);
 
-        final Collection<DifferencesPair> diffPairs = access.getDifferencePairs();
+        final Collection<WstSoundingIdPair> diffPairs = access.getDifferencePairs();
 
         final DoubleRange calcRange = access.getRange();
 
@@ -66,7 +64,7 @@
 
         final FlowDepthCalculationResults results = new FlowDepthCalculationResults(calcModeLabel, user, riverInfo, calcRange, useTkh);
 
-        for (final DifferencesPair diffPair : diffPairs) {
+        for (final WstSoundingIdPair diffPair : diffPairs) {
             final FlowDepthCalculationResult result = calculateResult(calcRange, diffPair, problems, infoProvider, useTkh);
             if (result != null)
                 results.addResult(result);
@@ -80,34 +78,29 @@
      *
      * @param infoProvider
      */
-    private FlowDepthCalculationResult calculateResult(final DoubleRange calcRange, final DifferencesPair diffPair,
-            final Calculation problems, final RiverInfoProvider infoProvider, final boolean useTkh) {
+    private FlowDepthCalculationResult calculateResult(final DoubleRange calcRange, final WstSoundingIdPair diffPair, final Calculation problems,
+            final RiverInfoProvider infoProvider, final boolean useTkh) {
 
         /* access real input data from database */
         final String soundingId = diffPair.getSoundingId();
         final String wstId = diffPair.getWstId();
 
-        final BedHeightsFinder bedHeight = loadBedHeight(soundingId, calcRange);
-        if (bedHeight == null) {
-            final String message = Resources.format(this.context.getMeta(), "Failed to access sounding with id '{0}'", soundingId);
-            problems.addProblem(message);
+        final BedHeightsFinder bedHeight = BedHeightsFinder.forId(this.context, soundingId, calcRange, problems);
+        if (bedHeight == null)
             return null;
-        }
 
         /* REMARK: fetch ALL wst kms, because we want to determine the original reference gauge */
-        final WaterlevelData waterlevel = new WaterlevelFetcher().findWaterlevel(this.context, wstId, Double.NaN, Double.NaN);
-        if (waterlevel == null) {
-            final String message = Resources.format(this.context.getMeta(), "Failed to access waterlevel with id '{0}'", wstId);
-            problems.addProblem(message);
+        final WaterlevelData waterlevel = new WaterlevelFetcher().findWaterlevel(this.context, wstId, Double.NaN, Double.NaN, problems);
+        if (waterlevel == null)
             return null;
-        }
+
         final WKms wstKms = waterlevel.getWkms();
 
         final String wspLabel = wstKms.getName();
         final String soundingLabel = bedHeight.getInfo().getDescription();
         final String label = String.format("%s - %s", wspLabel, soundingLabel);
 
-        checkYearDifference(label, waterlevel, bedHeight.getInfo().getYear(), problems);
+        FlowDepthUtils.checkYearDifference(label, waterlevel, bedHeight.getInfo().getYear(), problems);
         checkWaterlevelDiscretisation(wstKms, calcRange, problems);
         // TODO: prüfen, ob sohlhöhen die calcRange abdecken/überschneiden
 
@@ -117,61 +110,19 @@
         final int wspYear = waterlevel.getYear();
         final WstInfo wstInfo = new WstInfo(wspLabel, wspYear, riverInfoProvider.getReferenceGauge());
 
+        final WaterlevelValuesFinder waterlevelProvider = WaterlevelValuesFinder.fromKms(wstKms);
         final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wstKms);
 
         final River river = riverInfoProvider.getRiver();
-        final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(useTkh, this.context, problems, label, river, calcRange, dischargeProvider,
+        final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(useTkh, this.context, problems, label, river, calcRange, waterlevelProvider,
+                dischargeProvider,
                 bedHeight);
 
-        final FlowDepthCalculator calculator = new FlowDepthCalculator(riverInfoProvider, wstKms, dischargeProvider, bedHeight, tkhCalculator);
+        final FlowDepthCalculator calculator = new FlowDepthCalculator(riverInfoProvider, wspLabel, bedHeight, tkhCalculator);
         return calculator.execute(label, wstInfo, calcRange);
     }
 
-
-    /**
-     * Checks the year difference between waterlevels and sounding, and issues a warning if too big.
-     *
-     * Zeitraum Zeitliche Differenz [a]
-     * X ≥ 1998 ± 3
-     * 1958 ≤ X < 1998 ± 6
-     * 1918 ≤ X < 1958 ± 12
-     * X < 1918 ± 25
-     */
-    private void checkYearDifference(final String label, final WaterlevelData waterlevel, final Integer soundingYear, final Calculation problems) {
-        if (soundingYear == null)
-            return;
-
-        final int wstYear = waterlevel.getYear();
-        if (wstYear < 0)
-            return;
-
-        final int maxDifference = getMaxDifferenceYears(soundingYear);
-
-        final int difference = Math.abs(soundingYear - wstYear);
-        if (difference > maxDifference) {
-            final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.year_difference", null, label, wstYear,
-                    soundingYear);
-            problems.addProblem(message);
-        }
-    }
-
-    private int getMaxDifferenceYears(final int year) {
-
-        if (year < 1918)
-            return 25;
-
-        if (1918 <= year && year < 1958)
-            return 12;
-
-        if (1958 <= year && year < 1998)
-            return 6;
-
-        /* >= 1998 */
-        return 3;
-    }
-
     /* Checks if the discretisation of the waterlevel exceeds 1000m */
-
     private void checkWaterlevelDiscretisation(final WKms wstKms, final DoubleRange calcRange, final Calculation problems) {
 
         final int size = wstKms.size();
@@ -190,37 +141,4 @@
             }
         }
     }
-
-    private BedHeightsFinder loadBedHeight(final String soundingId, final DoubleRange calcRange) {
-
-        // REMARK: absolutely unbelievable....
-        // The way how bed-heights (and other data too) is accessed is different for nearly every calculation-type
-        // throughout flys.
-        // The knowledge on how to parse the datacage-ids is spread through the complete code-base...
-
-        // We use here the way on how bed-heights are accessed by the BedDifferenceAccess/BedDifferenceCalculation, but
-        // this is plain random
-        final String[] parts = soundingId.split(";");
-
-        final BedHeightsArtifact artifact = (BedHeightsArtifact) RiverUtils.getArtifact(parts[0], this.context);
-
-        final Integer bedheightId = artifact.getDataAsInteger("height_id");
-        if (bedheightId == null) {
-            // FIXME: error message!
-            return null;
-        }
-
-        // REMARK: this only works with type 'single'; unclear on how to distinguish from epoch data (or whatever the
-        // other type means)
-        // Luckily, the requirement is to only access 'single' data here.
-        // final String bedheightType = artifact.getDataAsString("type");
-
-        // REMARK: BedDifferences uses this, but we also need the metadata of the BedHeight
-        // REMARK: second absolutely awful thing: BedHeight is a hibernate binding class, accessing the database via
-        // hibernate stuff
-        // BedHeightFactory uses its own (direct) way of accessing the data, with its own implemented data classes.
-        // return BedHeightFactory.getHeight(bedheightType, bedheightId, from, to);
-
-        return BedHeightsFinder.forId(bedheightId, calcRange);
-    }
 }
\ No newline at end of file

http://dive4elements.wald.intevation.org