Mercurial > dive4elements > river
diff artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java @ 9259:66b003701546
Added infrastructure height and Q annotation to S-Info flood duration curve chart
author | mschaefer |
---|---|
date | Mon, 16 Jul 2018 08:43:07 +0200 |
parents | ef7b65576d4b |
children | e5367900dd6d |
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java Mon Jul 16 08:41:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java Mon Jul 16 08:43:07 2018 +0200 @@ -10,7 +10,6 @@ package org.dive4elements.river.artifacts.sinfo.flood_duration; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -27,13 +26,13 @@ import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.model.WQDay; import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.sinfo.common.GaugeDurationValuesFinder; import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider; import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType; import org.dive4elements.river.artifacts.sinfo.common.WQBaseTableFinder; import org.dive4elements.river.artifacts.sinfo.flood_duration.RiversideRadioChoice.RiversideChoiceKey; import org.dive4elements.river.exports.WaterlevelDescriptionBuilder; -import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StickyAxisAnnotation; import org.dive4elements.river.jfree.StickyAxisAnnotation.SimpleAxis; import org.dive4elements.river.model.Attribute.AttributeKey; @@ -50,7 +49,7 @@ */ final class FloodDurationCalculator { - private final Collection<ResultRow> rows = new ArrayList<>(); + private final List<ResultRow> rows = new ArrayList<>(); private final RiverInfoProvider riverInfoProvider; @@ -95,19 +94,16 @@ final WQKms[] wqkmsArray = calculateWaterlevels(winfo, stationsSorted, problems); // Determine discharge state labels of the main values - final WaterlevelDescriptionBuilder wdescBuilder = new WaterlevelDescriptionBuilder(winfo, this.context); - final String[] mainValueLabels = findMainValueLabels(wqkmsArray, winfo.getQs(), wdescBuilder, problems); + updateMainValueLabels(wqkmsArray, winfo, problems); // Create a finder for Q in the {river}.wst km-w-q table final WQBaseTableFinder wqFinder = WQBaseTableFinder.loadValues(this.riverInfoProvider.getRiver(), calcRange.getMinimumDouble(), calcRange.getMaximumDouble(), problems); - final WaterlevelDescriptionBuilder descBuilder = new WaterlevelDescriptionBuilder(winfo, this.context); - // Calculate the durations and create the result rows for (int i = 0; i <= stationsSorted.length - 1; i++) { final Gauge gauge = this.riverInfoProvider.getGauge(stationsSorted[i], true); - final ResultRow row = createRow(descBuilder, stationsSorted[i], gauge, firstGauge, wqkmsArray, durFinders.get(gauge), i); + final ResultRow row = createRow(stationsSorted[i], gauge, firstGauge, wqkmsArray, durFinders.get(gauge), i); if (allStations.containsKey(stationsSorted[i]) && (allStations.get(stationsSorted[i]) != null)) calculateInfrastructure(row, gauge, allStations.get(stationsSorted[i]), wqFinder, durFinders); this.rows.add(row); @@ -117,10 +113,16 @@ this.rows.add(row2); } } + final String[] mainValueLabels = new String[wqkmsArray.length]; + for (int i = 0; i <= wqkmsArray.length - 1; i++) + mainValueLabels[i] = wqkmsArray[i].getName(); results.addResult(new FloodDurationCalculationResult(label, mainValueLabels, this.rows), problems); + calcWQDays(problems, stationsSorted[0], AttributeKey.LEFT, winfo, results); - calcMainValueAnnotations(label, problems, 0, AttributeKey.LEFT, wqkmsArray, mainValueLabels, results); - // TODO Infrastrukturhoehe + + calcMainValueAnnotations(problems, 0, AttributeKey.LEFT, wqkmsArray, results); + + calcInfrastructureAnnotations(problems, this.rows.get(0), wqkmsArray, results); } /** @@ -149,42 +151,56 @@ /** * Calculate the data for the W and Q main value lines in the duration curve chart and add to result collection */ - private void calcMainValueAnnotations(final String label, final Calculation problems, final int stationIndex, final AttributeKey riverside, - final WQKms[] wqkmsArray, final String[] mainValueLabels, final FloodDurationCalculationResults results) { + private void calcMainValueAnnotations(final Calculation problems, final int stationIndex, final AttributeKey riverside, + final WQKms[] wqkmsArray, final FloodDurationCalculationResults results) { - // Same way as in MainValueWFacet and ..QFacet + // Same way as in MainValueWFacet and ..QFacet, but special label handling final List<StickyAxisAnnotation> ws = new ArrayList<>(); final List<StickyAxisAnnotation> qs = new ArrayList<>(); for (int i = 0; i <= wqkmsArray.length - 1; i++) { - final StickyAxisAnnotation qAnnotation = new StickyAxisAnnotation(mainValueLabels[i], (float) wqkmsArray[i].getQ(stationIndex), SimpleAxis.Y_AXIS, + final String qLabel = wqkmsArray[i].getName().startsWith("W=") ? "Q(" + wqkmsArray[i].getName() + ")" : wqkmsArray[i].getName(); + final StickyAxisAnnotation qAnnotation = new StickyAxisAnnotation(qLabel, (float) wqkmsArray[i].getQ(stationIndex), SimpleAxis.Y_AXIS, FloodDurationCurveGenerator.YAXIS.Q.idx); qs.add(qAnnotation); - setHitPoint((WQDay) results.getDurationCurve().getData(), qAnnotation); - final StickyAxisAnnotation wAnnotation = new StickyAxisAnnotation(mainValueLabels[i], (float) wqkmsArray[i].getW(stationIndex), SimpleAxis.Y_AXIS, + FloodDurationMainValuesQFacet.setHitPoint((WQDay) results.getDurationCurve().getData(), qAnnotation); + final String wLabel = !wqkmsArray[i].getName().startsWith("W=") ? "W(" + wqkmsArray[i].getName() + ")" : wqkmsArray[i].getName(); + final StickyAxisAnnotation wAnnotation = new StickyAxisAnnotation(wLabel, (float) wqkmsArray[i].getW(stationIndex), SimpleAxis.Y_AXIS, FloodDurationCurveGenerator.YAXIS.W.idx); ws.add(wAnnotation); - setHitPoint((WQDay) results.getDurationCurve().getData(), wAnnotation); + FloodDurationMainValuesWFacet.setHitPoint((WQDay) results.getDurationCurve().getData(), wAnnotation); } - // TODO RiverAnnotation ersetzen weil das eine NotSerializableException erzeugt - results.setMainValueQAnnotation(new RiverAnnotation(label, qs)); - results.setMainValueWAnnotation(new RiverAnnotation(label, ws)); + results.getMainValueQAnnotations().clear(); + results.getMainValueQAnnotations().addAll(qs); + results.getMainValueWAnnotations().clear(); + results.getMainValueWAnnotations().addAll(ws); } /** - * Set the hit-point in Q where a line drawn from the axis would hit the - * curve in WQDay (if hit). - * Employ linear interpolation. + * Calculate the data for the W and Q lines in the duration curve chart for the infrastructure height and add to result + * collection */ - private static void setHitPoint(final WQDay wqday, final StickyAxisAnnotation annotation) { + private void calcInfrastructureAnnotations(final Calculation problems, final ResultRow row, final WQKms[] wqkmsArray, + final FloodDurationCalculationResults results) { - final float q = annotation.getPos(); - final Double day = wqday.interpolateDayByQ(q); - if (day != null) { - annotation.setHitPoint(day.floatValue()); + if (row.getValue(SInfoResultType.infrastructuretype) == null) { + results.setInfrastructureWAnnotation(null); + results.setInfrastructureQAnnotation(null); + return; } - // else if (log.isDebugEnabled()) { - // log.debug("StickyAnnotation does not hit wqday curve: " + q); - // } + // Same way as in MainValueWFacet and ..QFacet + final String label = Resources.getMsg(this.context.getMeta(), "sinfo.chart.flood_duration.curve.infrastructure", + "sinfo.chart.flood_duration.curve.infrastructure", + SInfoResultType.infrastructuretype.exportValue(this.context, row.getValue(SInfoResultType.infrastructuretype)) + + ", " + SInfoResultType.riverside.exportValue(this.context, row.getValue(SInfoResultType.riverside))); + final StickyAxisAnnotation qAnnotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.floodDischarge), + SimpleAxis.Y_AXIS, FloodDurationCurveGenerator.YAXIS.Q.idx); + FloodDurationMainValuesQFacet.setHitPoint((WQDay) results.getDurationCurve().getData(), qAnnotation); + final StickyAxisAnnotation wAnnotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.infrastructureHeight), + SimpleAxis.Y_AXIS, FloodDurationCurveGenerator.YAXIS.W.idx); + FloodDurationMainValuesWFacet.setHitPoint((WQDay) results.getDurationCurve().getData(), wAnnotation); + + results.setInfrastructureQAnnotation(qAnnotation); + results.setInfrastructureWAnnotation(wAnnotation); } /** @@ -262,24 +278,38 @@ } /** - * Determines the waterlevel/discharge state labels for the selected Q or W values + * Determines the waterlevel/discharge state labels for the selected Q or W values and sets them in the WQKms array */ - private String[] findMainValueLabels(final WQKms[] wqkmsArray, final double[] qs, final WaterlevelDescriptionBuilder descBuilder, - final Calculation problems) { + private void updateMainValueLabels(final WQKms[] wqkmsArray, final WINFOArtifact winfo, final Calculation problems) { - final String[] mainValueLabels = new String[wqkmsArray.length]; for (int i = 0; i <= wqkmsArray.length - 1; i++) - mainValueLabels[i] = descBuilder.getDesc(wqkmsArray[i]); - return mainValueLabels; + wqkmsArray[i].setName(buildWQDescription(wqkmsArray[i], winfo)); + } + + /** + * + * @param wqkms + * @param descBuilder + * @return + */ + private String buildWQDescription(final WQKms wqkms, final WINFOArtifact winfo) { + final WaterlevelDescriptionBuilder descBuilder = new WaterlevelDescriptionBuilder(winfo, this.context); + final String description = descBuilder.getDesc(wqkms); + if (!description.isEmpty() && Character.isDigit(description.charAt(0))) { + if (winfo.isQ()) + return "Q=" + description; + else + return "W=" + description; + } + else + return description; } /** * Create a result row for a station and its gauge, and add w-q-values as selected - * - * @param descBuilder */ - private ResultRow createRow(final WaterlevelDescriptionBuilder descBuilder, final Double station, final Gauge gauge, final Gauge firstGauge, - final WQKms[] wqkmsArray, final GaugeDurationValuesFinder durationFinder, final int kmIndex) { + private ResultRow createRow(final Double station, final Gauge gauge, final Gauge firstGauge, final WQKms[] wqkmsArray, + final GaugeDurationValuesFinder durationFinder, final int kmIndex) { final ResultRow row = ResultRow.create(); row.putValue(GeneralResultType.station, station); @@ -294,14 +324,12 @@ final List<DurationWaterlevel> waterlevels = new ArrayList<>(wqkmsArray.length); - for (final WQKms wqKm : wqkmsArray) { - assert (wqKm.getKm(kmIndex) == station.doubleValue()); + for (final WQKms wqKms : wqkmsArray) { + assert (wqKms.getKm(kmIndex) == station.doubleValue()); - final int overflowDays = (int) Math.round(underflowDaysToOverflowDays(durationFinder.getDuration(wqKm.getQ(kmIndex)))); + final int overflowDays = (int) Math.round(underflowDaysToOverflowDays(durationFinder.getDuration(wqKms.getQ(kmIndex)))); - final String waterlevelLabel = descBuilder.getDesc(wqKm); - - final DurationWaterlevel dw = new DurationWaterlevel(wqKm.getW(kmIndex), overflowDays, wqKm.getQ(kmIndex), waterlevelLabel); + final DurationWaterlevel dw = new DurationWaterlevel(wqKms.getW(kmIndex), overflowDays, wqKms.getQ(kmIndex), wqKms.getName()); waterlevels.add(dw); } row.putValue(SInfoResultType.customMultiRowColWaterlevel, waterlevels);