changeset 9295:385b52ccde23

Work on U-Info salix line calculation and chart (no scenario case)
author mschaefer
date Tue, 24 Jul 2018 18:51:47 +0200
parents 7a8b9331a946
children 77f24792d75f
files artifacts/doc/conf/artifacts/uinfo.xml artifacts/doc/conf/themes.xml artifacts/doc/conf/themes/default.xml artifacts/doc/conf/themes/second.xml artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/RiverInfoProvider.java artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineProcessor.java artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineResultFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineState.java artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixMnwMwResultFacet.java artifacts/src/main/java/org/dive4elements/river/utils/GaugeIndex.java artifacts/src/main/resources/messages.properties artifacts/src/main/resources/messages_de.properties gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties
diffstat 18 files changed, 553 insertions(+), 105 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/doc/conf/artifacts/uinfo.xml	Tue Jul 24 16:55:43 2018 +0200
+++ b/artifacts/doc/conf/artifacts/uinfo.xml	Tue Jul 24 18:51:47 2018 +0200
@@ -169,6 +169,12 @@
 
     <state id="state.uinfo.salix_line" description="state.uinfo.salix_line" state="org.dive4elements.river.artifacts.uinfo.salix.SalixLineState" helpText="help.state.uinfo.salix_line">
       <outputmodes>
+        <outputmode name="uinfo_salix_line" description="output.uinfo_salix_line" mime-type="image/png" type="chart">
+          <facets>
+            <facet name="uinfo_facet_salix" description="salix line"/>
+            <facet name="uinfo_facet_mnwmw" description="mnw-mw differences"/>
+          </facets>
+        </outputmode>
 
         <!-- FIXME: i01n name in FLYSConstants -->
         <outputmode name="uinfo_salix_line_export" description="output.uinfo_salix_line_export" mime-type="text/plain" type="export">
--- a/artifacts/doc/conf/themes.xml	Tue Jul 24 16:55:43 2018 +0200
+++ b/artifacts/doc/conf/themes.xml	Tue Jul 24 18:51:47 2018 +0200
@@ -471,5 +471,10 @@
         <mapping from="sinfo_tkk.manualpoints" to="ManualPoints" />
         <mapping from="sinfo_collision.manualpoints" to="ManualPoints" />
         <mapping from="sinfo_flood_duration.manualpoints" to="ManualPoints" />
+        
+        <mapping from="uinfo_facet_salix_line" to="UInfoSalixLine" />
+        <mapping from="uinfo_facet_salix_mnwmw" to="UInfoSalixMnwMw" />
+        
+        <mapping from="uinfo_salix_line.manualpoints" to="ManualPoints" />
     </mappings>
 </themes>
\ No newline at end of file
--- a/artifacts/doc/conf/themes/default.xml	Tue Jul 24 16:55:43 2018 +0200
+++ b/artifacts/doc/conf/themes/default.xml	Tue Jul 24 18:51:47 2018 +0200
@@ -2913,4 +2913,20 @@
       <field name="showlinelabel" type="boolean" display="Linienbeschriftung anzeigen" default="true" hints="hidden" />
     </fields>
   </theme>
+  <theme name="UInfoSalixLine">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 64" />
+    </fields>
+  </theme>
+  <theme name="UInfoSalixMnwMw">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 64, 255" />
+    </fields>
+  </theme>
 </themegroup>
\ No newline at end of file
--- a/artifacts/doc/conf/themes/second.xml	Tue Jul 24 16:55:43 2018 +0200
+++ b/artifacts/doc/conf/themes/second.xml	Tue Jul 24 18:51:47 2018 +0200
@@ -2901,4 +2901,20 @@
       <field name="showlinelabel" type="boolean" display="Linienbeschriftung anzeigen" default="true" hints="hidden" />
     </fields>
   </theme>
+  <theme name="UInfoSalixLine">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 128, 64" />
+    </fields>
+  </theme>
+  <theme name="UInfoSalixMnwMw">
+    <inherits>
+      <inherit from="LongitudinalSectionW" />
+    </inherits>
+    <fields>
+      <field name="linecolor" type="Color" display="Linienfarbe" default="0, 64, 255" />
+    </fields>
+  </theme>
 </themegroup>
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java	Tue Jul 24 16:55:43 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java	Tue Jul 24 18:51:47 2018 +0200
@@ -148,7 +148,8 @@
         SFDUR("sinfo_flood_duration"), //
         STKH("sinfo_tkk"), //
         SFW("sinfo_flood_height"), //
-        SFDC("sinfo_floodduration_curve");
+        SFDC("sinfo_floodduration_curve"), //
+        USL("uinfo_salix_line");
 
         private final String chartTypeString;
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/RiverInfoProvider.java	Tue Jul 24 16:55:43 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/RiverInfoProvider.java	Tue Jul 24 18:51:47 2018 +0200
@@ -124,4 +124,8 @@
     public River getRiver() {
         return this.river;
     }
+
+    public List<Gauge> getGauges() {
+        return this.gaugeIndex.getGauges();
+    }
 }
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java	Tue Jul 24 16:55:43 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java	Tue Jul 24 18:51:47 2018 +0200
@@ -9,24 +9,18 @@
  */
 package org.dive4elements.river.artifacts.uinfo.salix;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.lang.math.DoubleRange;
 import org.dive4elements.artifacts.CallContext;
-import org.dive4elements.river.artifacts.common.GeneralResultType;
-import org.dive4elements.river.artifacts.common.ResultRow;
 import org.dive4elements.river.artifacts.model.Calculation;
 import org.dive4elements.river.artifacts.model.CalculationResult;
 import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
 import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
-import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType;
 import org.dive4elements.river.model.River;
 
 /**
@@ -65,83 +59,89 @@
         // use_scenario (boolean)
         // ld_from_part; ld_to_part
         // scenario_selection (mögliche Werte:"scenarioType.option1" "scenarioType.option2" "scenarioType.option3"
+        final RiverInfoProvider riverInfoProvider = RiverInfoProvider.forRange(this.context, river, range);
 
         // FIXME: real calculation
 
         final SalixLineCalculationResults results = new SalixLineCalculationResults(calcModeLabel, user, riverInfo, range);
 
-        final Collection<ResultRow> rows = new ArrayList<>();
-        SalixLineCalculationNoScenarioResult result = null; // verzweigung etwas ungünstig. möglicherweise auch die Abstraktion. ist erstmal nur ne idee
-        final ResultRow row1 = ResultRow.create(). //
-                putValue(GeneralResultType.station, 100).//
-                putValue(UInfoResultType.salixline, 28).//
-                putValue(UInfoResultType.salix_delta_mw, 2);
-
-        if (!useScenario) {
-
-            rows.add(row1);
-            result = new SalixLineCalculationNoScenarioResult("Ergebnis 1", null, rows);
-        } else {
-
-            if (scenario.equals("scenarioType.option1")) { // REGIONAL
-
-                final int[] scenarios = accessSalix.getRegionalScenarioIntegers();
-                final List<SalixScenario> list = new ArrayList<>();
-                for (final int scen_val : scenarios) {
-                    list.add(new SalixScenario(scen_val, 666.));// TODO: replace 666 by real calculated value
-                }
-                row1.putValue(UInfoResultType.customMultiRowColSalixRegionalValue_Dwspl, list);//
-                rows.add(row1);
-                result = new SalixLineCalculationRegionalResult("Ergebnis 1 regional test", null, rows, scenarios);
-
-            } else if (scenario.equals("scenarioType.option2")) { // SUPRA-REGIONAL
-
-                final String supraRegional = accessSalix.getSupraRegionalString();
-                final List<SalixZone> list = SalixZone.parse(supraRegional);
-
-                final Map<DoubleRange, SalixScenario> rangeScenarioMap = new HashMap<>();
-                // make double range
-                for (int i = 0; i < list.size(); i++) {
-                    final SalixZone zone = list.get(i);
-                    final double upper = i < list.size() - 1 ? (zone.getUpperFromTo() - 0.0001) : zone.getUpperFromTo() + 0.0001;// "halboffenes Intervall
+        final SalixLineCalculator calculator = new SalixLineCalculator(this.context, riverInfoProvider);
+        calculator.execute(problems, uinfo, results);
 
-                    final DoubleRange zonerange = new DoubleRange((double) zone.getLowerFromTo(), upper);
-                    final double salixValue = 666.;// TODO: calculate the salix value
-                    final SalixScenario salixscen = new SalixScenario(zone.getDwsplValue(), salixValue);
-
-                    rangeScenarioMap.put(zonerange, salixscen);
-                }
-
-                // make calculation
-                double currentKm = range.getMinimumDouble();
-                final double step = 0.1; // TODO: get from global setting?
-                while (currentKm < range.getMaximumDouble()) {
-                    final ResultRow rowSupraRegional = ResultRow.create(). //
-                            putValue(GeneralResultType.station, currentKm).//
-                            putValue(UInfoResultType.salixline, 28).//
-                            putValue(UInfoResultType.salix_delta_mw, 2);
-
-                    final SalixScenario scenarioCurrentKm = findScenarioByKm(currentKm, rangeScenarioMap);
-
-                    if (scenarioCurrentKm != null) { // should not happen, scenarioCurrentKm == null -> BUG
-                        rowSupraRegional.putValue(UInfoResultType.salix_line_scenario, scenarioCurrentKm.getSalixValue());
-                        rowSupraRegional.putValue(UInfoResultType.salix_line_scenario_dwspl, scenarioCurrentKm.getDwspl());
-                    }
-                    rows.add(rowSupraRegional);
-
-                    currentKm = currentKm + step;
-                }
-
-                result = new SalixLineCalculationSupraRegionalResult("Ergebnis 1 supra regional test", null, rows);
-
-            } else if (scenario.equals("scenarioType.option3")) { // HISTORICAL
-                row1.putValue(UInfoResultType.salixlinehist, 66).//
-                        putValue(UInfoResultType.salix_line_scenario_dwspl, 88);
-                rows.add(row1);
-                result = new SalixLineCalculationHistoricalResult("Ergebnis 1 historical test", null, rows);
-            }
-        }
-        results.addResult(result, problems);
+        // final Collection<ResultRow> rows = new ArrayList<>();
+        // SalixLineCalculationNoScenarioResult result = null; // verzweigung etwas ungünstig. möglicherweise auch die
+        // Abstraktion. ist erstmal nur ne idee
+        // final ResultRow row1 = ResultRow.create(). //
+        // putValue(GeneralResultType.station, 100).//
+        // putValue(UInfoResultType.salixline, 28).//
+        // putValue(UInfoResultType.salix_delta_mw, 2);
+        //
+        // if (!useScenario) {
+        //
+        // rows.add(row1);
+        // result = new SalixLineCalculationNoScenarioResult("Ergebnis 1", null, rows);
+        // } else {
+        //
+        // if (scenario.equals("scenarioType.option1")) { // REGIONAL
+        //
+        // final int[] scenarios = accessSalix.getRegionalScenarioIntegers();
+        // final List<SalixScenario> list = new ArrayList<>();
+        // for (final int scen_val : scenarios) {
+        // list.add(new SalixScenario(scen_val, 666.));// TODO: replace 666 by real calculated value
+        // }
+        // row1.putValue(UInfoResultType.customMultiRowColSalixRegionalValue_Dwspl, list);//
+        // rows.add(row1);
+        // result = new SalixLineCalculationRegionalResult("Ergebnis 1 regional test", null, rows, scenarios);
+        //
+        // } else if (scenario.equals("scenarioType.option2")) { // SUPRA-REGIONAL
+        //
+        // final String supraRegional = accessSalix.getSupraRegionalString();
+        // final List<SalixZone> list = SalixZone.parse(supraRegional);
+        //
+        // final Map<DoubleRange, SalixScenario> rangeScenarioMap = new HashMap<>();
+        // // make double range
+        // for (int i = 0; i < list.size(); i++) {
+        // final SalixZone zone = list.get(i);
+        // final double upper = i < list.size() - 1 ? (zone.getUpperFromTo() - 0.0001) : zone.getUpperFromTo() + 0.0001;//
+        // "halboffenes Intervall
+        //
+        // final DoubleRange zonerange = new DoubleRange((double) zone.getLowerFromTo(), upper);
+        // final double salixValue = 666.;// TODO: calculate the salix value
+        // final SalixScenario salixscen = new SalixScenario(zone.getDwsplValue(), salixValue);
+        //
+        // rangeScenarioMap.put(zonerange, salixscen);
+        // }
+        //
+        // // make calculation
+        // double currentKm = range.getMinimumDouble();
+        // final double step = 0.1; // TODO: get from global setting?
+        // while (currentKm < range.getMaximumDouble()) {
+        // final ResultRow rowSupraRegional = ResultRow.create(). //
+        // putValue(GeneralResultType.station, currentKm).//
+        // putValue(UInfoResultType.salixline, 28).//
+        // putValue(UInfoResultType.salix_delta_mw, 2);
+        //
+        // final SalixScenario scenarioCurrentKm = findScenarioByKm(currentKm, rangeScenarioMap);
+        //
+        // if (scenarioCurrentKm != null) { // should not happen, scenarioCurrentKm == null -> BUG
+        // rowSupraRegional.putValue(UInfoResultType.salix_line_scenario, scenarioCurrentKm.getSalixValue());
+        // rowSupraRegional.putValue(UInfoResultType.salix_line_scenario_dwspl, scenarioCurrentKm.getDwspl());
+        // }
+        // rows.add(rowSupraRegional);
+        //
+        // currentKm = currentKm + step;
+        // }
+        //
+        // result = new SalixLineCalculationSupraRegionalResult("Ergebnis 1 supra regional test", null, rows);
+        //
+        // } else if (scenario.equals("scenarioType.option3")) { // HISTORICAL
+        // row1.putValue(UInfoResultType.salixlinehist, 66).//
+        // putValue(UInfoResultType.salix_line_scenario_dwspl, 88);
+        // rows.add(row1);
+        // result = new SalixLineCalculationHistoricalResult("Ergebnis 1 historical test", null, rows);
+        // }
+        // }
+        // results.addResult(result, problems);
         return new CalculationResult(results, problems);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java	Tue Jul 24 18:51:47 2018 +0200
@@ -0,0 +1,153 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+package org.dive4elements.river.artifacts.uinfo.salix;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.WINFOArtifact;
+import org.dive4elements.river.artifacts.access.ComputationRangeAccess;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.WstValueTable;
+import org.dive4elements.river.artifacts.model.WstValueTable.QPosition;
+import org.dive4elements.river.artifacts.model.WstValueTableFactory;
+import org.dive4elements.river.artifacts.sinfo.common.GaugeDischargeValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.WinfoArtifactWrapper;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.MainValue;
+import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
+
+/**
+ * Calculation of the result rows of the u-info salix line calc mode
+ *
+ * @author Matthias Schäfer
+ */
+public class SalixLineCalculator {
+
+    private final List<ResultRow> rows = new ArrayList<>();
+
+    private final RiverInfoProvider riverInfoProvider;
+
+    private final CallContext context;
+
+    private final Map<Gauge, QPosition> gaugeMwPos;
+    private final Map<Gauge, QPosition> gaugeMnwPos;
+    private final Map<Gauge, QPosition> gaugeMhwPos;
+
+    private Calculation problems;
+
+    private WstValueTable wst;
+
+    public SalixLineCalculator(final CallContext context, final RiverInfoProvider riverInfoProvider) {
+        this.context = context;
+        this.riverInfoProvider = riverInfoProvider;
+        this.gaugeMwPos = new HashMap<>();
+        this.gaugeMnwPos = new HashMap<>();
+        this.gaugeMhwPos = new HashMap<>();
+    }
+
+
+    /**
+     * Calculate the salix line result rows
+     */
+    public void execute(final Calculation problems, final UINFOArtifact uinfo, final SalixLineCalculationResults results) {
+
+        this.problems = problems;
+        this.wst = WstValueTableFactory.getTable(this.riverInfoProvider.getRiver());
+
+        fetchGaugeMainValuePositions();
+
+        final WINFOArtifact winfo = new WinfoArtifactWrapper(uinfo);
+        winfo.addStringData("ld_mode", "distance");
+        winfo.addStringData("ld_step", "100");
+        for (final double station : new ComputationRangeAccess(winfo).getKms()) {
+            this.rows.add(createRow(station));
+        }
+        results.addResult(new SalixLineCalculationNoScenarioResult("Salix", null, this.rows), problems);
+    }
+
+    /**
+     * Fetch MW, MNW and MHW of all gauges and determine the wst QPosition for each one
+     */
+    private void fetchGaugeMainValuePositions() {
+        this.gaugeMwPos.clear();
+        this.gaugeMnwPos.clear();
+        this.gaugeMhwPos.clear();
+        for (final Gauge gauge : this.riverInfoProvider.getGauges()) {
+            this.gaugeMwPos.put(gauge, null);
+            this.gaugeMnwPos.put(gauge, null);
+            this.gaugeMhwPos.put(gauge, null);
+            final GaugeDischargeValuesFinder finder = GaugeDischargeValuesFinder.loadValues(gauge, this.problems);
+            if (finder == null)
+                continue;
+            final double gaugeKm = gauge.getStation().doubleValue();
+            for (final MainValue mv : MainValue.getValuesOfGaugeAndType(gauge, MainValueTypeKey.W)) {
+                if (mv.getMainValue().getName().equalsIgnoreCase("mw"))
+                    this.gaugeMwPos.put(gauge, this.wst.getQPosition(gaugeKm, finder.getDischarge(mv.getValue().doubleValue())));
+                else if (mv.getMainValue().getName().equalsIgnoreCase("mnw"))
+                    this.gaugeMnwPos.put(gauge, this.wst.getQPosition(gaugeKm, finder.getDischarge(mv.getValue().doubleValue())));
+                else if (mv.getMainValue().getName().equalsIgnoreCase("mhw"))
+                    this.gaugeMhwPos.put(gauge, this.wst.getQPosition(gaugeKm, finder.getDischarge(mv.getValue().doubleValue())));
+            }
+        }
+    }
+
+    /**
+     * Create a result row for a station and its gauge, and add w-q-values as selected
+     */
+    private ResultRow createRow(final double station) {
+
+        final ResultRow row = ResultRow.create();
+        final Gauge gauge = this.riverInfoProvider.getGauge(station, true);
+        row.putValue(GeneralResultType.station, station);
+        final double mnw = interpolateW(station, this.gaugeMnwPos.get(gauge));
+        final double mw = interpolateW(station, this.gaugeMwPos.get(gauge));
+        final double mhw = interpolateW(station, this.gaugeMhwPos.get(gauge));
+        row.putValue(SInfoResultType.waterlevel, mnw);
+        row.putValue(SInfoResultType.waterlevel1, mw);
+        row.putValue(SInfoResultType.waterlevel2, mhw);
+        row.putValue(UInfoResultType.salixline, calcSalix(mhw, mw));
+        row.putValue(UInfoResultType.salix_delta_mw, calcMwmnw(mw, mnw));
+        return row;
+    }
+
+    /**
+     * Interpolates the W for a station with a fixed (virtual) wst column position
+     */
+    private double interpolateW(final double station, final QPosition qPosition) {
+        if (qPosition != null)
+            return this.wst.interpolateW(station, qPosition, this.problems);
+        else
+            return Double.NaN;
+    }
+
+    /**
+     * Calculates the salix value
+     */
+    private double calcSalix(final double mhw, final double mw) {
+        return mhw - 2.31 - mw;
+    }
+
+    /**
+     * Calculates the inverse MW-MNW difference
+     */
+    private double calcMwmnw(final double mw, final double mnw) {
+        return mnw - mw;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineProcessor.java	Tue Jul 24 18:51:47 2018 +0200
@@ -0,0 +1,96 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.artifacts.uinfo.salix;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.exports.StyledSeriesBuilder;
+import org.dive4elements.river.exports.process.DefaultProcessor;
+import org.dive4elements.river.exports.process.WOutProcessor;
+import org.dive4elements.river.jfree.StyledXYSeries;
+import org.dive4elements.river.themes.ThemeDocument;
+import org.dive4elements.river.utils.RiverUtils;
+import org.jfree.data.xy.XYSeries;
+
+/**
+ * Processor to generate the facets and data series of salix line
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public final class SalixLineProcessor extends DefaultProcessor {
+
+    private static final String FACET_SALIX_LINE = "uinfo_facet_salix";
+
+    private static final String FACET_SALIX_MNWMW = "uinfo_facet_mnwmw";
+
+    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();
+
+    static {
+        HANDLED_FACET_TYPES.add(FACET_SALIX_LINE);
+        HANDLED_FACET_TYPES.add(FACET_SALIX_MNWMW);
+    }
+
+    public static Facet createSalixLineFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int facetIndex, final int resultIndex, final String description) {
+
+        return new SalixLineResultFacet(FACET_SALIX_LINE, description);
+    }
+
+    public static Facet createSalixMnwMwFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
+            final int facetIndex, final int resultIndex, final String description) {
+
+        return new SalixMnwMwResultFacet(FACET_SALIX_MNWMW, description);
+    }
+
+    @Override
+    public final String getAxisLabel(final DiagramGenerator generator) {
+
+        final D4EArtifact flys = (D4EArtifact) generator.getMaster();
+        final String unit = RiverUtils.getRiver(flys).getWstUnit().getName();
+        return generator.msg(WOutProcessor.I18N_AXIS_LABEL, WOutProcessor.I18N_AXIS_LABEL_DEFAULT, unit);
+    }
+
+    @Override
+    public final boolean canHandle(final String facettype) {
+        return HANDLED_FACET_TYPES.contains(facettype);
+    }
+
+    @Override
+    public void doOut(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
+
+        // log.debug("Processing facet: " + bundle.getFacetName());
+        final CallContext context = generator.getContext();
+        final Object data = bundle.getData(context);
+
+        final XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
+
+        if (bundle.getFacetName().equals(FACET_SALIX_LINE)) {
+            StyledSeriesBuilder.addPoints(series, ((SalixLineCalculationNoScenarioResult) data).getStationPoints(UInfoResultType.salixline), true);
+            generator.addAxisSeries(series, this.axisName, visible);
+            return;
+        }
+
+        if (bundle.getFacetName().equals(FACET_SALIX_MNWMW)) {
+            StyledSeriesBuilder.addPoints(series, ((SalixLineCalculationNoScenarioResult) data).getStationPoints(UInfoResultType.salix_delta_mw), true);
+            generator.addAxisSeries(series, this.axisName, visible);
+            return;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineResultFacet.java	Tue Jul 24 18:51:47 2018 +0200
@@ -0,0 +1,66 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.artifacts.uinfo.salix;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+
+/**
+ * Facet of the U-Info salix line curve.
+ */
+public class SalixLineResultFacet extends DataFacet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static Logger log = Logger.getLogger(SalixLineResultFacet.class);
+
+    private int resultIndex;
+
+    public SalixLineResultFacet() {
+        // required for clone operation deepCopy()
+    }
+
+    public SalixLineResultFacet(final String name, final String description) {
+        super(name, description);
+    }
+
+    @Override
+    public final Object getData(final Artifact artifact, final CallContext context) {
+
+        log.debug("Get data for result at index: " + this.resultIndex);
+
+        final D4EArtifact flys = (D4EArtifact) artifact;
+
+        final CalculationResult res = (CalculationResult) flys.compute(context, this.hash, this.stateId, this.type, false);
+
+        final AbstractCalculationResults<AbstractCalculationResult> data = (AbstractCalculationResults<AbstractCalculationResult>) res.getData();
+
+        return data.getResults().get(this.resultIndex);
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        // FIXME: why not simply use the full constructor instead?
+        final SalixLineResultFacet copy = new SalixLineResultFacet();
+        // FIXME: why does DataFacet does not override set? Bad access to variables of parent!
+        copy.set(this);
+        copy.type = this.type;
+        copy.hash = this.hash;
+        copy.stateId = this.stateId;
+        return copy;
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineState.java	Tue Jul 24 16:55:43 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineState.java	Tue Jul 24 18:51:47 2018 +0200
@@ -80,6 +80,9 @@
         final List<SalixLineCalculationNoScenarioResult> resultList = results.getResults();
 
         if (!resultList.isEmpty()) {
+            facets.add(SalixLineProcessor.createSalixLineFacet(context, hash, this.id, resultList.get(0), 0, 0, "Salix-Linie"));
+            facets.add(SalixLineProcessor.createSalixMnwMwFacet(context, hash, this.id, resultList.get(0), 0, 0, "MNW-MW"));
+
             final Facet csv = new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id);
             final Facet pdf = new DataFacet(FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, this.id);
 
@@ -95,10 +98,10 @@
         return res;
     }
 
-    private CalculationResult doCompute(final UINFOArtifact sinfo, final CallContext context, final Object old) {
+    private CalculationResult doCompute(final UINFOArtifact uinfo, final CallContext context, final Object old) {
         if (old instanceof CalculationResult)
             return (CalculationResult) old;
 
-        return new SalixLineCalculation(context).calculate(sinfo);
+        return new SalixLineCalculation(context).calculate(uinfo);
     }
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixMnwMwResultFacet.java	Tue Jul 24 18:51:47 2018 +0200
@@ -0,0 +1,66 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.artifacts.uinfo.salix;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.Facet;
+import org.dive4elements.artifacts.Artifact;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.D4EArtifact;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResult;
+import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.DataFacet;
+
+/**
+ * Facet of the U-Info salix line curve.
+ */
+public class SalixMnwMwResultFacet extends DataFacet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static Logger log = Logger.getLogger(SalixMnwMwResultFacet.class);
+
+    private int resultIndex;
+
+    public SalixMnwMwResultFacet() {
+        // required for clone operation deepCopy()
+    }
+
+    public SalixMnwMwResultFacet(final String name, final String description) {
+        super(name, description);
+    }
+
+    @Override
+    public final Object getData(final Artifact artifact, final CallContext context) {
+
+        log.debug("Get data for result at index: " + this.resultIndex);
+
+        final D4EArtifact flys = (D4EArtifact) artifact;
+
+        final CalculationResult res = (CalculationResult) flys.compute(context, this.hash, this.stateId, this.type, false);
+
+        final AbstractCalculationResults<AbstractCalculationResult> data = (AbstractCalculationResults<AbstractCalculationResult>) res.getData();
+
+        return data.getResults().get(this.resultIndex);
+    }
+
+    /** Copy deeply. */
+    @Override
+    public Facet deepCopy() {
+        // FIXME: why not simply use the full constructor instead?
+        final SalixMnwMwResultFacet copy = new SalixMnwMwResultFacet();
+        // FIXME: why does DataFacet does not override set? Bad access to variables of parent!
+        copy.set(this);
+        copy.type = this.type;
+        copy.hash = this.hash;
+        copy.stateId = this.stateId;
+        return copy;
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/utils/GaugeIndex.java	Tue Jul 24 16:55:43 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/utils/GaugeIndex.java	Tue Jul 24 18:51:47 2018 +0200
@@ -1,6 +1,6 @@
 /** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
- * Software engineering by 
- *  Björnsen Beratende Ingenieure GmbH 
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
  *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
  *
  * This file is Free Software under the GNU AGPL (>=v3)
@@ -18,35 +18,39 @@
  * @author Gernot Belger
  */
 public class GaugeIndex {
-	private List<Gauge> gauges;
-	
-	private Gauge lastGauge = null;
-
-	public GaugeIndex( List<Gauge> gauges) {
-		this.gauges = gauges;
-	}
-	
-	public Gauge findGauge(double km) {
+    private final List<Gauge> gauges;
 
-		// REMARK: this is code copied from WaterlevelExporter, which is honestly not very fast/good.
-		// Instead we need to index by range with an RTree and directly acccess the right gauge.
-		
-		if( lastGauge != null && lastGauge.getRange().contains(km) )
-			return lastGauge;
-		
-		final Gauge gauge = findGauge(km, gauges);
+    private Gauge lastGauge = null;
 
-        lastGauge = gauge;
-            
+    public GaugeIndex(final List<Gauge> gauges) {
+        this.gauges = gauges;
+    }
+
+    public Gauge findGauge(final double km) {
+
+        // REMARK: this is code copied from WaterlevelExporter, which is honestly not very fast/good.
+        // Instead we need to index by range with an RTree and directly acccess the right gauge.
+
+        if( this.lastGauge != null && this.lastGauge.getRange().contains(km) )
+            return this.lastGauge;
+
+        final Gauge gauge = findGauge(km, this.gauges);
+
+        this.lastGauge = gauge;
+
         return gauge;
-	}
-	
-    private static Gauge findGauge(double km, List<Gauge> gauges) {
-        for (Gauge gauge: gauges) {
+    }
+
+    private static Gauge findGauge(final double km, final List<Gauge> gauges) {
+        for (final Gauge gauge: gauges) {
             if (gauge.getRange().contains(km)) {
                 return gauge;
             }
         }
         return null;
     }
+
+    public List<Gauge> getGauges() {
+        return this.gauges;
+    }
 }
\ No newline at end of file
--- a/artifacts/src/main/resources/messages.properties	Tue Jul 24 16:55:43 2018 +0200
+++ b/artifacts/src/main/resources/messages.properties	Tue Jul 24 18:51:47 2018 +0200
@@ -1121,6 +1121,10 @@
 uinfo.export.url.inundationduration.vegetation = Vegetationszonen ({0})
 uinfo.export.url.inundationduration.vegetation_scenario= Vegetationszonen Szenario ({0}, {1}cm)
 uinfo.export.url.inundationduration.scenario = \u00dcberflutungsdauer Szenario ({0}, {1}cm)
+uinfo_facet_salix_line = Salix-Linie
+uinfo_facet_salix_line.description = Salix-Linie
+uinfo_facet_salix_mnwmw = (MW-MNW)x(-1)
+uinfo_facet_salix_mnwmw.description = (MW-MNW)x(-1)
 
 predefineddepthevol.total.title = Gesamt: {0}
 predefineddepthevol.peryear.title = J\u00e4hrlich: {0}
--- a/artifacts/src/main/resources/messages_de.properties	Tue Jul 24 16:55:43 2018 +0200
+++ b/artifacts/src/main/resources/messages_de.properties	Tue Jul 24 18:51:47 2018 +0200
@@ -1121,6 +1121,10 @@
 uinfo.export.url.inundationduration.vegetation = Vegetationszonen ({0})
 uinfo.export.url.inundationduration.vegetation_scenario= Vegetationszonen Szenario ({0}, {1}cm)
 uinfo.export.url.inundationduration.scenario = \u00dcberflutungsdauer Szenario ({0}, {1}cm) 
+uinfo_facet_salix_line = Salix-Linie
+uinfo_facet_salix_line.description = Salix-Linie
+uinfo_facet_salix_mnwmw = (MW-MNW)x(-1)
+uinfo_facet_salix_mnwmw.description = (MW-MNW)x(-1)
 
 predefineddepthevol.total.title = Gesamt: {0}
 predefineddepthevol.peryear.title = J\u00e4hrlich: {0}
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Tue Jul 24 16:55:43 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Tue Jul 24 18:51:47 2018 +0200
@@ -1569,6 +1569,8 @@
 
     String uinfo_salix_input_complete();
 
+    String uinfo_salix_line();
+
     String common_input_hint_year();
 
     String error_invalid_integer();
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Tue Jul 24 16:55:43 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Tue Jul 24 18:51:47 2018 +0200
@@ -843,6 +843,7 @@
 uinfo_salix_km_has_gaps = Der Km-Bereich ist nicht vollst. belegt.
 uinfo_salix_km_anschluss = Der eingegebene Bereich schlie\u00dft nicht an den letzten Wert an.
 uinfo_salix_input_complete = Die gesamte Strecke ist bereits mit Werten belegt.
+uinfo_salix_line = Salix-Linie (Fluss/Aue-Konnektivit\u00e4t) - L\u00e4ngsschnitt
 
 bundu = Betrieb und Unterhaltung 
 bundu_bezugswst_fix_choice_title= Fixierungsauswahl
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Tue Jul 24 16:55:43 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Tue Jul 24 18:51:47 2018 +0200
@@ -843,6 +843,7 @@
 uinfo_salix_km_has_gaps = Der Km-Bereich ist nicht vollst. belegt.
 uinfo_salix_km_anschluss = Der eingegebene Bereich schlie\u00dft nicht an den letzten Wert an.
 uinfo_salix_input_complete = Die gesamte Strecke ist bereits mit Werten belegt.
+uinfo_salix_line = Salix-Linie (Fluss/Aue-Konnektivit\u00e4t) - L\u00e4ngsschnitt
 
 bundu = Betrieb und Unterhaltung
 bundu_bezugswst_fix_choice_title= Fixierungsauswahl

http://dive4elements.wald.intevation.org