view artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java @ 9361:2aec052d4088

Refactoring on SalixLineCalculationResult etc., calculation using MQ etc., scenario (regional+supra) csv columns and meta data added
author mschaefer
date Wed, 01 Aug 2018 18:01:11 +0200
parents a978b601a034
children 2da486c7c05f
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.apache.commons.lang.math.DoubleRange;
import org.dive4elements.artifacts.CallContext;
import org.dive4elements.river.artifacts.access.RangeAccess;
import org.dive4elements.river.artifacts.common.GeneralResultType;
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 ScenarioType scenarioType = accessSalix.getScenario();

        final RiverInfoProvider riverInfoProvider = RiverInfoProvider.forRange(this.context, river, range);

        final SalixLineCalculationResults results = new SalixLineCalculationResults(calcModeLabel, user, riverInfo, range);

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

        calculator.execute(problems, uinfo, rangeScenarios, scenarioType, buildScenarioLabels(accessSalix), buildPartialRangeString(accessSalix),
                buildAdditionalString(accessSalix), results);

        return new CalculationResult(results, problems);
    }

    /**
     * Build a map of delta-Ws by from-km 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");
        }
        else if (access.getScenario() == ScenarioType.SUPRAREGIONAL)
            labels.add(Resources.getMsg(this.context.getMeta(), "uinfo_salix_scenario_supraregional"));
        else if (access.getScenario() == ScenarioType.HISTORICAL)
            labels.add(Resources.getMsg(this.context.getMeta(), "uinfo_salix_scenario_historical"));
        return labels.toArray(new String[labels.size()]);
    }

    /**
     * Build the km range string for the scenario type
     */
    private String buildPartialRangeString(final SalixLineAccess access) {
        if ((access.getScenario() == ScenarioType.REGIONAL) || (access.getScenario() == ScenarioType.HISTORICAL)) {
            return String.format("%s - %s", GeneralResultType.station.exportValue(this.context, access.getFromPart().doubleValue()),
                    GeneralResultType.station.exportValue(this.context, access.getToPart().doubleValue()));
        }
        if (access.getScenario() == ScenarioType.SUPRAREGIONAL) {
            String ranges = "";
            String sep = "";
            final List<SalixZone> parts = SalixZone.parse(access.getSupraRegionalString());
            for (final SalixZone part : parts) {
                if (part.getDwsplValue() != 0) {
                    ranges = ranges + sep + String.format("%s - %s", GeneralResultType.station.exportValue(this.context, part.getFromKm().doubleValue()),
                            GeneralResultType.station.exportValue(this.context, part.getToKm().doubleValue()));
                    sep = ", ";
                }
            }
            return ranges;
        }
        return "";
    }

    /**
     * Build the delta w or time string for the scenario type
     */
    private String buildAdditionalString(final SalixLineAccess access) {
        if (access.getScenario() == ScenarioType.REGIONAL) {
            String deltas = "";
            String sep = "";
            for (final int d : access.getRegionalScenarioIntegers()) {
                deltas = deltas + sep + Integer.toString(d);
                sep = ", ";
            }
            return deltas;
        }
        if (access.getScenario() == ScenarioType.HISTORICAL) {
            if (access.getYear() != null)
                return access.getYear().toString();
            else
                return access.getEpoch().toString();
        }
        if (access.getScenario() == ScenarioType.SUPRAREGIONAL) {
            String deltas = "";
            String sep = "";
            final List<SalixZone> parts = SalixZone.parse(access.getSupraRegionalString());
            for (final SalixZone part : parts) {
                if (part.getDwsplValue() != 0) {
                    deltas = deltas + sep + Integer.toString(part.getDwsplValue());
                    sep = ", ";
                }
            }
            return deltas;
        }
        return "";
    }
}

http://dive4elements.wald.intevation.org