@@ -3,35 +3,270 @@ |
/** |
* |
* @author RUMPAL SIDHU |
+ * @author Shaun Case |
*/ |
+import csip.utils.Dates; |
+import csip.utils.JSONUtils; |
+ |
import java.util.Date; |
import java.util.ArrayList; |
import java.util.Calendar; |
import java.util.GregorianCalendar; |
+import java.sql.Connection; |
+import java.sql.DriverManager; |
+import java.sql.ResultSet; |
+import java.sql.SQLException; |
+import java.sql.Statement; |
+import java.util.Map; |
+import java.util.concurrent.TimeUnit; |
+ |
+import org.codehaus.jettison.json.JSONArray; |
+import org.codehaus.jettison.json.JSONObject; |
|
public class Crop { |
|
+ // Inner Classes |
+ class NutrientApplication { |
+ |
+ class Nutrient { |
+ private String error_msg = ""; |
+ private String nutrientApplied; |
+ private double applicationRate; |
+ |
+ public Nutrient(String nutrientApplied, double applicationRate) { |
+ this.nutrientApplied = nutrientApplied; |
+ this.applicationRate = applicationRate; |
+ |
+ if ( !nutrientApplied.equals("Nitrogen") && !nutrientApplied.equals("Phosphorus") ) { |
+ this.error_msg += "Invalid input data. Bad nutrient name"; |
+ } |
+ } |
+ |
+ //Get Methods |
+ public String getNutrientApplied() { |
+ return this.nutrientApplied; |
+ } |
+ |
+ public double getApplicationRate() { |
+ return this.applicationRate; |
+ } |
+ |
+ public String getErrorMsg(){ |
+ return this.error_msg; |
+ } |
+ |
+ public Boolean validate(){ |
+ return (this.error_msg.isEmpty()); |
+ } |
+ } |
+ |
+ private String error_msg = ""; |
+ private String applicationDate; |
+ private boolean incorporated; |
+ private ArrayList<Crop.NutrientApplication.Nutrient> nutrientList; |
+ private int appMethodScore = 0; |
+ private int[] nutrientTimingScores = new int[2]; |
+ |
+ public NutrientApplication(String applicationDate, String incorporated, JSONArray applications) { |
+ this.applicationDate = applicationDate; |
+ nutrientTimingScores[N_APP_TIMING_SCORE] = nutrientTimingScores[P_APP_TIMING_SCORE] = -1; |
+ |
+ if ( ( !"true".equalsIgnoreCase(incorporated) ) && ( !"false".equalsIgnoreCase(incorporated) ) ) { |
+ this.error_msg += "Invalid incorporation value for nutrient application " + applicationDate; |
+ } |
+ else{ |
+ this.incorporated = Boolean.parseBoolean(incorporated); |
+ nutrientList = new ArrayList<>(); |
+ |
+ try{ |
+ for (int k = 0; k < applications.length(); k++) { |
+ Map<String, JSONObject> nutrient = JSONUtils.preprocess(applications.getJSONArray(k)); |
+ nutrientList.add(new Crop.NutrientApplication.Nutrient(JSONUtils.getStringParam(nutrient, "nutrient_applied", "err"), JSONUtils.getDoubleParam(nutrient, "application_rate", 0))); |
+ } |
+ } |
+ catch(Exception ex){ |
+ this.error_msg += "Cannot process applied nutrient list. " + ex.getMessage(); |
+ } |
+ } |
+ } |
+ |
+ //Get Methods |
+ public Date getApplicationDate() throws Exception { |
+ String[] parse = this.applicationDate.split("-"); |
+ //Some say should set to use UTC first...do we wanna do that? |
+ Calendar date = new GregorianCalendar(Integer.parseInt(parse[0]), |
+ Integer.parseInt(parse[1]) - 1, Integer.parseInt(parse[2])); |
+ return date.getTime(); |
+ } |
+ |
+ public boolean isIncorporated() { |
+ return this.incorporated; |
+ } |
+ |
+ public ArrayList getNutrientList() { |
+ return this.nutrientList; |
+ } |
+ |
+ public String getErrorMsg(){ |
+ for (Crop.NutrientApplication.Nutrient nutrient : this.nutrientList ){ |
+ this.error_msg += nutrient.getErrorMsg(); |
+ } |
+ return this.error_msg; |
+ } |
+ |
+ public Boolean validate(){ |
+ for( Crop.NutrientApplication.Nutrient nutrient : nutrientList ) |
+ if ( !nutrient.validate() ) |
+ this.error_msg += "; " + nutrient.getErrorMsg(); |
+ |
+ return (this.error_msg.isEmpty()); |
+ } |
+ |
+ public int[] getNutrientTimingScores( Boolean split ){ |
+ if ( ( nutrientTimingScores[N_APP_TIMING_SCORE] < 0 ) || ( nutrientTimingScores[P_APP_TIMING_SCORE] < 0 ) ){ |
+ int tempNScore = 100; |
+ int tempPScore = 100; |
+ ResultSet resultSet; |
+ |
+ for ( Crop.NutrientApplication.Nutrient nutrient : nutrientList ){ |
+ int app_timing_score; |
+ |
+ try{ |
+ long app_day_diff = Dates.diffInMillis( getCropPlantDate(), getApplicationDate() ); |
+ app_day_diff = TimeUnit.MILLISECONDS.toDays(app_day_diff); |
+ |
+ String query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='"; |
+ |
+ query += nutrient.getNutrientApplied() + "' "; |
+ query += "AND app_mgt_kind='Timing' AND app_mgt_factor='" + (split? "split":"nosplit") + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";"; |
+ |
+ resultSet = statement.executeQuery(query); |
+ if ( !resultSet.first() ) { |
+ app_timing_score = -1; |
+ } |
+ else { |
+ app_timing_score = resultSet.getInt("app_mgt_score"); |
+ } |
+ |
+ switch (nutrient.getNutrientApplied()) |
+ { |
+ case "Nitrogen": |
+ if ( app_timing_score < tempNScore ) |
+ tempNScore = app_timing_score; |
+ break; |
+ |
+ case "Phosphorus": |
+ if ( app_timing_score < tempPScore ) |
+ tempPScore = app_timing_score; |
+ break; |
+ |
+ default: |
+ this.error_msg += "Invalid nutrient name specified"; |
+ } |
+ } |
+ catch (Exception ex){ |
+ this.error_msg += "Cannot calculate nutrient application timing scores: " + ex.getMessage(); |
+ } |
+ |
+ if ( this.error_msg.isEmpty() ){ |
+ nutrientTimingScores[N_APP_TIMING_SCORE] = tempNScore; |
+ nutrientTimingScores[P_APP_TIMING_SCORE] = tempPScore; |
+ } |
+ } |
+ } |
+ |
+ return nutrientTimingScores; |
+ } |
+ |
+ public Boolean allNutrientsIncorporated(){ |
+ return this.incorporated; |
+ } |
+ } |
+ |
+ |
+ // Begin Crop Class |
+ public static final int N_APP_RATE_SCORE = 0; |
+ public static final int P_APP_RATE_SCORE = 1; |
+ public static final int N_APP_TIMING_SCORE = 0; |
+ public static final int P_APP_TIMING_SCORE = 1; |
+ |
private int mgtCropId; |
private String cropPlantDate; |
+ private Date plantDate; |
private double cropYield; |
private String cropYieldUnits; |
- private ArrayList<Nutrient> nutrientApplicationList; |
- |
+ private ArrayList<Crop.NutrientApplication> nutrientApplicationList; |
+ private m.wqm.nutappmgtscores.Result calc_result; |
+ private Statement statement; |
+ private String cropType = ""; |
+ private String error_msg = ""; |
+ private Boolean multipleNutrientApplication = false; |
+ private int n_app_timing_score = 100; |
+ private int p_app_timing_score = 100; |
+ private int app_method_score = 0; |
+ private int[] appRateScore = new int[2]; |
+ private int[] appNutrientTimingScore = new int[2]; |
+ private String pSoilTestResult = "None"; |
+ |
public Crop(int mgtCropId,String cropPlantDate, double cropYield, |
- String cropYieldUnits, ArrayList<Nutrient> nutrientApplicationList) { |
+ String cropYieldUnits, JSONArray applicationList, String pSoilTestResult, Statement statement){ |
this.mgtCropId = mgtCropId; |
this.cropPlantDate = cropPlantDate; |
this.cropYield = cropYield; |
this.cropYieldUnits = cropYieldUnits; |
- this.nutrientApplicationList = nutrientApplicationList; |
+ this.statement = statement; |
+ this.pSoilTestResult = pSoilTestResult; |
+ |
+ nutrientApplicationList = new ArrayList<>(); |
+ |
+ try{ |
+ plantDate = getCropPlantDate(); |
+ for (int j = 0; j < applicationList.length(); j++) { |
+ Map<String, JSONObject> application = JSONUtils.preprocess(applicationList.getJSONArray(j)); |
+ nutrientApplicationList.add(new Crop.NutrientApplication(JSONUtils.getStringParam(application, "nutrient_application_date", "err"), JSONUtils.getStringParam(application, "incorporated", ""), JSONUtils.getJSONArrayParam(application, "application"))); |
+ } |
+ } |
+ catch( Exception ex){ |
+ error_msg += "Cannot process list of applied nutrients. " + ex.getMessage(); |
+ } |
+ |
+ multipleNutrientApplication = (nutrientApplicationList.size() > 1); |
+ this.appRateScore[N_APP_RATE_SCORE] = this.appRateScore[P_APP_RATE_SCORE] = -1; |
+ this.appNutrientTimingScore[N_APP_TIMING_SCORE] = this.appNutrientTimingScore[P_APP_TIMING_SCORE] = -1; |
} |
|
- //Getter methods |
+ //Get methods |
public int getMgtCropId() { |
return this.mgtCropId; |
} |
|
- public Date getCropPlantDate() throws Exception { |
+ public String getErrorMsg(){ |
+ for ( Crop.NutrientApplication nutrientApplied: this.nutrientApplicationList ){ |
+ error_msg += nutrientApplied.getErrorMsg(); |
+ } |
+ return error_msg; |
+ } |
+ |
+ public String getCropType(){ |
+ if ( (cropType.isEmpty()) && (error_msg.isEmpty()) ){ |
+ ResultSet resultSet; |
+ String query = "SELECT wqm_crop_type FROM wqm_crops WHERE wqm_crop_id=" + mgtCropId + " AND wqm_crop_units='" + cropYieldUnits + "';"; |
+ try{ |
+ resultSet = statement.executeQuery(query); |
+ if (!resultSet.first()){ |
+ error_msg += "That crop, " + mgtCropId + ", and crop yield units, "+ cropYieldUnits + ", was not found in the database"; |
+ } |
+ else{ |
+ cropType = resultSet.getString("wqm_crop_type"); |
+ } |
+ } |
+ catch( Exception ex ) { |
+ error_msg += ex.getMessage(); |
+ } |
+ } |
+ return cropType; |
+ } |
+ public final Date getCropPlantDate() throws Exception { |
String[] parse = this.cropPlantDate.split("-"); |
Calendar date = new GregorianCalendar(Integer.parseInt(parse[0]), |
Integer.parseInt(parse[1]) - 1, Integer.parseInt(parse[2])); |
@@ -49,4 +284,186 @@ |
public ArrayList getNutrientApplicationList() { |
return this.nutrientApplicationList; |
} |
+ |
+ public int[] getNutrientApplicationRateScores(){ |
+ if ( ( appRateScore[N_APP_RATE_SCORE] <0 ) || ( appRateScore[P_APP_RATE_SCORE] <0 ) ) { |
+ try{ |
+ if ( nutrientApplicationList.isEmpty() ){ |
+ ResultSet resultSet; |
+ |
+ appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0; |
+ String queryNitrogen = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='Nitrogen' AND app_mgt_kind='Rate' AND app_mgt_factor='none';"; |
+ String queryPhosporous = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='Phosphorus' AND app_mgt_kind='Rate' AND app_mgt_factor='none' AND soil_test_result='" + pSoilTestResult + "';"; |
+ |
+ resultSet = statement.executeQuery(queryNitrogen); |
+ if ( resultSet.first() ) |
+ appRateScore[N_APP_RATE_SCORE] = resultSet.getInt("app_mgt_score"); |
+ |
+ resultSet = statement.executeQuery(queryPhosporous); |
+ if ( resultSet.first() ) |
+ appRateScore[P_APP_RATE_SCORE] = resultSet.getInt("app_mgt_score"); |
+ } |
+ else{ |
+ ResultSet resultSet; |
+ String query; |
+ |
+ double nrate = 0.0; |
+ double prate = 0.0; |
+ |
+ double wqm_crop_pct_dmat = 0.0; |
+ double wqm_pct_nitrogen = 0.0; |
+ double wqm_pct_phosphorus = 0.0; |
+ double wqm_crop_yield = 0.0; |
+ |
+ int ncrop_app_rate_score = 0; |
+ int pcrop_app_rate_score = 0; |
+ |
+ for (Crop.NutrientApplication nutrient : nutrientApplicationList) { |
+ ArrayList<Crop.NutrientApplication.Nutrient> nutrientAppliedList = nutrient.getNutrientList(); |
+ for (Crop.NutrientApplication.Nutrient nApplied : nutrientAppliedList) { |
+ switch(nApplied.getNutrientApplied()){ //Note: This switch requires JDK 1.7 or above |
+ case "Nitrogen": |
+ nrate = nrate + nApplied.getApplicationRate(); |
+ break; |
+ case "Phosphorus": |
+ prate = prate + nApplied.getApplicationRate(); |
+ break; |
+ } |
+ } |
+ } |
+ |
+ query = "SELECT wqm_crop_pct_dmat, wqm_pct_nitrogen, wqm_pct_phosphorus, wqm_crop_yield FROM wqm_crops WHERE wqm_crop_id=" + mgtCropId + ";"; |
+ resultSet = statement.executeQuery(query); |
+ if (resultSet.first()) { |
+ wqm_crop_pct_dmat = resultSet.getDouble("wqm_crop_pct_dmat"); |
+ wqm_pct_nitrogen = resultSet.getDouble("wqm_pct_nitrogen"); |
+ wqm_pct_phosphorus = resultSet.getDouble("wqm_pct_phosphorus"); |
+ wqm_crop_yield = resultSet.getDouble("wqm_crop_yield"); |
+ |
+ // Added wqm_crop_yield to the calc per bug #462839 |
+ double n_growout = cropYield * wqm_crop_yield * wqm_crop_pct_dmat * wqm_pct_nitrogen; |
+ double p_growout = cropYield * wqm_crop_yield * wqm_crop_pct_dmat * wqm_pct_phosphorus; |
+ |
+ double n_remove_ratio = nrate / n_growout; |
+ double p_remove_ratio = prate / p_growout; |
+ |
+ query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor="; |
+ |
+ switch( cropType ){ |
+ case "Small Grain": //Note the case conflicts here... |
+ query += "'small grain'"; |
+ break; |
+ |
+ default: |
+ query += "'none'"; |
+ } |
+ query += " AND remove_ratio_1 <= " + n_remove_ratio + "AND remove_ratio_2 > " + n_remove_ratio + ";"; |
+ |
+ resultSet = statement.executeQuery(query); |
+ if (resultSet.first()) { |
+ ncrop_app_rate_score = resultSet.getInt("app_mgt_score"); |
+ } |
+ else{ |
+ appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0; |
+ } |
+ |
+ pcrop_app_rate_score = -1; |
+ //#Compute P application management rate scores based on removal ratio and soil test result |
+ switch (pSoilTestResult){ |
+ case "High": |
+ if (p_remove_ratio >= 1.2) { |
+ pcrop_app_rate_score = 0; |
+ } |
+ break; |
+ case "Medium": case "Low": |
+ if (p_remove_ratio >= 1.6) { |
+ pcrop_app_rate_score = 0; |
+ } |
+ break; |
+ case "None": |
+ if (p_remove_ratio >= 1.2) { |
+ pcrop_app_rate_score = 0; |
+ } |
+ break; |
+ } |
+ |
+ if ( pcrop_app_rate_score == -1 ){ |
+ query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='Phosphorus' AND app_mgt_kind='Rate' AND app_mgt_factor='app' AND soil_test_result='" + pSoilTestResult +"' AND remove_ratio_1 <= " + p_remove_ratio + " AND remove_ratio_2 > " + p_remove_ratio + ";"; |
+ resultSet = statement.executeQuery(query); |
+ if (resultSet.first()) { |
+ pcrop_app_rate_score = resultSet.getInt("app_mgt_score"); |
+ } |
+ } |
+ |
+ if (pcrop_app_rate_score != -1){ |
+ //#Update N and P application management rate scores for the AoA |
+ appRateScore[N_APP_RATE_SCORE] = ncrop_app_rate_score; |
+ appRateScore[P_APP_RATE_SCORE] = pcrop_app_rate_score; |
+ } |
+ else{//We have a problem...no validity in any following computations if we proceed since the last query failed to find any data. What would you like to do? |
+ appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0; |
+ } |
+ } |
+ else{ //We have a problem...no validity in any following computations if we proceed. What would you like to do? |
+ appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0; |
+ } |
+ } |
+ } |
+ catch (Exception ex) { |
+ error_msg += ex.getMessage(); |
+ } |
+ } |
+ |
+ return this.appRateScore; |
+ } |
+ |
+ public int[] getNutrientApplicationTimingScores(){ |
+ if ( ( appNutrientTimingScore[N_APP_TIMING_SCORE] <0 ) || ( appNutrientTimingScore[P_APP_TIMING_SCORE] <0 ) ) { |
+ int tempNScore = 100; |
+ int tempPScore = 100; |
+ |
+ for ( Crop.NutrientApplication nutrientApplication : this.nutrientApplicationList ){ |
+ // Call each application compare its results to the last and adjust main score if necessary. |
+ int[] tempAppTimingScores = nutrientApplication.getNutrientTimingScores( this.multipleNutrientApplication ); |
+ |
+ if ( tempAppTimingScores[N_APP_TIMING_SCORE] < tempNScore ) |
+ tempNScore = tempAppTimingScores[N_APP_TIMING_SCORE]; |
+ |
+ if ( tempAppTimingScores[P_APP_TIMING_SCORE] < tempPScore ) |
+ tempPScore = tempAppTimingScores[P_APP_TIMING_SCORE]; |
+ } |
+ |
+ appNutrientTimingScore[P_APP_TIMING_SCORE] = tempPScore; |
+ appNutrientTimingScore[N_APP_TIMING_SCORE] = tempNScore; |
+ } |
+ |
+ return this.appNutrientTimingScore; |
+ } |
+ |
+ public Boolean allNutrientsIncorporated(){ |
+ Boolean ret_val = true; |
+ for( Crop.NutrientApplication nutrientApplication : this.nutrientApplicationList ){ |
+ if ( !nutrientApplication.allNutrientsIncorporated() ){ |
+ ret_val = false; |
+ break; |
+ } |
+ } |
+ |
+ return ret_val; |
+ } |
+ |
+ public String processCropData(){ |
+ String ret_val = ""; |
+ |
+ return ret_val; |
+ } |
+ |
+ public Boolean validate(){ |
+ for( Crop.NutrientApplication tNutrientApplication : nutrientApplicationList ) |
+ if ( !tNutrientApplication.validate() ) |
+ error_msg += "; " + tNutrientApplication.getErrorMsg(); |
+ |
+ |
+ return ( error_msg.isEmpty() ); |
+ } |
} |
@@ -3,7 +3,10 @@ |
/** |
* |
* @author RUMPAL SIDHU |
+ * @author Shaun Case |
+ * |
*/ |
+ |
import csip.ModelDataService; |
import csip.utils.JSONUtils; |
import csip.utils.Dates; |
@@ -43,325 +46,143 @@ |
private ArrayList<Input> input; |
//Response |
private ArrayList<Result> result; |
- |
+ |
+ //private class variables for this service |
+ private int AoAId = 0; |
+ private String p_soil_test_result = "err"; |
+ private ArrayList<Crop> cropList; |
+ private String error_msg = ""; |
+ private Connection conn = null; |
+ private Statement statement = null; |
+ |
@Override |
protected void preProcess() throws Exception { |
- input = new ArrayList<>(); |
- int AoAId = getIntParam("aoa_id", 0); |
- String p_soil_test_result = getStringParam("p_soil_test_result", "err"); |
- ArrayList<Crop> cropList = new ArrayList<>(); |
- JSONArray cropIds = getJSONArrayParam("cropIds"); |
- for (int i = 0; i < cropIds.length(); i++) { |
- Map<String, JSONObject> mgtCropId = JSONUtils.preprocess(cropIds.getJSONArray(i)); |
+ try{ |
+ Class.forName(CLASS_NAME); |
+ conn = DriverManager.getConnection(CONNECTION, USER, PASS); |
+ statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); |
+ } |
+ catch(ClassNotFoundException | SQLException ex) { |
+ if (ex instanceof SQLException) { |
+ LOG.info("Did not open database for WQM-16!"); |
+ LOG.info(ex.getMessage()); |
+ error_msg = "Could not open database for WQM-16! " + ex.getMessage(); |
+ } |
+ else{ |
+ error_msg = "Could not instantiate postgres database object: " + ex.getMessage(); |
+ } |
+ } |
|
- int cropId = JSONUtils.getIntParam(mgtCropId, "mgt_crop_id", 0); |
- String cropPlantDate = JSONUtils.getStringParam(mgtCropId, "crop_plant_date", "err"); |
- double cropYield = JSONUtils.getDoubleParam(mgtCropId, "crop_yield", 0); |
- String cropYieldUnits = JSONUtils.getStringParam(mgtCropId, "crop_yield_units", "err"); |
- ArrayList<Nutrient> nutrientApplicationList = new ArrayList<>(); |
- JSONArray applicationList = JSONUtils.getJSONArrayParam(mgtCropId, "applicationList"); |
- for (int j = 0; j < applicationList.length(); j++) { |
- Map<String, JSONObject> application = JSONUtils.preprocess(applicationList.getJSONArray(j)); |
- String nutrient_application_date = JSONUtils.getStringParam(application, "nutrient_application_date", "err"); |
- boolean incorporated = JSONUtils.getBooleanParam(application, "incorporated", false); |
- ArrayList<NutrientApplied> nutrientAppliedList = new ArrayList<>(); |
- JSONArray applicate = JSONUtils.getJSONArrayParam(application, "application"); |
- for (int k = 0; k < applicate.length(); k++) { |
- Map<String, JSONObject> a = JSONUtils.preprocess(applicate.getJSONArray(k)); |
- String nutrient_applied = JSONUtils.getStringParam(a, "nutrient_applied", "err"); |
- double application_rate = JSONUtils.getDoubleParam(a, "application_rate", 0); |
- nutrientAppliedList.add(new NutrientApplied(nutrient_applied, application_rate)); |
- } |
- nutrientApplicationList.add(new Nutrient(nutrient_application_date, incorporated, nutrientAppliedList)); |
- } |
- cropList.add(new Crop(cropId, cropPlantDate, cropYield, cropYieldUnits, nutrientApplicationList)); |
+ if (error_msg.isEmpty()){ |
+ AoAId = getIntParam("aoa_id", 0); |
+ p_soil_test_result = getStringParam("p_soil_test_result", "err"); |
+ cropList = new ArrayList<>(); |
+ |
+ JSONArray cropIds = getJSONArrayParam("cropIds"); |
+ for (int i = 0; i < cropIds.length(); i++) { |
+ Map<String, JSONObject> mgtCropId = JSONUtils.preprocess(cropIds.getJSONArray(i)); |
+ cropList.add( new Crop(JSONUtils.getIntParam(mgtCropId, "mgt_crop_id", 0), JSONUtils.getStringParam(mgtCropId, "crop_plant_date", "err"), |
+ JSONUtils.getDoubleParam(mgtCropId, "crop_yield", 0), JSONUtils.getStringParam(mgtCropId, "crop_yield_units", "err"), |
+ JSONUtils.getJSONArrayParam(mgtCropId, "applicationList"), p_soil_test_result, statement)); |
+ } |
+ |
+ ValidateInput(); |
} |
- input.add(new m.wqm.nutappmgtscores.Input(AoAId, cropList, p_soil_test_result)); |
} |
|
@Override |
- protected String process() throws Exception { |
- result = new ArrayList<>(); |
- Connection conn = null; |
- Statement statement = null; |
+ protected String process() throws Exception { |
+ String ret_val = EXEC_OK; |
+ int n_app_timing_score = 100; |
+ int p_app_timing_score = 100; |
+ int app_method_score = -1; |
+ int n_app_rate_score = 0; |
+ int p_app_rate_score = 0; |
+ int this_crop_id = 0; |
String query; |
ResultSet resultSet; |
+ |
+ if ( !error_msg.isEmpty()){ |
+ ret_val = error_msg; |
+ } |
+ else{ |
+ result = new ArrayList<>(); |
|
- try { |
- Class.forName(CLASS_NAME); |
- conn = DriverManager.getConnection(CONNECTION, USER, PASS); |
- conn.setAutoCommit(false); |
- statement = conn.createStatement(); |
- for (Input ip : input) { |
- int n_app_timing_score = 100; |
- int p_app_timing_score = 100; |
- int app_method_score = 0; |
- int n_app_rate_score = 0; |
- int p_app_rate_score = 0; |
- int this_crop_id = 0; |
- ArrayList<Crop> cropList = ip.getCropList(); |
+ try { |
for (Crop crop : cropList) { |
- ArrayList<Nutrient> nutrientApplicationList = crop.getNutrientApplicationList(); |
- this_crop_id = crop.getMgtCropId(); |
+ |
+ String crop_type = crop.getCropType(); |
+//////TODO: Remember to check for errors from the classes.... /////// |
+ if ( !crop_type.isEmpty() ){ |
+ //#Update N and P application management rate scores for each crop |
+ int[] app_rate_scores = crop.getNutrientApplicationRateScores(); |
+ if ( !(error_msg = crop.getErrorMsg()).isEmpty() ) |
+ break; |
+ |
+ //Cummulative sum of N and P application management scores over all crops for the AoA |
+ n_app_rate_score += app_rate_scores[Crop.N_APP_RATE_SCORE]; |
+ p_app_rate_score += app_rate_scores[Crop.P_APP_RATE_SCORE]; |
+ |
+ |
+ //#Compute N and P application timing scores for the crop and update timing scores for the AoA |
+ int [] app_time_scores = crop.getNutrientApplicationTimingScores(); |
+ if ( !(error_msg = crop.getErrorMsg()).isEmpty() ) |
+ break; |
|
- //#Determine crop type of the crop |
- query = "SELECT wqm_crop_type FROM wqm_crops WHERE wqm_crop_id=" + this_crop_id + ";"; |
- resultSet = statement.executeQuery(query); |
- String crop_type = "err"; |
- while (resultSet.next()) { |
- crop_type = resultSet.getString("wqm_crop_type"); |
+ // There is a problem with the logic of the specification here...It does not take into account the actual timing of applications when |
+ // there are mulitple crops and multiple years invovled....these final values are probably not correct. The "-1" below is placed here |
+ // in an attempt to fix the missing database values problem that also exists with this logic at the nutrient level. |
+ if (( app_time_scores[Crop.N_APP_TIMING_SCORE] < n_app_timing_score ) || (n_app_timing_score == -1)) |
+ n_app_timing_score = app_time_scores[Crop.N_APP_TIMING_SCORE]; |
+ |
+ if (( app_time_scores[Crop.P_APP_TIMING_SCORE] < p_app_timing_score ) || (p_app_timing_score == -1)) |
+ p_app_timing_score = app_time_scores[Crop.P_APP_TIMING_SCORE]; |
+ |
+ //#If any nutrient application for any crop is not incorporated, the method score for the AoA is zero |
+ if ( !crop.allNutrientsIncorporated() ){ |
+ app_method_score = 0; |
+ } |
+ if ( !(error_msg = crop.getErrorMsg()).isEmpty() ) |
+ break; |
} |
- |
- //#Determine whether split nutrient applications or not |
- int app_count = 0; |
- String app_type; |
- //For each nutrient_application_date in the crop period |
- //for (Nutrient i : nutrientApplication) { |
- // app_count = app_count + 1; |
- //} |
- app_count = nutrientApplicationList.size(); |
- if (app_count == 1) { |
- app_type = "nosplit"; |
- } else { |
- app_type = "split"; |
- } |
- //If no nutrient_application_date (no nutrient applications for the crop) |
- int ncrop_app_rate_score = 0; |
- int pcrop_app_rate_score = 0; |
- if (nutrientApplicationList.isEmpty()) { |
- //#Compute score for not fertilizing. |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "None" + "';"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- n_app_rate_score = resultSet.getInt("app_mgt_score"); |
- } |
- switch (ip.getPSoilTestResult()) { |
- case "High": { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "None" + "' AND soil_test_result='" + "High" + "';"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- p_app_rate_score = resultSet.getInt("app_mgt_score"); |
- } |
- break; |
- } |
- case "Medium": { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "None" + "' AND soil_test_result='" + "Medium" + "';"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- p_app_rate_score = resultSet.getInt("app_mgt_score"); |
- } |
- break; |
- } |
- case "None": { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "None" + "' AND soil_test_result='" + "None" + "';"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- p_app_rate_score = resultSet.getInt("app_mgt_score"); |
- } |
- } |
- } |
- } else { //Else #Compute N and P removal ratios |
- double nrate = 0.0; |
- double prate = 0.0; |
- for (Nutrient nutrient : nutrientApplicationList) { |
- ArrayList<NutrientApplied> nutrientAppliedList = nutrient.getNutrientAppliedList(); |
- for (NutrientApplied nApplied : nutrientAppliedList) { |
- if (nApplied.getNutrientApplied().equals("Nitrogen")) { |
- nrate = nrate + nApplied.getApplicationRate(); |
- } else { |
- prate = prate + nApplied.getApplicationRate(); |
- } |
- } |
- } |
- double wqm_crop_pct_dmat = 0.0; |
- double wqm_pct_nitrogen = 0.0; |
- double wqm_pct_phosphorus = 0.0; |
- query = "SELECT wqm_crop_pct_dmat, wqm_pct_nitrogen, wqm_pct_phosphorus FROM wqm_crops WHERE wqm_crop_id=" + this_crop_id + ";"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- wqm_crop_pct_dmat = resultSet.getDouble("wqm_crop_pct_dmat"); |
- wqm_pct_nitrogen = resultSet.getDouble("wqm_pct_nitrogen"); |
- wqm_pct_phosphorus = resultSet.getDouble("wqm_pct_phosphorus"); |
- } |
- |
- double n_growout = crop.getCropYield() * wqm_crop_pct_dmat * wqm_pct_nitrogen; |
- double p_growout = crop.getCropYield() * wqm_crop_pct_dmat * wqm_pct_phosphorus; |
- |
- double n_remove_ratio = nrate / n_growout; |
- double p_remove_ratio = prate / p_growout; |
- |
- //#Compute N application management rate score based on removal ratio and whether small grain or not |
- if (crop_type.equals("small grain")) { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "small grain" + "' AND remove_ratio_1 <= " + n_remove_ratio + "AND remove_ratio_2 > " + n_remove_ratio + ";"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- ncrop_app_rate_score = resultSet.getInt("app_mgt_score"); |
- } |
- } else { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "other" + "' AND remove_ratio_1 <= " + n_remove_ratio + "AND remove_ratio_2 > " + n_remove_ratio + ";"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- ncrop_app_rate_score = resultSet.getInt("app_mgt_score"); |
- } |
- } |
- |
- //#Compute P application management rate scores based on removal ratio and soil test result |
- switch (ip.getPSoilTestResult()) { |
- case "High": { |
- if (p_remove_ratio >= 1.2) { |
- pcrop_app_rate_score = 0; |
- } else { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "app" + "' AND soil_test_result'=" + "High" + "'AND remove_ratio_1 <= " + p_remove_ratio + "AND remove_ratio_2 > " + p_remove_ratio + ";"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- pcrop_app_rate_score = resultSet.getInt("app_mgt_score"); |
- } |
- } |
- break; |
- } |
- case "Medium": { |
- if (p_remove_ratio >= 1.6) { |
- pcrop_app_rate_score = 0; |
- } else { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "app" + "' AND soil_test_result'=" + "Medium" + "'AND remove_ratio_1 <= " + p_remove_ratio + "AND remove_ratio_2 > " + p_remove_ratio + ";"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- pcrop_app_rate_score = resultSet.getInt("app_mgt_score"); |
- } |
- } |
- break; |
- } |
- case "Low": { |
- if (p_remove_ratio >= 1.6) { |
- pcrop_app_rate_score = 0; |
- } else { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "app" + "' AND soil_test_result'=" + "Low" + "'AND remove_ratio_1 <= " + p_remove_ratio + "AND remove_ratio_2 > " + p_remove_ratio + ";"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- pcrop_app_rate_score = resultSet.getInt("app_mgt_score"); |
- } |
- } |
- break; |
- } |
- case "None": { |
- if (p_remove_ratio >= 1.2) { |
- pcrop_app_rate_score = 0; |
- } else { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "app" + "' AND soil_test_result'=" + "None" + "'AND remove_ratio_1 <= " + p_remove_ratio + "AND remove_ratio_2 > " + p_remove_ratio + ";"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- pcrop_app_rate_score = resultSet.getInt("app_mgt_score"); |
- } |
- } |
- break; |
- } |
- } |
- //#Update N and P application management rate scores for the AoA |
- n_app_rate_score = n_app_rate_score + ncrop_app_rate_score; |
- p_app_rate_score = p_app_rate_score + pcrop_app_rate_score; |
- } |
- //#Compute N and P application timing scores for the crop and update timin scores for the AoA |
- int ncrop_app_timing_score = 0; |
- int pcrop_app_timing_score = 0; |
- for (Nutrient nutrient : nutrientApplicationList) { |
- long app_day_diff = Dates.diffInMillis(crop.getCropPlantDate(), nutrient.getApplicationDate()); |
- app_day_diff = TimeUnit.MICROSECONDS.convert(app_day_diff, TimeUnit.DAYS); |
- ArrayList<NutrientApplied> nutrientAppliedList = nutrient.getNutrientAppliedList(); |
- for (NutrientApplied nApplied : nutrientAppliedList) { |
- switch (nApplied.getNutrientApplied()) { |
- case "Nitrogen": { |
- if (app_type.equals("split")) { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Timing" + "' AND app_mgt_factor='" + "split" + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- ncrop_app_timing_score = resultSet.getInt("app_mgt_score"); |
- //Doubt |
- if (resultSet.wasNull()) { |
- n_app_timing_score = 0; |
- } else if (ncrop_app_timing_score < n_app_timing_score) { |
- n_app_timing_score = ncrop_app_timing_score; |
- } |
- } |
- |
- } else { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Timing" + "' AND app_mgt_factor='" + "nosplit" + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- ncrop_app_timing_score = resultSet.getInt("app_mgt_score"); |
- //Doubt |
- if (resultSet.wasNull()) { |
- n_app_timing_score = 0; |
- } else if (ncrop_app_timing_score < n_app_timing_score) { |
- n_app_timing_score = ncrop_app_timing_score; |
- } |
- } |
- } |
- break; |
- } |
- case "Phosphorus": { |
- if (app_type.equals("split")) { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Timing" + "' AND app_mgt_factor='" + "split" + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- pcrop_app_timing_score = resultSet.getInt("app_mgt_score"); |
- //Doubt |
- if (resultSet.wasNull()) { |
- p_app_timing_score = 0; |
- } else if (pcrop_app_timing_score < p_app_timing_score) { |
- p_app_timing_score = ncrop_app_timing_score; |
- } |
- } |
- } else { |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Timing" + "' AND app_mgt_factor='" + "nosplit" + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- pcrop_app_timing_score = resultSet.getInt("app_mgt_score"); |
- //Doubt |
- if (resultSet.wasNull()) { |
- p_app_timing_score = 0; |
- } else if (pcrop_app_timing_score < p_app_timing_score) { |
- p_app_timing_score = pcrop_app_timing_score; |
- } |
- } |
- } |
- } |
- } |
- } |
- } |
- for (Nutrient nutrient : nutrientApplicationList) { |
- //#If any nutrient application for any crop is not incorporated, the method score for the AoA is zero |
- if (!nutrient.isIncorporated()) { |
- app_method_score = 0; |
- break; |
- } else if (nutrient.isIncorporated()) { //#If all nutrient applications for all crops are incorporated, the method score for incorporation applies to the AoA |
- query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE app_mgt_kind='" + "Method" + "' AND app_mgt_factor='" + "incorporate" + "';"; |
- resultSet = statement.executeQuery(query); |
- while (resultSet.next()) { |
- app_method_score = resultSet.getInt("app_mgt_score"); |
- } |
- } |
+ else{ |
+ ret_val = error_msg = "Cannot get crop_type. " + crop.getErrorMsg(); |
} |
} |
+ |
+ // If all crops' nutrients were incorporated this value will still be -1 |
+ if ( app_method_score == -1 ){ |
+ query = "SELECT app_mgt_score from wqm_nutrient_application_mgt_scores WHERE app_mgt_kind='Method' AND app_mgt_factor='incorporate';"; |
+ resultSet = statement.executeQuery(query); |
+ if ( resultSet.first() ){ |
+ app_method_score = resultSet.getInt("app_mgt_score"); |
+ } |
+ } |
+ |
//#Compute application management scores for nitrogen in groundwater, nitrogen in surface water, and phosphorus in surface water |
int nleach_app_mgt_score = n_app_rate_score + n_app_timing_score + app_method_score; |
int nsurf_app_mgt_score = n_app_rate_score + n_app_timing_score + app_method_score; |
int psurf_app_mgt_score = p_app_rate_score + p_app_timing_score + app_method_score; |
- m.wqm.nutappmgtscores.Result result1 = new m.wqm.nutappmgtscores.Result(ip.getAoAId(), nleach_app_mgt_score, nsurf_app_mgt_score, psurf_app_mgt_score, n_app_rate_score, n_app_timing_score, p_app_rate_score, p_app_timing_score, app_method_score); |
- result.add(result1); |
+ m.wqm.nutappmgtscores.Result result1 = new m.wqm.nutappmgtscores.Result(AoAId, nleach_app_mgt_score, nsurf_app_mgt_score, psurf_app_mgt_score, n_app_rate_score, n_app_timing_score, p_app_rate_score, p_app_timing_score, app_method_score); |
+ result.add(result1); |
+ |
+ conn.close(); |
+ } catch (SQLException se) { |
+ LOG.info("Did not open database for WQM-16!"); |
+ LOG.info(se.getMessage()); |
+ ret_val += se.getMessage(); |
+ }catch (Exception ex ){ |
+ ret_val += ex.getMessage(); |
+ } finally { |
+ if (statement != null) { |
+ statement.close(); |
+ } |
+ if (conn != null) { |
+ conn.close(); |
+ } |
} |
- conn.close(); |
- } catch (SQLException se) { |
- LOG.info("Did not open database for WQM-16!"); |
- LOG.info(se.getMessage()); |
- } finally { |
- if (statement != null) { |
- statement.close(); |
- } |
- if (conn != null) { |
- conn.close(); |
- } |
- } |
- return EXEC_OK; |
+ } |
+ return (error_msg.isEmpty()? EXEC_OK:error_msg); |
} |
|
@Override |
@@ -383,4 +204,12 @@ |
} |
putResult("Result", resultArr); |
} |
+ |
+ private boolean ValidateInput(){ |
+ for( Crop tCrop : cropList ) |
+ if ( !tCrop.validate() ) |
+ error_msg += "; " + tCrop.getErrorMsg(); |
+ |
+ return (error_msg.isEmpty()); |
+ } |
} |