changeset 9446:e60584f2a531

Added bundu bzws calculation for missing volumes (masses still not yet ready) and results1/2/3
author mschaefer
date Tue, 21 Aug 2018 18:19:35 +0200
parents ff0e5386de70
children 3f4215ddd6b4
files artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/BunduResultType.java artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult1.java artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult2.java artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult3.java artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BunduAccess.java artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractExportContext.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.properties gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties
diffstat 11 files changed, 303 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/BunduResultType.java	Tue Aug 21 14:16:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/BunduResultType.java	Tue Aug 21 18:19:35 2018 +0200
@@ -278,6 +278,63 @@
     };
 
     /**
+     * List of missing depth values of the 10 fields of a cross section
+     */
+    public static final BunduResultType missDepthFields = new BunduResultType(I18NStrings.UNIT_NONE, null) {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    /**
+     * List of missing width values of the 10 fields of a cross section
+     */
+    public static final BunduResultType missWidthFields = new BunduResultType(I18NStrings.UNIT_NONE, null) {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    /**
+     * List of missing area values of the 10 fields of a cross section
+     */
+    public static final BunduResultType missAreaFields = new BunduResultType(I18NStrings.UNIT_NONE, null) {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String exportValue(final CallContext context, final Object value) {
+            final double doubleValue = asDouble(value);
+            return exportDoubleValue(context, doubleValue);
+        }
+
+        @Override
+        protected NumberFormat createFormatter(final CallContext context) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    /**
      * List of volume values of the 10 fields of a cross section
      */
     public static final BunduResultType missVolumeFields = new BunduResultType(I18NStrings.UNIT_NONE, "bundu.export.bezugswst.csv.meta.miss.volume.field") {
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java	Tue Aug 21 14:16:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java	Tue Aug 21 18:19:35 2018 +0200
@@ -17,6 +17,7 @@
 import org.dive4elements.river.artifacts.access.FixRealizingAccess;
 import org.dive4elements.river.artifacts.bundu.BUNDUArtifact;
 import org.dive4elements.river.artifacts.bundu.BunduResultType;
+import org.dive4elements.river.artifacts.common.AbstractResultType;
 import org.dive4elements.river.artifacts.common.GeneralResultType;
 import org.dive4elements.river.artifacts.common.ResultRow;
 import org.dive4elements.river.artifacts.model.Calculation;
@@ -42,11 +43,24 @@
 
     // private static Logger log = Logger.getLogger(BezugswstCalculation.class);
 
+    /**
+     * Additional depth (m) to compute the excavation volume
+     */
+    private final static double EXCAVATION_DEPTH = 0.2; // REMARK Sollte von außen einstellbar sein
+
+    /**
+     * Excavation costs (euro) per cubic meter
+     */
+    private final static double EXPENSE_PER_CBM = 12.0; // REMARK Sollte von außen einstellbar sein
+
     private final CallContext context;
 
+    private final List<ResultRow> rows;
+
 
     public BezugswstCalculation(final CallContext context) {
         this.context = context;
+        this.rows = new ArrayList<>();
     }
 
 
@@ -94,87 +108,40 @@
         if (channelFinder == null)
             return new CalculationResult(results, problems);
 
-        // Calculate the result rows
-        final List<ResultRow> rows = new ArrayList<>();
+        // Compute the result rows
         for (int i = 0; i <= wqkms.size() - 1; i++) {
-            rows.add(createRow(wqkms.getKm(i), wqkms.getW(i), wqkms.getQ(i), bedHeightsFinder, channelFinder, riverInfoProvider, wstInfo));
+            this.rows.add(createRow(wqkms.getKm(i), wqkms.getW(i), wqkms.getQ(i), bedHeightsFinder, channelFinder, riverInfoProvider, wstInfo));
+        }
+
+        // Compute the missing volumes
+        if (access.isCalculateMissingValue()) {
+            computeMissingVolumes(access.getMissingVolFrom().doubleValue(), access.getMissingVolTo().doubleValue(), problems);
+            // TODO Lagerungsdichte holen/berechnen (density) und Massen berechnen
         }
 
         // Add the result to the results collection
         final WaterlevelDescriptionBuilder descBuilder = new WaterlevelDescriptionBuilder(winfo, this.context);
         final String qtext = descBuilder.getMetadataQ();
-        final BezugswstMainCalculationResult result = new BezugswstMainCalculationResult("bundu-bzws", rows, bedHeightsFinder.getInfo(), wstInfo,
+        final BezugswstMainCalculationResult result = new BezugswstMainCalculationResult("bundu-bzws", this.rows, bedHeightsFinder.getInfo(), wstInfo,
                 access.getFunction(), preprocessing, startYear, endYear, ud, qtext, wqkms, missingVolFrom, missingVolTo);
         results.addResult(result, problems);
 
-        // // missing volume calculation
-        // if (access.getMissingVolFrom() != null) {
-        // /// FIRST RESULT
-        // final List<ResultRow> listResult1 = new ArrayList<>();
-        // final ResultRow rowResult1 = ResultRow.create();
-        // rowResult1.putValue(BunduResultType.bezugswst, 45.15);
-        // rowResult1.putValue(GeneralResultType.dischargeQwithUnit, 890);
-        // rowResult1.putValue(GeneralResultType.waterlevelLabel, "GLQ");
-        // rowResult1.putValue(GeneralResultType.gaugeLabel, "Bonn");
-        //
-        // rowResult1.putValue(BunduResultType.sounding, "NIEDERRHEIN_QP-2002");
-        // rowResult1.putValue(BunduResultType.channelLowerEdge, 42.65);
-        // rowResult1.putValue(BunduResultType.channelMinDepth, 2.5);
-        // rowResult1.putValue(BunduResultType.hasMissingDepth, Resources.getMsg(meta, "true"));
-        // rowResult1.putValue(BunduResultType.missVolume, 2250);
-        // rowResult1.putValue(BunduResultType.missMass, 3897);
-        // rowResult1.putValue(BunduResultType.excavationVolume, 2475);
-        // rowResult1.putValue(BunduResultType.excavationCosts, 999.99);
-        // rowResult1.putValue(BunduResultType.channelWidth, 150);
-        // rowResult1.putValue(BunduResultType.density, 1732);
-        //
-        // rowResult1.putValue(GeneralResultType.location, "Spitzenlage");
-        // listResult1.add(rowResult1);
-        //
-        // final BezugswstMissVolCalculationResult1 r1 = new BezugswstMissVolCalculationResult1(
-        // Resources.getMsg(meta, "bundu.export.csv.title.bezugswst.result1"), listResult1);
-        // results.addResult(r1, null);
-        //
-        // // SECOND RESULT
-        // final List<ResultRow> listResult2 = new ArrayList<>();
-        // final ResultRow rowResult2 = ResultRow.create();
-        //
-        // rowResult2.putValue(GeneralResultType.station, 890);
-        // final List<String> fieldValues = new ArrayList<>();
-        // fieldValues.add("444 [m³] / 765 [t]");
-        // fieldValues.add("4.444 [m³] / 1.765 [t]");
-        // fieldValues.add("444 [m³] / 765 [t]");
-        // fieldValues.add("");
-        // fieldValues.add("");
-        // fieldValues.add("");
-        // fieldValues.add("");
-        // fieldValues.add("");
-        // fieldValues.add("");
-        // fieldValues.add("444 [m³] / 765 [t]");
-        // rowResult2.putValue(BunduResultType.fields, fieldValues);
-        // rowResult2.putValue(BunduResultType.meanBedheight, "9.444 [m³] / 8.765 [t]");
-        //
-        // listResult2.add(rowResult2);
-        //
-        // final BezugswstMissVolCalculationResult2 r2 = new BezugswstMissVolCalculationResult2(
-        // Resources.getMsg(meta, "bundu.export.csv.title.bezugswst.result2"), listResult2);
-        // results.addResult(r2, null);
-        //
-        // // Third RESULT
-        // final List<ResultRow> listResult3 = new ArrayList<>();
-        // final ResultRow rowResult3 = ResultRow.create();
-        //
-        // rowResult3.putValue(BunduResultType.stationForMiss, "650 - 651");
-        // rowResult3.putValue(BunduResultType.missVolume, 52950);
-        // rowResult3.putValue(BunduResultType.missMass, 91491);
-        //
-        // listResult3.add(rowResult3);
-        //
-        // final BezugswstMissVolCalculationResult3 r3 = new BezugswstMissVolCalculationResult3(
-        // Resources.getMsg(meta, "bundu.export.csv.title.bezugswst.result3"), listResult3);
-        // results.addResult(r3, null);
-        //
-        // }
+        // Create the missing volume results
+        if (access.getMissingVolFrom() != null) {
+            final String title1 = Resources.getMsg(this.context.getMeta(), "bundu.export.csv.title.bezugswst.result1");
+            final BezugswstMissVolCalculationResult1 r1 = new BezugswstMissVolCalculationResult1(title1, this.rows);
+            results.addResult(r1, null);
+
+            final String title2 = Resources.getMsg(this.context.getMeta(), "bundu.export.csv.title.bezugswst.result2");
+            final BezugswstMissVolCalculationResult2 r2 = new BezugswstMissVolCalculationResult2(title2, this.rows);
+            results.addResult(r2, null);
+
+            final String title3 = Resources.getMsg(this.context.getMeta(), "bundu.export.csv.title.bezugswst.result3");
+            final List<ResultRow> totalRows = new ArrayList<>();
+            totalRows.add(createTotalsRow(missingVolFrom.doubleValue(), missingVolTo.doubleValue(), problems));
+            final BezugswstMissVolCalculationResult3 r3 = new BezugswstMissVolCalculationResult3(title3, totalRows);
+            results.addResult(r3, null);
+        }
 
         return new CalculationResult(results, problems);
     }
@@ -206,6 +173,7 @@
     private ResultRow createRow(final double station, final double w, final double q, final BedHeightsFinder bedHeightsFinder,
             final ChannelFinder channelFinder, final RiverInfoProvider riverInfoProv, final WstInfo wstInfo) {
 
+        // Set W and Q
         final ResultRow row = ResultRow.create();
         row.putValue(GeneralResultType.station, station);
         row.putValue(BunduResultType.bezugswst, w);
@@ -213,6 +181,8 @@
         row.putValue(GeneralResultType.waterlevelLabel, wstInfo.getLabel());
         row.putValue(GeneralResultType.gaugeLabel, riverInfoProv.findGauge(station));
         row.putValue(GeneralResultType.location, riverInfoProv.getLocation(station));
+
+        // Set bed and channel bottom height
         final double msh = bedHeightsFinder.getMeanBedHeight(station);
         row.putValue(SInfoResultType.meanBedHeight, msh);
         if (!Double.isNaN(w) && !Double.isNaN(msh))
@@ -221,19 +191,180 @@
             row.putValue(SInfoResultType.flowdepth, Double.NaN);
         final double channelDepth = channelFinder.getDepth(station);
         row.putValue(BunduResultType.channelDepth, channelDepth);
+        double channelHeight;
         if (!Double.isNaN(w) && !Double.isNaN(channelDepth))
-            row.putValue(BunduResultType.channelLowerEdge, Formatter.roundFlowDepth(w).subtract(Formatter.roundFlowDepth(channelDepth)).doubleValue());
+            channelHeight = Formatter.roundFlowDepth(w).subtract(Formatter.roundFlowDepth(channelDepth)).doubleValue();
         else
-            row.putValue(BunduResultType.channelLowerEdge, Double.NaN);
+            channelHeight = Double.NaN;
+        row.putValue(BunduResultType.channelLowerEdge, channelHeight);
+        final double channelWidth = channelFinder.getWidth(station);
+        row.putValue(BunduResultType.channelWidth, channelWidth);
+
+        // Set field heights and missing heights
         final List<Double> fieldHeights = new ArrayList<>();
         final List<Double> fieldDepths = new ArrayList<>();
+        final List<Double> fieldMissDepths = new ArrayList<>();
+        final List<Double> fieldMissWidths = new ArrayList<>();
+        int missFieldCnt = 0;
         for (int i = BedHeightValueType.FIELD_FIRST_INDEX; i <= BedHeightValueType.FIELD_LAST_INDEX; i++) {
             final double h = bedHeightsFinder.getFieldHeight(station, i);
             fieldHeights.add(Double.valueOf(h));
-            fieldDepths.add(w - h);
+            fieldDepths.add(Double.valueOf(w - h));
+            if (h > channelHeight + 0.001) {
+                missFieldCnt++;
+                fieldMissDepths.add(Double.valueOf(h - channelHeight));
+                fieldMissWidths.add(Double.valueOf(channelWidth / BedHeightValueType.FIELD_LAST_INDEX));
+            }
+            else {
+                fieldMissDepths.add(Double.valueOf(0.0));
+                fieldMissWidths.add(Double.valueOf(0.0));
+            }
         }
+        row.putValue(BunduResultType.missDepthFields, fieldMissDepths);
+        row.putValue(BunduResultType.missWidthFields, fieldMissWidths);
+        row.putValue(BunduResultType.hasMissingDepth, (missFieldCnt >= 1));
         row.putValue(BunduResultType.bedHeightFields, fieldHeights);
         row.putValue(BunduResultType.depthFields, fieldDepths);
+
+        // Preset the missing volume fields with NaN
+        row.putValue(BunduResultType.excavationCosts, Double.NaN);
+        row.putValue(BunduResultType.excavationVolume, Double.NaN);
+        row.putValue(BunduResultType.missVolumeMeanBed, Double.NaN);
+        row.putValue(BunduResultType.missMassMeanBed, Double.NaN);
+        row.putValue(BunduResultType.missVolumeTotal, Double.NaN);
+        row.putValue(BunduResultType.missMassTotal, Double.NaN);
+        row.putValue(BunduResultType.density, Double.NaN);
+        row.putValue(BunduResultType.missStationRangeFrom, Double.NaN);
+        row.putValue(BunduResultType.missStationRangeTo, Double.NaN);
+
         return row;
     }
+
+    /**
+     * Computes the missing volumes in a km range
+     */
+    private void computeMissingVolumes(final double kmFrom, final double kmTo, final Calculation problems) {
+        // Search start km
+        int first = -1;
+        for (int j = 0; j <= this.rows.size() - 1; j++) {
+            if (this.rows.get(j).getDoubleValue(GeneralResultType.station) > kmFrom - 0.0001) {
+                first = j;
+                break;
+            }
+        }
+        if (first < 0)
+            return;
+        int last = this.rows.size() - 1;
+        int i = first;
+        while (i <= this.rows.size() - 1) {
+            if (this.rows.get(i).getDoubleValue(GeneralResultType.station) > kmTo + 0.0001)
+                break;
+            if (this.rows.get(i).getDoubleValue(GeneralResultType.station) > kmTo - 0.0001)
+                last = i;
+            final List<Double> areas = new ArrayList<>();
+            final List<Double> volumes = new ArrayList<>();
+            double vTotal = 0.0;
+            double vExcav = 0.0;
+            double expenses = 0.0;
+            for (int j = BedHeightValueType.FIELD_FIRST_INDEX; j <= BedHeightValueType.FIELD_LAST_INDEX; j++) {
+                if (getFieldValue(i, BunduResultType.missDepthFields, j) > 0.0001) {
+                    computeMissingVolume(volumes, areas, i, first, last, j);
+                    vTotal += volumes.get(j - 1);
+                    vExcav += volumes.get(j - 1) + areas.get(j - 1) * EXCAVATION_DEPTH;
+                    expenses += vExcav * EXPENSE_PER_CBM;
+                }
+                else {
+                    volumes.add(Double.valueOf(0.0));
+                    areas.add(Double.valueOf(0.0));
+                }
+            }
+            this.rows.get(i).putValue(BunduResultType.missVolumeFields, volumes);
+            this.rows.get(i).putValue(BunduResultType.missAreaFields, areas);
+            this.rows.get(i).putValue(BunduResultType.missVolumeTotal, vTotal);
+            this.rows.get(i).putValue(BunduResultType.excavationVolume, vExcav);
+            this.rows.get(i).putValue(BunduResultType.excavationCosts, expenses);
+            i++;
+        }
+    }
+
+    /**
+     * Computes the missing volume of a field of a km row
+     */
+    private void computeMissingVolume(final List<Double> volumes, final List<Double> areas, final int current, final int first, final int last,
+            final int field) {
+        final double areaCurr = missingArea(current, first, last, field);
+        final double areaPrev = missingArea(current - 1, first, last, field);
+        final double areaNext = missingArea(current + 1, first, last, field);
+        final double kmCurr = missingKm(current);
+        final double kmPrev = missingKm(current - 1);
+        final double kmNext = missingKm(current + 1);
+        if (Double.isNaN(kmPrev) || Double.isNaN(kmNext)) {
+            volumes.add(Double.valueOf(0.0));
+            areas.add(Double.valueOf(0.0));
+        }
+        else {
+            final double area1 = 0.5 * (areaCurr + areaPrev);
+            final double area2 = 0.5 * (areaCurr + areaNext);
+            volumes.add(Double.valueOf((Math.abs(kmCurr - kmPrev) * 0.5 * area1) + (Math.abs(kmNext - kmCurr) * 0.5 * area2)));
+            areas.add(Double.valueOf(area1 + area2));
+        }
+    }
+
+    /**
+     * Gets the missing area of a field and a row if in range, otherwise 0.0
+     */
+    private double missingArea(final int rowIndex, final int first, final int last, final int fieldIndex) {
+        if ((first <= rowIndex) && (rowIndex <= last))
+            return getFieldValue(rowIndex, BunduResultType.missDepthFields, fieldIndex)
+                    * getFieldValue(rowIndex, BunduResultType.missWidthFields, fieldIndex);
+        else
+            return 0.0;
+    }
+
+    /**
+     * Gets the km of a row if within range, otherwise NaN
+     */
+    private double missingKm(final int rowIndex) {
+        if ((0 <= rowIndex) && (rowIndex <= this.rows.size() - 1))
+            return this.rows.get(rowIndex).getDoubleValue(GeneralResultType.station);
+        else
+            return Double.NaN;
+    }
+
+    /**
+     * Gets a value of one of the field list types of a row
+     *
+     * @param rowIndex
+     * @param type
+     * @param fieldIndex
+     *            1-based field index
+     */
+    private double getFieldValue(final int rowIndex, final AbstractResultType type, final int fieldIndex) {
+        @SuppressWarnings("unchecked")
+        final List<Double> values = (List<Double>) this.rows.get(rowIndex).getValue(type);
+        return values.get(fieldIndex - 1);
+    }
+
+    /**
+     * Computes the volume and mass total of all rows with missing volumes
+     */
+    private ResultRow createTotalsRow(final double kmFrom, final double kmTo, final Calculation problems) {
+        // Search start km
+        double vTotal = 0.0;
+        double mTotal = 0.0;
+        for (final ResultRow row : this.rows) {
+            final double volume = row.getDoubleValue(BunduResultType.missVolumeMeanBed);
+            final double mass = row.getDoubleValue(BunduResultType.missMassMeanBed);
+            if (!Double.isNaN(volume) && !Double.isNaN(mass)) {
+                vTotal += volume;
+                mTotal += mass;
+            }
+        }
+        final ResultRow sumRow = ResultRow.create();
+        sumRow.putValue(BunduResultType.missStationRangeFrom, Double.valueOf(kmFrom));
+        sumRow.putValue(BunduResultType.missStationRangeTo, Double.valueOf(kmTo));
+        sumRow.putValue(BunduResultType.missVolumeTotal, vTotal);
+        sumRow.putValue(BunduResultType.missMassTotal, mTotal);
+        return sumRow;
+    }
 }
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult1.java	Tue Aug 21 14:16:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult1.java	Tue Aug 21 18:19:35 2018 +0200
@@ -52,6 +52,7 @@
 
         final Collection<String> lines = new ArrayList<>(20);
 
+        lines.add(exportContext.formatRowValue(row, GeneralResultType.station));
         lines.add(exportContext.formatRowValue(row, BunduResultType.bezugswst));
         lines.add(exportContext.formatRowValue(row, GeneralResultType.dischargeQwithUnit));
         lines.add(exportContext.formatRowValue(row, GeneralResultType.waterlevelLabel));
@@ -76,10 +77,11 @@
     @Override
     public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
 
-        final int colSize = 15;
+        final int colSize = 16;
         exportContextCSV.writeTitleForTabs("bundu.export.csv.title.bezugswst.result1", colSize); // Voraussetzung für Tabs ist, dass der Titel vor den Headern
         final Collection<String> header = new ArrayList<>(colSize);
 
+        header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station));
         header.add(exportContextCSV.formatCsvHeader(BunduResultType.bezugswst) + " [" + river.getWstUnit() + "]");
         header.add(exportContextCSV.formatCsvHeader(GeneralResultType.dischargeQwithUnit));
         header.add(exportContextCSV.formatCsvHeader(GeneralResultType.waterlevelLabel));
@@ -120,6 +122,7 @@
     protected void addJRTableHeader(final ExportContextPDF exportContextPDF, final MetaAndTableJRDataSource source) {
         /* column headings */
 
+        exportContextPDF.addJRMetadata(source, "station_header", GeneralResultType.station);
         exportContextPDF.addJRMetadata(source, "bezugswst_header", BunduResultType.bezugswst);
         exportContextPDF.addJRMetadata(source, "discharge_header", GeneralResultType.dischargeQwithUnit);
         exportContextPDF.addJRMetadata(source, "waterlevel_name_header", GeneralResultType.waterlevelLabel);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult2.java	Tue Aug 21 14:16:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult2.java	Tue Aug 21 18:19:35 2018 +0200
@@ -22,6 +22,7 @@
 import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource;
 import org.dive4elements.river.artifacts.common.ResultRow;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.model.BedHeightValueType;
 
 /**
  * Contains the results of a //TODO LINK{@link BezugswstCalculation}.
@@ -35,7 +36,6 @@
     private static final String JASPER_FILE = "/jasper/templates/bundu.bezugswst.result2.jrxml";
     private static final String fieldVolumeMsgKey = "bundu.export.bezugswst.csv.meta.miss.volume.field";
     private static final String fieldMassMsgKey = "bundu.export.bezugswst.csv.meta.miss.mass.field";
-    private static final int fieldSize = 10;
 
     public BezugswstMissVolCalculationResult2(final String label, final Collection<ResultRow> rows) {
         super(label, rows);
@@ -57,12 +57,14 @@
         final Collection<String> lines = new ArrayList<>(20);
 
         lines.add(exportContext.formatRowValue(row, GeneralResultType.station));
-        final List<String> vFields = (List<String>) row.getValue(BunduResultType.missVolumeFields);
-        assert (vFields.size() == fieldSize); // immer abgleichen mit der Calculation!
-        final List<String> mFields = (List<String>) row.getValue(BunduResultType.missMassFields);
+        @SuppressWarnings("unchecked")
+        final List<Double> vFields = (List<Double>) row.getValue(BunduResultType.missVolumeFields);
+        assert (vFields.size() == fieldSize()); // immer abgleichen mit der Calculation!
+        @SuppressWarnings("unchecked")
+        final List<Double> mFields = (List<Double>) row.getValue(BunduResultType.missMassFields);
         for (int i = 0; i <= vFields.size() - 1; i++) {
-            lines.add(vFields.get(i));
-            lines.add(mFields.get(i));
+            lines.add(BunduResultType.missVolumeFields.exportValue(exportContext.getContext(), vFields.get(i)));
+            lines.add(BunduResultType.missMassFields.exportValue(exportContext.getContext(), mFields.get(i)));
         }
         lines.add(exportContext.formatRowValue(row, BunduResultType.missVolumeMeanBed));
         lines.add(exportContext.formatRowValue(row, BunduResultType.missMassMeanBed));
@@ -73,13 +75,13 @@
     @Override
     public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) {
 
-        final int colSize = 2 * fieldSize + 2;
+        final int colSize = 2 * fieldSize() + 3;
         exportContextCSV.writeTitleForTabs("bundu.export.csv.title.bezugswst.result2", colSize); // Voraussetzung für Tabs ist, dass der Titel vor den Headern
         final Collection<String> header = new ArrayList<>(colSize);
 
         header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station));
 
-        for (int i = 1; i <= fieldSize; i++) {
+        for (int i = 1; i <= fieldSize(); i++) {
             header.add(exportContextCSV.msg(fieldVolumeMsgKey, i));
             header.add(exportContextCSV.msg(fieldMassMsgKey, i));
         }
@@ -90,6 +92,13 @@
 
     }
 
+    /**
+     * Number of elements of the various field lists
+     */
+    private int fieldSize() {
+        return BedHeightValueType.FIELD_LAST_INDEX - BedHeightValueType.FIELD_FIRST_INDEX + 1;
+    }
+
     @Override
     protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) {
 
@@ -106,8 +115,9 @@
     protected void addJRTableHeader(final ExportContextPDF exportContextPDF, final MetaAndTableJRDataSource source) {
         /* column headings */
 
+        // TODO Auftrennung jeder Volumen+Masse-Spalte in zwei getrennte Volumen- und Masse-Spalten
         exportContextPDF.addJRMetadata(source, "station_header", GeneralResultType.station);
-        for (int i = 1; i <= fieldSize; i++) {
+        for (int i = 1; i <= fieldSize(); i++) {
             exportContextPDF.addJRMetadata(source, "field_header" + String.valueOf(i), exportContextPDF.msg(fieldVolumeMsgKey, i));
             exportContextPDF.addJRMetadata(source, "field_header" + String.valueOf(i), exportContextPDF.msg(fieldMassMsgKey, i));
         }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult3.java	Tue Aug 21 14:16:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult3.java	Tue Aug 21 18:19:35 2018 +0200
@@ -49,7 +49,7 @@
 
     protected String[] formatRow(final AbstractExportContext exportContext, final ResultRow row) {
 
-        final Collection<String> lines = new ArrayList<>(20);
+        final Collection<String> lines = new ArrayList<>(4);
 
         lines.add(exportContext.formatRowValue(row, BunduResultType.missStationRangeFrom));
         lines.add(exportContext.formatRowValue(row, BunduResultType.missStationRangeTo));
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BunduAccess.java	Tue Aug 21 14:16:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BunduAccess.java	Tue Aug 21 18:19:35 2018 +0200
@@ -85,7 +85,7 @@
             return null;
     }
 
-    private boolean isCalculateMissingValue() { // probably public
+    public boolean isCalculateMissingValue() {
         return getBoolean("missing_volume");
     }
 
@@ -159,10 +159,10 @@
     // return this.analysisPeriods;
     // }
 
-    /**
-     * @return DateRange object ranging from eldest to youngest date
-     *         of analysis and reference periods.
-     */
+    // /**
+    // * @return DateRange object ranging from eldest to youngest date
+    // * of analysis and reference periods.
+    // */
     // @Override
     // public DateRange getDateRange() {
     // final DateRange refP = getReferencePeriod();
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractExportContext.java	Tue Aug 21 14:16:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractExportContext.java	Tue Aug 21 18:19:35 2018 +0200
@@ -37,7 +37,7 @@
         this.results = results;
     }
 
-    protected final CallContext getContext() {
+    public final CallContext getContext() {
         return this.context;
     }
 
--- a/artifacts/src/main/resources/messages.properties	Tue Aug 21 14:16:15 2018 +0200
+++ b/artifacts/src/main/resources/messages.properties	Tue Aug 21 18:19:35 2018 +0200
@@ -1314,10 +1314,10 @@
 bundu_facet_bedheight.description = Mittlere Sohlh\u00f6he ({0}) 
 bundu_facet_channelmin.description = Sohle (Sollzustand)
 bundu_facet_field_bedheight.description = Sohlh\u00f6he Feld {0} 
-bundu.chart.depth.section.title = h-L\u00e4ngsschnitt
-bundu_facet_flowdepth.filtered.description = h (BZWS, {0})
-bundu_facet_channeldepth.description = h (Solltiefe)
-bundu_facet_field_depth.description = h Feld {0} 
+bundu.chart.depth.section.title = \u0394h-L\u00e4ngsschnitt
+bundu_facet_flowdepth.filtered.description = \u0394h (BZWS, {0})
+bundu_facet_channeldepth.description = \u0394h (Solltiefe)
+bundu_facet_field_depth.description = \u0394h Feld {0} 
 bundu.channelfinder.empty = The database does not contain any values for the river and the reference year
 bundu.channelfinder.missing = no channel data available
 
--- a/artifacts/src/main/resources/messages_de.properties	Tue Aug 21 14:16:15 2018 +0200
+++ b/artifacts/src/main/resources/messages_de.properties	Tue Aug 21 18:19:35 2018 +0200
@@ -1314,10 +1314,10 @@
 bundu_facet_bedheight.description = Mittlere Sohlh\u00f6he ({0}) 
 bundu_facet_channelmin.description = Sohle (Sollzustand)
 bundu_facet_field_bedheight.description = Sohlh\u00f6he Feld {0} 
-bundu.chart.depth.section.title = h-L\u00e4ngsschnitt
-bundu_facet_flowdepth.filtered.description = h (BZWS, {0})
-bundu_facet_channeldepth.description = h (Solltiefe)
-bundu_facet_field_depth.description = h Feld {0} 
+bundu.chart.depth.section.title = \u0394h-L\u00e4ngsschnitt
+bundu_facet_flowdepth.filtered.description = \u0394h (BZWS, {0})
+bundu_facet_channeldepth.description = \u0394h (Solltiefe)
+bundu_facet_field_depth.description = \u0394h Feld {0} 
 bundu.channelfinder.empty = Die Datenbank enth\u00e4lt keine Fahrrinnedaten f\u00fcr das Gew\u00e4sser und das Bezugsjahr
 bundu.channelfinder.missing = keine Fahrrinnedaten vorhanden
 
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Tue Aug 21 14:16:15 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Tue Aug 21 18:19:35 2018 +0200
@@ -861,7 +861,7 @@
 bundu_wst_export = Bezugswasserst\u00e4nde Export
 bundu_ws_wq_info = Die Abfl\u00fcsse MNQ, MQ und MHQ sind anhand der Tagesmittelwerte des Abflusses berechnet.
 bundu_wspl_longitudinal_section = BZWS - L\u00e4ngsschnitt
-bundu_depth_longitudinal_section = BZWS h - L\u00e4ngsschnitt
+bundu_depth_longitudinal_section = BZWS \u0394h - L\u00e4ngsschnitt
 
 chart_settings_export_metadata = Show Meta-Data
 export_csv_title = Title: 
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Tue Aug 21 14:16:15 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Tue Aug 21 18:19:35 2018 +0200
@@ -861,7 +861,7 @@
 bundu_wst_export = Bezugswasserst\u00e4nde Export
 bundu_ws_wq_info = Die Abfl\u00fcsse MNQ, MQ und MHQ sind anhand der Tagesmittelwerte des Abflusses berechnet.
 bundu_wspl_longitudinal_section = BZWS - L\u00e4ngsschnitt
-bundu_depth_longitudinal_section = BZWS h - L\u00e4ngsschnitt
+bundu_depth_longitudinal_section = BZWS \u0394h - L\u00e4ngsschnitt
 
 chart_settings_export_metadata = Metadaten anzeigen
 export_csv_title = Titel: 

http://dive4elements.wald.intevation.org