diff artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalculation.java @ 9487:504f63512379

Sinfo collisions: calculation of multiple epochs, avoiding duplicate collision events in the details report
author mschaefer
date Tue, 18 Sep 2018 12:21:17 +0200
parents 7b2b086e45f0
children 853f2dafc16e
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalculation.java	Mon Sep 17 19:07:57 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalculation.java	Tue Sep 18 12:21:17 2018 +0200
@@ -12,7 +12,10 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.NavigableSet;
+import java.util.TreeSet;
 
 import org.apache.commons.lang.math.DoubleRange;
 import org.dive4elements.artifacts.CallContext;
@@ -66,14 +69,23 @@
 
         final Collection<ResultRow> overViewRows = new ArrayList<>();
 
+        final List<DateRange> years = new ArrayList<>();
+        final NavigableSet<Integer> detailYears = new TreeSet<>();
         if (access.getYears() != null) {
-            for (final int year : access.getYears())
+            for (final int year : access.getYears()) {
                 calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), year, year, false);
+                years.add(new DateRange(DateUtil.getStartDateFromYear(year), DateUtil.getEndDateFromYear(year)));
+                detailYears.add(Integer.valueOf(year));
+            }
         } else {
-            for (final DateRange dr : access.getEpochs())
+            for (final DateRange dr : access.getEpochs()) {
                 calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), true);
+                years.add(dr);
+                detailYearsAdd(detailYears, dr);
+            }
         }
-        final CollisionCalcOverviewResult overviewResult = new CollisionCalcOverviewResult(access.getYearsHeader(), access.getYears(), overViewRows);
+        final CollisionCalcOverviewResult overviewResult = new CollisionCalcOverviewResult(access.getYearsHeader(), (access.getYears() == null), years,
+                overViewRows);
         results.addResult(overviewResult, problems);
 
         // create q-for-w-finders for all gauges of the calculation km range
@@ -86,14 +98,9 @@
         }
         final Collection<ResultRow> detailsRows = new ArrayList<>();
 
-        // 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);
-        } else {
-            for (final DateRange dr : access.getEpochs())
-                calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), qFinders, zoneFinders);
-        }
+        // calculate secondary results for each year
+        for (final Integer year : detailYears)
+            calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), year, qFinders, zoneFinders);
         final CollisionCalcDetailResult detailResult = new CollisionCalcDetailResult("Details", detailsRows);
         results.addResult(detailResult, problems);
 
@@ -101,6 +108,14 @@
     }
 
     /**
+     * Adds all years of an epoch to a set
+     */
+    private void detailYearsAdd(final NavigableSet<Integer> detailYears, final DateRange epoch) {
+        for (int year = epoch.getFromYear(); year <= epoch.getToYear(); year++)
+            detailYears.add(Integer.valueOf(year));
+    }
+
+    /**
      * 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
      */
@@ -108,19 +123,32 @@
             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.years, yearsToString(isEpoch, fromYear, toYear))
                     .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
+     * Returns the string representation of a year or epoch
+     */
+    public static String yearsToString(final boolean isEpoch, final DateRange years) {
+        return yearsToString(isEpoch, years.getFromYear(), years.getToYear());
+    }
+
+    /**
+     * Returns the string representation of a year or epoch
+     */
+    public static String yearsToString(final boolean isEpoch, final int fromYear, final int toYear) {
+        return (isEpoch ? String.format("%d-%d", fromYear, toYear) : Integer.toString(fromYear));
+    }
+
+    /**
+     * Calculates the collision details for a km range of a river and a year, 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, GaugeMainValueFinder> zoneFinders) {
-        for (final CollisionValue collision : CollisionValue.getValues(riverInfo.getRiver(), fromKm, toKm, DateUtil.getStartDateFromYear(fromYear),
-                DateUtil.getEndDateFromYear(toYear))) {
+            final int year, final Map<Gauge, GaugeDischargeValuesFinder> qFinders, final Map<Gauge, GaugeMainValueFinder> zoneFinders) {
+        for (final CollisionValue collision : CollisionValue.getValues(riverInfo.getRiver(), fromKm, toKm, DateUtil.getStartDateFromYear(year),
+                DateUtil.getEndDateFromYear(year))) {
             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;

http://dive4elements.wald.intevation.org