Utils.java [src/java/d/util] Revision: default  Date:
/*
 * $Id$
 *
 * This file is part of the Cloud Services Integration Platform (CSIP),
 * a Model-as-a-Service framework, API, and application suite.
 *
 * 2012-2017, OMSLab, Colorado State University.
 *
 * OMSLab licenses this file to you under the MIT license.
 * See the LICENSE file in the project root for more information.
 */
package d.util;

import csip.Config;
import static d.soils.wwe02_wepssoilinput.V2_0.KEY_ORGANIC_LAYER_THRESHOLD;
import java.text.NumberFormat;
import java.util.Locale;
import soils.Component;
import soils.Horizon;
import soils.utils.EvalResult;

/**
 *
 * @author brad
 */
public class Utils {
    
    public static final String SIUnits = "SI"; // will delete when depending classes are removed
    private static final String[] ORGANIC_TEXTURES = {"mpm", "mpt", "muck", "peat", "spm", "udom", "pdom", "hpm"};
    
    public enum Metric {
        MM(.001),CM(.01),DM(.1),M(1),DKM(10),HM(100),KM(1000);
        
        private final double value;
        private Metric(double value){
            this.value = value;
        }
        
        public double getValue(){
            return value;
        }
    
    }
    
    public static String formatDouble(double val, int numdig) {
        if (Double.isNaN(val)) {
            return "NaN";
        }	
        if (val < 0.001 && val > -0.001 && val != 0.0) {
            String tmp = Double.toString(val);
            int pdx = tmp.indexOf('.');
            int edx = tmp.indexOf('E');
            if (edx == -1) {
                edx = tmp.indexOf('e');
            }
            if ((pdx + numdig) >= edx) {
                return tmp;
            }
            return tmp.substring(0, pdx + numdig + 1) + tmp.substring(edx);
        }
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
        java.text.FieldPosition fp = new java.text.FieldPosition(NumberFormat.INTEGER_FIELD);
        nf.setMaximumFractionDigits(numdig);
        nf.setMinimumFractionDigits(numdig);
        nf.setGroupingUsed(false);
        return nf.format(val, new StringBuffer(), fp).toString();
    }
    
    public static String chkSoilandSandPcts(Component comp) {
        String warningMessage = null;
        
        NumberFormat.getInstance().setMaximumFractionDigits(4);

        for(Horizon horizon : comp.horizons.values()){
            if ((Math.abs(horizon.sandtotal_r() + horizon.silttotal_r() + horizon.claytotal_r() - 1.0) > 0.0001)) {
                 warningMessage = "Bad soil fractions for layer "
                        + horizon.chkey() + " sand " + Utils.formatDouble(horizon.sandtotal_r(), 4)
                        + " silt " + Utils.formatDouble(horizon.silttotal_r(), 4) + " clay "
                        + Utils.formatDouble(horizon.claytotal_r(), 4);
            }
            
            if(warningMessage != null)
                break;

            if (horizon.sandvc_r() + horizon.sandco_r() + horizon.sandmed_r()
                    + horizon.sandfine_r() + horizon.sandvf_r() > horizon.sandtotal_r() + 0.0001) {
                warningMessage = "sand fractions exceed total sand for layer "
                        + horizon.chkey() + " sand " + Utils.formatDouble(horizon.sandtotal_r(), 4)
                        + " veryCoarseSandFraction " + Utils.formatDouble(horizon.sandvc_r(), 4)
                        + " coarseSandFraction " + Utils.formatDouble(horizon.sandco_r(), 4)
                        + " mediumSandFraction " + Utils.formatDouble(horizon.sandmed_r(), 4)
                        + " fineSandFraction " + Utils.formatDouble(horizon.sandfine_r(), 4)
                        + " veryFineSandFraction " + Utils.formatDouble(horizon.sandvf_r(), 4);
            }
            if(warningMessage != null)
                break;
        }
        return warningMessage;
    }
    
    public static boolean isLayerOrganic(String hzname, String desgnmaster, String texture, double organicMatter) {
        //horizon name
        if (hzname != null && hzname.startsWith("O")) {
            return true;
        }

        if (desgnmaster != null && desgnmaster.startsWith("O")) {
            return true;
        }

        for (String organicTexture : ORGANIC_TEXTURES) {
            if (organicTexture.equals(texture)) {
                return true;
            }
        }

        if ((organicMatter * 100) > Config.getDouble(KEY_ORGANIC_LAYER_THRESHOLD, 15)) { // om_r was converted to decimal for the model but we are comparing percent
            return true;
        }

        //aka, a mineral layer
        return false;
    }
    
    public static Horizon getSurfaceHorizon(Component comp){
        Horizon surfaceHorizon = null;
        for(Horizon h : comp.horizons.values()){ // They are ordered by deptht_r
            surfaceHorizon = h;
            break;
        }
        return surfaceHorizon;
    }
    
    public static double checkBoundaries(double val, double low, double high){
        
        if(val < low)
            val = low;
        if(val > high)
            val = high;
        
        return val;
    }
    
    public static double metricConversion(double value,Metric from,Metric to){
        double converted;
            
        converted = value / (to.value / from.value); 
        
        return converted;
    }
    
    public static double pctToFraction(double value){
        return value / 100;
    }
    
    public static double averageMissingValue(double h,double l, double r){
        return averageMissingValue(h,l,r,Double.NaN);
    }
    
    public static double averageMissingValue(double h,double l, double r,double defaultVal){
        double value;
        if(EvalResult.testDefaultDouble(r))
            if(EvalResult.testDefaultDouble(h) || EvalResult.testDefaultDouble(l))
                value =  defaultVal;
            else
                value = (h+l)/2;
        else
            value = r;
        
        return value;
    }
}