gernotbelger@9145: /* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde gernotbelger@9145: * Software engineering by gernotbelger@9145: * Björnsen Beratende Ingenieure GmbH gernotbelger@9145: * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt gernotbelger@9145: * gernotbelger@9145: * This file is Free Software under the GNU AGPL (>=v3) gernotbelger@9145: * and comes with ABSOLUTELY NO WARRANTY! Check out the gernotbelger@9145: * documentation coming with Dive4Elements River for details. gernotbelger@9145: */ gernotbelger@9145: package org.dive4elements.river.artifacts.sinfo.flood_duration; gernotbelger@9145: gernotbelger@9205: import java.text.NumberFormat; gernotbelger@9150: import java.util.ArrayList; gernotbelger@9145: import java.util.Collection; mschaefer@9202: import java.util.Collections; mschaefer@9202: import java.util.List; gernotbelger@9145: mschaefer@9176: import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult; gernotbelger@9205: import org.dive4elements.river.artifacts.common.AbstractExportContext; gernotbelger@9150: import org.dive4elements.river.artifacts.common.ExportContextCSV; gernotbelger@9195: import org.dive4elements.river.artifacts.common.ExportContextPDF; gernotbelger@9150: import org.dive4elements.river.artifacts.common.GeneralResultType; mschaefer@9202: import org.dive4elements.river.artifacts.common.IResultType; gernotbelger@9150: import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource; gernotbelger@9145: import org.dive4elements.river.artifacts.common.ResultRow; mschaefer@9202: import org.dive4elements.river.artifacts.sinfo.common.SInfoI18NStrings; gernotbelger@9150: import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType; gernotbelger@9150: import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; gernotbelger@9145: mschaefer@9202: import gnu.trove.TDoubleArrayList; mschaefer@9202: gernotbelger@9145: /** mschaefer@9176: * Contains the result of a {@link FloodDurationCalculation}. gernotbelger@9145: * gernotbelger@9145: * @author Gernot Belger gernotbelger@9145: */ mschaefer@9202: public final class FloodDurationCalculationResult extends AbstractCalculationExportableResult { gernotbelger@9145: gernotbelger@9145: private static final long serialVersionUID = 1L; gernotbelger@9150: gernotbelger@9205: private final String[] mainvalueLabels; mschaefer@9176: gernotbelger@9205: private final int waterlevelCount; gernotbelger@9205: // private final WstInfo wstInfo; gernotbelger@9205: private final int maxWaterlevelPdf = 3; gernotbelger@9205: gernotbelger@9205: private enum ExportMode { gernotbelger@9205: pdf, csv gernotbelger@9205: } mschaefer@9202: mschaefer@9202: public FloodDurationCalculationResult(final String label, final String[] mainvalueLabels, final Collection rows) { mschaefer@9176: super(label, rows); gernotbelger@9205: this.mainvalueLabels = mainvalueLabels; // TODO: löschen (?) gernotbelger@9205: this.waterlevelCount = mainvalueLabels.length; mschaefer@9202: } mschaefer@9202: mschaefer@9202: /** mschaefer@9202: * The label of one of the optional main values, or null mschaefer@9202: */ gernotbelger@9205: // public String getMainValueLabel(final int index) { gernotbelger@9205: // if (index <= this.mainvalueLabels.length - 1) gernotbelger@9205: // return this.mainvalueLabels[index]; gernotbelger@9205: // else gernotbelger@9205: // return null; gernotbelger@9205: // } mschaefer@9202: mschaefer@9202: /** mschaefer@9202: * Collection of the result rows containing only the rows describing an infrastructure mschaefer@9202: */ mschaefer@9202: @Override mschaefer@9202: public Collection getRows() { mschaefer@9202: final List infrasOnlyRows = new ArrayList<>(); mschaefer@9202: for (final ResultRow row : this.rows) mschaefer@9202: if (row.getValue(SInfoResultType.infrastructuretype) != null) mschaefer@9202: infrasOnlyRows.add(row); mschaefer@9202: return Collections.unmodifiableCollection(infrasOnlyRows); mschaefer@9202: } mschaefer@9202: mschaefer@9202: /** mschaefer@9202: * Fetches the km-longitudinal section of the infrastructures and one of their result fields mschaefer@9202: */ mschaefer@9202: public final double[][] fetchInfrastructurePoints(final IResultType type) { mschaefer@9202: final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size()); mschaefer@9202: final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size()); mschaefer@9202: for (final ResultRow row : this.rows) { mschaefer@9202: if (row.getValue(SInfoResultType.infrastructuretype) != null) { mschaefer@9202: xPoints.add(row.getDoubleValue(GeneralResultType.station)); mschaefer@9202: yPoints.add(row.getDoubleValue(type)); mschaefer@9202: } mschaefer@9202: } mschaefer@9202: return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() }; mschaefer@9202: } mschaefer@9202: mschaefer@9202: /** mschaefer@9202: * Fetches the km-longitudinal section of a main value mschaefer@9202: */ mschaefer@9202: public final double[][] fetchMainValuePoints(final IResultType type) { mschaefer@9202: final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size()); mschaefer@9202: final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size()); mschaefer@9202: // final IResultType check = new IResultType[] { SInfoResultType.mainValue1Duration, SInfoResultType.mainValue2Duration, mschaefer@9202: // SInfoResultType.mainValue3Duration }[index]; mschaefer@9202: for (final ResultRow row : this.rows) { mschaefer@9202: // if (!Double.isNaN(row.getDoubleValue(check))) { mschaefer@9202: xPoints.add(row.getDoubleValue(GeneralResultType.station)); mschaefer@9202: yPoints.add(row.getDoubleValue(type)); mschaefer@9202: // } mschaefer@9202: } mschaefer@9202: return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() }; gernotbelger@9150: } gernotbelger@9145: mschaefer@9176: @Override gernotbelger@9195: protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) { mschaefer@9202: if (this.mainvalueLabels.length >= 1) { mschaefer@9202: // "##METADATEN WASSERSPIEGELLAGE" mschaefer@9202: exportContextCSV.writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL); gernotbelger@9205: for (int i = 1; i <= getWaterlevelCount(); // this.mainvalueLabels.length; gernotbelger@9205: i++) { mschaefer@9202: // "# Bezeichnung der Wasserspiegellage: " mschaefer@9202: final String label = this.getMainValueLabel(i - 1); mschaefer@9202: exportContextCSV.writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL_NAME, String.format("%d: %s", i, label)); mschaefer@9202: } mschaefer@9202: // "# Bezugspegel: " mschaefer@9202: exportContextCSV.writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL_GAUGE, "TODO: gauge"); mschaefer@9202: } gernotbelger@9205: exportContextCSV.writeBlankLine(); mschaefer@9176: } mschaefer@9176: mschaefer@9176: @Override mschaefer@9176: protected String getJasperFile() { gernotbelger@9205: if (this.waterlevelCount <= 1) gernotbelger@9205: return "/jasper/templates/sinfo.floodduration.jrxml"; gernotbelger@9205: else gernotbelger@9205: return "/jasper/templates/sinfo.floodduration2.jrxml"; mschaefer@9176: } mschaefer@9176: gernotbelger@9205: protected String[] formatRow(final AbstractExportContext exportContextCSV, final ResultRow row, final ExportMode mode) { mschaefer@9176: mschaefer@9176: final Collection lines = new ArrayList<>(10); mschaefer@9176: mschaefer@9176: lines.add(exportContextCSV.formatRowValue(row, GeneralResultType.station)); mschaefer@9176: lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.riverside)); mschaefer@9176: lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.floodDuration)); mschaefer@9176: lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.floodDischarge)); mschaefer@9176: lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.infrastructureHeight)); mschaefer@9176: lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.infrastructuretype)); mschaefer@9176: gernotbelger@9205: final List waterlevelList = (List) row.getValue(SInfoResultType.customMultiRowColWaterlevel); gernotbelger@9205: if (waterlevelList != null) { gernotbelger@9205: final NumberFormat wFormatter = exportContextCSV.getFlowDepthFormatter(); gernotbelger@9205: final NumberFormat qFormatter = exportContextCSV.getQFormatter(); gernotbelger@9205: gernotbelger@9205: for (int i = 0; i < waterlevelList.size(); i++) { gernotbelger@9205: gernotbelger@9205: if (i == this.maxWaterlevelPdf && mode == ExportMode.pdf) gernotbelger@9205: break; gernotbelger@9205: gernotbelger@9205: final DurationWaterlevel item = waterlevelList.get(i); gernotbelger@9205: lines.add(item.getWFormatted(wFormatter)); gernotbelger@9205: lines.add(item.getFloodDurDaysPerYearFormatted()); gernotbelger@9205: lines.add(item.getQFormatted(qFormatter)); gernotbelger@9205: lines.add(item.getBezeichnung()); mschaefer@9202: } mschaefer@9202: } mschaefer@9176: gernotbelger@9205: if ((this.waterlevelCount == 0 || this.waterlevelCount == 2) && mode == ExportMode.pdf) { gernotbelger@9205: // lines.add("dummy1"); gernotbelger@9205: // lines.add("dummy2"); gernotbelger@9205: // lines.add("dummy3"); gernotbelger@9205: // lines.add("dummy4"); gernotbelger@9205: } gernotbelger@9205: mschaefer@9176: lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.gaugeLabel)); mschaefer@9176: lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.location)); mschaefer@9176: mschaefer@9176: return lines.toArray(new String[lines.size()]); gernotbelger@9150: } gernotbelger@9150: gernotbelger@9150: @Override gernotbelger@9195: public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) { gernotbelger@9150: mschaefer@9176: final Collection header = new ArrayList<>(20); gernotbelger@9150: gernotbelger@9150: header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station)); gernotbelger@9150: header.add(exportContextCSV.formatCsvHeader(SInfoResultType.riverside)); mschaefer@9176: header.add(exportContextCSV.formatCsvHeader(SInfoResultType.floodDuration)); mschaefer@9176: header.add(exportContextCSV.msgUnitCSV(SInfoResultType.floodDischarge, SInfoResultType.floodDischarge.getUnit())); mschaefer@9176: header.add(exportContextCSV.msgUnitCSV(SInfoResultType.infrastructureHeight, SInfoResultType.infrastructureHeight.getUnit())); gernotbelger@9150: header.add(exportContextCSV.formatCsvHeader(SInfoResultType.infrastructuretype)); gernotbelger@9150: gernotbelger@9205: // add dynamic headers gernotbelger@9205: final int waterlevelCount = // results. gernotbelger@9205: getWaterlevelCount(); gernotbelger@9205: for (int i = 0; i < waterlevelCount; i++) { gernotbelger@9205: final int naturalIndex = i + 1; gernotbelger@9205: final String appendIndex = new StringBuilder().append("_").append(naturalIndex).toString(); gernotbelger@9205: final Object[] args = new Object[] { appendIndex }; gernotbelger@9205: // new StringBuilder().append('\u2081').toString(); // schlechter UTF-8-Support für subscript ints gernotbelger@9205: header.add(exportContextCSV.msg(DurationWaterlevel.getHeaderW(), new Object[] { appendIndex, "results.getRiver().getWstUnit()" })); gernotbelger@9205: header.add(exportContextCSV.msg(DurationWaterlevel.getHeaderFloodDurPerYear(), args)); gernotbelger@9205: header.add(exportContextCSV.msg(DurationWaterlevel.getHeaderQ(), args)); gernotbelger@9205: header.add(exportContextCSV.msg(DurationWaterlevel.getHeaderBezeichn(), args)); mschaefer@9202: } gernotbelger@9150: gernotbelger@9150: header.add(exportContextCSV.formatCsvHeader(SInfoResultType.gaugeLabel)); gernotbelger@9150: header.add(exportContextCSV.formatCsvHeader(SInfoResultType.location)); gernotbelger@9150: gernotbelger@9150: exportContextCSV.writeCSVLine(header.toArray(new String[header.size()])); gernotbelger@9145: gernotbelger@9145: } gernotbelger@9145: gernotbelger@9150: @Override gernotbelger@9195: protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) { gernotbelger@9150: gernotbelger@9205: return this.formatRow(exportContextCSV, row, ExportMode.csv); gernotbelger@9150: } gernotbelger@9150: gernotbelger@9150: @Override gernotbelger@9195: protected String[] formatPDFRow(final ExportContextPDF exportContextPDF, final ResultRow row) { gernotbelger@9150: gernotbelger@9205: return this.formatRow(exportContextPDF, row, ExportMode.pdf); gernotbelger@9145: } gernotbelger@9145: mschaefer@9176: @Override gernotbelger@9195: protected void addJRTableHeader(final ExportContextPDF exportContextPDF, final MetaAndTableJRDataSource source) { gernotbelger@9150: mschaefer@9176: /* column headings */ mschaefer@9176: exportContextPDF.addJRMetadata(source, "station_header", GeneralResultType.station); mschaefer@9176: exportContextPDF.addJRMetadata(source, "riverside_header", SInfoResultType.riverside); mschaefer@9176: exportContextPDF.addJRMetadata(source, "inundationduration_header", SInfoResultType.floodDuration); mschaefer@9176: exportContextPDF.addJRMetadata(source, "inundationduration_q_header", SInfoResultType.floodDischarge); mschaefer@9202: exportContextPDF.addJRMetadata(source, "infrastructure_height_header", SInfoResultType.infrastructureHeight); mschaefer@9176: exportContextPDF.addJRMetadata(source, "infrastructure_type_header", SInfoResultType.infrastructuretype); gernotbelger@9150: gernotbelger@9205: // add dynamic headers gernotbelger@9205: gernotbelger@9205: if (this.waterlevelCount == 0 || this.waterlevelCount == 2) { gernotbelger@9205: // source.addMetaData("dummy1", "dummy1"); gernotbelger@9205: // source.addMetaData("dummy2", "dummy2"); gernotbelger@9205: // source.addMetaData("dummy3", "dummy3"); gernotbelger@9205: // source.addMetaData("dummy4", "dummy4"); gernotbelger@9205: } gernotbelger@9205: gernotbelger@9205: for (int i = 0; i < this.waterlevelCount; i++) { gernotbelger@9205: final int naturalIndex = i + 1; gernotbelger@9205: gernotbelger@9205: final Object[] args = new String[] { new StringBuilder().append("_").append(naturalIndex).toString() }; gernotbelger@9205: exportContextPDF.addJRMetadata(source, getPdfHeader("w", naturalIndex), exportContextPDF.msg(DurationWaterlevel.getHeaderW(), args)); gernotbelger@9205: exportContextPDF.addJRMetadata(source, getPdfHeader("duration", naturalIndex), gernotbelger@9205: exportContextPDF.msg(DurationWaterlevel.getHeaderFloodDurPerYear(), args)); gernotbelger@9205: exportContextPDF.addJRMetadata(source, getPdfHeader("q", naturalIndex), exportContextPDF.msg(DurationWaterlevel.getHeaderQ(), args)); gernotbelger@9205: exportContextPDF.addJRMetadata(source, getPdfHeader("bezeichnung", naturalIndex), gernotbelger@9205: exportContextPDF.msg(DurationWaterlevel.getHeaderBezeichn(), args)); gernotbelger@9205: } gernotbelger@9150: mschaefer@9176: exportContextPDF.addJRMetadata(source, "gauge_header", SInfoResultType.gaugeLabel); mschaefer@9176: exportContextPDF.addJRMetadata(source, "location_header", SInfoResultType.location); gernotbelger@9150: } gernotbelger@9205: gernotbelger@9205: public final int getWaterlevelCount() { gernotbelger@9205: return this.waterlevelCount; gernotbelger@9205: } gernotbelger@9205: gernotbelger@9205: private final String getPdfHeader(final String rootStr, final int index) { gernotbelger@9205: final String hd = "_header"; gernotbelger@9205: final StringBuilder builder = new StringBuilder(); gernotbelger@9205: return builder.append(rootStr).append("_").append(index).append(hd).toString(); gernotbelger@9205: } gernotbelger@9205: gernotbelger@9205: public String getMainValueLabel(final int j) { gernotbelger@9205: gernotbelger@9205: if (this.mainvalueLabels != null && j < this.mainvalueLabels.length) gernotbelger@9205: return this.mainvalueLabels[j]; gernotbelger@9205: return ""; gernotbelger@9205: } gernotbelger@9145: }