changeset 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 ce13a2f07290
children c347512a07bd
files artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcOverviewResult.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcProcessor.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalculation.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionState.java
diffstat 5 files changed, 76 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcFacet.java	Mon Sep 17 19:07:57 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcFacet.java	Tue Sep 18 12:21:17 2018 +0200
@@ -22,22 +22,22 @@
 public class CollisionCalcFacet extends ResultFacet {
 
     private static final long serialVersionUID = 1;
-    private int year;
+    private String years;
 
     private CollisionCalcFacet() {
         super();
         // required for clone operation deepCopy()
     }
 
-    public CollisionCalcFacet(final int facetIndex, final int resultIndex, final int year, final String name, final String description,
+    public CollisionCalcFacet(final int facetIndex, final int resultIndex, final String years, final String name, final String description,
             final String yAxisLabelKey, final ComputeType type, final String hash, final String stateId) {
+
         super(facetIndex, resultIndex, name, description, yAxisLabelKey, type, stateId, hash);
-
-        this.year = year;
+        this.years = years;
     }
 
-    public int getYear() {
-        return this.year;
+    public String getYears() {
+        return this.years;
     }
 
     /** Copy deeply. */
@@ -50,7 +50,7 @@
         copy.type = this.type;
         copy.hash = this.hash;
         copy.stateId = this.stateId;
-        copy.year = this.year;
+        copy.years = this.years;
         return copy;
     }
 }
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcOverviewResult.java	Mon Sep 17 19:07:57 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcOverviewResult.java	Tue Sep 18 12:21:17 2018 +0200
@@ -11,6 +11,7 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 import org.apache.commons.collections.Predicate;
 import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
@@ -20,6 +21,7 @@
 import org.dive4elements.river.artifacts.common.IResultType;
 import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
 import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.DateRange;
 import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
 
@@ -34,24 +36,31 @@
 
     private static final String JASPER_FILE = "/jasper/templates/sinfo.collision.overview.jrxml";
 
-    private final int[] singleYears;
+    private final boolean isEpochs;
 
-    public CollisionCalcOverviewResult(final String label, final int[] singleYears, final Collection<ResultRow> rows) {
+    private final List<DateRange> years;
+
+    public CollisionCalcOverviewResult(final String label, final boolean isEpochs, final Collection<DateRange> years, final Collection<ResultRow> rows) {
         super(label, rows);
-        this.singleYears = singleYears;
+        this.isEpochs = isEpochs;
+        this.years = new ArrayList<>(years);
     }
 
-    public int[] getSingleYears() {
-        return this.singleYears;
+    public boolean getIsEpochs() {
+        return this.isEpochs;
     }
 
-    public double[][] getStationPointsByYear(final IResultType type, final int year) {
+    public List<DateRange> getYears() {
+        return this.years;
+    }
+
+    public double[][] getStationPointsByYear(final IResultType type, final String years) {
 
         final Predicate filter = new Predicate() {
             @Override
             public boolean evaluate(final Object object) {
                 final ResultRow row = (ResultRow) object;
-                return getSingleYears() == null || Integer.valueOf(row.getValue(SInfoResultType.years).toString()) == year;
+                return row.getValue(SInfoResultType.years).toString().equals(years);
             }
         };
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcProcessor.java	Mon Sep 17 19:07:57 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcProcessor.java	Tue Sep 18 12:21:17 2018 +0200
@@ -60,11 +60,10 @@
     protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
 
         final CollisionCalcFacet facet = (CollisionCalcFacet) bundle.getFacet();
-        final int year = facet.getYear();
 
         final CollisionCalcOverviewResult result = (CollisionCalcOverviewResult) getResult(generator, bundle);
 
-        final double[][] points = result.getStationPointsByYear(SInfoResultType.collisionCount, year);
+        final double[][] points = result.getStationPointsByYear(SInfoResultType.collisionCount, facet.getYears());
 
         return buildSeriesForPoints(points, generator, bundle, theme, visible, null);
     }
@@ -76,14 +75,9 @@
         // result index; however name and index are used on client side as unique id.
 
         final CollisionCalcOverviewResult ccoResult = (CollisionCalcOverviewResult) result;
-        if (ccoResult.getSingleYears() == null) {
-            final String facetDescription = Resources.getMsg(context.getMeta(), I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, result.getLabel());
-            return new CollisionCalcFacet(themeCount, resultIndex, -1, FACET_COLLISION_CALC_COUNT, facetDescription, I18N_AXIS_LABEL, ComputeType.ADVANCE, hash,
-                    id);
-        } else {
-            final String facetDescription = Resources.getMsg(context.getMeta(), I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, Integer.toString(year));
-            return new CollisionCalcFacet(themeCount, resultIndex, year, COLLISION_FACETS[themeCount % 3], facetDescription, I18N_AXIS_LABEL,
-                    ComputeType.ADVANCE, hash, id);
-        }
+        final String years = CollisionCalculation.yearsToString(ccoResult.getIsEpochs(), ccoResult.getYears().get(themeCount));
+        final String facetDescription = Resources.getMsg(context.getMeta(), I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, years);
+        return new CollisionCalcFacet(themeCount, resultIndex, years, COLLISION_FACETS[themeCount % 3], facetDescription, I18N_AXIS_LABEL,
+                ComputeType.ADVANCE, hash, id);
     }
 }
\ No newline at end of file
--- 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;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionState.java	Mon Sep 17 19:07:57 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionState.java	Tue Sep 18 12:21:17 2018 +0200
@@ -18,6 +18,7 @@
 import org.dive4elements.river.artifacts.model.Calculation;
 import org.dive4elements.river.artifacts.model.CalculationResult;
 import org.dive4elements.river.artifacts.model.DataFacet;
+import org.dive4elements.river.artifacts.model.DateRange;
 import org.dive4elements.river.artifacts.model.EmptyFacet;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.model.ReportFacet;
@@ -81,15 +82,8 @@
         for (int index = 0; index < resultList.size(); index++) {
             if (resultList.get(index) instanceof CollisionCalcOverviewResult) {
                 final CollisionCalcOverviewResult result = (CollisionCalcOverviewResult) resultList.get(index);
-
-                final int[] singleYears = result.getSingleYears();
-
-                if (singleYears == null)
-                    facets.add(CollisionCalcProcessor.createFacet(context, hash, this.id, result, index, -1, themeCount++));
-                else {
-                    for (final int singleYear : singleYears)
-                        facets.add(CollisionCalcProcessor.createFacet(context, hash, this.id, result, index, singleYear, themeCount++));
-                }
+                for (final DateRange dr : result.getYears())
+                    facets.add(CollisionCalcProcessor.createFacet(context, hash, this.id, result, index, dr.getFromYear(), themeCount++));
             }
         }
 

http://dive4elements.wald.intevation.org