Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/exports/FixWaterlevelExporter.java @ 9459:f06e3766997f
fallunterscheidung isQ - fixWaterlevelExporter
author | gernotbelger |
---|---|
date | Tue, 28 Aug 2018 19:21:44 +0200 |
parents | 65f28328c9a3 |
children | dd05a5eef210 |
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde * Software engineering by Intevation GmbH * * 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.exports; import java.io.OutputStream; import java.text.NumberFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.dive4elements.river.artifacts.D4EArtifact; import org.dive4elements.river.artifacts.access.RangeAccess; import org.dive4elements.river.artifacts.common.DefaultCalculationResults; import org.dive4elements.river.artifacts.common.ExportContextPDF; import org.dive4elements.river.artifacts.common.GeneralResultType; import org.dive4elements.river.artifacts.common.JasperReporter; import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource; import org.dive4elements.river.artifacts.model.ConstantWQKms; import org.dive4elements.river.artifacts.model.DischargeTables; import org.dive4elements.river.artifacts.model.WQKms; import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils; import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; import org.dive4elements.river.model.DischargeTable; import org.dive4elements.river.model.Gauge; import org.dive4elements.river.utils.Formatter; import org.dive4elements.river.utils.RiverUtils; import org.dive4elements.river.utils.RiverUtils.WQ_MODE; import au.com.bytecode.opencsv.CSVWriter; import net.sf.jasperreports.engine.JRException; /** * Generates different output formats (wst, csv, pdf) of data that resulted from * a waterlevel computation. * * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public class FixWaterlevelExporter extends WaterlevelExporter { /** The log used in this exporter. */ private static Logger log = Logger.getLogger(FixWaterlevelExporter.class); private final Map<String, Double> gaugeQ_W_Map = new HashMap<>(); @Override protected void writeRow4(final CSVWriter writer, final double wqkm[], final D4EArtifact flys, final Gauge gauge) { if (!isQ()) { super.writeRow4(writer, wqkm, flys, gauge); } else { final NumberFormat kmf = getKmFormatter(); final NumberFormat wf = getWFormatter(); final NumberFormat qf = getQFormatter(); final String waterlevel = getWaterlevel(wqkm[1], gauge); writer.writeNext(new String[] { kmf.format(wqkm[2]), wf.format(wqkm[0]), waterlevel, qf.format(RiverUtils.roundQ(wqkm[1])), RiverUtils.getLocationDescription(flys, wqkm[2]) }); } } /** Write an csv-row at gauge location. */ @Override protected void writeRow6(final CSVWriter writer, final double wqkm[], final String wOrQDesc, final D4EArtifact flys, final Gauge gauge) { if (!isQ()) { super.writeRow6(writer, wqkm, wOrQDesc, flys, gauge); } else { final NumberFormat kmf = getKmFormatter(); final NumberFormat wf = getWFormatter(); final NumberFormat qf = getQFormatter(); final String waterlevel = getWaterlevel(wqkm[1], gauge); writer.writeNext(new String[] { kmf.format(wqkm[2]), wf.format(wqkm[0]), waterlevel, qf.format(RiverUtils.roundQ(wqkm[1])), wOrQDesc, RiverUtils.getLocationDescription(flys, wqkm[2]), gauge.getName() }); } } private String getWaterlevel(final double discharge, final Gauge gauge) { final NumberFormat formatter = Formatter.getWaterlevelW(this.context); final Double waterlevel = this.getWforGaugeAndQ(gauge, discharge); if (waterlevel != null) return formatter.format(waterlevel); return ""; } private Double getWforGaugeAndQ(final Gauge gauge, final double q) { final String key = gauge.getName() + String.valueOf(q); if (!this.gaugeQ_W_Map.containsKey(key)) { final DischargeTable dt = gauge.fetchMasterDischargeTable(); final double[][] table = DischargeTables.loadDischargeTableValues(dt); final double[] qs = DischargeTables.getWsForQ(table, q); // final DischargeTables dct = new DischargeTables(gauge.getRiver().getName(), gauge.getName()); // final double[] qs = DischargeTables.getWsForQ(dct.getFirstTable(), q); // TODO: KLÄREN, welche Abflusstabelle // genommen werden soll! if (qs != null && qs.length > 0) { this.gaugeQ_W_Map.put(key, qs[0]); } } return this.gaugeQ_W_Map.get(key); } /** * Write the header, with different headings depending on whether at a * gauge or at a location. */ @Override protected void writeCSVHeader(final CSVWriter writer, final boolean atGauge, final boolean isQ) { if (!isQ()) { super.writeCSVHeader(writer, atGauge, isQ); } else { log.info("WaterlevelExporter.writeCSVHeader"); final String unit = RiverUtils.getRiver((D4EArtifact) this.master).getWstUnit().getName(); final String headerWamPegelNeu = msg("fix.export.csv.w_at_gauge"); if (atGauge) { writer.writeNext(new String[] { msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }), headerWamPegelNeu, msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), // FIXME: use WaterlevelDescriptionBuilder instead and also remove all this duplicate code. (isQ ? msg(CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER) : msg(CSV_W_DESC_HEADER, DEFAULT_CSV_W_DESC_HEADER)), msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER), msg(CSV_GAUGE_HEADER, DEFAULT_CSV_GAUGE_HEADER) }); } else { writer.writeNext(new String[] { msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { unit }), headerWamPegelNeu, msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER) }); } } } @Override protected void writePDF(final OutputStream out) { log.debug("write PDF"); if (!isQ()) { super.writePDF(out); } else { final MetaAndTableJRDataSource source = new MetaAndTableJRDataSource(); final String jasperFile = "/jasper/templates/fix_waterlevel.jrxml"; // "/jasper/fix_waterlevel_en.jasper"); addMetaData(source); try { final List<String[]> sorted = getRows(); // Custom Result could be nice, too... for (final String[] list : sorted) { source.addData(list); } final JasperReporter reporter = new JasperReporter(); reporter.addReport(jasperFile, source); reporter.exportPDF(out); } catch (final JRException je) { log.warn("Error generating PDF Report!", je); } } } private void addMetaData(final MetaAndTableJRDataSource source) { final D4EArtifact flys = (D4EArtifact) this.master; final String user = CalculationUtils.findArtifactUser(this.context, flys); final RangeAccess ra = new RangeAccess(flys); final RiverInfo ri = new RiverInfo(ra.getRiver()); final DefaultCalculationResults results = new DefaultCalculationResults(msg("calculation.analysis"), user, ri, ra.getRange()); final ExportContextPDF contextPdf = new ExportContextPDF(this.context, results); contextPdf.addJRMetaDataDefaults(source); contextPdf.addJRMetaDataForModules(source); /* column headings */ contextPdf.addJRMetadata(source, "station_header", GeneralResultType.station); contextPdf.addJRMetadata(source, "fix_w", msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER, new Object[] { ri.getWstUnit() })); contextPdf.addJRMetadata(source, "w_at_gauge_header", msg("fix.export.csv.w_at_gauge")); contextPdf.addJRMetadata(source, "fix_q", msg(CSV_Q_HEADER)); contextPdf.addJRMetadata(source, "waterlevel_name_header", msg("common.export.csv.header.mainvalue_label")); contextPdf.addJRMetadata(source, "location_header", msg("common.export.csv.header.location")); contextPdf.addJRMetadata(source, "gauge_header", msg("common.export.csv.header.gauge")); } private List<String[]> getRows() { final List<String[]> list = new ArrayList<>(); final WQ_MODE mode = RiverUtils.getWQMode((D4EArtifact) this.master); final boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE; final boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE; Double first = Double.NaN; Double last = Double.NaN; for (final WQKms[] tmp : this.data) { for (final WQKms wqkms : tmp) { list.addAll(getRows2(wqkms, atGauge, isQ)); final double[] firstLast = wqkms.getFirstLastKM(); if (first.isNaN()) { /* Initialize */ first = firstLast[0]; last = firstLast[1]; } if (firstLast[0] > firstLast[1]) { /* * Calculating upstream we assert that it is * impossible that the direction changes during this * loop */ first = Math.max(first, firstLast[0]); last = Math.min(last, firstLast[1]); } else if (firstLast[0] < firstLast[1]) { first = Math.min(first, firstLast[0]); last = Math.max(last, firstLast[1]); } else { first = last = firstLast[0]; } } } /* Append the official fixing at the bottom */ for (final WQKms wqkms : this.officalFixings) { list.addAll(getRows2(filterWQKms(wqkms, first, last), atGauge, isQ)); } return list; } private List<String[]> getRows2(final WQKms wqkms, final boolean atGauge, final boolean isQ) { log.debug("WaterlevelExporter.addWKmsData"); // OLD CODE :-/ final List<String[]> list = new ArrayList<>(); // Skip constant data. if (wqkms instanceof ConstantWQKms) { return null; } final NumberFormat kmf = getKmFormatter(); final NumberFormat wf = getWFormatter(); final NumberFormat qf = getQFormatter(); final int size = wqkms.size(); double[] result = new double[3]; final D4EArtifact flys = (D4EArtifact) this.master; final RangeAccess rangeAccess = new RangeAccess(flys); final Gauge gauge = rangeAccess.getRiver().determineRefGauge(rangeAccess.getKmRange(), rangeAccess.isRange()); final String gaugeName = gauge.getName(); String desc = ""; final String notinrange = msg(CSV_NOT_IN_GAUGE_RANGE, DEFAULT_CSV_NOT_IN_GAUGE_RANGE); final double a = gauge.getRange().getA().doubleValue(); final double b = gauge.getRange().getB().doubleValue(); desc = getDesc(wqkms, isQ); final long startTime = System.currentTimeMillis(); for (int i = 0; i < size; i++) { result = wqkms.get(i, result); final double q = result[1]; final String waterlevel = this.getWaterlevel(q, gauge); // THIS IS NEW (and makes common super method // difficult) if (atGauge) { list.add(new String[] { kmf.format(result[2]), wf.format(result[0]), waterlevel, qf.format(RiverUtils.roundQ(result[1])), desc, RiverUtils.getLocationDescription(flys, result[2]), result[2] >= a && result[2] <= b ? gaugeName : notinrange }); } else { list.add(new String[] { kmf.format(result[2]), wf.format(result[0]), waterlevel, qf.format(RiverUtils.roundQ(result[1])), desc, RiverUtils.getLocationDescription(flys, result[2]), result[2] >= a && result[2] <= b ? gaugeName : notinrange }); } } return list; } }