package org.openlca.core.math.data_quality; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.openlca.core.math.data_quality.Aggregation.AggregationValue; import org.openlca.core.matrix.LongPair; import org.openlca.core.results.ContributionResult; class DQCalculator { private final Map<Long, List<AggregationValue>> flowAggregations = new HashMap<>(); private final Map<Long, List<AggregationValue>> impactAggregations = new HashMap<>(); private final Map<LongPair, List<AggregationValue>> impactAggregationsPerFlow = new HashMap<>(); private final Map<LongPair, List<AggregationValue>> impactAggregationsPerProcess = new HashMap<>(); private final ContributionResult result; private final DQData data; private final DQCalculationSetup setup; public DQCalculator(ContributionResult result, DQData data, DQCalculationSetup setup) { this.result = result; this.data = data; this.setup = setup; } void calculate() { for (long processId : result.productIndex.getProcessIds()) { for (long flowId : result.flowIndex.getFlowIds()) { addValues(processId, flowId); } } } private void addValues(long processId, long flowId) { double[] dqValues = getDqValues(processId, flowId); BigDecimal flowResult = new BigDecimal(getFlowResult(processId, flowId)); if (dqValues == null || flowResult.equals(BigDecimal.ZERO)) return; addValue(flowAggregations, flowId, flowResult, dqValues); if (!result.hasImpactResults()) return; addImpactValues(processId, flowId, flowResult, dqValues); } private void addImpactValues(long processId, long flowId, BigDecimal flowResult, double[] dqValues) { for (long impactId : result.impactIndex.getKeys()) { double impactFactor = getImpactFactor(result, impactId, flowId); if (impactFactor == 0d) continue; BigDecimal factor = flowResult.multiply(new BigDecimal(impactFactor)); addValue(impactAggregations, impactId, factor, dqValues); addValue(impactAggregationsPerFlow, new LongPair(flowId, impactId), factor, dqValues); addValue(impactAggregationsPerProcess, new LongPair(processId, impactId), factor, dqValues); } } private <T> void addValue(Map<T, List<AggregationValue>> map, T key, BigDecimal factor, double[] dqValues) { List<AggregationValue> list = safeGetList(key, map); int max = setup.exchangeDqSystem.getScoreCount(); for (int i = 0; i < dqValues.length; i++) { double v = dqValues[i]; if (v != 0d || setup.processingType == ProcessingType.EXCLUDE) continue; dqValues[i] = max; } list.add(new AggregationValue(dqValues, factor)); } private double[] getDqValues(long processId, long flowId) { return data.exchangeData.get(new LongPair(processId, flowId)); } private double getFlowResult(long processId, long flowId) { return Math.abs(result.getSingleFlowResult(processId, flowId)); } Map<Long, double[]> getFlowValues() { return aggregate(flowAggregations); } Map<Long, double[]> getImpactValues() { return aggregate(impactAggregations); } Map<LongPair, double[]> getImpactPerProcessValues() { return aggregate(impactAggregationsPerProcess); } Map<LongPair, double[]> getImpactPerFlowValues() { return aggregate(impactAggregationsPerFlow); } private <T> Map<T, double[]> aggregate(Map<T, List<AggregationValue>> map) { Map<T, double[]> values = new HashMap<>(); for (T key : map.keySet()) { List<AggregationValue> toAggregate = map.get(key); double[] result = Aggregation.applyTo(toAggregate, setup.aggregationType); values.put(key, result); } return values; } private <T> List<AggregationValue> safeGetList(T key, Map<T, List<AggregationValue>> map) { List<AggregationValue> list = map.get(key); if (list != null) return list; map.put(key, list = new ArrayList<>()); return list; } private double getImpactFactor(ContributionResult result, long impactId, long flowId) { int flowIndex = result.flowIndex.getIndex(flowId); int impactIndex = result.impactIndex.getIndex(impactId); return result.impactFactors.get(impactIndex, flowIndex); } }