V1_0.java [src/java/m/wqm/scsednutsrp] Revision: beeb863466e13252033d084c2a99e430f219b84d  Date: Sat Sep 26 12:06:33 MDT 2015
package m.wqm.scsednutsrp;

import csip.ModelDataService;
import csip.ServiceException;
import java.util.ArrayList;
import javax.ws.rs.Path;
import oms3.annotations.Description;
import oms3.annotations.Name;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import csip.utils.JSONUtils;
import java.util.Map;
import org.codehaus.jettison.json.JSONException;

/**
 *
 * @author Srinivas
 * @author Rumpal Sidhu
 */
@Name("WQM-06: Sediment and Nutrient Soil Runoff Potential (SedNutSRP)")
@Description("This service computes sediment and nutrient soil runoff potential for soil components in an area of analysis, and then compute soil runoff potential representing the area of analysis. The service primarily will consume data from the WQM-2 soil attributes service to compute soil runoff potential values for subsequent use by WQM-13 to compute threshold treatment level scores.")
@Path("m/scsednut_srp/1.0")
public class V1_0 extends ModelDataService {

    private final String[] srpList = new String[]{"LOW", "MODERATE", "MODERATELY HIGH", "HIGH"};
    //Request
    private int aoaId;
    private ArrayList<SoilComponent> soilComponentList;
    //Result
    private String aoaSrp;
    private String error_msg;

    @Override
    protected void preProcess() throws Exception {
        soilComponentList = new ArrayList<>();
        this.error_msg = "";
        try {
            aoaId = getIntParam("AoAId");
            JSONArray groups = getJSONArrayParam("soilcomponents");
            for (int i = 0; i < groups.length(); i++) {
                Map<String, JSONObject> group = JSONUtils.preprocess(groups.getJSONArray(i));
                SoilComponent input = new SoilComponent(
                        JSONUtils.getStringParam(group, "cokey", "err"),
                        JSONUtils.getDoubleParam(group, "aoa_comp_area", 0),
                        JSONUtils.getStringParam(group, "aoa_comp_hsg", "err"),
                        JSONUtils.getStringParam(group, "aoa_comp_taxorder", "err"),
                        JSONUtils.getDoubleParam(group, "aoa_comp_kfact", 0),
                        JSONUtils.getDoubleParam(group, "aoa_comp_slope", 0),
                        JSONUtils.getDoubleParam(group, "aoa_comp_coarse_frag", 0),
                        JSONUtils.getBooleanParam(group, "aoa_comp_drained", false),
                        JSONUtils.getStringParam(group, "aoa_comp_wtbl", "err"),
                        JSONUtils.getBooleanParam(group, "aoa_comp_hwt_lt_24", false));
                soilComponentList.add(input);
            }
        } catch (ServiceException | JSONException ex) {
            this.error_msg += "  " + ex.getMessage() + ". ";
        }
    }

    @Override
    protected String process() throws Exception {
        try {
            if (this.error_msg.isEmpty()) {
                this.computeSedNutSRP();
            }
            if (this.error_msg.isEmpty()) {
                this.computeAoaSrp();
            }
        } catch (Exception ex) {
            LOG.info(ex.getMessage());
            this.error_msg += ex.getMessage();
        }
        return (this.error_msg.isEmpty() ? EXEC_OK : this.error_msg);
    }

    @Override
    protected void postProcess() throws Exception {
        putResult("aoa_id", aoaId, "Area of analysis identifier");
        putResult("aoa_srp", aoaSrp, "Soil runoff potential for the area of analysis");
        JSONArray resultArr = new JSONArray();
        for (SoilComponent sc : soilComponentList) {
            JSONArray array = new JSONArray();
            array.put(JSONUtils.dataDesc("cokey", sc.getCokey(), "Soil component key"));
            array.put(JSONUtils.dataDesc("comp_srp", sc.getSrp(), "Soil runoff potential for soil component"));
            resultArr.put(JSONUtils.dataDesc("soil_component", array, "Soil Component"));
        }
        putResult("soil_components", resultArr, "List of Soil Components");
    }

    //Compute sediment and nutrient soil runoff potential for each soil component in the AoA
    private void computeSedNutSRP() {
        int comp_srp_number = -2;
        for (SoilComponent ip : soilComponentList) {
            switch (ip.getHsg()) {
                case "A":
                    comp_srp_number = 0;
                    break;
                case "B":
                    comp_srp_number = this.computeSRPHsgB(ip);
                    break;
                case "C":
                    comp_srp_number = this.computeSRPHsgC(ip);
                    break;
                case "D":
                    if ((ip.getWtbl().equals("Perched")
                            || ip.getWtbl().equals("Apparent")) || ip.isHwt_lt_24()) {
                        comp_srp_number = 3;
                    } else if (ip.getSlope() < 2 && ip.getKfact() < 0.28) {
                        comp_srp_number = 0;
                    } else if (ip.getSlope() < 2 && ip.getKfact() >= 0.28) {
                        comp_srp_number = 1;
                    } else if (ip.getSlope() >= 2 && ip.getSlope() <= 4) {
                        comp_srp_number = 2;
                    } else if (ip.getSlope() > 4) {
                        comp_srp_number = 3;
                    }
                    break;
                case "A/D":
                    if (ip.isDrained()) {
                        comp_srp_number = 0;
                    } else {
                        comp_srp_number = this.computeSRPHsgD(ip);
                    }
                    break;
                case "B/D":
                    if (ip.isDrained()) {
                        comp_srp_number = this.computeSRPHsgB(ip);
                    } else {
                        comp_srp_number = this.computeSRPHsgD(ip);
                    }
                    break;
                case "C/D":
                    if (ip.isDrained()) {
                        comp_srp_number = this.computeSRPHsgC(ip);
                    } else {
                        comp_srp_number = this.computeSRPHsgD(ip);
                    }
                    break;
            }
            if (comp_srp_number != -1 && comp_srp_number != -2) {
                ip.setSrpNumber(comp_srp_number);
                ip.setSrp(srpList[comp_srp_number]);
            } else {
                error_msg = "Error.";
            }
        }
    }

    public int computeSRPHsgB(SoilComponent ip) {
        int srp_number = -1;
        if (ip.getSlope() < 4) {
            srp_number = 0;
        } else if (ip.getSlope() >= 4 && ip.getSlope() <= 6 && ip.getKfact() < 0.32) {
            srp_number = 1;
        } else if (ip.getSlope() >= 4 && ip.getSlope() <= 6 && ip.getKfact() >= 0.32) {
            srp_number = 2;
        } else if (ip.getSlope() > 6) {
            srp_number = 3;
        }
        return srp_number;
    }

    public int computeSRPHsgC(SoilComponent ip) {
        int srp_number = -1;
        if (ip.getSlope() < 2) {
            srp_number = 0;
        } else if (ip.getSlope() >= 2 && ip.getSlope() <= 6 && ip.getKfact() < 0.28) {
            srp_number = 1;
        } else if (ip.getSlope() >= 2 && ip.getSlope() <= 6 && ip.getKfact() >= 0.28) {
            srp_number = 2;
        } else if (ip.getSlope() > 6) {
            srp_number = 3;
        }
        return srp_number;
    }

    public int computeSRPHsgD(SoilComponent ip) {
        int srp_number = -1;
        if (ip.getSlope() < 2 && ip.getKfact() < 0.28) {
            srp_number = 0;
        } else if (ip.getSlope() < 2 && ip.getKfact() >= 0.28) {
            srp_number = 1;
        } else if (ip.getSlope() >= 2 && ip.getSlope() <= 4) {
            srp_number = 2;
        } else if ((ip.getSlope() > 4) || ((ip.getWtbl().equals("Perched")
                || ip.getWtbl().equals("Apparent")) || ip.isHwt_lt_24())) {
            srp_number = 3;
        }
        return srp_number;
    }

    //Compute weighted average nutrient soil leaching potential for the AoA
    void computeAoaSrp() {
        double srpProduct = 0;
        double aoaArea = 0;
        for (SoilComponent sc : soilComponentList) {
            srpProduct += (sc.getSrpNumber() * sc.getArea());
            aoaArea += sc.getArea();
        }
        double aoaSrpFract = srpProduct / aoaArea;

        if (aoaSrpFract <= 0.50) {
            aoaSrp = "LOW";
        } else if (aoaSrpFract > 0.50 && aoaSrpFract <= 1.50) {
            aoaSrp = "MODERATE";
        } else if (aoaSrpFract > 1.50 && aoaSrpFract <= 2.50) {
            aoaSrp = "MODERATELY HIGH";
        } else {
            aoaSrp = "HIGH";
        }
    }

}