view artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java @ 9318:7b2b086e45f0

collision pdf details, ResultType refactoring, bezugswst result
author gernotbelger
date Fri, 27 Jul 2018 10:11:23 +0200
parents 72b3270e1568
children a978b601a034
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.uinfo.salix;

import java.util.ArrayList;
import java.util.List;
import java.util.NavigableMap;
import java.util.TreeMap;

import org.dive4elements.artifacts.CallContext;
import org.dive4elements.river.artifacts.access.RangeAccess;
import org.dive4elements.river.artifacts.model.Calculation;
import org.dive4elements.river.artifacts.model.CalculationResult;
import org.dive4elements.river.artifacts.resources.Resources;
import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
import org.dive4elements.river.artifacts.uinfo.salix.SalixLineAccess.ScenarioType;
import org.dive4elements.river.model.River;

/**
 * @author Domenico Nardi Tironi
 *
 */
final class SalixLineCalculation {

    private final CallContext context;

    public SalixLineCalculation(final CallContext context) {
        this.context = context;
    }

    public CalculationResult calculate(final UINFOArtifact uinfo) {
        final Calculation problems = new Calculation();

        final String calcModeLabel = Resources.getMsg(this.context.getMeta(), uinfo.getCalculationMode().name());
        final String user = CalculationUtils.findArtifactUser(this.context, uinfo);

        final SalixLineAccess accessSalix = new SalixLineAccess(uinfo);

        final River river = accessSalix.getRiver();
        final RiverInfo riverInfo = new RiverInfo(river);

        // final DoubleRange range = accessSalix.getRange();
        // final boolean useScenario = accessSalix.getUseScenario();
        // final String selectedScenario = accessSalix.getScenario();
        // final Double fromPart = accessSalix.getFromPart();
        // final Double toPart = accessSalix.getToPart();
        //
        // final boolean useSCenario = accessSalix.getUseScenario();
        // final String scenario = accessSalix.getScenario();
        // calculation_mode
        // ld_from , ld_to
        // use_scenario (boolean)
        // ld_from_part; ld_to_part
        // scenario_selection (mögliche Werte:"scenarioType.option1" "scenarioType.option2" "scenarioType.option3"
        final RiverInfoProvider riverInfoProvider = RiverInfoProvider.forRange(this.context, river, accessSalix.getRange());

        // FIXME: real calculation

        final SalixLineCalculationResults results = new SalixLineCalculationResults(calcModeLabel, user, riverInfo, accessSalix.getRange());

        final SalixLineCalculator calculator = new SalixLineCalculator(this.context, riverInfoProvider);
        final NavigableMap<Double, List<Double>> rangeScenarios = buildRangeScenarios(accessSalix);

        calculator.execute(problems, uinfo, rangeScenarios, accessSalix.getScenario(), buildScenarioLabels(accessSalix), results);

        // final Collection<ResultRow> rows = new ArrayList<>();
        // SalixLineCalculationNoScenarioResult result = null; // verzweigung etwas ungünstig. möglicherweise auch die
        // Abstraktion. ist erstmal nur ne idee
        // final ResultRow row1 = ResultRow.create(). //
        // putValue(BunduResultType.station, 100).//
        // putValue(UInfoResultType.salixline, 28).//
        // putValue(UInfoResultType.salix_delta_mw, 2);
        //
        // if (!useScenario) {
        //
        // rows.add(row1);
        // result = new SalixLineCalculationNoScenarioResult("Ergebnis 1", null, rows);
        // } else {
        //
        // if (scenario.equals("scenarioType.option1")) { // REGIONAL
        //
        // final int[] scenarios = accessSalix.getRegionalScenarioIntegers();
        // final List<SalixScenario> list = new ArrayList<>();
        // for (final int scen_val : scenarios) {
        // list.add(new SalixScenario(scen_val, 666.));// TODO: replace 666 by real calculated value
        // }
        // row1.putValue(UInfoResultType.customMultiRowColSalixRegionalValue_Dwspl, list);//
        // rows.add(row1);
        // result = new SalixLineCalculationRegionalResult("Ergebnis 1 regional test", null, rows, scenarios);
        //
        // } else if (scenario.equals("scenarioType.option2")) { // SUPRA-REGIONAL
        //
        // final String supraRegional = accessSalix.getSupraRegionalString();
        // final List<SalixZone> list = SalixZone.parse(supraRegional);
        //
        // final Map<DoubleRange, SalixScenario> rangeScenarioMap = new HashMap<>();
        // // make double range
        // for (int i = 0; i < list.size(); i++) {
        // final SalixZone zone = list.get(i);
        // final double upper = i < list.size() - 1 ? (zone.getUpperFromTo() - 0.0001) : zone.getUpperFromTo() + 0.0001;//
        // "halboffenes Intervall
        //
        // final DoubleRange zonerange = new DoubleRange((double) zone.getLowerFromTo(), upper);
        // final double salixValue = 666.;// TODO: calculate the salix value
        // final SalixScenario salixscen = new SalixScenario(zone.getDwsplValue(), salixValue);
        //
        // rangeScenarioMap.put(zonerange, salixscen);
        // }
        //
        // // make calculation
        // double currentKm = range.getMinimumDouble();
        // final double step = 0.1; // TODO: get from global setting?
        // while (currentKm < range.getMaximumDouble()) {
        // final ResultRow rowSupraRegional = ResultRow.create(). //
        // putValue(BunduResultType.station, currentKm).//
        // putValue(UInfoResultType.salixline, 28).//
        // putValue(UInfoResultType.salix_delta_mw, 2);
        //
        // final SalixScenario scenarioCurrentKm = findScenarioByKm(currentKm, rangeScenarioMap);
        //
        // if (scenarioCurrentKm != null) { // should not happen, scenarioCurrentKm == null -> BUG
        // rowSupraRegional.putValue(UInfoResultType.salix_line_scenario, scenarioCurrentKm.getSalixValue());
        // rowSupraRegional.putValue(UInfoResultType.salix_line_scenario_dwspl, scenarioCurrentKm.getDwspl());
        // }
        // rows.add(rowSupraRegional);
        //
        // currentKm = currentKm + step;
        // }
        //
        // result = new SalixLineCalculationSupraRegionalResult("Ergebnis 1 supra regional test", null, rows);
        //
        // } else if (scenario.equals("scenarioType.option3")) { // HISTORICAL
        // row1.putValue(UInfoResultType.salixlinehist, 66).//
        // putValue(UInfoResultType.salix_line_scenario_dwspl, 88);
        // rows.add(row1);
        // result = new SalixLineCalculationHistoricalResult("Ergebnis 1 historical test", null, rows);
        // }
        // }
        // results.addResult(result, problems);
        return new CalculationResult(results, problems);
    }

    // private SalixScenario findScenarioByKm(final double km, final Map<DoubleRange, SalixScenario> rangeScenarioMap) {
    // final Iterator<DoubleRange> rangeIterator = rangeScenarioMap.keySet().iterator();
    // while (rangeIterator.hasNext()) {
    // final DoubleRange range = rangeIterator.next();
    // if (range.containsDouble(km + 0.0001)) {
    // return rangeScenarioMap.get(range);
    // }
    // }
    // return null;
    // }

    /**
     * Build a map of delta-Ws by km-range for the selected scenario
     */
    private NavigableMap<Double, List<Double>> buildRangeScenarios(final SalixLineAccess access) {
        final NavigableMap<Double, List<Double>> rangeScenarios = new TreeMap<>();
        if (access.getScenario() == ScenarioType.REGIONAL)
            fillRangeScenarios(rangeScenarios, access, access.getFromPart().doubleValue(), access.getToPart().doubleValue(),
                    access.getRegionalScenarioIntegers());
        else if (access.getScenario() == ScenarioType.SUPRAREGIONAL)
            fillRangeScenarios(rangeScenarios, access.getSupraRegionalString());
        // TODO else if (access.getScenario().equals(ScenarioType.HISTORICAL.getKey()))
        // historisches Szenario aus MSH etc.
        else
            fillRangeScenarios(rangeScenarios, access);
        return rangeScenarios;
    }

    /**
     * Fill a map of delta-Ws with only one 0-delta for the whole calc range (no scenario)
     */
    private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final RangeAccess calcRange) {
        final List<Double> nulls = new ArrayList<>();
        nulls.add(0.0);
        rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls);
    }

    /**
     * Fill a map of delta-Ws by km-range from the regional scenario input data
     */
    private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final RangeAccess calcRange, final double partFrom,
            final double partTo, final int[] deltaWs) {
        final List<Double> nulls = new ArrayList<>();
        final List<Double> dwsm = new ArrayList<>();
        for (int i = 0; i <= deltaWs.length - 1; i++) {
            nulls.add(0.0);
            dwsm.add(deltaWs[i] / 100.0);
        }
        rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls);
        rangeScenarios.put(Double.valueOf(partFrom - 0.0001), dwsm);
        rangeScenarios.put(Double.valueOf(partTo + 0.0001), nulls);
    }

    /**
     * Fill a map of delta-Ws by km-range from the supraregional scenario input data
     * (the zones input by the user cover the calc range completely)
     */
    private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final String zones) {
        final List<SalixZone> parts = SalixZone.parse(zones);
        for (final SalixZone part : parts) {
            final List<Double> dwsm = new ArrayList<>();
            dwsm.add(part.getDwsplValue() / 100.0);
            rangeScenarios.put(Double.valueOf(part.getFromKm().doubleValue() - 0.0001), dwsm);
        }
    }

    /**
     * Build the list of delta-w labels for the scenario type
     */
    private String[] buildScenarioLabels(final SalixLineAccess access) {
        final List<String> labels = new ArrayList<>();
        if (access.getScenario() == ScenarioType.REGIONAL) {
            final int[] deltaws = access.getRegionalScenarioIntegers();
            for (int i = 0; i <= deltaws.length - 1; i++)
                if (deltaws[i] != 0)
                    labels.add(Integer.toString(deltaws[i]) + " cm");
        }
        return labels.toArray(new String[labels.size()]);
    }
}

http://dive4elements.wald.intevation.org