# HG changeset patch # User Andre Heinecke # Date 1371046048 -7200 # Node ID 152e1ba8e5bdfe00fc88967f1ffc26421d6c1a5e # Parent 5fda7065b74a9228a7020e7a3fb66c565f803db1 Rework ATWriter/Exporter - Make the write function static as both data and gauge information is necessary for writing. - Use the rivers WST unit for the gauge datum - Handle the case that we are at a gauge - Differentiate between calculated values - Always work with w in CM and thus avoid double number format problems diff -r 5fda7065b74a -r 152e1ba8e5bd artifacts/src/main/java/org/dive4elements/river/exports/ATExporter.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ATExporter.java Wed Jun 12 16:02:33 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ATExporter.java Wed Jun 12 16:07:28 2013 +0200 @@ -85,15 +85,6 @@ return; } - ATWriter at; - try { - at = new ATWriter(data); - } - catch (IllegalArgumentException iae) { - logger.error("creating ATWriter failed", iae); - throw new IOException(iae); - } - River river = RiverUtils.getRiver(master); RangeAccess rangeAccess = new RangeAccess(master); double[] kms = rangeAccess.getLocations(); @@ -103,7 +94,8 @@ // at gauge. TimeInterval interval = gauge.fetchMasterDischargeTable().getTimeInterval(); - at.write( + ATWriter.write( + data, new OutputStreamWriter(out, DEFAULT_ENCODING), context.getMeta(), river.getName(), @@ -111,11 +103,12 @@ gauge.getName(), gauge.getDatum(), interval.getStartTime(), - false); + river.getWstUnit().getName()); } else { // at km - at.write( + ATWriter.write( + data, new OutputStreamWriter(out), context.getMeta(), river.getName(), @@ -123,7 +116,7 @@ null, null, null, - true); + river.getWstUnit().getName()); } } diff -r 5fda7065b74a -r 152e1ba8e5bd artifacts/src/main/java/org/dive4elements/river/exports/ATWriter.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ATWriter.java Wed Jun 12 16:02:33 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ATWriter.java Wed Jun 12 16:07:28 2013 +0200 @@ -46,30 +46,124 @@ public static final String I18N_AT_GAUGE_HEADER = "export.discharge.curve.at.gauge.header"; + public static final String I18N_AT_CALC_GAUGE_HEADER = + "export.discharge.curve.at.gauge.calc.header"; + public static final String EMPTY = " "; - protected double minW; - protected double maxW; - protected double minQ; - protected double maxQ; - - protected UnivariateRealFunction qFunc; - - public ATWriter() { + public static double getQ(int w, UnivariateRealFunction qFunc) { + try { + double val = qFunc.value(w); + return val; + } + catch (FunctionEvaluationException aode) { + // should not happen + logger.error("spline interpolation failed", aode); + return Double.NaN; + } } - public ATWriter(WQ wq) throws IllegalArgumentException { + public static void printQ(PrintWriter out, double q) { + String format; + if (q < 1d) format = " % 8.3f"; + else if (q < 10d) format = " % 8.2f"; + else if (q < 100d) format = " % 8.1f"; + else { + format = " % 8.0f"; + if (q > 1000d) q = Math.rint(q/10d)*10d; + } + out.printf(Locale.US, format, q); + } + + protected static void printCalculatedGaugeHeader( + PrintWriter out, + CallMeta callMeta, + String river, + double km, + String gName, + BigDecimal datum, + Date date, + String unit + ) { + out.print("*" + Resources.getMsg( + callMeta, + I18N_AT_CALC_GAUGE_HEADER, + I18N_AT_CALC_GAUGE_HEADER, + new Object[] { river, gName, datum, unit } )); + out.print("\r\n"); + } + + protected static void printGaugeHeader( + PrintWriter out, + CallMeta callMeta, + String river, + double km, + String gName, + BigDecimal datum, + Date date, + String unit + ) { + DateFormat f = DateFormat.getDateInstance(DateFormat.MEDIUM, + Resources.getLocale(callMeta)); + out.print("*" + Resources.getMsg( + callMeta, + I18N_AT_GAUGE_HEADER, + I18N_AT_GAUGE_HEADER, + new Object[] { river, gName, f.format(date), datum, unit} )); + out.print("\r\n"); + } + + protected static void printHeader( + PrintWriter out, + CallMeta callMeta, + String river, + double km + ) { + out.print("*" + Resources.getMsg( + callMeta, + I18N_AT_HEADER, + I18N_AT_HEADER, + new Object[] { river, km } )); + out.print("\r\n"); + } + + public static void write( + WQ values, + Writer writer, + CallMeta meta, + String river, + double km, + String gName, + BigDecimal datum, + Date date, + String unit) + throws IOException + { + int minW; + int maxW; + double minQ; + double maxQ; + + UnivariateRealFunction qFunc; + + WQ wq = WQ.getFixedWQforExportAtGauge(values, datum); + + // If we converted to centimeter we know that the WQ table is + // calculated because of the assumption that all calculations + // are in Meter and only the discharge tables data is in meter. + boolean isCalculation = wq.getReferenceSystem() != values.getReferenceSystem(); int [] bounds = wq.longestIncreasingWRangeIndices(); if (logger.isDebugEnabled()) { - logger.debug("exporting w between indices " + - bounds[0] + " and " + bounds[1] + " (" + - wq.getW(bounds[0]) + ", " + wq.getW(bounds[1])); + logger.debug("exporting " + (isCalculation ? "calculated " : "") + + "w between indices " + bounds[0] + " and " + bounds[1] + " (" + + (int)Math.ceil(wq.getW(bounds[0])) + ", " + + (int)Math.floor(wq.getW(bounds[1]))+ ")"); } if (bounds[1]-bounds[0] < 1) { // Only first w can be written out. - minW = maxW = wq.getW(bounds[0]); + minW = maxW = (int)Math.round(wq.getW(bounds[0])); minQ = maxQ = wq.getQ(bounds[0]); // constant function qFunc = new PolynomialFunction(new double [] { minQ }); @@ -89,117 +183,50 @@ ? new LinearInterpolator().interpolate(ws, qs) : new SplineInterpolator().interpolate(ws, qs); - minW = wq.getW(bounds[0]); - maxW = wq.getW(bounds[1]); + minW = (int)Math.ceil(wq.getW(bounds[0])); + maxW = (int)Math.floor(wq.getW(bounds[1])); minQ = wq.getQ(bounds[0]); maxQ = wq.getQ(bounds[1]); - } - - public double getQ(double w) { - - try { - return qFunc.value(w); - } - catch (FunctionEvaluationException aode) { - // should not happen - logger.warn("spline interpolation failed", aode); - return w <= minW ? minQ : maxQ; - } - } - - public static void printQ(PrintWriter out, double q) { - String format; - if (q < 1d) format = " % 8.3f"; - else if (q < 10d) format = " % 8.2f"; - else if (q < 100d) format = " % 8.1f"; - else { - format = " % 8.0f"; - if (q > 1000d) q = Math.rint(q/10d)*10d; - } - out.printf(Locale.US, format, q); - } - - - protected static void printGaugeHeader( - PrintWriter out, - CallMeta callMeta, - String river, - double km, - String gName, - BigDecimal datum, - Date date - ) { - DateFormat f = DateFormat.getDateInstance(); - out.print("*" + Resources.getMsg( - callMeta, - I18N_AT_GAUGE_HEADER, - I18N_AT_GAUGE_HEADER, - new Object[] { river, gName, f.format(date), datum } )); - out.print("\r\n"); - } - - protected static void printHeader( - PrintWriter out, - CallMeta callMeta, - String river, - double km - ) { - out.print("*" + Resources.getMsg( - callMeta, - I18N_AT_HEADER, - I18N_AT_HEADER, - new Object[] { river, km } )); - out.print("\r\n"); - } - - public void write( - Writer writer, - CallMeta meta, - String river, - double km, - String gName, - BigDecimal datum, - Date date, - boolean wOutUnitIsMeter) - throws IOException - { PrintWriter out = new PrintWriter(writer); // A header is required, because the desktop version of FLYS will skip // the first row. if (gName != null) { - printGaugeHeader(out, meta, river, km, gName, datum, date); + printGaugeHeader(out, meta, river, km, gName, datum, date, unit); + if (isCalculation) { + printCalculatedGaugeHeader(out, meta, river, km, gName, datum, date, unit); + } } else { printHeader(out, meta, river, km); } - double rest = (minW * 100.0) % 10.0; + int rest = minW % 10; - double startW = Math.rint((minW - rest*0.01)*10.0)*0.1; + int startW = minW - rest; if (logger.isDebugEnabled()) { logger.debug("startW: " + startW); logger.debug("rest: " + rest); + logger.debug("maxW: " + maxW); } int col = 0; - for (double w = startW; w <= maxW; w += 0.01) { + for (int w = startW; w < maxW; w++) { if (col == 0) { - if (wOutUnitIsMeter) { - // For some crazy reason W's at a gauge should be in the - // unit but W's exported elsewhere should be in Meter - out.printf(Locale.US, "%5.2f", w); - } else { - out.printf(Locale.US, "%8d", (int)Math.round(w * 100d)); - } + out.printf(Locale.US, "%8d", w); } if (w < minW) { out.print(EMPTY); - } - else { - printQ(out, getQ(w)); + } else { + double actQ = getQ(w, qFunc); + if (Double.isNaN(actQ)) { + // Can't happen™ + break; + } else { + printQ(out, actQ); + } } if (++col >= COLUMNS) {