gernotbelger@8996: /** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde gernotbelger@8996: * Software engineering by gernotbelger@8996: * Björnsen Beratende Ingenieure GmbH gernotbelger@8996: * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt gernotbelger@8996: * gernotbelger@8996: * This file is Free Software under the GNU AGPL (>=v3) gernotbelger@8996: * and comes with ABSOLUTELY NO WARRANTY! Check out the gernotbelger@8996: * documentation coming with Dive4Elements River for details. gernotbelger@8996: */ gernotbelger@8996: package org.dive4elements.river.artifacts.uinfo.salix; gernotbelger@8996: mschaefer@9309: import java.util.ArrayList; mschaefer@9309: import java.util.List; mschaefer@9309: import java.util.NavigableMap; mschaefer@9309: import java.util.TreeMap; gernotbelger@8996: gernotbelger@9321: import org.apache.commons.lang.math.DoubleRange; gernotbelger@8996: import org.dive4elements.artifacts.CallContext; mschaefer@9309: import org.dive4elements.river.artifacts.access.RangeAccess; gernotbelger@8996: import org.dive4elements.river.artifacts.model.Calculation; gernotbelger@8996: import org.dive4elements.river.artifacts.model.CalculationResult; gernotbelger@8996: import org.dive4elements.river.artifacts.resources.Resources; mschaefer@9295: import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider; gernotbelger@8996: import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils; gernotbelger@8996: import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; gernotbelger@8996: import org.dive4elements.river.artifacts.uinfo.UINFOArtifact; mschaefer@9309: import org.dive4elements.river.artifacts.uinfo.salix.SalixLineAccess.ScenarioType; gernotbelger@8996: import org.dive4elements.river.model.River; gernotbelger@8996: gernotbelger@8996: /** gernotbelger@8996: * @author Domenico Nardi Tironi gernotbelger@8996: * gernotbelger@8996: */ gernotbelger@8996: final class SalixLineCalculation { gernotbelger@8996: gernotbelger@8996: private final CallContext context; gernotbelger@8996: gernotbelger@8996: public SalixLineCalculation(final CallContext context) { gernotbelger@8996: this.context = context; gernotbelger@8996: } gernotbelger@8996: gernotbelger@8996: public CalculationResult calculate(final UINFOArtifact uinfo) { gernotbelger@8996: final Calculation problems = new Calculation(); gernotbelger@8996: gernotbelger@8996: final String calcModeLabel = Resources.getMsg(this.context.getMeta(), uinfo.getCalculationMode().name()); gernotbelger@8996: final String user = CalculationUtils.findArtifactUser(this.context, uinfo); gernotbelger@8996: gernotbelger@9070: final SalixLineAccess accessSalix = new SalixLineAccess(uinfo); gernotbelger@9070: gernotbelger@9070: final River river = accessSalix.getRiver(); gernotbelger@8996: final RiverInfo riverInfo = new RiverInfo(river); gernotbelger@8996: gernotbelger@9321: final DoubleRange range = accessSalix.getRange(); gernotbelger@9068: gernotbelger@9321: final ScenarioType scenarioType = accessSalix.getScenario(); gernotbelger@9070: gernotbelger@9321: final RiverInfoProvider riverInfoProvider = RiverInfoProvider.forRange(this.context, river, range); gernotbelger@8996: gernotbelger@9321: final SalixLineCalculationResults results = new SalixLineCalculationResults(calcModeLabel, user, riverInfo, range); gernotbelger@9321: gernotbelger@9321: final SalixLineCalculator calculator = new SalixLineCalculator(riverInfoProvider); mschaefer@9309: final NavigableMap> rangeScenarios = buildRangeScenarios(accessSalix); mschaefer@9309: gernotbelger@9321: calculator.execute(problems, uinfo, rangeScenarios, scenarioType, buildScenarioLabels(accessSalix), results); gernotbelger@9243: mschaefer@9295: // final Collection rows = new ArrayList<>(); mschaefer@9295: // SalixLineCalculationNoScenarioResult result = null; // verzweigung etwas ungünstig. möglicherweise auch die mschaefer@9295: // Abstraktion. ist erstmal nur ne idee mschaefer@9295: // final ResultRow row1 = ResultRow.create(). // gernotbelger@9318: // putValue(BunduResultType.station, 100).// mschaefer@9295: // putValue(UInfoResultType.salixline, 28).// mschaefer@9295: // putValue(UInfoResultType.salix_delta_mw, 2); mschaefer@9295: // mschaefer@9295: // if (!useScenario) { mschaefer@9295: // mschaefer@9295: // rows.add(row1); mschaefer@9295: // result = new SalixLineCalculationNoScenarioResult("Ergebnis 1", null, rows); mschaefer@9295: // } else { mschaefer@9295: // mschaefer@9295: // if (scenario.equals("scenarioType.option1")) { // REGIONAL mschaefer@9295: // mschaefer@9295: // final int[] scenarios = accessSalix.getRegionalScenarioIntegers(); mschaefer@9295: // final List list = new ArrayList<>(); mschaefer@9295: // for (final int scen_val : scenarios) { mschaefer@9295: // list.add(new SalixScenario(scen_val, 666.));// TODO: replace 666 by real calculated value mschaefer@9295: // } mschaefer@9295: // row1.putValue(UInfoResultType.customMultiRowColSalixRegionalValue_Dwspl, list);// mschaefer@9295: // rows.add(row1); mschaefer@9295: // result = new SalixLineCalculationRegionalResult("Ergebnis 1 regional test", null, rows, scenarios); mschaefer@9295: // mschaefer@9295: // } else if (scenario.equals("scenarioType.option2")) { // SUPRA-REGIONAL mschaefer@9295: // mschaefer@9295: // final String supraRegional = accessSalix.getSupraRegionalString(); mschaefer@9295: // final List list = SalixZone.parse(supraRegional); mschaefer@9295: // mschaefer@9295: // final Map rangeScenarioMap = new HashMap<>(); mschaefer@9295: // // make double range mschaefer@9295: // for (int i = 0; i < list.size(); i++) { mschaefer@9295: // final SalixZone zone = list.get(i); mschaefer@9295: // final double upper = i < list.size() - 1 ? (zone.getUpperFromTo() - 0.0001) : zone.getUpperFromTo() + 0.0001;// mschaefer@9295: // "halboffenes Intervall mschaefer@9295: // mschaefer@9295: // final DoubleRange zonerange = new DoubleRange((double) zone.getLowerFromTo(), upper); mschaefer@9295: // final double salixValue = 666.;// TODO: calculate the salix value mschaefer@9295: // final SalixScenario salixscen = new SalixScenario(zone.getDwsplValue(), salixValue); mschaefer@9295: // mschaefer@9295: // rangeScenarioMap.put(zonerange, salixscen); mschaefer@9295: // } mschaefer@9295: // mschaefer@9295: // // make calculation mschaefer@9295: // double currentKm = range.getMinimumDouble(); mschaefer@9295: // final double step = 0.1; // TODO: get from global setting? mschaefer@9295: // while (currentKm < range.getMaximumDouble()) { mschaefer@9295: // final ResultRow rowSupraRegional = ResultRow.create(). // gernotbelger@9318: // putValue(BunduResultType.station, currentKm).// mschaefer@9295: // putValue(UInfoResultType.salixline, 28).// mschaefer@9295: // putValue(UInfoResultType.salix_delta_mw, 2); mschaefer@9295: // mschaefer@9295: // final SalixScenario scenarioCurrentKm = findScenarioByKm(currentKm, rangeScenarioMap); mschaefer@9295: // mschaefer@9295: // if (scenarioCurrentKm != null) { // should not happen, scenarioCurrentKm == null -> BUG mschaefer@9295: // rowSupraRegional.putValue(UInfoResultType.salix_line_scenario, scenarioCurrentKm.getSalixValue()); mschaefer@9295: // rowSupraRegional.putValue(UInfoResultType.salix_line_scenario_dwspl, scenarioCurrentKm.getDwspl()); mschaefer@9295: // } mschaefer@9295: // rows.add(rowSupraRegional); mschaefer@9295: // mschaefer@9295: // currentKm = currentKm + step; mschaefer@9295: // } mschaefer@9295: // mschaefer@9295: // result = new SalixLineCalculationSupraRegionalResult("Ergebnis 1 supra regional test", null, rows); mschaefer@9295: // mschaefer@9295: // } else if (scenario.equals("scenarioType.option3")) { // HISTORICAL mschaefer@9295: // row1.putValue(UInfoResultType.salixlinehist, 66).// mschaefer@9295: // putValue(UInfoResultType.salix_line_scenario_dwspl, 88); mschaefer@9295: // rows.add(row1); mschaefer@9295: // result = new SalixLineCalculationHistoricalResult("Ergebnis 1 historical test", null, rows); mschaefer@9295: // } mschaefer@9295: // } mschaefer@9295: // results.addResult(result, problems); gernotbelger@8996: return new CalculationResult(results, problems); gernotbelger@8996: } gernotbelger@9243: mschaefer@9309: /** mschaefer@9309: * Build a map of delta-Ws by km-range for the selected scenario mschaefer@9309: */ mschaefer@9309: private NavigableMap> buildRangeScenarios(final SalixLineAccess access) { mschaefer@9309: final NavigableMap> rangeScenarios = new TreeMap<>(); mschaefer@9309: if (access.getScenario() == ScenarioType.REGIONAL) mschaefer@9309: fillRangeScenarios(rangeScenarios, access, access.getFromPart().doubleValue(), access.getToPart().doubleValue(), mschaefer@9309: access.getRegionalScenarioIntegers()); mschaefer@9309: else if (access.getScenario() == ScenarioType.SUPRAREGIONAL) mschaefer@9309: fillRangeScenarios(rangeScenarios, access.getSupraRegionalString()); mschaefer@9309: // TODO else if (access.getScenario().equals(ScenarioType.HISTORICAL.getKey())) mschaefer@9309: // historisches Szenario aus MSH etc. mschaefer@9309: else mschaefer@9309: fillRangeScenarios(rangeScenarios, access); gernotbelger@9321: mschaefer@9309: return rangeScenarios; mschaefer@9309: } mschaefer@9309: mschaefer@9309: /** mschaefer@9309: * Fill a map of delta-Ws with only one 0-delta for the whole calc range (no scenario) mschaefer@9309: */ mschaefer@9309: private void fillRangeScenarios(final NavigableMap> rangeScenarios, final RangeAccess calcRange) { mschaefer@9309: final List nulls = new ArrayList<>(); mschaefer@9309: nulls.add(0.0); mschaefer@9309: rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls); mschaefer@9309: } mschaefer@9309: mschaefer@9309: /** mschaefer@9309: * Fill a map of delta-Ws by km-range from the regional scenario input data mschaefer@9309: */ mschaefer@9309: private void fillRangeScenarios(final NavigableMap> rangeScenarios, final RangeAccess calcRange, final double partFrom, mschaefer@9309: final double partTo, final int[] deltaWs) { mschaefer@9309: final List nulls = new ArrayList<>(); mschaefer@9309: final List dwsm = new ArrayList<>(); mschaefer@9309: for (int i = 0; i <= deltaWs.length - 1; i++) { mschaefer@9309: nulls.add(0.0); mschaefer@9309: dwsm.add(deltaWs[i] / 100.0); mschaefer@9309: } mschaefer@9309: rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls); mschaefer@9309: rangeScenarios.put(Double.valueOf(partFrom - 0.0001), dwsm); mschaefer@9309: rangeScenarios.put(Double.valueOf(partTo + 0.0001), nulls); mschaefer@9309: } mschaefer@9309: mschaefer@9309: /** mschaefer@9309: * Fill a map of delta-Ws by km-range from the supraregional scenario input data mschaefer@9309: * (the zones input by the user cover the calc range completely) mschaefer@9309: */ mschaefer@9309: private void fillRangeScenarios(final NavigableMap> rangeScenarios, final String zones) { mschaefer@9309: final List parts = SalixZone.parse(zones); mschaefer@9309: for (final SalixZone part : parts) { mschaefer@9309: final List dwsm = new ArrayList<>(); mschaefer@9309: dwsm.add(part.getDwsplValue() / 100.0); mschaefer@9309: rangeScenarios.put(Double.valueOf(part.getFromKm().doubleValue() - 0.0001), dwsm); mschaefer@9309: } mschaefer@9309: } mschaefer@9309: mschaefer@9316: /** mschaefer@9316: * Build the list of delta-w labels for the scenario type mschaefer@9316: */ mschaefer@9316: private String[] buildScenarioLabels(final SalixLineAccess access) { mschaefer@9316: final List labels = new ArrayList<>(); mschaefer@9316: if (access.getScenario() == ScenarioType.REGIONAL) { mschaefer@9316: final int[] deltaws = access.getRegionalScenarioIntegers(); mschaefer@9316: for (int i = 0; i <= deltaws.length - 1; i++) mschaefer@9316: if (deltaws[i] != 0) mschaefer@9316: labels.add(Integer.toString(deltaws[i]) + " cm"); gernotbelger@9243: } mschaefer@9316: return labels.toArray(new String[labels.size()]); gernotbelger@9243: } gernotbelger@8996: }