comparison 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
comparison
equal deleted inserted replaced
9486:ce13a2f07290 9487:504f63512379
10 package org.dive4elements.river.artifacts.sinfo.collision; 10 package org.dive4elements.river.artifacts.sinfo.collision;
11 11
12 import java.util.ArrayList; 12 import java.util.ArrayList;
13 import java.util.Collection; 13 import java.util.Collection;
14 import java.util.HashMap; 14 import java.util.HashMap;
15 import java.util.List;
15 import java.util.Map; 16 import java.util.Map;
17 import java.util.NavigableSet;
18 import java.util.TreeSet;
16 19
17 import org.apache.commons.lang.math.DoubleRange; 20 import org.apache.commons.lang.math.DoubleRange;
18 import org.dive4elements.artifacts.CallContext; 21 import org.dive4elements.artifacts.CallContext;
19 import org.dive4elements.river.artifacts.common.GeneralResultType; 22 import org.dive4elements.river.artifacts.common.GeneralResultType;
20 import org.dive4elements.river.artifacts.common.ResultRow; 23 import org.dive4elements.river.artifacts.common.ResultRow;
64 67
65 final CollisionCalculationResults results = new CollisionCalculationResults(calcModeLabel, user, riverInfo, calcRange, access.getYearsHeader()); 68 final CollisionCalculationResults results = new CollisionCalculationResults(calcModeLabel, user, riverInfo, calcRange, access.getYearsHeader());
66 69
67 final Collection<ResultRow> overViewRows = new ArrayList<>(); 70 final Collection<ResultRow> overViewRows = new ArrayList<>();
68 71
72 final List<DateRange> years = new ArrayList<>();
73 final NavigableSet<Integer> detailYears = new TreeSet<>();
69 if (access.getYears() != null) { 74 if (access.getYears() != null) {
70 for (final int year : access.getYears()) 75 for (final int year : access.getYears()) {
71 calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), year, year, false); 76 calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), year, year, false);
77 years.add(new DateRange(DateUtil.getStartDateFromYear(year), DateUtil.getEndDateFromYear(year)));
78 detailYears.add(Integer.valueOf(year));
79 }
72 } else { 80 } else {
73 for (final DateRange dr : access.getEpochs()) 81 for (final DateRange dr : access.getEpochs()) {
74 calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), true); 82 calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), true);
83 years.add(dr);
84 detailYearsAdd(detailYears, dr);
85 }
75 } 86 }
76 final CollisionCalcOverviewResult overviewResult = new CollisionCalcOverviewResult(access.getYearsHeader(), access.getYears(), overViewRows); 87 final CollisionCalcOverviewResult overviewResult = new CollisionCalcOverviewResult(access.getYearsHeader(), (access.getYears() == null), years,
88 overViewRows);
77 results.addResult(overviewResult, problems); 89 results.addResult(overviewResult, problems);
78 90
79 // create q-for-w-finders for all gauges of the calculation km range 91 // create q-for-w-finders for all gauges of the calculation km range
80 final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange); 92 final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
81 final Map<Gauge, GaugeDischargeValuesFinder> qFinders = new HashMap<>(); 93 final Map<Gauge, GaugeDischargeValuesFinder> qFinders = new HashMap<>();
84 qFinders.put(gauge, GaugeDischargeValuesFinder.loadValues(gauge, problems)); 96 qFinders.put(gauge, GaugeDischargeValuesFinder.loadValues(gauge, problems));
85 zoneFinders.put(gauge, GaugeMainValueFinder.loadValues(MainValueTypeKey.Q, gauge, problems)); 97 zoneFinders.put(gauge, GaugeMainValueFinder.loadValues(MainValueTypeKey.Q, gauge, problems));
86 } 98 }
87 final Collection<ResultRow> detailsRows = new ArrayList<>(); 99 final Collection<ResultRow> detailsRows = new ArrayList<>();
88 100
89 // calculate secondary results for each year or epoch 101 // calculate secondary results for each year
90 if (access.getYears() != null) { 102 for (final Integer year : detailYears)
91 for (final int year : access.getYears()) 103 calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), year, qFinders, zoneFinders);
92 calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), year, year, qFinders, zoneFinders);
93 } else {
94 for (final DateRange dr : access.getEpochs())
95 calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), qFinders, zoneFinders);
96 }
97 final CollisionCalcDetailResult detailResult = new CollisionCalcDetailResult("Details", detailsRows); 104 final CollisionCalcDetailResult detailResult = new CollisionCalcDetailResult("Details", detailsRows);
98 results.addResult(detailResult, problems); 105 results.addResult(detailResult, problems);
99 106
100 return new CalculationResult(results, problems); 107 return new CalculationResult(results, problems);
108 }
109
110 /**
111 * Adds all years of an epoch to a set
112 */
113 private void detailYearsAdd(final NavigableSet<Integer> detailYears, final DateRange epoch) {
114 for (int year = epoch.getFromYear(); year <= epoch.getToYear(); year++)
115 detailYears.add(Integer.valueOf(year));
101 } 116 }
102 117
103 /** 118 /**
104 * Calculates the collision counts for a km range of a river and a year or year range (epoch), 119 * Calculates the collision counts for a km range of a river and a year or year range (epoch),
105 * and adds them to a ResultRow collection 120 * and adds them to a ResultRow collection
106 */ 121 */
107 private void calculateOverview(final Collection<ResultRow> rows, final River river, final double fromKm, final double toKm, final int fromYear, 122 private void calculateOverview(final Collection<ResultRow> rows, final River river, final double fromKm, final double toKm, final int fromYear,
108 final int toYear, final boolean isEpoch) { 123 final int toYear, final boolean isEpoch) {
109 for (final CollisionAggregateValue aggregate : CollisionAggregateValue.getValuesByKm(river, fromKm, toKm, fromYear, toYear)) { 124 for (final CollisionAggregateValue aggregate : CollisionAggregateValue.getValuesByKm(river, fromKm, toKm, fromYear, toYear)) {
110 rows.add(ResultRow.create().putValue(GeneralResultType.station, aggregate.getStation()) 125 rows.add(ResultRow.create().putValue(GeneralResultType.station, aggregate.getStation())
111 .putValue(SInfoResultType.years, (isEpoch ? String.format("%d-%d", fromYear, toYear) : Integer.toString(fromYear))) 126 .putValue(SInfoResultType.years, yearsToString(isEpoch, fromYear, toYear))
112 .putValue(SInfoResultType.collisionCount, aggregate.getCount())); 127 .putValue(SInfoResultType.collisionCount, aggregate.getCount()));
113 } 128 }
114 } 129 }
115 130
116 /** 131 /**
117 * Calculates the collision details for a km range of a river and a year or year range (epoch), 132 * Returns the string representation of a year or epoch
118 * and adds them to a ResultRow collection 133 */
134 public static String yearsToString(final boolean isEpoch, final DateRange years) {
135 return yearsToString(isEpoch, years.getFromYear(), years.getToYear());
136 }
137
138 /**
139 * Returns the string representation of a year or epoch
140 */
141 public static String yearsToString(final boolean isEpoch, final int fromYear, final int toYear) {
142 return (isEpoch ? String.format("%d-%d", fromYear, toYear) : Integer.toString(fromYear));
143 }
144
145 /**
146 * Calculates the collision details for a km range of a river and a year, and adds them to a ResultRow collection
119 */ 147 */
120 private void calculateDetails(final Collection<ResultRow> rows, final RiverInfoProvider riverInfo, final double fromKm, final double toKm, 148 private void calculateDetails(final Collection<ResultRow> rows, final RiverInfoProvider riverInfo, final double fromKm, final double toKm,
121 final int fromYear, final int toYear, final Map<Gauge, GaugeDischargeValuesFinder> qFinders, final Map<Gauge, GaugeMainValueFinder> zoneFinders) { 149 final int year, final Map<Gauge, GaugeDischargeValuesFinder> qFinders, final Map<Gauge, GaugeMainValueFinder> zoneFinders) {
122 for (final CollisionValue collision : CollisionValue.getValues(riverInfo.getRiver(), fromKm, toKm, DateUtil.getStartDateFromYear(fromYear), 150 for (final CollisionValue collision : CollisionValue.getValues(riverInfo.getRiver(), fromKm, toKm, DateUtil.getStartDateFromYear(year),
123 DateUtil.getEndDateFromYear(toYear))) { 151 DateUtil.getEndDateFromYear(year))) {
124 final Gauge gauge = riverInfo.getGauge(collision.getStation(), true); 152 final Gauge gauge = riverInfo.getGauge(collision.getStation(), true);
125 final double q = qFinders.get(gauge).getDischarge(collision.getGaugeW()); 153 final double q = qFinders.get(gauge).getDischarge(collision.getGaugeW());
126 final double qOut = Double.isInfinite(q) ? Double.NaN : q; 154 final double qOut = Double.isInfinite(q) ? Double.NaN : q;
127 rows.add(ResultRow.create().putValue(GeneralResultType.station, collision.getStation()) 155 rows.add(ResultRow.create().putValue(GeneralResultType.station, collision.getStation())
128 .putValue(GeneralResultType.dateShort, collision.getEventDate()).putValue(SInfoResultType.collisionGaugeW, collision.getGaugeW()) 156 .putValue(GeneralResultType.dateShort, collision.getEventDate()).putValue(SInfoResultType.collisionGaugeW, collision.getGaugeW())

http://dive4elements.wald.intevation.org