diff artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalculation.java @ 9157:f9bb5d0a6ff3

Added the S-Info collision calculation and chart output
author mschaefer
date Tue, 19 Jun 2018 14:19:32 +0200
parents 23945061daec
children 1614cb14308f
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalculation.java	Tue Jun 19 14:16:45 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalculation.java	Tue Jun 19 14:19:32 2018 +0200
@@ -11,6 +11,8 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.commons.lang.math.DoubleRange;
 import org.dive4elements.artifacts.CallContext;
@@ -18,12 +20,18 @@
 import org.dive4elements.river.artifacts.common.ResultRow;
 import org.dive4elements.river.artifacts.model.Calculation;
 import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DateRange;
 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.common.SInfoResultType;
 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.backend.utils.DateUtil;
+import org.dive4elements.river.model.Gauge;
 import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.CollisionAggregateValue;
+import org.dive4elements.river.model.sinfo.CollisionValue;
 
 class CollisionCalculation {
 
@@ -39,46 +47,89 @@
 
         final String user = CalculationUtils.findArtifactUser(this.context, sinfo);
 
-        /* access input data */
+        // access input data
         final CollisionAccess access = new CollisionAccess(sinfo);
         final River river = access.getRiver();
         final RiverInfo riverInfo = new RiverInfo(river);
 
         final DoubleRange calcRange = access.getRange();
 
-        /* calculate results for each diff pair */
+        // calculate results for each year or epoch
         final Calculation problems = new Calculation();
 
-        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
-
         final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
 
-        final int[] years = access.getYears();
-        final int[][] epochs = access.getEpochs();
+        final CollisionCalculationResults results = new CollisionCalculationResults(calcModeLabel, user, riverInfo, calcRange, access.getYearsHeader());
 
         final Collection<ResultRow> overViewRows = new ArrayList<>();
+
+        if (access.getYears() != null) {
+            for (final int year : access.getYears())
+                calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), year, year, false);
+        }
+        else {
+            for (final DateRange dr : access.getEpochs())
+                calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), true);
+        }
+        final CollisionCalcOverviewResult overviewResult = new CollisionCalcOverviewResult(access.getYearsHeader(), overViewRows);
+        results.addResult(overviewResult, problems);
+
+        // create q-for-w-finders for all gauges of the calculation km range
+        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
+        final Map<Gauge, GaugeDischargeValuesFinder> qFinders = new HashMap<>();
+        final Map<Gauge, GaugeDischargeZoneFinder> zoneFinders = new HashMap<>();
+        for (final Gauge gauge : river.determineGauges(calcRange.getMinimumDouble(), calcRange.getMaximumDouble())) {
+            qFinders.put(gauge, GaugeDischargeValuesFinder.loadValues(gauge, problems));
+            zoneFinders.put(gauge, GaugeDischargeZoneFinder.loadValues(gauge, problems));
+        }
         final Collection<ResultRow> detailsRows = new ArrayList<>();
 
-        // TODO: calculate
-
-        final CollisionCalculationResults results = new CollisionCalculationResults(calcModeLabel, user, riverInfo, calcRange);
-
-        final ResultRow row = ResultRow.create().putValue(GeneralResultType.station, 8888.888);
-        final ResultRow row2 = ResultRow.create().putValue(GeneralResultType.station, 777.888);
-
-        for (int i = 0; i < 300; i++) {
-            overViewRows.add(row);
-            overViewRows.add(row2);
+        // calculate secondary results for each year or epoch
+        if (access.getYears() != null) {
+            for (final int year : access.getYears())
+                calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), year, year, qFinders, zoneFinders);
         }
-        final CollisionCalcOverviewResult overviewResult = new CollisionCalcOverviewResult("Overview", overViewRows); // TODO: get Title-Strings from messages
-        results.addResult(overviewResult, problems);
-        for (int i = 0; i < 200; i++) {
-            detailsRows.add(row);
-            detailsRows.add(row2);
+        else {
+            for (final DateRange dr : access.getEpochs())
+                calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), qFinders, zoneFinders);
         }
         final CollisionCalcDetailResult detailResult = new CollisionCalcDetailResult("Details", detailsRows);
         results.addResult(detailResult, problems);
 
         return new CalculationResult(results, problems);
     }
+
+    /**
+     * Calculates the collision counts for a km range of a river and a year or year range (epoch),
+     * and adds them to a ResultRow collection
+     */
+    private void calculateOverview(final Collection<ResultRow> rows, final River river, final double fromKm, final double toKm, final int fromYear,
+            final int toYear, final boolean isEpoch) {
+        for (final CollisionAggregateValue aggregate : CollisionAggregateValue.getValuesByKm(river, fromKm, toKm, fromYear, toYear)) {
+            rows.add(ResultRow.create().putValue(GeneralResultType.station, aggregate.getStation())
+                    .putValue(SInfoResultType.years, (isEpoch? String.format("%d-%d", fromYear, toYear) : Integer.toString(fromYear)))
+                    .putValue(SInfoResultType.collisionCount, aggregate.getCount()));
+        }
+    }
+
+    /**
+     * Calculates the collision details for a km range of a river and a year or year range (epoch),
+     * and adds them to a ResultRow collection
+     */
+    private void calculateDetails(final Collection<ResultRow> rows, final RiverInfoProvider riverInfo, final double fromKm, final double toKm,
+            final int fromYear, final int toYear, final Map<Gauge, GaugeDischargeValuesFinder> qFinders,
+            final Map<Gauge, GaugeDischargeZoneFinder> zoneFinders) {
+        for (final CollisionValue collision : CollisionValue.getValues(riverInfo.getRiver(), fromKm, toKm, DateUtil.getStartDateFromYear(fromYear),
+                DateUtil.getEndDateFromYear(toYear))) {
+            final Gauge gauge = riverInfo.getGauge(collision.getStation(), true);
+            final double q = qFinders.get(gauge).getDischarge(collision.getGaugeW());
+            final double qOut = Double.isInfinite(q) ? Double.NaN : q;
+            rows.add(ResultRow.create().putValue(GeneralResultType.station, collision.getStation())
+                    .putValue(GeneralResultType.date, collision.getEventDate())
+                    .putValue(SInfoResultType.collisionGaugeW, collision.getGaugeW())
+                    .putValue(SInfoResultType.gaugeLabel, collision.getGaugeName())
+                    .putValue(SInfoResultType.discharge, qOut)
+                    .putValue(SInfoResultType.dischargeZone, zoneFinders.get(gauge).getDischargeZone(q)));
+        }
+    }
 }
\ No newline at end of file

http://dive4elements.wald.intevation.org