mschaefer@8898: /* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde mschaefer@8898: * Software engineering by mschaefer@8898: * Björnsen Beratende Ingenieure GmbH mschaefer@8898: * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt mschaefer@8898: * mschaefer@8898: * This file is Free Software under the GNU AGPL (>=v3) mschaefer@8898: * and comes with ABSOLUTELY NO WARRANTY! Check out the mschaefer@8898: * documentation coming with Dive4Elements River for details. mschaefer@8898: */ mschaefer@8898: gernotbelger@8915: package org.dive4elements.river.artifacts.sinfo.tkhcalculation; mschaefer@8898: mschaefer@8898: import java.util.List; mschaefer@8952: import java.util.Map.Entry; mschaefer@8952: import java.util.NavigableMap; mschaefer@8952: import java.util.TreeMap; mschaefer@8898: mschaefer@8898: import org.apache.commons.lang.math.DoubleRange; gernotbelger@8964: import org.dive4elements.river.artifacts.model.Calculation; mschaefer@8952: import org.dive4elements.river.backend.SessionHolder; mschaefer@8898: import org.dive4elements.river.model.River; mschaefer@8952: import org.hibernate.SQLQuery; mschaefer@8952: import org.hibernate.Session; mschaefer@8952: import org.hibernate.type.StandardBasicTypes; mschaefer@8898: mschaefer@8898: /** gernotbelger@8915: * @author Matthias Schäfer mschaefer@8898: */ mschaefer@9016: public final class SoilKindKmValueFinder { mschaefer@8952: mschaefer@8952: /***** FIELDS *****/ mschaefer@8952: gernotbelger@8915: // private static Logger log = Logger.getLogger(SoilKindKmValueFinder.class); gernotbelger@8915: mschaefer@8952: /** mschaefer@8952: * Query selecting the bed mobility attribute for a range of stations of a river mschaefer@8952: */ mschaefer@8952: private static final String SQL_BED_MOBILITY = "SELECT bmv.station, bmv.moving" mschaefer@8952: + " FROM bed_mobility bm INNER JOIN bed_mobility_values bmv ON bm.id = bmv.bed_mobility_id" gernotbelger@8964: + " WHERE (bm.river_id=:river_id) AND (bmv.station BETWEEN (:fromkm-0.0001) AND (:tokm+0.0001))" + " ORDER BY bmv.station ASC"; gernotbelger@8915: gernotbelger@8964: private final NavigableMap kmMobility = new TreeMap<>(); mschaefer@8952: gernotbelger@8964: private Calculation problems; mschaefer@8952: mschaefer@8952: /***** CONSTRUCTORS *****/ mschaefer@8952: gernotbelger@8964: private SoilKindKmValueFinder(final Calculation problems, final List queryRows) { gernotbelger@8964: this.problems = problems; mschaefer@8952: mschaefer@8952: for (int i = 0; i <= queryRows.size() - 1; i++) { mschaefer@8952: this.kmMobility.put(Double.valueOf((double) queryRows.get(i)[0]), (((int) queryRows.get(i)[1]) == 1) ? SoilKind.mobil : SoilKind.starr); mschaefer@8952: } mschaefer@8952: } mschaefer@8952: mschaefer@8952: /***** METHODS *****/ gernotbelger@8915: mschaefer@8898: /** gernotbelger@8915: * Loads the range of the river's kms with their soil kind. gernotbelger@8915: * gernotbelger@8915: * @return Whether the load has been successful mschaefer@8898: */ gernotbelger@8964: public static SoilKindKmValueFinder loadValues(final Calculation problems, final River river, final DoubleRange kmRange) { mschaefer@8952: final Session session = SessionHolder.HOLDER.get(); gernotbelger@8964: final SQLQuery sqlQuery = session.createSQLQuery(SQL_BED_MOBILITY).addScalar("station", StandardBasicTypes.DOUBLE).addScalar("moving", gernotbelger@8964: StandardBasicTypes.INTEGER); mschaefer@8952: sqlQuery.setInteger("river_id", river.getId().intValue()); mschaefer@8952: sqlQuery.setDouble("fromkm", kmRange.getMinimumDouble()); mschaefer@8952: sqlQuery.setDouble("tokm", kmRange.getMaximumDouble()); mschaefer@8952: final List rows = sqlQuery.list(); mschaefer@8952: if (rows.size() >= 1) gernotbelger@8964: return new SoilKindKmValueFinder(problems, rows); gernotbelger@8964: gernotbelger@8964: problems.addProblem("soilkindkmvaluefinder.empty"); gernotbelger@8964: return null; gernotbelger@8915: } gernotbelger@8915: mschaefer@8898: /***** METHODS *****/ gernotbelger@8915: mschaefer@8898: /** mschaefer@8898: * Searches a km with its soil kind mschaefer@8898: */ gernotbelger@8964: public SoilKind findSoilKind(final double km) { gernotbelger@8964: gernotbelger@8964: if (this.kmMobility.containsKey(Double.valueOf(km))) mschaefer@8952: return this.kmMobility.get(Double.valueOf(km)); gernotbelger@8964: gernotbelger@8964: final Entry streamUp = this.kmMobility.floorEntry(Double.valueOf(km)); gernotbelger@8980: if (streamUp == null) { gernotbelger@8964: reportProblem(km); gernotbelger@8964: return null; mschaefer@8898: } gernotbelger@8964: gernotbelger@8964: // Return the soil kind of the neighbouring station with the shorter distance to the candidate. gernotbelger@8964: final Entry streamDown = this.kmMobility.ceilingEntry(Double.valueOf(km)); gernotbelger@8964: if (streamDown == null) gernotbelger@8964: return streamUp.getValue(); gernotbelger@8964: gernotbelger@8964: final double streamUpValue = streamUp.getKey().doubleValue(); gernotbelger@8964: final double streamDownValue = streamDown.getKey().doubleValue(); gernotbelger@8964: gernotbelger@8964: if ((streamUpValue + streamDownValue) / 2 <= km) gernotbelger@8964: return streamUp.getValue(); gernotbelger@8964: gernotbelger@8964: return streamDown.getValue(); gernotbelger@8964: } gernotbelger@8964: gernotbelger@8964: private void reportProblem(final double km) { gernotbelger@8964: if (this.problems == null) gernotbelger@8964: return; gernotbelger@8964: gernotbelger@8964: this.problems.addProblem(km, "soilkindkmvaluefinder.missing"); gernotbelger@8964: gernotbelger@8964: // report problem only once gernotbelger@8964: this.problems = null; mschaefer@8898: } gernotbelger@8915: }