changeset 9450:7e1fb8d0cb0d

Bundu bzws calculation nearly completed, some corrections with csv output, started with linking the minfo density calculation
author mschaefer
date Wed, 22 Aug 2018 19:12:51 +0200
parents ba3ad54edbae
children fd6621f47a72 af163ce96eb4
files artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/BunduResultType.java artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BedQualityCalculator.java artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult2.java artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BunduMinfoArtifactWrapper.java artifacts/src/main/resources/messages.properties artifacts/src/main/resources/messages_de.properties
diffstat 7 files changed, 310 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/BunduResultType.java	Wed Aug 22 14:07:39 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/BunduResultType.java	Wed Aug 22 19:12:51 2018 +0200
@@ -94,7 +94,7 @@
 
         @Override
         protected NumberFormat createFormatter(final CallContext context) {
-            return Formatter.getWaterlevelQ(context); // Richtiges Format? TODO check!
+            return Formatter.getFlowDepth(context);
         }
     };
 
@@ -207,6 +207,38 @@
         }
     };
 
+    public static final BunduResultType missDepthMeanBed = 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) {
+            return Formatter.getFlowDepth(context);
+        }
+    };
+
+    public static final BunduResultType missAreaMeanBed = 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) {
+            return Formatter.getMassFormat(context);
+        }
+    };
+
     public static final BunduResultType missVolumeMeanBed = new BunduResultType(I18NStrings.UNIT_NONE, "bundu.export.bezugswst.csv.meta.miss.volume.mean_bed") {
 
         private static final long serialVersionUID = 1L;
@@ -219,7 +251,7 @@
 
         @Override
         protected NumberFormat createFormatter(final CallContext context) {
-            return Formatter.getIntegerFormatter(context);
+            return Formatter.getMassFormat(context);
         }
     };
 
@@ -235,7 +267,7 @@
 
         @Override
         protected NumberFormat createFormatter(final CallContext context) {
-            return Formatter.getIntegerFormatter(context);
+            return Formatter.getMassFormat(context);
         }
     };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BedQualityCalculator.java	Wed Aug 22 19:12:51 2018 +0200
@@ -0,0 +1,68 @@
+/** 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.bundu.bezugswst;
+
+import java.util.Date;
+
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.access.BedQualityAccess;
+import org.dive4elements.river.artifacts.bundu.BUNDUArtifact;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.Calculation.Problem;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.minfo.BedQualityCalculation;
+import org.dive4elements.river.artifacts.model.minfo.BedQualityResult;
+import org.dive4elements.river.artifacts.model.minfo.BedQualityResultValue;
+import org.dive4elements.river.model.River;
+
+/**
+ * Calculator for bed quality parameters in a km range and time period, wrapping the minfo BedQualityCalculation
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public class BedQualityCalculator {
+
+    private final CallContext context;
+
+    private final BUNDUArtifact bundu;
+
+
+    public BedQualityCalculator(final CallContext context, final BUNDUArtifact bundu) {
+        this.context = context;
+        this.bundu = bundu;
+    }
+
+    /**
+     * Calculates the river bed sublayer densities for an array of kms and a time period of measurements
+     */
+    public double[][] execute(final Calculation problems, final River river, final double[] kms, final Date startDay, final Date endDay) {
+        final BedQualityCalculation bqCalc = new BedQualityCalculation();
+        final BedQualityAccess access = createBqAccess(kms[0], kms[kms.length - 1], startDay, endDay);
+        final CalculationResult bqCalcResult = bqCalc.calculate(access);
+        if (bqCalcResult.getReport().getProblems() != null) {
+            for (final Problem problem : bqCalcResult.getReport().getProblems())
+                problems.addProblem(problem);
+        }
+        final BedQualityResult[] results = (BedQualityResult[]) bqCalcResult.getData();
+        final BedQualityResult result = results[0];
+        final BedQualityResultValue bqResValue = result.getValue("density", "sublayer");
+        return bqResValue.getDataInterpolated(kms);
+    }
+
+    /**
+     * Creates an access object for the bed quality calculation
+     */
+    private BedQualityAccess createBqAccess(final double fromKm, final double toKm, final Date startDay, final Date endDay) {
+        final BunduMinfoArtifactWrapper minfo = new BunduMinfoArtifactWrapper(this.bundu, startDay, endDay);
+        return new BedQualityAccess(minfo, this.context);
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java	Wed Aug 22 14:07:39 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java	Wed Aug 22 19:12:51 2018 +0200
@@ -11,6 +11,7 @@
 package org.dive4elements.river.artifacts.bundu.bezugswst;
 
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.List;
 
 import org.dive4elements.artifacts.CallContext;
@@ -57,11 +58,16 @@
 
     private final List<ResultRow> rows;
 
+    private Double missKmFrom;
+
+    private Double missKmTo;
+
     public BezugswstCalculation(final CallContext context) {
         this.context = context;
         this.rows = new ArrayList<>();
     }
 
+
     /**
      * Calculates the result rows of a bundu bzws workflow
      */
@@ -77,8 +83,8 @@
         final int startYear = access.getStartYear();
         final int endYear = access.getBezugsJahr();
         final Integer ud = access.getUd();
-        final Double missingVolFrom = access.getMissingVolFrom();
-        final Double missingVolTo = access.getMissingVolTo();
+        this.missKmFrom = access.getMissingVolFrom();
+        this.missKmTo = access.getMissingVolTo();
 
         final BezugswstCalculationResults results = new BezugswstCalculationResults(calcModeLabel, user, riverInfo, access.getRange());
 
@@ -113,15 +119,22 @@
 
         // Compute the missing volumes
         if (access.isCalculateMissingValue()) {
-            computeMissingVolumes(access.getMissingVolFrom().doubleValue(), access.getMissingVolTo().doubleValue(), problems);
-            // TODO Lagerungsdichte holen/berechnen (density) und Massen berechnen
+            computeMissingVolumes(problems);
+            final BedQualityCalculator bqCalculator = new BedQualityCalculator(this.context, bunduartifact);
+            final double[] kms = new double[] { this.missKmFrom.doubleValue(), this.missKmTo.doubleValue() };
+            final Calendar endDay = Calendar.getInstance();
+            endDay.set(access.getBezugsJahr().intValue(), 11, 31);
+            final Calendar startDay = Calendar.getInstance();
+            startDay.set(endDay.get(Calendar.YEAR) - 20, 0, 1);
+            // TODO final double[][] kmDensities = bqCalculator.execute(problems, river, kms, startDay.getTime(), endDay.getTime());
+            computeMissingMasses(problems);
         }
 
         // 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", this.rows, bedHeightsFinder.getInfo(), wstInfo,
-                access.getFunction(), preprocessing, startYear, endYear, ud, qtext, wqkms, missingVolFrom, missingVolTo);
+                access.getFunction(), preprocessing, startYear, endYear, ud, qtext, wqkms, this.missKmFrom, this.missKmTo);
         results.addResult(result, problems);
 
         // Create the missing volume results
@@ -131,12 +144,13 @@
             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);
+            final List<ResultRow> rows2 = copyMissRows();
+            final BezugswstMissVolCalculationResult2 r2 = new BezugswstMissVolCalculationResult2(title2, rows2);
             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));
+            totalRows.add(createTotalsRow(problems));
             final BezugswstMissVolCalculationResult3 r3 = new BezugswstMissVolCalculationResult3(title3, totalRows);
             results.addResult(r3, null);
         }
@@ -179,6 +193,7 @@
         row.putValue(GeneralResultType.waterlevelLabel, wstInfo.getLabel());
         row.putValue(GeneralResultType.gaugeLabel, riverInfoProv.findGauge(station));
         row.putValue(GeneralResultType.location, riverInfoProv.getLocation(station));
+        row.putValue(BunduResultType.sounding, bedHeightsFinder.getInfo().getDescription());
 
         // Set bed and channel bottom height
         final double msh = bedHeightsFinder.getMeanBedHeight(station);
@@ -197,12 +212,19 @@
         row.putValue(BunduResultType.channelLowerEdge, channelHeight);
         final double channelWidth = channelFinder.getWidth(station);
         row.putValue(BunduResultType.channelWidth, channelWidth);
+        if (!Double.isNaN(channelHeight)) {
+            if (msh > channelHeight + 0.001)
+                row.putValue(BunduResultType.missDepthMeanBed, msh - channelHeight);
+            else
+                row.putValue(BunduResultType.missDepthMeanBed, 0.0);
+        }
 
         // 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<>();
+        final List<Double> fieldNulls = 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);
@@ -216,10 +238,20 @@
                 fieldMissDepths.add(Double.valueOf(0.0));
                 fieldMissWidths.add(Double.valueOf(0.0));
             }
+            fieldNulls.add(Double.NaN);
         }
-        row.putValue(BunduResultType.missDepthFields, fieldMissDepths);
-        row.putValue(BunduResultType.missWidthFields, fieldMissWidths);
-        row.putValue(BunduResultType.hasMissingDepth, (missFieldCnt >= 1));
+        if (isKmInMissingVolumeRange(station)) {
+            row.putValue(BunduResultType.missDepthFields, fieldMissDepths);
+            row.putValue(BunduResultType.missWidthFields, fieldMissWidths);
+            row.putValue(BunduResultType.hasMissingDepth, (missFieldCnt >= 1));
+        }
+        else {
+            row.putValue(BunduResultType.missDepthFields, fieldNulls);
+            row.putValue(BunduResultType.missWidthFields, fieldNulls);
+            row.putValue(BunduResultType.hasMissingDepth, null);
+        }
+        row.putValue(BunduResultType.missVolumeFields, fieldNulls);
+        row.putValue(BunduResultType.missMassFields, fieldNulls);
         row.putValue(BunduResultType.bedHeightFields, fieldHeights);
         row.putValue(BunduResultType.depthFields, fieldDepths);
 
@@ -240,11 +272,11 @@
     /**
      * Computes the missing volumes in a km range
      */
-    private void computeMissingVolumes(final double kmFrom, final double kmTo, final Calculation problems) {
+    private void computeMissingVolumes(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) {
+            if (isKmInMissingVolumeRange(this.rows.get(j).getDoubleValue(GeneralResultType.station))) {
                 first = j;
                 break;
             }
@@ -252,36 +284,33 @@
         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)
+        for (int i = first; i <= this.rows.size() - 1; i++) {
+            if (!isKmInMissingVolumeRange(this.rows.get(i).getDoubleValue(GeneralResultType.station)))
                 break;
-            if (this.rows.get(i).getDoubleValue(GeneralResultType.station) > kmTo - 0.0001)
+            if (this.rows.get(i).getDoubleValue(GeneralResultType.station) > this.missKmTo.doubleValue() - 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));
                 }
             }
+            final double[] meanBedVolumeArea = computeMeanBedMissingAreaAndVolume(i, first, last);
+            this.rows.get(i).putValue(BunduResultType.missVolumeMeanBed, meanBedVolumeArea[0]);
+            this.rows.get(i).putValue(BunduResultType.missAreaMeanBed, meanBedVolumeArea[1]);
             this.rows.get(i).putValue(BunduResultType.missVolumeFields, volumes);
-            // TODO: berechnete masse hier einfügen!
-            this.rows.get(i).putValue(BunduResultType.missMassFields, 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++;
+            this.rows.get(i).putValue(BunduResultType.excavationCosts, vExcav * EXPENSE_PER_CBM);
         }
     }
 
@@ -290,21 +319,21 @@
      */
     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)));
+        final double area1 = Double.isNaN(kmPrev) ? 0.0 : 0.5 * (areaCurr + areaPrev);
+        final double area2 = Double.isNaN(kmNext) ? 0.0 : 0.5 * (areaCurr + areaNext);
+        final double volume = Double.valueOf((Math.abs(kmCurr - kmPrev) * 500 * area1) + (Math.abs(kmNext - kmCurr) * 500 * area2));
+        volumes.add(volume);
+        if (!Double.isNaN(volume))
             areas.add(Double.valueOf(area1 + area2));
-        }
+        else
+            areas.add(Double.NaN);
     }
 
     /**
@@ -318,13 +347,69 @@
     }
 
     /**
+     * Computes the missing area and volume of the mean bed height of a km row
+     */
+    private double[] computeMeanBedMissingAreaAndVolume(final int current, final int first, final int last) {
+
+        final double areaCurr = meanBedMissingArea(current, first, last);
+        final double areaPrev = meanBedMissingArea(current - 1, first, last);
+        final double areaNext = meanBedMissingArea(current + 1, first, last);
+        final double kmCurr = missingKm(current);
+        final double kmPrev = missingKm(current - 1);
+        final double kmNext = missingKm(current + 1);
+        final double area1 = Double.isNaN(kmPrev) ? 0.0 : 0.5 * (areaCurr + areaPrev);
+        final double area2 = Double.isNaN(kmNext) ? 0.0 : 0.5 * (areaCurr + areaNext);
+        final double volume = Double.valueOf((Math.abs(kmCurr - kmPrev) * 500 * area1) + (Math.abs(kmNext - kmCurr) * 500 * area2));
+        final double area = Double.isNaN(volume) ? Double.NaN : Double.valueOf(area1 + area2);
+        return new double[] { volume, area };
+    }
+
+    /**
+     * Gets the missing area of the mean bed height and a row if in range, otherwise 0.0
+     */
+    private double meanBedMissingArea(final int rowIndex, final int first, final int last) {
+        if ((first <= rowIndex) && (rowIndex <= last)) {
+            final double dh = this.rows.get(rowIndex).getDoubleValue(BunduResultType.channelDepth)
+                    - this.rows.get(rowIndex).getDoubleValue(SInfoResultType.flowdepth);
+            if (dh > 0.0)
+                return dh * this.rows.get(rowIndex).getDoubleValue(BunduResultType.channelWidth);
+            return 0.0;
+        }
+        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;
+        return Double.NaN;
+    }
+
+    /**
+     * Computes the missing masses
+     */
+    private void computeMissingMasses(final Calculation problems) {
+        for (final ResultRow row : this.rows) {
+            @SuppressWarnings("unchecked")
+            final List<Double> volumes = (List<Double>) row.getValue(BunduResultType.missVolumeFields);
+            if ((volumes == null) || Double.isNaN(volumes.get(0)))
+                continue;
+            final double density = getDensity(row.getDoubleValue(GeneralResultType.station));
+            final List<Double> masses = new ArrayList<>();
+            double kmTotal = 0.0;
+            for (int j = BedHeightValueType.FIELD_FIRST_INDEX; j <= BedHeightValueType.FIELD_LAST_INDEX; j++) {
+                final double m = volumes.get(j - 1) * density;
+                masses.add(m);
+                if (!Double.isNaN(m))
+                    kmTotal += m;
+            }
+            row.putValue(BunduResultType.density, density);
+            row.putValue(BunduResultType.missMassFields, masses);
+            row.putValue(BunduResultType.missMassTotal, kmTotal);
+            row.putValue(BunduResultType.missMassMeanBed, row.getDoubleValue(BunduResultType.missVolumeMeanBed) * density);
+        }
     }
 
     /**
@@ -344,23 +429,57 @@
     /**
      * Computes the volume and mass total of all rows with missing volumes
      */
-    private ResultRow createTotalsRow(final double kmFrom, final double kmTo, final Calculation problems) {
+    private ResultRow createTotalsRow(final Calculation problems) {
         // Search start km
         double vTotal = 0.0;
         double mTotal = 0.0;
+        double eTotal = 0.0;
+        double cTotal = 0.0;
         for (final ResultRow row : this.rows) {
-            final double volume = row.getDoubleValue(BunduResultType.missVolumeMeanBed);
-            final double mass = row.getDoubleValue(BunduResultType.missMassMeanBed);
+            final double volume = row.getDoubleValue(BunduResultType.missVolumeTotal);
+            final double mass = row.getDoubleValue(BunduResultType.missMassTotal);
+            final double excavation = row.getDoubleValue(BunduResultType.excavationVolume);
+            final double costs = row.getDoubleValue(BunduResultType.excavationCosts);
             if (!Double.isNaN(volume) && !Double.isNaN(mass)) {
                 vTotal += volume;
                 mTotal += mass;
+                eTotal += excavation;
+                cTotal += costs;
             }
         }
         final ResultRow sumRow = ResultRow.create();
-        sumRow.putValue(BunduResultType.missStationRangeFrom, Double.valueOf(kmFrom));
-        sumRow.putValue(BunduResultType.missStationRangeTo, Double.valueOf(kmTo));
+        sumRow.putValue(BunduResultType.missStationRangeFrom, Double.valueOf(this.missKmFrom));
+        sumRow.putValue(BunduResultType.missStationRangeTo, Double.valueOf(this.missKmTo));
         sumRow.putValue(BunduResultType.missVolumeTotal, vTotal);
         sumRow.putValue(BunduResultType.missMassTotal, mTotal);
+        // TODO sumRow.putValue(BunduResultType.excavationVolumeTotal, eTotal);
+        // TODO sumRow.putValue(BunduResultType.excavationCostsTotal, cTotal);
         return sumRow;
     }
+
+    /**
+     * Copies the rows of the missing volume calculation range into a new list
+     */
+    private List<ResultRow> copyMissRows() {
+        final List<ResultRow> missRows = new ArrayList<>();
+        for (final ResultRow row : this.rows) {
+            final double km = row.getDoubleValue(GeneralResultType.station);
+            if (isKmInMissingVolumeRange(km))
+                missRows.add(row);
+        }
+        return missRows;
+    }
+
+    private double getDensity(final double km) {
+        return 1.73; // TODO
+    }
+
+    /**
+     * Checks whether a km lies in the missing volume calculation range
+     */
+    private boolean isKmInMissingVolumeRange(final double km) {
+        if ((this.missKmFrom == null) || (this.missKmTo == null))
+            return false;
+        return (this.missKmFrom.doubleValue() - 0.0001 < km) && (km < this.missKmTo.doubleValue() + 0.0001);
+    }
 }
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult2.java	Wed Aug 22 14:07:39 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstMissVolCalculationResult2.java	Wed Aug 22 19:12:51 2018 +0200
@@ -82,11 +82,9 @@
 
         header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station));
 
-        for (int i = 1; i <= fieldSize() * 2; i++) {
-            final double index = Math.ceil(i / 2.);
-            header.add(exportContextCSV.msg(fieldVolumeMsgKey, index));
-            i++;
-            header.add(exportContextCSV.msg(fieldMassMsgKey, index));
+        for (int i = 1, j = 1; i <= fieldSize() * 2; i += 2, j++) {
+            header.add(exportContextCSV.msg(fieldVolumeMsgKey, j));
+            header.add(exportContextCSV.msg(fieldMassMsgKey, j));
         }
         header.add(exportContextCSV.formatCsvHeader(BunduResultType.missVolumeMeanBed));
         header.add(exportContextCSV.formatCsvHeader(BunduResultType.missMassMeanBed));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BunduMinfoArtifactWrapper.java	Wed Aug 22 19:12:51 2018 +0200
@@ -0,0 +1,44 @@
+/** 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.bundu.bezugswst;
+
+import java.util.Collection;
+import java.util.Date;
+
+import org.dive4elements.artifactdatabase.data.DefaultStateData;
+import org.dive4elements.artifactdatabase.data.StateData;
+import org.dive4elements.river.artifacts.D4EArtifact;
+
+/**
+ * Wrapper around an (bundu) artifact to be extended and used for calculations that expect a MinfoArtifact
+ * (BedQualityCalculation)
+ *
+ * @author Matthias Schäfer
+ */
+public final class BunduMinfoArtifactWrapper extends D4EArtifact {
+
+    private static final long serialVersionUID = 1L;
+
+    public BunduMinfoArtifactWrapper(final D4EArtifact dataSource, final Date startDay, final Date endDay) {
+
+        final Collection<StateData> allData = dataSource.getAllData();
+        for (final StateData stateData : allData) {
+
+            final DefaultStateData clonedData = new DefaultStateData();
+            clonedData.set(stateData);
+
+            addData(clonedData.getName(), clonedData);
+        }
+
+        addStringData("calculation_mode", "calc.bed.quality");
+        addStringData("bed_diameter", "d50"); // REMARK we don't need any calculation for d50 but the BedQualityCalculation must have at least one diameter
+        addStringData("periods", Long.toString(startDay.getTime()) + "," + Long.toString(endDay.getTime()));
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/resources/messages.properties	Wed Aug 22 14:07:39 2018 +0200
+++ b/artifacts/src/main/resources/messages.properties	Wed Aug 22 19:12:51 2018 +0200
@@ -917,8 +917,8 @@
 bundu.export.bezugswst.pdf.meta.miss.channel.width = Breite Fahr-rinnen-kasten [m]
 bundu.export.bezugswst.csv.meta.miss.costs = Baggerkosten [\u20ac]
 bundu.export.bezugswst.pdf.meta.miss.costs = Bagger-kosten [\u20ac]
-bundu.export.bezugswst.csv.meta.miss.excavation = Baggervolumina [m\u00b3]
-bundu.export.bezugswst.pdf.meta.miss.excavation = Bagger-volumina [m\u00b3]
+bundu.export.bezugswst.csv.meta.miss.excavation = Baggervolumen [m\u00b3]
+bundu.export.bezugswst.pdf.meta.miss.excavation = Bagger-volumen [m\u00b3]
 bundu.export.bezugswst.csv.meta.miss.mass.total = Masse Fehltiefe ges. [t]
 bundu.export.bezugswst.csv.meta.miss.volume.total = Volumen Fehltiefe ges. [m\u00b3]
 bundu.export.bezugswst.csv.meta.miss.exists = Fehltiefe vorhanden?
--- a/artifacts/src/main/resources/messages_de.properties	Wed Aug 22 14:07:39 2018 +0200
+++ b/artifacts/src/main/resources/messages_de.properties	Wed Aug 22 19:12:51 2018 +0200
@@ -917,8 +917,8 @@
 bundu.export.bezugswst.pdf.meta.miss.channel.width = Breite Fahr-rinnen-kasten [m]
 bundu.export.bezugswst.csv.meta.miss.costs = Baggerkosten [\u20ac]
 bundu.export.bezugswst.pdf.meta.miss.costs = Bagger-kosten [\u20ac]
-bundu.export.bezugswst.csv.meta.miss.excavation = Baggervolumina [m\u00b3]
-bundu.export.bezugswst.pdf.meta.miss.excavation = Bagger-volumina [m\u00b3]
+bundu.export.bezugswst.csv.meta.miss.excavation = Baggervolumen [m\u00b3]
+bundu.export.bezugswst.pdf.meta.miss.excavation = Bagger-volumen [m\u00b3]
 bundu.export.bezugswst.csv.meta.miss.mass.total = Masse Fehltiefe ges. [t]
 bundu.export.bezugswst.csv.meta.miss.volume.total = Volumen Fehltiefe ges. [m\u00b3]
 bundu.export.bezugswst.csv.meta.miss.exists = Fehltiefe vorhanden?

http://dive4elements.wald.intevation.org