gernotbelger@8915: /** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde gernotbelger@8915: * Software engineering by gernotbelger@8915: * Björnsen Beratende Ingenieure GmbH gernotbelger@8915: * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt gernotbelger@8915: * gernotbelger@8915: * This file is Free Software under the GNU AGPL (>=v3) gernotbelger@8915: * and comes with ABSOLUTELY NO WARRANTY! Check out the gernotbelger@8915: * documentation coming with Dive4Elements River for details. gernotbelger@8915: */ gernotbelger@9499: package org.dive4elements.river.artifacts.model.river; gernotbelger@8915: gernotbelger@8915: import java.util.List; gernotbelger@8915: gernotbelger@8915: import org.apache.commons.lang.math.DoubleRange; gernotbelger@8915: import org.dive4elements.artifacts.CallContext; gernotbelger@8915: import org.dive4elements.river.artifacts.model.LocationProvider; gernotbelger@8915: import org.dive4elements.river.artifacts.model.WKms; gernotbelger@8915: import org.dive4elements.river.artifacts.resources.Resources; gernotbelger@8915: import org.dive4elements.river.artifacts.states.WaterlevelData; gernotbelger@8915: import org.dive4elements.river.model.Gauge; gernotbelger@8915: import org.dive4elements.river.model.River; gernotbelger@8915: import org.dive4elements.river.utils.GaugeIndex; gernotbelger@8915: gernotbelger@8915: /** gernotbelger@8915: * @author Gernot Belger gernotbelger@8915: * gernotbelger@8915: */ gernotbelger@8915: public final class RiverInfoProvider { gernotbelger@8915: gernotbelger@8915: private static final String CSV_NOT_IN_GAUGE_RANGE = "export.waterlevel.csv.not.in.gauge.range"; gernotbelger@8915: gernotbelger@8915: private final River river; gernotbelger@8915: private final GaugeIndex gaugeIndex; gernotbelger@8915: private final Gauge refGauge; gernotbelger@8915: private final boolean showAllGauges; gernotbelger@8915: private final String notinrange; gernotbelger@8915: gernotbelger@8915: public static RiverInfoProvider forRange(final CallContext context, final River river, final DoubleRange calcRange) { gernotbelger@8915: gernotbelger@9499: final List gauges; gernotbelger@9499: if (calcRange == null) gernotbelger@9499: gauges = river.getGauges(); mschaefer@9528: else gernotbelger@9499: gauges = river.determineGauges(calcRange.getMinimumDouble(), calcRange.getMaximumDouble()); gernotbelger@9499: gernotbelger@8915: final GaugeIndex gaugeIndex = new GaugeIndex(gauges); gernotbelger@8915: gernotbelger@8915: final String notinrange = Resources.getMsg(context.getMeta(), CSV_NOT_IN_GAUGE_RANGE, CSV_NOT_IN_GAUGE_RANGE); gernotbelger@8915: gernotbelger@8915: return new RiverInfoProvider(notinrange, river, false, gaugeIndex, null); gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: private RiverInfoProvider(final String notinrange, final River river, final boolean showAllGauges, final GaugeIndex gaugeIndex, final Gauge refGauge) { gernotbelger@8915: this.notinrange = notinrange; gernotbelger@8915: this.river = river; gernotbelger@8915: this.showAllGauges = showAllGauges; gernotbelger@8915: this.gaugeIndex = gaugeIndex; gernotbelger@8915: this.refGauge = refGauge; gernotbelger@8915: } gernotbelger@8915: mschaefer@9528: /** mschaefer@9528: * Creates a new provider as a copy of this one, re-determining the reference gauge by a waterlevel mschaefer@9528: */ gernotbelger@8915: public RiverInfoProvider forWaterlevel(final WaterlevelData waterlevel) { gernotbelger@8915: final WKms wstKms = waterlevel.getWkms(); gernotbelger@8915: final Gauge waterlevelRefGauge = findReferenceGauge(wstKms); gernotbelger@8915: final boolean waterlevelShowAllGauges = waterlevel.isShowAllGauges(); gernotbelger@8915: gernotbelger@8915: return new RiverInfoProvider(this.notinrange, this.river, waterlevelShowAllGauges, this.gaugeIndex, waterlevelRefGauge); gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: /** mschaefer@9528: * Create a new provider as a copy of this one, re-determining the reference gauge by the upstream side of a range mschaefer@9528: */ mschaefer@9528: public RiverInfoProvider forReferenceRange(final DoubleRange range, final boolean isShowAllGauges) { mschaefer@9528: final Gauge kmRefGauge = findReferenceGauge(range); mschaefer@9528: return new RiverInfoProvider(this.notinrange, this.river, isShowAllGauges, this.gaugeIndex, kmRefGauge); mschaefer@9528: } mschaefer@9528: mschaefer@9528: /** mschaefer@9528: * Determines the reference gauge, in the same way as the WaterlevelArtifact would do it gernotbelger@8915: */ gernotbelger@8915: private Gauge findReferenceGauge(final WKms wkms) { gernotbelger@8915: gernotbelger@8915: final double[] wstFromTo = findWstFromTo(wkms); gernotbelger@8915: return this.river.determineRefGauge(wstFromTo, true); gernotbelger@8915: } gernotbelger@8915: mschaefer@9528: /** mschaefer@9528: * Determines the reference gauge for a km range of the active river mschaefer@9528: */ mschaefer@9528: private Gauge findReferenceGauge(final DoubleRange range) { mschaefer@9528: mschaefer@9528: final double from = range.getMinimumDouble(); mschaefer@9528: final double to = range.getMaximumDouble(); mschaefer@9528: final boolean waterIncreasing = this.river.getKmUp(); mschaefer@9528: final double[] wstFromTo = waterIncreasing ? new double[] { to, from } : new double[] { from, to }; mschaefer@9528: return this.river.determineRefGauge(wstFromTo, true); mschaefer@9528: } mschaefer@9528: gernotbelger@8915: private static double[] findWstFromTo(final WKms wkms) { gernotbelger@8915: gernotbelger@8915: final double from = wkms.getKm(0); gernotbelger@8915: final double to = wkms.getKm(wkms.size() - 1); gernotbelger@8915: gernotbelger@8915: final boolean waterIncreasing = wkms.guessWaterIncreasing(); gernotbelger@8915: if (waterIncreasing) gernotbelger@8915: return new double[] { to, from }; gernotbelger@8915: gernotbelger@8915: return new double[] { from, to }; gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: public String getLocation(final double km) { gernotbelger@8915: return LocationProvider.getLocation(this.river.getName(), km); gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: public String findGauge(final double km) { gernotbelger@8915: // REMARK: access the gauge once only during calculation gernotbelger@8915: final Gauge gauge = getGauge(km); gernotbelger@8915: gernotbelger@8915: return gauge == null ? this.notinrange : gauge.getName(); gernotbelger@8915: } gernotbelger@8915: mschaefer@9397: public Gauge getGauge(final double km) { gernotbelger@8915: gernotbelger@8915: // REMARK: using same logic as in WaterlevelExporter here gernotbelger@8915: mschaefer@9158: return getGauge(km, this.showAllGauges); mschaefer@9158: } mschaefer@9158: mschaefer@9158: public Gauge getGauge(final double km, final boolean allGauges) { mschaefer@9158: if (allGauges) gernotbelger@8915: return this.gaugeIndex.findGauge(km); gernotbelger@8915: mschaefer@9018: if ((this.refGauge != null) && this.refGauge.getRange().contains(km)) gernotbelger@8915: return this.refGauge; gernotbelger@8915: gernotbelger@8915: return null; gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: public String getReferenceGauge() { gernotbelger@8915: return this.refGauge == null ? this.notinrange : this.refGauge.getName(); gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: public River getRiver() { gernotbelger@8915: return this.river; gernotbelger@8915: } mschaefer@9295: mschaefer@9295: public List getGauges() { mschaefer@9295: return this.gaugeIndex.getGauges(); mschaefer@9295: } gernotbelger@8915: }