changeset 4011:bf687419feba

Merged
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Tue, 02 Oct 2012 09:25:41 +0200
parents efb067ab2ca4 (current diff) 60d88ec49c3b (diff)
children 9743bf17fce3
files flys-artifacts/ChangeLog
diffstat 7 files changed, 418 insertions(+), 215 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Measurement.java	Mon Oct 01 10:57:21 2012 +0200
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Measurement.java	Tue Oct 02 09:25:41 2012 +0200
@@ -21,10 +21,7 @@
 
     protected List<Sieve> sieves;
 
-    protected SieveArray  sieveArray;
-
-    protected Measurement prev;
-    protected Measurement next;
+    protected SieveArray sieveArray;
 
     public Measurement() {
     }
@@ -32,16 +29,6 @@
     public Measurement(Map<String, Object> data, List<Sieve> sieves) {
         this.data = data;
         this.sieves = sieves;
-        adjustOriginalSieves();
-        this.sieveArray = calculateSieveArray();
-    }
-
-    public Measurement head() {
-        Measurement current = this;
-        while (current.prev != null) {
-            current = current.prev;
-        }
-        return current;
     }
 
     protected double get(String name) {
@@ -53,10 +40,14 @@
         data.put(name, Double.valueOf(value));
     }
 
-    protected Object getData(String name) {
+    public Object getData(String name) {
         return data.get(name);
     }
 
+    public Map<String, Object> getData() {
+        return data;
+    }
+
     protected void putData(String name, Object value) {
         data.put(name, value);
     }
@@ -78,18 +69,15 @@
     }
 
     public double BL_G() {
-        // TODO: Implement me!
-        return Double.NaN;
+        return get("BL_G");
     }
 
     public double BL_C() {
-        // TODO: Implement me!
-        return Double.NaN;
+        return get("BL_C");
     }
 
     public double BL_S() {
-        // TODO: Implement me!
-        return Double.NaN;
+        return get("BL_S");
     }
 
     public double S_BL_S() {
@@ -132,43 +120,10 @@
      * @return The sieveArray.
      */
     public SieveArray getSieveArray() {
-        return this.sieveArray;
-    }
-
-    /**
-     * Gets the prev for this instance.
-     *
-     * @return The prev.
-     */
-    public Measurement getPrev() {
-        return this.prev;
-    }
-
-    /**
-     * Sets the prev for this instance.
-     *
-     * @param prev The prev.
-     */
-    public void setPrev(Measurement prev) {
-        this.prev = prev;
-    }
-
-    /**
-     * Gets the next for this instance.
-     *
-     * @return The next.
-     */
-    public Measurement getNext() {
-        return this.next;
-    }
-
-    /**
-     * Sets the next for this instance.
-     *
-     * @param next The next.
-     */
-    public void setNext(Measurement next) {
-        this.next = next;
+        if (sieveArray == null) {
+            sieveArray = calculateSieveArray();
+        }
+        return sieveArray;
     }
 
     protected Sieve findSieve(double diameter) {
@@ -189,7 +144,7 @@
         }
     }
 
-    protected void adjustOriginalSieves() {
+    public void adjustSieves() {
 
         // If we already have an 8mm diameter sieve
         // we dont need to 'invent' it.
@@ -206,7 +161,7 @@
         Sieve four = findSieve(4d);
 
         if (six == null || ten == null || four == null) {
-            log.warn("missind diameter");
+            log.warn("missing diameter");
             return;
         }
 
@@ -221,10 +176,9 @@
 
         sieves.add(new Sieve(8d, eightValue));
         sieves.add(new Sieve(4d, newFourValue));
-   }
+    }
 
-
-    public SieveArray calculateSieveArray() {
+    protected SieveArray calculateSieveArray() {
 
         SieveArray sa = new SieveArray();
 
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/MeasurementFactory.java	Mon Oct 01 10:57:21 2012 +0200
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/MeasurementFactory.java	Tue Oct 02 09:25:41 2012 +0200
@@ -1,16 +1,13 @@
 package de.intevation.flys.artifacts.model.sq;
 
 import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
-
-import de.intevation.flys.artifacts.model.DateRange;
-
-import de.intevation.flys.backend.SedDBSessionHolder;
-
-import java.util.HashMap;
 import java.util.Map;
-
-import org.apache.log4j.Logger;
+import java.util.TreeMap;
 
 import org.hibernate.SQLQuery;
 import org.hibernate.Session;
@@ -19,77 +16,75 @@
 
 import org.hibernate.type.StandardBasicTypes;
 
+import de.intevation.flys.artifacts.model.DateRange;
+
+import de.intevation.flys.backend.SedDBSessionHolder;
+
 public class MeasurementFactory
 {
-    private static final Logger log =
-        Logger.getLogger(MeasurementFactory.class);
+    public static final String SQL_TOTALS =
+        "SELECT " +
+            "m.Q_BPEGEL AS Q_BPEGEL,"+
+            "m.TSCHWEB  AS TSCHWEB," +
+            "m.TSAND    AS TSAND " +
+        "FROM MESSUNG m " +
+            "JOIN STATION   s ON m.STATIONID   = s.STATIONID " +
+            "JOIN GEWAESSER r ON s.GEWAESSERID = r.GEWAESSERID " +
+        "WHERE " +
+            "r.NAME = :river_name " +
+            "AND m.Q_BPEGEL IS NOT NULL " +
+            "AND s.KM BETWEEN :location - 0.001 AND :location + 0.001 " +
+            "AND m.DATUM BETWEEN :from AND :to " +
+            "AND m.DATUM IS NOT NULL";
 
-    public static final String SQL_MEASSURE =
-        "SELECT m.datum        AS DATUM," +
-               "g.GLOTRECHTEID AS GLOTRECHTEID," +
-               "gp.LFDNR       AS LFDNR," +
-               "g.UFERABST     AS UFERABST," +
-               "g.UFERABLINKS  AS UFERABLINKS," +
-               "m.TSCHWEB      AS TSCHWEB," +
-               "m.TSAND        AS TSAND," +
-               "gp.MESSDAUER   AS MESSDAUER," +
-               "gp.MENGE       AS MENGE," +
-               "gp.GTRIEB      AS GTRIEB," +
-               "m.TGESCHIEBE   AS TGESCHIEBE," +
-               "sie.SIEB01     AS SIEB01," +
-               "sie.SIEB02     AS SIEB02," +
-               "sie.SIEB03     AS SIEB03," +
-               "sie.SIEB04     AS SIEB04," +
-               "sie.SIEB05     AS SIEB05," +
-               "sie.SIEB06     AS SIEB06," +
-               "sie.SIEB07     AS SIEB07," +
-               "sie.SIEB08     AS SIEB08," +
-               "sie.SIEB09     AS SIEB09," +
-               "sie.SIEB10     AS SIEB10," +
-               "sie.SIEB11     AS SIEB11," +
-               "sie.SIEB12     AS SIEB12," +
-               "sie.SIEB13     AS SIEB13," +
-               "sie.SIEB14     AS SIEB14," +
-               "sie.SIEB15     AS SIEB15," +
-               "sie.SIEB16     AS SIEB16," +
-               "sie.SIEB17     AS SIEB17," +
-               "sie.SIEB18     AS SIEB18," +
-               "sie.SIEB19     AS SIEB19," +
-               "sie.SIEB20     AS SIEB20," +
-               "sie.SIEB21     AS SIEB21," +
-               "gs.RSIEB01     AS RSIEB01," +
-               "gs.RSIEB02     AS RSIEB02," +
-               "gs.RSIEB03     AS RSIEB03," +
-               "gs.RSIEB04     AS RSIEB04," +
-               "gs.RSIEB05     AS RSIEB05," +
-               "gs.RSIEB06     AS RSIEB06," +
-               "gs.RSIEB07     AS RSIEB07," +
-               "gs.RSIEB08     AS RSIEB08," +
-               "gs.RSIEB09     AS RSIEB09," +
-               "gs.RSIEB10     AS RSIEB10," +
-               "gs.RSIEB11     AS RSIEB11," +
-               "gs.RSIEB12     AS RSIEB12," +
-               "gs.RSIEB13     AS RSIEB13," +
-               "gs.RSIEB14     AS RSIEB14," +
-               "gs.RSIEB15     AS RSIEB15," +
-               "gs.RSIEB16     AS RSIEB16," +
-               "gs.RSIEB17     AS RSIEB17," +
-               "gs.RSIEB18     AS RSIEB18," +
-               "gs.RSIEB19     AS RSIEB19," +
-               "gs.RSIEB20     AS RSIEB20," +
-               "gs.RSIEB21     AS RSIEB21," +
-               "gs.REST        AS REST " +
+    public static final String SQL_FACTIONS =
+        "SELECT " +
+            "m.datum        AS DATUM," +
+            "m.Q_BPEGEL     AS Q_BPEGEL,"+
+            "g.GLOTRECHTEID AS GLOTRECHTEID," +
+            "gp.LFDNR       AS LFDNR," +
+            "g.UFERABST     AS UFERABST," +
+            "g.UFERABLINKS  AS UFERABLINKS," +
+            "m.TSCHWEB      AS TSCHWEB," +
+            "m.TSAND        AS TSAND," +
+            "gp.GTRIEB      AS GTRIEB," +
+            "m.TGESCHIEBE   AS TGESCHIEBE," +
+            "si.SIEB01 AS SIEB01, si.SIEB02 AS SIEB02," +
+            "si.SIEB03 AS SIEB03, si.SIEB04 AS SIEB04," +
+            "si.SIEB05 AS SIEB05, si.SIEB06 AS SIEB06," +
+            "si.SIEB07 AS SIEB07, si.SIEB08 AS SIEB08," +
+            "si.SIEB09 AS SIEB09, si.SIEB10 AS SIEB10," +
+            "si.SIEB11 AS SIEB11, si.SIEB12 AS SIEB12," +
+            "si.SIEB13 AS SIEB13, si.SIEB14 AS SIEB14," +
+            "si.SIEB15 AS SIEB15, si.SIEB16 AS SIEB16," +
+            "si.SIEB17 AS SIEB17, si.SIEB18 AS SIEB18," +
+            "si.SIEB19 AS SIEB19, si.SIEB20 AS SIEB20," +
+            "si.SIEB21 AS SIEB21," +
+            "gs.RSIEB01 AS RSIEB01, gs.RSIEB02 AS RSIEB02," +
+            "gs.RSIEB03 AS RSIEB03, gs.RSIEB04 AS RSIEB04," +
+            "gs.RSIEB05 AS RSIEB05, gs.RSIEB06 AS RSIEB06," +
+            "gs.RSIEB07 AS RSIEB07, gs.RSIEB08 AS RSIEB08," +
+            "gs.RSIEB09 AS RSIEB09, gs.RSIEB10 AS RSIEB10," +
+            "gs.RSIEB11 AS RSIEB11, gs.RSIEB12 AS RSIEB12," +
+            "gs.RSIEB13 AS RSIEB13, gs.RSIEB14 AS RSIEB14," +
+            "gs.RSIEB15 AS RSIEB15, gs.RSIEB16 AS RSIEB16," +
+            "gs.RSIEB17 AS RSIEB17, gs.RSIEB18 AS RSIEB18," +
+            "gs.RSIEB19 AS RSIEB19, gs.RSIEB20 AS RSIEB20," +
+            "gs.RSIEB21 AS RSIEB21, gs.REST    AS REST " +
         "FROM MESSUNG m " +
             "JOIN STATION    s ON m.STATIONID    = s.STATIONID " +
-            "JOIN glotrechte g ON m.MESSUNGID    = g.MESSUNGID " +
-            "JOIN gprobe    gp ON g.GLOTRECHTEID = gp.GLOTRECHTEID " +
+            "JOIN GEWAESSER  r ON s.GEWAESSERID  = r.GEWAESSERID " +
+            "JOIN GLOTRECHTE g ON m.MESSUNGID    = g.MESSUNGID " +
+            "JOIN GPROBE    gp ON g.GLOTRECHTEID = gp.GLOTRECHTEID " +
             "JOIN GSIEBUNG  gs ON g.GLOTRECHTEID = gs.GLOTRECHTEID " +
+            "JOIN GSIEBSATZ si ON m.GSIEBSATZID  = si.GSIEBSATZID " +
         "WHERE " +
-            "g.NAME = :river_name " +
+            "r.NAME = :river_name " +
             "AND m.Q_BPEGEL IS NOT NULL " +
             "AND s.KM BETWEEN :location - 0.001 AND :location + 0.001 " +
             "AND m.DATUM BETWEEN :from AND :to " +
             "AND m.TGESCHIEBE IS NOT NULL " +
+            "AND m.DATUM IS NOT NULL " +
             "AND (" +
                 "COALESCE(gs.RSIEB01, 0) + COALESCE(gs.RSIEB02, 0) +" +
                 "COALESCE(gs.RSIEB03, 0) + COALESCE(gs.RSIEB04, 0) +" +
@@ -102,75 +97,125 @@
                 "COALESCE(gs.RSIEB17, 0) + COALESCE(gs.RSIEB18, 0) +" +
                 "COALESCE(gs.RSIEB19, 0) + COALESCE(gs.RSIEB20, 0) +" +
                 "COALESCE(gs.RSIEB21, 0) + COALESCE(gs.REST, 0)) > 0 " +
-        "ORDER BY m.DATUM, gp.LFDNR, g.UFERABST";
-
-    public static final class MeasurementResultTransformer
-    extends                   BasicTransformerAdapter
-    {
-        public static MeasurementResultTransformer INSTANCE =
-            new MeasurementResultTransformer();
-
-        public MeasurementResultTransformer() {
-        }
-
-        private static final int index(String s) {
-            return Integer.parseInt(s.substring(s.length()-2))-1;
-        }
+        "ORDER BY " +
+            "m.DATUM, g.UFERABST, g.GLOTRECHTEID, gp.LFDNR";
 
-        @Override
-        public Object transformTuple(Object [] tuple, String [] aliases) {
-            Map<String, Object> map = new HashMap<String, Object>();
-
-            Sieve [] sieves = new Sieve[20];
-
-            List<Sieve> validSieves = new ArrayList<Sieve>(20);
+    public static final BasicTransformerAdapter TOTALS_TRANSFORMER =
+        new BasicTransformerAdapter() {
+			private static final long serialVersionUID = 1L;
 
-            for (int i = 0; i < tuple.length; ++i) {
-                Object value = tuple[i];
-                if (value == null) {
-                    continue;
+			@Override
+            public Object transformTuple(Object [] tuple, String [] aliases) {
+                Map<String, Object> map = new HashMap<String, Object>();
+                for (int i = 0; i < tuple.length; ++i) {
+                    Object value = tuple[i];
+                    if (value != null) {
+                        map.put(aliases[i], value);
+                    }
                 }
-                String alias = aliases[i];
-                if (alias.startsWith("SIEB")) {
-                    Sieve s = new Sieve((Double)value, 0d);
-                    sieves[index(alias)] = s;
-                }
-                else if (alias.startsWith("RSIEB")) {
-                    Sieve s = sieves[index(alias)];
-                    if (s != null) {
-                        s.setLoad((Double)value);
+                return new Measurement(map, Collections.<Sieve>emptyList());
+            }
+        };
+
+    private static final int index(String s) {
+        return Integer.parseInt(s.substring(s.length()-2))-1;
+    }
+
+    public static final BasicTransformerAdapter FRACTIONS_TRANSFORMER =
+        new BasicTransformerAdapter() {
+			private static final long serialVersionUID = 1L;
+
+            @Override
+            public Object transformTuple(Object [] tuple, String [] aliases) {
+                Map<String, Object> map = new HashMap<String, Object>();
+
+                Sieve [] sieves = new Sieve[21];
+
+                List<Sieve> validSieves = new ArrayList<Sieve>(21);
+
+                for (int i = 0; i < tuple.length; ++i) {
+                    Object value = tuple[i];
+                    if (value == null) {
+                        continue;
+                    }
+                    String alias = aliases[i];
+                    if (alias.startsWith("SIEB")) {
+                        Sieve s = new Sieve((Double)value, 0d);
+                        sieves[index(alias)] = s;
+                    }
+                    else if (alias.startsWith("RSIEB")) {
+                        Sieve s = sieves[index(alias)];
+                        if (s != null) {
+                            s.setLoad((Double)value);
+                            validSieves.add(s);
+                        }
+                    }
+                    else if (alias.equals("REST")) {
+                        Sieve s = new Sieve(0d, (Double)value);
                         validSieves.add(s);
                     }
-                }
-                else if (alias.equals("REST")) {
-                    Sieve s = new Sieve(0d, (Double)value);
-                    validSieves.add(s);
+                    else {
+                        map.put(alias, value);
+                    }
                 }
-                else {
-                    map.put(alias, value);
-                }
+
+                return new Measurement(map, validSieves);
             }
-
-            return new Measurement(map, validSieves);
-        }
-    } // class BasicTransformerAdapter
+        };
 
     private MeasurementFactory() {
     }
 
-    protected static Measurements load(
+    public static Measurements getMeasurements(
+        String    river,
+        double    location,
+        DateRange dateRange
+    ) {
+        Session session = SedDBSessionHolder.HOLDER.get();
+        try {
+            List<Measurement> totals = loadTotals(
+                session, river, location, dateRange);
+
+            List<Measurement> accumulated = loadFractions(
+                session, river, location, dateRange);
+
+            return new Measurements(totals, accumulated);
+        }
+        finally {
+            session.close();
+        }
+    }
+
+    protected static List<Measurement> loadTotals(
         Session   session,
         String    river,
         double    location,
         DateRange dateRange
     ) {
-        boolean debug = log.isDebugEnabled();
+        SQLQuery query = session.createSQLQuery(SQL_TOTALS)
+            .addScalar("Q_BPEGEL", StandardBasicTypes.DOUBLE)
+            .addScalar("TSCHWEB",  StandardBasicTypes.DOUBLE)
+            .addScalar("TSAND",    StandardBasicTypes.DOUBLE);
 
-        if (debug) {
-            log.debug(SQL_MEASSURE);
-        }
+        query.setString("river_name", river);
+        query.setDouble("location", location);
+        query.setDate("from", dateRange.getFrom());
+        query.setDate("to", dateRange.getTo());
 
-        SQLQuery query = session.createSQLQuery(SQL_MEASSURE)
+        query.setResultTransformer(TOTALS_TRANSFORMER);
+
+        @SuppressWarnings("unchecked")
+        List<Measurement> result = (List<Measurement>)query.list();
+        return result;
+    }
+
+    protected static List<Measurement> loadFractions(
+        Session   session,
+        String    river,
+        double    location,
+        DateRange dateRange
+    ) {
+        SQLQuery query = session.createSQLQuery(SQL_FACTIONS)
             .addScalar("Q_BPEGEL",     StandardBasicTypes.DOUBLE)
             .addScalar("DATUM",        StandardBasicTypes.DATE)
             .addScalar("GLOTRECHTEID", StandardBasicTypes.INTEGER)
@@ -179,8 +224,6 @@
             .addScalar("UFERABLINKS",  StandardBasicTypes.DOUBLE)
             .addScalar("TSCHWEB",      StandardBasicTypes.DOUBLE)
             .addScalar("TSAND",        StandardBasicTypes.DOUBLE)
-            .addScalar("MESSDAUER",    StandardBasicTypes.DOUBLE)
-            .addScalar("MENGE",        StandardBasicTypes.DOUBLE)
             .addScalar("GTRIEB",       StandardBasicTypes.DOUBLE)
             .addScalar("TGESCHIEBE",   StandardBasicTypes.DOUBLE)
             .addScalar("RSIEB01",      StandardBasicTypes.DOUBLE)
@@ -232,48 +275,183 @@
         query.setDate("from", dateRange.getFrom());
         query.setDate("to", dateRange.getTo());
 
-        query.setResultTransformer(MeasurementResultTransformer.INSTANCE);
+        query.setResultTransformer(FRACTIONS_TRANSFORMER);
 
         @SuppressWarnings("unchecked")
-		List<Measurement> measuments = (List<Measurement>)query.list();
+        List<Measurement> measuments = (List<Measurement>)query.list();
+
+        List<Measurement> same = new ArrayList<Measurement>();
 
         Integer lastLR = null;
 
-        for (int i = 0, N = measuments.size(); i < N; ++i) {
-            Measurement m = measuments.get(i);
+        List<Measurement> accumulated = new ArrayList<Measurement>();
+
+        for (Measurement m: measuments) {
 
             Integer currentLR = (Integer)m.getData("GLOTRECHTEID");
 
             boolean newDS = lastLR == null
                 || (currentLR != null && !lastLR.equals(currentLR));
 
-            Measurement p = i >   0 ? measuments.get(i-1) : null;
-            Measurement n = i < N-1 ? measuments.get(i+1) : null;
-            m.setPrev(newDS ? null : p);
-            m.setNext(n);
-
-            if (p != null && newDS) {
-                p.setNext(null);
+            if (newDS && !same.isEmpty()) {
+                accumulated.add(accumulate(same));
+                same.clear();
             }
 
             lastLR = currentLR;
         }
 
-        return new Measurements(measuments);
+        if (!same.isEmpty()) {
+            accumulated.add(accumulate(same));
+        }
+
+        for (Measurement m: accumulated) {
+            m.adjustSieves();
+        }
+
+        return separateByDate(accumulated);
     }
 
-    public static Measurements getMeasurements(
-        String    river,
-        double    location,
-        DateRange dateRange
-    ) {
-        Session session = SedDBSessionHolder.HOLDER.get();
-        try {
-            return load(session, river, location, dateRange);
+    protected static List<Measurement> separateByDate(List<Measurement> measurements) {
+
+        List<Measurement> result = new ArrayList<Measurement>();
+
+        List<Measurement> same = new ArrayList<Measurement>();
+
+        Date lastDate = null;
+
+        for (Measurement m: measurements) {
+            Date currentDate = (Date)m.getData("DATUM");
+            if ((lastDate == null
+            || !equalDate(currentDate, lastDate))
+            && !same.isEmpty()
+            ) {
+                result.add(processSameDate(same));
+                same.clear();
+            }
+            same.add(m);
+            lastDate = currentDate;
         }
-        finally {
-            session.close();
+
+        if (!same.isEmpty()) {
+            result.add(processSameDate(same));
         }
+
+        return result;
+    }
+
+
+    protected static Measurement processSameDate(List<Measurement> measurements) {
+        int N = measurements.size();
+        if (N == 1) {
+            Measurement current = measurements.get(0);
+            double left = current.get("UFERABLINKS");
+            double right = current.get("UFERABST");
+            current.set("EFFWIDTH", left + right);
+        }
+        else {
+            for (int i = 0; i < N; ++i) {
+                Measurement current = measurements.get(i);
+
+                if (i == 0) {
+                    Measurement next = measurements.get(i+1);
+                    double distCurrent = current.get("UFERABST");
+                    double distNext = next.get("UFERABST");
+                    current.set("EFFWIDTH", distNext - distCurrent);
+                }
+                else if (i == N-1) {
+                    Measurement prev = measurements.get(i-1);
+                    double distCurrent = current.get("UFERABST");
+                    double distPrev = prev.get("UFERABST");
+                    current.set("EFFWIDTH", distCurrent - distPrev);
+                }
+                else {
+                    Measurement prev = measurements.get(i-1);
+                    Measurement next = measurements.get(i+1);
+                    double distPrev = prev.get("UFERABST");
+                    double distNext = next.get("UFERABST");
+                    current.set("EFFWIDTH", 0.5*(distNext - distPrev));
+                }
+            }
+        }
+
+        double sumSandF   = 0d;
+        double sumCoarseF = 0d;
+        double sumGravelF = 0d;
+        double sumNorm    = 0d;
+
+        for (Measurement m: measurements) {
+            SieveArray sa   = m.getSieveArray();
+            double sandF    = sa.sandNormFraction();
+            double coarseF  = sa.coarseNormFraction();
+            double gravelF  = sa.gravelNormFraction();
+            double effWidth = m.get("EFFWIDTH");
+            double gt       = m.get("GTRIEB");
+            double scale    = effWidth*gt;
+            sumSandF   += scale*sandF;
+            sumCoarseF += scale*coarseF;
+            sumGravelF += scale*gravelF;
+            sumNorm    += scale;
+        }
+
+        Map<String, Object> data =
+            new HashMap<String, Object>(measurements.get(0).getData());
+
+        Measurement m = new Measurement(data, Collections.<Sieve>emptyList());
+
+        sumNorm = 1d/sumNorm;
+
+        m.set("BL_S", sumNorm*sumSandF);
+        m.set("BL_G", sumNorm*sumGravelF);
+        m.set("BL_C", sumNorm*sumCoarseF);
+
+        return m;
+    }
+
+
+    private static final boolean equalDate(Date a, Date b) {
+        Calendar ca = Calendar.getInstance();
+        Calendar cb = Calendar.getInstance();
+        ca.setTime(a);
+        cb.setTime(b);
+        return ca.get(Calendar.YEAR)         == cb.get(Calendar.YEAR)
+            && ca.get(Calendar.MONTH)        == cb.get(Calendar.MONTH)
+            && ca.get(Calendar.DAY_OF_MONTH) == cb.get(Calendar.DAY_OF_MONTH);
+    }
+
+
+    protected static Measurement accumulate(List<Measurement> measuments) {
+
+        int N = measuments.size();
+        if (N == 1) {
+            return measuments.get(0);
+        }
+
+        TreeMap<Double, double []> diameters =
+            new TreeMap<Double, double []>(Sieve.DIAMETER_CMP);
+
+        for (Measurement m: measuments) {
+            for (Sieve s: m.getSieves()) {
+                Double key = s.getDiameter();
+                double [] sum = diameters.get(key);
+                if (sum == null) {
+                    sum = new double[1];
+                    diameters.put(key, sum);
+                }
+                sum[0] += s.getLoad();
+            }
+        }
+        List<Sieve> accumulatedSieves = new ArrayList<Sieve>(diameters.size());
+        for (Map.Entry<Double, double []> entry: diameters.entrySet()) {
+            accumulatedSieves.add(
+                new Sieve(entry.getKey(),
+                    entry.getValue()[0]/N));
+        }
+
+        Map<String, Object> data =
+            new HashMap<String, Object>(measuments.get(0).getData());
+
+        return new Measurement(data, accumulatedSieves);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Measurements.java	Mon Oct 01 10:57:21 2012 +0200
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Measurements.java	Tue Oct 02 09:25:41 2012 +0200
@@ -56,16 +56,24 @@
     };
 
     protected List<Measurement> measuments;
+    protected List<Measurement> accumulated;
 
     public Measurements() {
     }
 
-    public Measurements(List<Measurement> measuments) {
+    public Measurements(
+        List<Measurement> measuments,
+        List<Measurement> accumulated
+    ) {
         this.measuments = measuments;
+        this.accumulated = accumulated;
     }
 
-    public List<SQ> extractSQ(SExtractor extractor) {
-        List<SQ> result = new ArrayList(measuments.size());
+    public static List<SQ> extractSQ(
+        List<Measurement> measuments,
+        SExtractor extractor
+    ) {
+        List<SQ> result = new ArrayList<SQ>(measuments.size());
         for (Measurement measument: measuments) {
             SQ sq = new SQ(extractor.getS(measument), measument.Q());
             if (sq.isValid()) {
@@ -76,27 +84,27 @@
     }
 
     public List<SQ> S_SF() {
-        return extractSQ(S_SF_EXTRACTOR);
+        return extractSQ(measuments, S_SF_EXTRACTOR);
     }
 
     public List<SQ> S_SS() {
-        return extractSQ(S_SS_EXTRACTOR);
+        return extractSQ(measuments, S_SS_EXTRACTOR);
     }
 
     public List<SQ> S_BL_S() {
-        return extractSQ(S_BL_S_EXTRACTOR);
+        return extractSQ(accumulated, S_BL_S_EXTRACTOR);
     }
 
     public List<SQ> S_BL_FG() {
-        return extractSQ(S_BL_FG_EXTRACTOR);
+        return extractSQ(accumulated, S_BL_FG_EXTRACTOR);
     }
 
     public List<SQ> S_BL_CG() {
-        return extractSQ(S_BL_CG_EXTRACTOR);
+        return extractSQ(accumulated, S_BL_CG_EXTRACTOR);
     }
 
     public List<SQ> S_BL() {
-        return extractSQ(S_BL_EXTRACTOR);
+        return extractSQ(accumulated, S_BL_EXTRACTOR);
     }
 
     public List<SQ> getSQs(int index) {
@@ -112,6 +120,25 @@
         return new ArrayList<SQ>(0);
     }
 
+    /**
+     * Gets the accumulated for this instance.
+     *
+     * @return The accumulated.
+     */
+    public List<Measurement> getAccumulated() {
+        return this.accumulated;
+    }
+
+    /**
+     * Sets the accumulated for this instance.
+     *
+     * @param accumulated The accumulated.
+     */
+    public void setAccumulated(List<Measurement> accumulated) {
+        this.accumulated = accumulated;
+    }
+
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder("Measurements [");
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Sieve.java	Mon Oct 01 10:57:21 2012 +0200
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Sieve.java	Tue Oct 02 09:25:41 2012 +0200
@@ -1,9 +1,22 @@
 package de.intevation.flys.artifacts.model.sq;
 
+import java.util.Comparator;
+
 public class Sieve
 {
     public static final double EPSILON = 1e-6;
 
+    public static final Comparator<Double> DIAMETER_CMP =
+        new Comparator<Double>() {
+            @Override
+            public int compare(Double a, Double b) {
+                double diff = a - b;
+                if (diff < -EPSILON) return -1;
+                if (diff >  EPSILON) return +1;
+                return 0;
+            }
+        };
+
     protected double diameter;
     protected double load;
 
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SieveArray.java	Mon Oct 01 10:57:21 2012 +0200
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/SieveArray.java	Tue Oct 02 09:25:41 2012 +0200
@@ -42,6 +42,7 @@
     public void calculateNormLoads() {
         double total = totalLoad();
         if (Math.abs(total) < EPSILON) {
+            System.arraycopy(loads, 0, normLoads, 0, loads.length);
             return;
         }
         total = 1d/total;
@@ -87,5 +88,29 @@
     public double getNormLoads(int index) {
         return this.normLoads[index];
     }
+
+    public double sandNormFraction() {
+        double sum = 0d;
+        for (int i = 8; i < normLoads.length; ++i) {
+            sum += normLoads[i];
+        }
+        return sum;
+    }
+
+    public double coarseNormFraction() {
+        double sum = 0d;
+        for (int i = 0; i < 4; ++i) {
+            sum += normLoads[i];
+        }
+        return sum;
+    }
+
+    public double gravelNormFraction() {
+        double sum = 0d;
+        for (int i = 4; i < 8; ++i) {
+            sum += normLoads[i];
+        }
+        return sum;
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/flys-client/ChangeLog	Mon Oct 01 10:57:21 2012 +0200
+++ b/flys-client/ChangeLog	Tue Oct 02 09:25:41 2012 +0200
@@ -1,3 +1,8 @@
+2012-10-01	Björn Ricks	<bjoern.ricks@intevation.de>
+
+	* src/main/java/de/intevation/flys/client/client/ui/ParameterMatrixPanel.java
+	  Add missing import of FLYSConstants
+
 2012-10-01	Björn Ricks	<bjoern.ricks@intevation.de>
 
 	* src/main/java/de/intevation/flys/client/server/FLYSArtifactCreator.java:
--- a/flys-client/src/main/java/de/intevation/flys/client/client/ui/ParameterMatrixPanel.java	Mon Oct 01 10:57:21 2012 +0200
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/ParameterMatrixPanel.java	Tue Oct 02 09:25:41 2012 +0200
@@ -14,6 +14,7 @@
 import com.smartgwt.client.widgets.layout.HLayout;
 import com.smartgwt.client.widgets.layout.VLayout;
 
+import de.intevation.flys.client.client.FLYSConstants;
 import de.intevation.flys.client.shared.model.Data;
 import de.intevation.flys.client.shared.model.DataItem;
 import de.intevation.flys.client.shared.model.DataList;

http://dive4elements.wald.intevation.org