sascha@650: package de.intevation.flys.artifacts.model;
sascha@650: 
sascha@3441: import de.intevation.flys.model.DischargeTable;
sascha@3441: import de.intevation.flys.model.Gauge;
sascha@3441: import de.intevation.flys.model.River;
sascha@3441: 
sascha@3419: import de.intevation.flys.utils.DoubleUtil;
sascha@3419: 
sascha@650: import java.io.Serializable;
sascha@650: 
sascha@3419: import java.util.ArrayList;
sascha@3441: import java.util.Collections;
sascha@3439: import java.util.Comparator;
sascha@3419: import java.util.List;
sascha@650: 
sascha@3419: import org.apache.log4j.Logger;
sascha@655: 
sascha@650: public class Segment
sascha@650: implements   Serializable
sascha@650: {
sascha@3441:     private static Logger log = Logger.getLogger(Segment.class);
sascha@650: 
sascha@3439:     public static final Comparator<Segment> REF_CMP =
sascha@3439:         new Comparator<Segment>() {
sascha@3439:             @Override
sascha@3439:             public int compare(Segment a, Segment b) {
sascha@3439:                 double d = a.referencePoint - b.referencePoint;
sascha@3439:                 if (d < 0d) return -1;
sascha@3439:                 return d > 0d ? +1 : 0;
sascha@3439:             }
sascha@3439:         };
sascha@3439: 
sascha@650:     protected double    from;
sascha@650:     protected double    to;
sascha@650:     protected double [] values;
sascha@655:     protected double [] backup;
sascha@655:     protected double    referencePoint;
sascha@650: 
sascha@650:     public Segment() {
sascha@650:     }
sascha@650: 
sascha@655:     public Segment(double referencePoint) {
sascha@655:         this.referencePoint = referencePoint;
sascha@655:     }
sascha@655: 
sascha@650:     public Segment(double from, double to, double [] values) {
sascha@650:         this.from   = from;
sascha@650:         this.to     = to;
sascha@650:         this.values = values;
sascha@650:     }
sascha@650: 
sascha@650:     public boolean isUp() {
sascha@650:         return from < to;
sascha@650:     }
sascha@650: 
sascha@3449:     public boolean inside(double km) {
sascha@3552:         return from < to
sascha@3449:             ? km >= from && km <= to
sascha@3449:             : km >= to   && km <= from;
sascha@3449:     }
sascha@3449: 
sascha@3419:     @Override
sascha@650:     public String toString() {
sascha@650:         StringBuilder sb = new StringBuilder("Segment: [");
sascha@650:         sb.append("from: ").append(from).append("; to: ")
sascha@670:           .append(to)
sascha@670:           .append("; ref: ").append(referencePoint)
sascha@670:           .append("; values: (");
sascha@650:         for (int i = 0; i < values.length; ++i) {
sascha@650:             if (i > 0) sb.append(", ");
sascha@650:             sb.append(values[i]);
sascha@650:         }
sascha@650:         sb.append(")]");
sascha@650:         return sb.toString();
sascha@650:     }
sascha@650: 
sascha@655:     public void setFrom(double from) {
sascha@655:         this.from = from;
sascha@655:     }
sascha@655: 
sascha@655:     public void backup() {
sascha@3419:         backup = values != null
sascha@3419:             ? (double [])values.clone()
sascha@3419:             : null;
sascha@655:     }
sascha@655: 
sascha@3449:     public double [] getBackup() {
sascha@3449:         return backup;
sascha@3449:     }
sascha@3449: 
sascha@655:     public double getFrom() {
sascha@655:         return from;
sascha@655:     }
sascha@655: 
sascha@655:     public void setTo(double to) {
sascha@655:         this.to = to;
sascha@655:     }
sascha@655: 
sascha@655:     public double getTo() {
sascha@655:         return to;
sascha@655:     }
sascha@655: 
sascha@655:     public void setValues(double [] values) {
sascha@655:         this.values = values;
sascha@655:     }
sascha@655: 
sascha@655:     public double [] getValues() {
sascha@655:         return values;
sascha@655:     }
sascha@655: 
sascha@3449:     public int numValues() {
sascha@3449:         return values.length;
sascha@3449:     }
sascha@3449: 
sascha@655:     public void setReferencePoint(double referencePoint) {
sascha@655:         this.referencePoint = referencePoint;
sascha@655:     }
sascha@655: 
sascha@655:     public double getReferencePoint() {
sascha@655:         return referencePoint;
sascha@655:     }
sascha@655: 
sascha@650:     public static List<Segment> parseSegments(String input) {
sascha@650: 
sascha@3776:         final List<Segment> segments = new ArrayList<Segment>();
sascha@650: 
sascha@3776:         DoubleUtil.parseSegments(input, new DoubleUtil.SegmentCallback() {
sascha@3776:             @Override
sascha@3776:             public void newSegment(double from, double to, double [] values) {
sascha@650:                 segments.add(new Segment(from, to, values));
sascha@650:             }
sascha@3776:         });
sascha@650: 
sascha@650:         return segments;
sascha@650:     }
sascha@3441: 
sascha@3441:     public static boolean setReferencePointConvertQ(
sascha@3441:         List<Segment> segments,
sascha@3441:         River         river,
sascha@3441:         boolean       isQ,
sascha@3441:         Calculation   report
sascha@3441:     ) {
sascha@3441:         int numResults = -1;
sascha@3441: 
sascha@3441:         boolean success = true;
sascha@3441: 
sascha@3441:         // assign reference points
sascha@3441:         for (Segment segment: segments) {
sascha@3441:             Gauge gauge = river.maxOverlap(segment.getFrom(), segment.getTo());
sascha@3441: 
sascha@3441:             if (gauge == null) {
sascha@3441:                 log.warn("no gauge found. Defaults to mid point.");
sascha@3441:                 segment.setReferencePoint(
sascha@3441:                     0.5*(segment.getFrom()+segment.getTo()));
sascha@3441:             }
sascha@3441:             else {
sascha@3441:                 double ref = gauge.getStation().doubleValue();
sascha@3441:                 log.debug(
sascha@3441:                     "reference gauge: " + gauge.getName() +
sascha@3441:                     " (km " + ref + ")");
sascha@3441:                 segment.setReferencePoint(ref);
sascha@3441:             }
sascha@3441: 
sascha@3441:             double [] values = segment.values;
sascha@3441: 
sascha@3441:             if (numResults == -1) {
sascha@3441:                 numResults = values.length;
sascha@3441:             }
sascha@3441:             else if (numResults != values.length) {
sascha@3441:                 log.warn("wrong length of values");
sascha@3441:                 return false;
sascha@3441:             }
sascha@3441: 
sascha@3441:             // convert to Q if needed
sascha@3441:             if (!isQ && gauge != null) {
sascha@3441: 
sascha@3441:                 DischargeTable dt = gauge.fetchMasterDischargeTable();
sascha@3441: 
sascha@3441:                 double [][] table =
sascha@3441:                     DischargeTables.loadDischargeTableValues(dt, 1);
sascha@3441: 
sascha@3441:                 // need the original values for naming
sascha@3441:                 segment.backup();
sascha@3441: 
sascha@3441:                 for (int i = 0; i < values.length; ++i) {
sascha@3441:                     double w = values[i] / 100.0;
sascha@3441:                     double [] qs = DischargeTables.getQsForW(table, w);
sascha@3441:                     if (qs.length == 0) {
sascha@3441:                         log.warn("No Qs found for W = " + values[i]);
sascha@3441:                         report.addProblem("cannot.find.w.for.q", values[i]);
sascha@3441:                         values[i] = Double.NaN;
sascha@3441:                         success = false;
sascha@3441:                     }
sascha@3441:                     else {
sascha@3441:                         values[i] = qs[0];
sascha@3441:                         if (qs.length > 1) {
sascha@3441:                             log.warn(
sascha@3441:                                 "More than one Q found for W = " + values[i]);
sascha@3441:                         }
sascha@3441:                     }
sascha@3441:                 }
sascha@3441:             }
sascha@3441:         } // for all segments
sascha@3441: 
sascha@3441:         Collections.sort(segments, Segment.REF_CMP);
sascha@3441: 
sascha@3441:         return success;
sascha@3441:     }
sascha@650: }
sascha@650: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :