comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java @ 9620:26e113e8224f

Nachtrag Pos. 20: flood duration calculation for multiple infrastructure groups/types, local class FloodDurationCalculationResult.Infrastructure renamed and extracted into own class
author mschaefer
date Thu, 10 Oct 2019 17:11:54 +0200
parents d889ffe2fb05
children 07f02019065e
comparison
equal deleted inserted replaced
9619:63bbd5e45839 9620:26e113e8224f
31 import org.dive4elements.river.artifacts.model.WstValueTable.QPosition; 31 import org.dive4elements.river.artifacts.model.WstValueTable.QPosition;
32 import org.dive4elements.river.artifacts.model.WstValueTableFactory; 32 import org.dive4elements.river.artifacts.model.WstValueTableFactory;
33 import org.dive4elements.river.artifacts.model.river.RiverInfoProvider; 33 import org.dive4elements.river.artifacts.model.river.RiverInfoProvider;
34 import org.dive4elements.river.artifacts.sinfo.common.GaugeDurationValuesFinder; 34 import org.dive4elements.river.artifacts.sinfo.common.GaugeDurationValuesFinder;
35 import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType; 35 import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
36 import org.dive4elements.river.artifacts.sinfo.flood_duration.FloodDurationCalculationResult.Infrastructure;
37 import org.dive4elements.river.artifacts.sinfo.flood_duration.RiversideRadioChoice.RiversideChoiceKey;
38 import org.dive4elements.river.exports.WaterlevelDescriptionBuilder; 36 import org.dive4elements.river.exports.WaterlevelDescriptionBuilder;
39 import org.dive4elements.river.model.Attribute.AttributeKey; 37 import org.dive4elements.river.model.Attribute.AttributeKey;
40 import org.dive4elements.river.model.Gauge; 38 import org.dive4elements.river.model.Gauge;
41 import org.dive4elements.river.model.sinfo.InfrastructureValue; 39 import org.dive4elements.river.model.sinfo.InfrastructureValue;
42 40
52 50
53 private final List<ResultRow> rows = new ArrayList<>(); 51 private final List<ResultRow> rows = new ArrayList<>();
54 52
55 private final RiverInfoProvider riverInfoProvider; 53 private final RiverInfoProvider riverInfoProvider;
56 private RiverInfoProvider riverInfoProvider2; 54 private RiverInfoProvider riverInfoProvider2;
55 private final Map<Double, List<InfrastructureValue>> stationInfras;
57 56
58 private final CallContext context; 57 private final CallContext context;
59 58
60 public FloodDurationCalculator(final CallContext context, final RiverInfoProvider riverInfoProvider) { 59 public FloodDurationCalculator(final CallContext context, final RiverInfoProvider riverInfoProvider) {
61 this.context = context; 60 this.context = context;
62 this.riverInfoProvider = riverInfoProvider; 61 this.riverInfoProvider = riverInfoProvider;
63 this.riverInfoProvider2 = null; 62 this.riverInfoProvider2 = null;
63 this.stationInfras = new HashMap<>();
64 } 64 }
65 65
66 /** 66 /**
67 * Calculate the infrastructures flood duration result rows 67 * Calculate the infrastructures flood duration result rows
68 */ 68 */
69 public void execute(final Calculation problems, final String label, final DoubleRange calcRange, final RiversideChoiceKey riverside, 69 public void execute(final Calculation problems, final String label, final DoubleRange calcRange, final AttributeKey riverside,
70 final Set<Infrastructure> infrastruktureKey, final boolean withWspl, final WINFOArtifact winfo, final FloodDurationCalculationResults results) { 70 final Set<String> infrastructureChoices, final boolean withWspl, final WINFOArtifact winfo, final FloodDurationCalculationResults results) {
71
72 // FIXME Schäfer:
73 // filter by infrastructureKey
74 // FIXME: Tironi: api gscheit benennen;
75 // Lösung finden für: Infrastructure enthält riverside, wird hier aber nicht benötigt (weil schon im choice)
76 71
77 // Find all gauges of the calc range, and create the duration finders 72 // Find all gauges of the calc range, and create the duration finders
78 final Map<Gauge, GaugeDurationValuesFinder> durFinders = new HashMap<>(); 73 final Map<Gauge, GaugeDurationValuesFinder> durFinders = new HashMap<>();
79 for (final Gauge gauge : this.riverInfoProvider.getGauges()) { 74 for (final Gauge gauge : this.riverInfoProvider.getGauges()) {
80 durFinders.put(gauge, GaugeDurationValuesFinder.loadValues(gauge, problems)); 75 durFinders.put(gauge, GaugeDurationValuesFinder.loadValues(gauge, problems));
81 } 76 }
82 77
83 // Find all infrastructures within the calc range 78 // Find all infrastructures within the calc range
84 final AttributeKey bankKey = riverside.getAttributeKey();
85 final List<InfrastructureValue> infras = InfrastructureValue.getValues(this.riverInfoProvider.getRiver(), calcRange.getMinimumDouble(), 79 final List<InfrastructureValue> infras = InfrastructureValue.getValues(this.riverInfoProvider.getRiver(), calcRange.getMinimumDouble(),
86 calcRange.getMaximumDouble(), bankKey); 80 calcRange.getMaximumDouble(), riverside, infrastructureChoices);
87 81
88 // Merge all stations (range/step, borders of gauge ranges, infrastructures) 82 // Merge all stations (range/step, borders of gauge ranges, infrastructures)
89 final Map<Double, InfrastructureValue> allStations = new HashMap<>(); 83 // final Map<Double, InfrastructureValue> allStations = new HashMap<>();
90 final Map<Double, InfrastructureValue> secondBank = new HashMap<>(); // any second infrastructure in case of both-banks-option 84 this.stationInfras.clear();
91 addRangeStations(allStations, winfo); 85 // final Map<Double, InfrastructureValue> secondBank = new HashMap<>(); // any second infrastructure in case of
92 addGaugeLimits(allStations, durFinders.keySet(), calcRange.getMinimumDouble(), calcRange.getMaximumDouble()); 86 // both-banks-option
93 addInfrastructures(allStations, secondBank, infras); 87 addRangeStations(winfo);
94 final double[] stationsSorted = sortStations(allStations.keySet()); 88 addGaugeLimits(durFinders.keySet(), calcRange.getMinimumDouble(), calcRange.getMaximumDouble());
89 addInfrastructures(infras);
90 final double[] stationsSorted = sortStations(this.stationInfras.keySet());
95 91
96 // Calculate W and Q for all stations and the selected discharge states/waterlevels 92 // Calculate W and Q for all stations and the selected discharge states/waterlevels
97 final WQKms[] wqkmsArray = calculateWsts(winfo, withWspl, stationsSorted, problems); 93 final WQKms[] wqkmsArray = calculateWsts(winfo, withWspl, stationsSorted, problems);
98 // final WaterlevelData waterlevel = new WaterlevelData(wqkmsArray[0], -1, false, true); 94 // final WaterlevelData waterlevel = new WaterlevelData(wqkmsArray[0], -1, false, true);
99 // this.riverInfoProvider2 = this.riverInfoProvider.forWaterlevel(waterlevel); 95 // this.riverInfoProvider2 = this.riverInfoProvider.forWaterlevel(waterlevel);
109 105
110 // Load base wst table (river).wst 106 // Load base wst table (river).wst
111 // (should be in cache since already used in calculateWaterlevels (winfo.computeWaterlevelData) 107 // (should be in cache since already used in calculateWaterlevels (winfo.computeWaterlevelData)
112 final WstValueTable wst = WstValueTableFactory.getTable(this.riverInfoProvider2.getRiver()); 108 final WstValueTable wst = WstValueTableFactory.getTable(this.riverInfoProvider2.getRiver());
113 109
114 final Set<FloodDurationCalculationResult.Infrastructure> infrastructures = new HashSet<>(); 110 final Set<FloodDurationInfrastructureChoice> infrastructures = new HashSet<>();
115 111
116 // Create the result rows, and calculate and add the flood durations etc. 112 // Create the result rows, and calculate and add the flood durations etc.
117 for (int i = 0; i <= stationsSorted.length - 1; i++) { 113 for (int i = 0; i <= stationsSorted.length - 1; i++) {
118 final Gauge gauge = this.riverInfoProvider2.getGauge(stationsSorted[i], true); 114 final Gauge gauge = this.riverInfoProvider2.getGauge(stationsSorted[i], true);
119 final ResultRow row = createRow(stationsSorted[i], wqkmsArray, gaugeWstDurations.get(gauge), i); 115 if (this.stationInfras.containsKey(stationsSorted[i])) {
120 if (allStations.containsKey(stationsSorted[i]) && (allStations.get(stationsSorted[i]) != null)) 116 for (final InfrastructureValue infra : this.stationInfras.get(stationsSorted[i])) {
121 calculateInfrastructure(row, gauge, allStations.get(stationsSorted[i]), wst, durFinders, infrastructures); 117 final ResultRow row = createRow(stationsSorted[i], wqkmsArray, gaugeWstDurations.get(gauge), i);
122 118 calculateInfrastructure(row, gauge, infra, wst, durFinders, infrastructures);
123 this.rows.add(row); 119 this.rows.add(row);
124 if (secondBank.containsKey(stationsSorted[i])) { 120 }
125 final ResultRow row2 = ResultRow.create(row);
126 calculateInfrastructure(row2, gauge, secondBank.get(stationsSorted[i]), wst, durFinders, infrastructures);
127 this.rows.add(row2);
128 } 121 }
129
130 } 122 }
131 123
132 // Get the labels of the selected waterlevels 124 // Get the labels of the selected waterlevels
133 final String[] wstLabels = new String[wqkmsArray.length]; 125 final String[] wstLabels = new String[wqkmsArray.length];
134 for (int i = 0; i <= wqkmsArray.length - 1; i++) 126 for (int i = 0; i <= wqkmsArray.length - 1; i++)
156 } 148 }
157 149
158 /** 150 /**
159 * Adds to a stations map all stations corresponding to the active range and step 151 * Adds to a stations map all stations corresponding to the active range and step
160 */ 152 */
161 private void addRangeStations(final Map<Double, InfrastructureValue> allStations, final WINFOArtifact winfo) { 153 private void addRangeStations(final WINFOArtifact winfo) {
162 for (final double station : new ComputationRangeAccess(winfo).getKms()) 154 for (final double station : new ComputationRangeAccess(winfo).getKms())
163 allStations.put(Double.valueOf(station), null); 155 this.stationInfras.put(Double.valueOf(station), new ArrayList<InfrastructureValue>());
164 } 156 }
165 157
166 /** 158 /**
167 * Adds to a stations map all range limits of the gauges within the calc range 159 * Adds to a stations map all range limits of the gauges within the calc range
168 */ 160 */
169 private void addGaugeLimits(final Map<Double, InfrastructureValue> allStations, final Set<Gauge> gauges, final double fromKm, final double toKm) { 161 private void addGaugeLimits(final Set<Gauge> gauges, final double fromKm, final double toKm) {
170 for (final Gauge gauge : gauges) { 162 for (final Gauge gauge : gauges) {
171 final Double kmA = Double.valueOf(gauge.getRange().getA().doubleValue()); 163 final Double kmA = Double.valueOf(gauge.getRange().getA().doubleValue());
172 final Double kmB = Double.valueOf(gauge.getRange().getB().doubleValue()); 164 final Double kmB = Double.valueOf(gauge.getRange().getB().doubleValue());
173 if (kmA > fromKm - 0.0001) 165 if (kmA > fromKm - 0.0001)
174 allStations.put(kmA, null); 166 this.stationInfras.put(kmA, new ArrayList<InfrastructureValue>());
175 if (kmB < toKm + 0.0001) 167 if (kmB < toKm + 0.0001)
176 allStations.put(kmB, null); 168 this.stationInfras.put(kmB, new ArrayList<InfrastructureValue>());
177 } 169 }
178 } 170 }
179 171
180 /** 172 /**
181 * Adds to a stations map all (first) infrastructures of a station, and the second, if any, to another map 173 * Adds all infrastructures of a station to the station map
182 */ 174 */
183 private void addInfrastructures(final Map<Double, InfrastructureValue> allStations, final Map<Double, InfrastructureValue> secondBank, 175 private void addInfrastructures(final List<InfrastructureValue> infrastructures) {
184 final List<InfrastructureValue> infrastructures) {
185 for (final InfrastructureValue infrastructure : infrastructures) { 176 for (final InfrastructureValue infrastructure : infrastructures) {
186 final Double station = infrastructure.getStation(); 177 final Double station = infrastructure.getStation();
187 if (!allStations.containsKey(station) || !(allStations.get(station) instanceof InfrastructureValue)) 178 if (this.stationInfras.containsKey(station))
188 allStations.put(station, infrastructure); 179 this.stationInfras.get(station).add(infrastructure);
189 else
190 secondBank.put(station, infrastructure);
191 } 180 }
192 } 181 }
193 182
194 /** 183 /**
195 * Returns a double array with a sorted stations set 184 * Returns a double array with a sorted stations set
310 299
311 /** 300 /**
312 * Calculate the result row fields for one infrastructure 301 * Calculate the result row fields for one infrastructure
313 */ 302 */
314 private void calculateInfrastructure(final ResultRow row, final Gauge gauge, final InfrastructureValue infrastructure, final WstValueTable wst, 303 private void calculateInfrastructure(final ResultRow row, final Gauge gauge, final InfrastructureValue infrastructure, final WstValueTable wst,
315 final Map<Gauge, GaugeDurationValuesFinder> durFinders, final Set<Infrastructure> infrastructures) { 304 final Map<Gauge, GaugeDurationValuesFinder> durFinders, final Set<FloodDurationInfrastructureChoice> infrastructures) {
316 305
317 // Interpolate the infrastructure height in the wst table to get the corresponding Q 306 // Interpolate the infrastructure height in the wst table to get the corresponding Q
318 final Calculation problems = new Calculation(); 307 final Calculation problems = new Calculation();
319 final double[] qs = wst.findQsForW(infrastructure.getStation().doubleValue(), infrastructure.getHeight().doubleValue(), problems); 308 final double[] qs = wst.findQsForW(infrastructure.getStation().doubleValue(), infrastructure.getHeight().doubleValue(), problems);
320 // TODO Fehlerbehandlung (kein Q gefunden) 309 // TODO Fehlerbehandlung (kein Q gefunden)
326 row.putValue(SInfoResultType.infrastructuregroup, infrastructure.getInfrastructure().getGroup().getName()); 315 row.putValue(SInfoResultType.infrastructuregroup, infrastructure.getInfrastructure().getGroup().getName());
327 row.putValue(SInfoResultType.infrastructuretype, infrastructure.getInfrastructure().getType().getName()); 316 row.putValue(SInfoResultType.infrastructuretype, infrastructure.getInfrastructure().getType().getName());
328 317
329 // Determine the relative column position of the Q of the infrastructure height 318 // Determine the relative column position of the Q of the infrastructure height
330 final QPosition qPos = wst.getQPosition(infrastructure.getStation().doubleValue(), q); 319 final QPosition qPos = wst.getQPosition(infrastructure.getStation().doubleValue(), q);
331 if (qPos == null) 320 if (qPos != null) {
332 return; 321 // Get the Q for the found column position for the station of the gauge
333 // Get the Q for the found column position for the station of the gauge 322 final double qGauge = wst.getQ(qPos, gauge.getStation().doubleValue());
334 final double qGauge = wst.getQ(qPos, gauge.getStation().doubleValue()); 323 // Interpolate the Q-D-table of the gauge
335 // Interpolate the Q-D-table of the gauge 324 final double dur = underflowDaysToOverflowDays(durFinders.get(gauge).getDuration(qGauge));
336 final double dur = underflowDaysToOverflowDays(durFinders.get(gauge).getDuration(qGauge)); 325 // Set D in the result row
337 // Set D in the result row 326 row.putValue(SInfoResultType.floodDuration, dur);
338 row.putValue(SInfoResultType.floodDuration, dur); 327 }
339 328 final FloodDurationInfrastructureChoice groupType = new FloodDurationInfrastructureChoice(row);
340 final FloodDurationCalculationResult.Infrastructure groupType = new FloodDurationCalculationResult.Infrastructure(row);
341 infrastructures.add(groupType); 329 infrastructures.add(groupType);
342 } 330 }
343 331
344 /** 332 /**
345 * Translates underflow duration into overflow duration 333 * Translates underflow duration into overflow duration

http://dive4elements.wald.intevation.org