Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepthdev/FlowDepthDevelopmentCalculation.java @ 9150:23945061daec
gigantic refactoring: exporter, result, results
to support multiple jaspers -> collisions
author | gernotbelger |
---|---|
date | Thu, 14 Jun 2018 16:56:31 +0200 |
parents | 5294114b1df4 |
children | 740d65e4aa14 |
line wrap: on
line source
/** 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.sinfo.flowdepthdev; import java.util.ArrayList; import java.util.Collection; import java.util.TreeSet; import org.apache.commons.lang.math.DoubleRange; import org.dive4elements.artifacts.CallContext; import org.dive4elements.river.artifacts.common.GeneralResultType; import org.dive4elements.river.artifacts.common.ResultRow; import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.model.WKms; import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.sinfo.SINFOArtifact; import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider; import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType; import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthUtils; import org.dive4elements.river.artifacts.sinfo.flowdepth.WstSoundingIdPair; import org.dive4elements.river.artifacts.sinfo.tkhcalculation.WaterlevelValuesFinder; import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder; import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo; import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils; import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; import org.dive4elements.river.artifacts.sinfo.util.WstInfo; import org.dive4elements.river.artifacts.states.WaterlevelData; import org.dive4elements.river.artifacts.states.WaterlevelFetcher; import org.dive4elements.river.model.River; /** * @author Gernot Belger */ final class FlowDepthDevelopmentCalculation { private final CallContext context; public FlowDepthDevelopmentCalculation(final CallContext context) { this.context = context; } public CalculationResult calculate(final SINFOArtifact sinfo) { final String user = CalculationUtils.findArtifactUser(this.context, sinfo); /* access input data */ final FlowDepthDevelopmentAccess access = new FlowDepthDevelopmentAccess(sinfo); final River river = access.getRiver(); final RiverInfo riverInfo = new RiverInfo(river); final WstSoundingIdPair currentPair = access.getCurrentPair(); final WstSoundingIdPair histPair = access.getHistoricalPair(); final DoubleRange calcRange = access.getRange(); /* calculate results for each diff pair */ final Calculation problems = new Calculation(); final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange); final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name()); final FlowDepthDevelopmentCalculationResults results = new FlowDepthDevelopmentCalculationResults(calcModeLabel, user, riverInfo, calcRange); final FlowDepthDevelopmentCalculationResult result = calculateResult(calcRange, currentPair, histPair, problems, infoProvider); results.addResult(result, problems); return new CalculationResult(results, problems); } private FlowDepthDevelopmentCalculationResult calculateResult(final DoubleRange calcRange, final WstSoundingIdPair currentPair, final WstSoundingIdPair histPair, final Calculation problems, final RiverInfoProvider infoProvider) { /* access real input data from database */ final WaterlevelData currentWaterlevel = loadWaterlevel(currentPair, calcRange, problems); if (currentWaterlevel == null) return null; final WaterlevelData historicalWaterlevel = loadWaterlevel(histPair, calcRange, problems); if (historicalWaterlevel == null) return null; final BedHeightsFinder currentSounding = loadBedHeight(currentPair, calcRange, problems); if (currentSounding == null) return null; final BedHeightsFinder historicalSounding = loadBedHeight(histPair, calcRange, problems); if (historicalSounding == null) return null; final BedHeightInfo currentSoundingInfo = currentSounding.getInfo(); final BedHeightInfo historicalSoundingInfo = historicalSounding.getInfo(); final int currentWstYear = currentWaterlevel.getYear(); final int historicalWstYear = historicalWaterlevel.getYear(); final int currentSoundingYear = currentSoundingInfo.getYear(); final int historicalSoundingYear = historicalSoundingInfo.getYear(); if (currentWstYear < 0) { problems.addProblem("flowdepthdevelopmentcalculation.missingCurrentYear", currentWaterlevel.getName()); return null; } if (historicalWstYear < 0) { problems.addProblem("flowdepthdevelopmentcalculation.missingHistoricalYear", historicalWaterlevel.getName()); return null; } FlowDepthUtils.checkYearDifference(Resources.getMsg(this.context.getMeta(), "flowdepthdevelopmentcalculation.yearDifferenceCurrent"), currentWstYear, currentSoundingYear, problems); FlowDepthUtils.checkYearDifference(Resources.getMsg(this.context.getMeta(), "flowdepthdevelopmentcalculation.yearDifferenceHistorical"), historicalWstYear, historicalSoundingYear, problems); /* re-determine the reference gauge, in the same way as the WaterlevelArtifact would do it */ final RiverInfoProvider currentRiverInfoProvider = infoProvider.forWaterlevel(currentWaterlevel); final RiverInfoProvider histRiverInfoProvider = infoProvider.forWaterlevel(historicalWaterlevel); final WstInfo currentWstInfo = new WstInfo(currentWaterlevel.getName(), currentWstYear, currentRiverInfoProvider.getReferenceGauge()); final WstInfo historicalWstInfo = new WstInfo(historicalWaterlevel.getName(), historicalWstYear, histRiverInfoProvider.getReferenceGauge()); final WKms currentWkms = currentWaterlevel.getWkms(); final WaterlevelValuesFinder currentWstProvider = WaterlevelValuesFinder.fromKms(problems, currentWkms); final WKms historicalWkms = historicalWaterlevel.getWkms(); final WaterlevelValuesFinder historicalWstProvider = WaterlevelValuesFinder.fromKms(problems, historicalWkms); final int currentMeanYear = (currentWstYear + currentSoundingYear) / 2; final int historcialMeanYear = (historicalWstYear + historicalSoundingYear) / 2; final double diffYear = currentMeanYear - historcialMeanYear; /* real calculation loop */ final Collection< ResultRow> rows = new ArrayList<>(); final Collection<Double> stations = determineCalculationSteps(currentSounding, historicalSounding); for (final double station : stations) { if (calcRange.containsDouble(station)) { final double currentWst = currentWstProvider.getWaterlevel(station); final double currentBedHeight = currentSounding.getMeanBedHeight(station); final double historicalWst = historicalWstProvider.getWaterlevel(station); final double historicalBedHeight = historicalSounding.getMeanBedHeight(station); /* ignore invalid lines */ if (Double.isNaN(currentWst) || Double.isNaN(currentBedHeight) || Double.isNaN(historicalWst) || Double.isNaN(historicalBedHeight)) continue; final double diffWst = (currentWst - historicalWst) * 100; final double diffBedHeight = (currentBedHeight - historicalBedHeight) * 100; final double flowDepthDevelopment = diffWst - diffBedHeight; final double flowDepthDevelopmentPerYear = flowDepthDevelopment / diffYear; final double currentFlowDepth = currentWst - currentBedHeight; final double historicalFlowDepth = historicalWst - historicalBedHeight; // REMARK: access the location once only during calculation final String location = currentRiverInfoProvider.getLocation(station); final ResultRow row = ResultRow.create().// putValue(GeneralResultType.station, station). // putValue(SInfoResultType.flowdepthDevelopment, flowDepthDevelopment). // putValue(SInfoResultType.flowdepthDevelopmentPerYear, flowDepthDevelopmentPerYear). // putValue(SInfoResultType.waterlevelDifference, diffWst). // putValue(SInfoResultType.bedHeightDifference, diffBedHeight). // putValue(SInfoResultType.flowdepthCurrent, currentFlowDepth). // putValue(SInfoResultType.flowdepthHistorical, historicalFlowDepth). // putValue(SInfoResultType.location, location); rows.add(row); } } final String label = buildLabel(currentWaterlevel, currentSoundingInfo, historicalWaterlevel, historicalSoundingInfo); return new FlowDepthDevelopmentCalculationResult(label, currentWstInfo, historicalWstInfo, currentSoundingInfo, historicalSoundingInfo, rows); } /** * Calculation steps are simply the union of all stations of all involved bed-height datasets */ private Collection<Double> determineCalculationSteps(final BedHeightsFinder currentSounding, final BedHeightsFinder historicalSounding) { final Collection<Double> allStations = new TreeSet<>(); allStations.addAll(currentSounding.getStations()); allStations.addAll(historicalSounding.getStations()); return allStations; } private String buildLabel(final WaterlevelData currentWaterlevel, final BedHeightInfo currentSounding, final WaterlevelData historicalWaterlevel, final BedHeightInfo historicalSounding) { return new StringBuilder(). // append(currentWaterlevel.getName()). // append('/'). // append(historicalWaterlevel.getName()). // append(" - "). // append(currentSounding.getDescription()). // append('/'). // append(historicalSounding.getDescription()). // toString(); } /* REMARK: fetch ALL wst kms, because we need to determine the original reference gauge */ private WaterlevelData loadWaterlevel(final WstSoundingIdPair pair, final DoubleRange calcRange, final Calculation problems) { final String wstId = pair.getWstId(); return new WaterlevelFetcher().findWaterlevel(this.context, wstId, calcRange, problems); } private BedHeightsFinder loadBedHeight(final WstSoundingIdPair pair, final DoubleRange calcRange, final Calculation problems) { final String soundingId = pair.getSoundingId(); return BedHeightsFinder.forId(this.context, soundingId, calcRange, problems); } }