WaterQualityInfo.java [src/WaterData] Revision: default  Date:
package WaterData;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

/**
* Last Updated: 2-April-2019
* @author Tyler Wible
* @since 21-June-2012
*/
public class WaterQualityInfo {
    /**
     * Anticipate a yyyy-mm-dd date format and convert the calendar year to a 'water year'
     * @param originalDate A string of the date in yyyy-mm-dd format
     * @return A 4-digit string of the water year (rather than calendar year)
     */
    public static String getWaterYear(String originalDate){
        int year = Integer.parseInt(originalDate.substring(0,4));
        int waterYear = year;
        String month = originalDate.substring(5,7);
        if ("10".equals(month) || "11".equals(month) || "12".equals(month)){
            waterYear += 1;
        }
        return String.valueOf(waterYear);
    }
    /**
     * @param wqTest  the water quality test desired "00600 Total nitrogen, water, unfiltered, milligrams per liter -- mg/L" (format: "5-digit test-name -- units") or "flow"
     * @param database
     * @return a string with the type of units for the current test.
     * @throws java.io.IOException
     */
    public static String[] getWqTestDataInfo(String wqTest, String database) throws IOException{
        String wqCode = "flow";
        String wqLabel = "flow";
        String wqUnits = "cfs";
        if(!wqTest.equalsIgnoreCase("flow")){
            wqCode = wqTest.substring(0,5);//pull just the 5 digit USGS WQ code
            wqLabel = wqTest.substring(6,wqTest.lastIndexOf("--")-1);//cut off the "98335" the test name and the "mg/L" units after the name
//            //Looks like the USGS website changes to auto-fetch units, so let's just use the old method of 'what was provided'
//            if(database.equalsIgnoreCase("USGS")){
//                //Get Units for current WQ test (5-digit code)
//                wqUnits = getUSGSwqUnits(wqCode);
//            }else{
//                wqUnits = wqTest.substring(wqTest.lastIndexOf("--") + 3);//keep the "mg/L" units after the name
//            }
            wqUnits = wqTest.substring(wqTest.lastIndexOf("--") + 3);//keep the "mg/L" units after the name
        }
        
        //Determine load duration curve calculation info. (wqUnits * flow * conversion = endUnits)
        double ldcConversion = getLdcWqConversion(wqUnits);
        String ldcEndUnits = getLdcWqEndUnits(wqUnits);
        
        String[] resultArray = {wqCode, wqLabel, wqUnits, String.valueOf(ldcConversion), ldcEndUnits};
        return resultArray;
    }
//    /**
//     * 
//     * @return an ArrayList<String> with all the metadata from USGS for all the water quality tests
//     * @throws IOException 
//     */
//    private static ArrayList<String> getUSGSwqParameters() throws IOException{
//        URL webpage = new URL("https://nwis.waterdata.usgs.gov/usa/nwis/pmcodes?radio_pm_search=param_group&pm_group=All+--+include+all+parameter+groups&pm_search=&casrn_search=&srsname_search=&format=rdb&show=parameter_group_nm&show=parameter_nm&show=casrn&show=srsname&show=parameter_units");
//        URLConnection yc = webpage.openConnection();
//        BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
//        String inputLine;
//        ArrayList<String> webpageAll = new ArrayList<>();
//        while ((inputLine = in.readLine()) != null) {
//            webpageAll.add(inputLine);
//        }
//        return webpageAll;
//    }
//    /**
//     * 
//     * @param parameterCode  USGS parameter code for a specific water quality test.
//     * @return a string with the type of units for the current test.
//     * @throws IOException 
//     */
//    public static String getUSGSwqUnits(String parameterCode) throws IOException{
//        ArrayList<String> webpageAll = getUSGSwqParameters();
//        String units = "0";
//        //Find the units of the specified test
//        for(int i=0; i<webpageAll.size(); i++){
//            String[] f = webpageAll.get(i).split("\t");
//            int line_length = f.length;
//            if((line_length >= 6) && (f[0].length() == 5)){
//                if(f[0].equals(parameterCode)){
//                    units = f[5];
//                }
//            }
//        }
//        return units;
//    }
//    /**
//     * 
//     * @param parameterCode  USGS parameter code for a specific water quality test.
//     * @return a string with the USGS label/name for the current test.
//     * @throws IOException 
//     */
//    public static String getUSGSwqLabel(String parameterCode) throws IOException{
//        ArrayList<String> webpageAll = getUSGSwqParameters();
//        String label = "?";
//        //Find the units of the specified test
//        for(int i=0; i<webpageAll.size(); i++){
//            String[] f = webpageAll.get(i).split("\t");
//            int line_length = f.length;
//            if((line_length >= 6) && (f[0].length() == 5)){
//                if(f[0].equals(parameterCode)){
//                    label = f[2];
//                }
//            }
//        }
//        return label;
//    }
    /**
     * @param units  the units of the current USGS water quality test.
     * @return a double with the correct load duration curve (LCD) conversion factor for the units.
     */
    public static double getLdcWqConversion(String units){
        double conversion = 0;
        if(units.equalsIgnoreCase("#/l")){
            conversion = (1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("#/m3")){
            conversion = (java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("#/ml")){
            conversion = (1000)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("MPN/100 ml")){
            conversion = (1.0/100.0)*(1000)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("MPN/100L")){
            conversion = (1.0/100.0)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("cfu/100ml")){
            conversion = (1.0/100.0)*(1000)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("cfu/mL")){
            conversion = (1000)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("col/mL")){
            conversion = (1000)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("cysts/100L")){
            conversion = (1.0/100.0)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("cysts/10L")){
            conversion = (1.0/10.0)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("g/cm3") || units.equalsIgnoreCase("g/mL @ 20C")){
            conversion = (java.lang.Math.pow(10,-6))*(1/1)*(1000)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("g/m3")){
            conversion = (java.lang.Math.pow(10,-6))*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("mg/l") || units.equalsIgnoreCase("mg/l CaCO3") || units.equalsIgnoreCase("mg/l NH4") || 
                    units.equalsIgnoreCase("mg/l NO3") || units.equalsIgnoreCase("mg/l PO4") || units.equalsIgnoreCase("mg/l SiO2") || 
                    units.equalsIgnoreCase("mg/l as H") || units.equalsIgnoreCase("mg/l as N") || units.equalsIgnoreCase("mg/l as Na") || 
                    units.equalsIgnoreCase("mg/l as P") || units.equalsIgnoreCase("mg/l as S") || units.equalsIgnoreCase("mgC3H6O2/L")){
            conversion = (java.lang.Math.pow(10,-6))*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("mg/mL @25C")){
            conversion = (java.lang.Math.pow(10,-6))*(1000)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("ml/l")){
            conversion = (1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("ng/l") || units.equalsIgnoreCase("pg/mL")){
            conversion = (java.lang.Math.pow(10,-12))*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("ng/m3") || units.equalsIgnoreCase("pg/l")){
            conversion = (java.lang.Math.pow(10,-12))*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("ocyst/100L")){
            conversion = (1.0/100.0)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("oocyst/10L")){
            conversion = (1.0/10.0)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("pfu/100L")){
            conversion = (1.0/100.0)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("pfu/100ml")){
            conversion = (1.0/100.0)*(1000)*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("pg/m3")){
            conversion = (java.lang.Math.pow(10,-15))*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("ug/L 2,4-D") || units.equalsIgnoreCase("ug/L U3O8") || units.equalsIgnoreCase("ug/L as As") || 
                    units.equalsIgnoreCase("ug/L as Cl") || units.equalsIgnoreCase("ug/L as N") || units.equalsIgnoreCase("ug/L as P") || 
                    units.equalsIgnoreCase("ug/l") || units.equalsIgnoreCase("ugAtrazn/L")){
            conversion = (java.lang.Math.pow(10,-9))*(1000)*(java.lang.Math.pow(0.3048,3))*(86400);
        }else if(units.equalsIgnoreCase("ug/m3")){
            conversion = (java.lang.Math.pow(10,-9))*(java.lang.Math.pow(0.3048,3))*(86400);
        }
        return conversion;
    }
    /**
     * @param units  the units of the current USGS water quality test.
     * @return a string with the load duration curve (LCD) end result units of the conversion.
     */
    public static String getLdcWqEndUnits(String units){
        String endUnits = "No Units";
        if(units.equalsIgnoreCase("#/l") || units.equalsIgnoreCase("#/m3") || units.equalsIgnoreCase("#/ml")){
            endUnits = "#/day";
        }else if(units.equalsIgnoreCase("MPN/100 ml") || units.equalsIgnoreCase("MPN/100L")){
            endUnits = "MPN/day";
        }else if(units.equalsIgnoreCase("cfu/100ml") || units.equalsIgnoreCase("cfu/mL")){
            endUnits = "cfu/day";
        }else if(units.equalsIgnoreCase("col/mL")){
            endUnits = "col/day";
        }else if(units.equalsIgnoreCase("cysts/100L") || units.equalsIgnoreCase("cysts/10L")){
            endUnits = "cysts/day";//= cysts/100L*cfs
        }else if(units.equalsIgnoreCase("mg/l") || units.equalsIgnoreCase("mg/l CaCO3") || units.equalsIgnoreCase("mg/l NH4") || 
                units.equalsIgnoreCase("mg/l NO3") || units.equalsIgnoreCase("mg/l PO4") || units.equalsIgnoreCase("mg/l SiO2") || 
                units.equalsIgnoreCase("mg/l as H") || units.equalsIgnoreCase("mg/l as N") || units.equalsIgnoreCase("mg/l as Na") || 
                units.equalsIgnoreCase("mg/l as P") || units.equalsIgnoreCase("mg/l as S") || units.equalsIgnoreCase("mgC3H6O2/L") || 
                units.equalsIgnoreCase("g/cm3") || units.equalsIgnoreCase("g/mL @ 20C") || units.equalsIgnoreCase("g/m3") || 
                units.equalsIgnoreCase("mg/mL @25C") || units.equalsIgnoreCase("ng/l") || units.equalsIgnoreCase("pg/mL") ||
                units.equalsIgnoreCase("ng/m3") || units.equalsIgnoreCase("pg/l") || units.equalsIgnoreCase("pg/m3") || 
                units.equalsIgnoreCase("ug/L 2,4-D") || units.equalsIgnoreCase("ug/L U3O8") || units.equalsIgnoreCase("ug/L as As") || 
                units.equalsIgnoreCase("ug/L as Cl") || units.equalsIgnoreCase("ug/L as N") || units.equalsIgnoreCase("ug/L as P") || 
                units.equalsIgnoreCase("ug/l") || units.equalsIgnoreCase("ugAtrazn/L") || units.equalsIgnoreCase("ug/m3")){
            endUnits = "kg/day";//= mg/l*cfs
        }else if(units.equalsIgnoreCase("ml/l")){
            endUnits = "ml/day";//= mg/l*cfs
        }else if(units.equalsIgnoreCase("pfu/100L") || units.equalsIgnoreCase("pfu/100ml")){
            endUnits = "pfu/day";
        }else if(units.equalsIgnoreCase("ocyst/100L")){
            endUnits = "ocyst/day";
        }else if(units.equalsIgnoreCase("oocyst/10L")){
            endUnits = "oocyst/day";
        }
        return endUnits;
    }
    /**
     * @param desiredUnits  the desired output units of this conversion (mg/L, ug/l, cfs)
     * @param currentUnits  the units of the current water quality data (g/l,  mg/l, ug/l,ng/l, pg/l, and cfs, mgd)
     * @return a double with the correct conversion factor for getting the currentUnits converted into the desiredUnits
     */
    public static double getWQconversion(String desiredUnits, String currentUnits){
        double conversion = -1.0;
        if(desiredUnits.equalsIgnoreCase("mg/l")){
            conversion = convertToMiligram(currentUnits);
        }else if(desiredUnits.equalsIgnoreCase("ug/l")){
            conversion = convertToMicrograms(currentUnits);
        }else if(desiredUnits.equalsIgnoreCase("cfs")){
            conversion = convertToCfs(currentUnits);
        }else if(desiredUnits.equalsIgnoreCase("std units")){
            conversion = 1.0;//leave pH units alone
        }else{
            //There are more units to be handled, but this is sufficient for now
            if(currentUnits.equalsIgnoreCase("#/100ml")){
                conversion = 1.0;//leave coliform units alone
            }
        }
        return conversion;
    }
    /**
     * @param units  the units of the current water quality data
     * @return a double with the correct conversion factor for the data into standardized (common) units
     */
    private static double convertToCfs(String units){
        double conversion = -1.0;
        if(units.equalsIgnoreCase("cfs")){
            conversion = 1.0;//convert to cfs
        }else if(units.equalsIgnoreCase("mgd")){
            conversion = 1.54722865;//convert to cfs
        }
        return conversion;
    }
    /**
    * @param units  the units of the current water quality data
    * @return a double with the correct conversion factor for the data into standardized (common) units
    */
    private static double convertToMiligram(String units){
        double conversion = -1.0;
        if(units.equalsIgnoreCase("g/l")){
            conversion = 1000.0;//convert to mg/l
        }else if(units.equalsIgnoreCase("mg/l")){
            conversion = 1.0;//convert to mg/l
        }else if(units.equalsIgnoreCase("ug/l")){
            conversion = 0.001;//convert to mg/l
        }else if(units.equalsIgnoreCase("ng/l")){
            conversion = (1.0/1000000.0);//convert to mg/l
        }else if(units.equalsIgnoreCase("pg/l")){
            conversion = (1.0/1000000000.0);//convert to mg/l
        }
        return conversion;
    }
    /**
    * @param units  the units of the current water quality data
    * @return a double with the correct conversion factor for the data into standardized (common) units
    */
    private static double convertToMicrograms(String units){
        double conversion = -1.0;
        if(units.equalsIgnoreCase("g/l")){
            conversion = 1000000.0;//convert to ug/l
        }else if(units.equalsIgnoreCase("mg/l")){
            conversion = 1000.0;//convert to ug/l
        }else if(units.equalsIgnoreCase("ug/l")){
            conversion = 1.0;//convert to ug/l
        }else if(units.equalsIgnoreCase("ng/l")){
            conversion = (1.0/1000.0);//convert to ug/l
        }else if(units.equalsIgnoreCase("pg/l")){
            conversion = (1.0/1000000.0);//convert to ug/l
        }
        return conversion;
    }
}