LMODOperation.java [src/java/m/wepp] Revision: Date:
package m.wepp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.GregorianCalendar;
/**
* This represents an LMOD operation
*
* @author jrf
*/
public class LMODOperation implements Comparable<LMODOperation> {
public enum RecStatus {
MISSING, OK, NOPROCESSES
};
float fuel = 0;
float stir = 0;
String date;
String opName;
String tranOpName;
RecStatus opStatus;
String vegName;
String tranVegName;
String resName;
String tranResName;
RecStatus vegStatus;
RecStatus resStatus;
String vegKey;
String resKey;
String resCropKey;
String harVegKey;
String opBlob;
String vegBlob;
String resBlob;
List<String> processes;
List<String> tillageKeys;
List<String> vegKeys;
String errors;
boolean cropGrowing;
boolean forceKillCrop;
boolean deletePlantProcess;
boolean interval;
WEPPModel wm;
LMODWeppData dbs;
float yield;
float resAmount;
float targetyield;
boolean use_CRLMOD;
/**
* This constructs the data require of WEPP for an LMOD operation. This can
* reference other databases to get the detail parameters.
*
* @param wm WEPP model for lower level functions
* @param date date of operation
* @param op name of operation
* @param veg vegetation name in operation (can be empty)
* @param res residue name in operation (can be empty)
* @param resA residue amount in operation (can be empty)
* @param yld yield amount in operation (can be empty)
* @param dbs details of WEPP data loaded so far.
* @param useR2Names true if using RUSLE2 names would require translation
* @param use_CRLMOD true if using CRLMOD database
*/
LMODOperation(WEPPModel wm, String date, String op, String veg, String res, String resA, String yld, LMODWeppData dbs, boolean useR2Names, boolean use_CRLMOD, boolean isintv) {
this.date = date;
this.wm = wm;
this.use_CRLMOD = use_CRLMOD;
opName = op;
vegName = veg;
resName = res;
interval = isintv;
errors = "";
cropGrowing = false;
forceKillCrop = false;
if (resA == null) {
resAmount = -999;
} else if (resA.equals("") || (resA.equalsIgnoreCase("null"))) {
resAmount = -999;
} else {
resAmount = Float.parseFloat(resA);
}
if (yld.equals("") || (yld.equalsIgnoreCase("null"))) {
yield = -999;
targetyield = yield;
} else {
yield = Float.parseFloat(yld);
targetyield = yield;
}
tranOpName = opName;
tranVegName = vegName;
tranResName = resName;
if (opName != null) {
if (opName.equals("")) {
tranOpName = null;
}
}
if (vegName != null) {
if (vegName.equals("")) {
tranVegName = null;
}
}
if (resName != null) {
if (resName.equals("")) {
tranResName = null;
}
}
processes = new ArrayList<>();
deletePlantProcess = false;
this.dbs = dbs;
readDBBlobs();
try {
processes = dbs.getProcesses(opBlob, opName, date);
fuel = dbs.getLastFuel();
stir = dbs.getLastSTIR();
vegKey = dbs.getVegs(vegBlob);
resCropKey = dbs.getVegs(resBlob); // this is really the crop key for the residue
if (resCropKey != null) {
resKey = dbs.addResidueRec(true, resCropKey, resAmount);
} else {
// check if remove is needed
double amount = checkRemResidue();
if (amount > 0) {
resKey = dbs.addResidueRecRem(false, "remove", (float) amount);
}
}
String nkey = dbs.attachYield(vegKey, yield);
if (nkey != null) {
vegKey = nkey;
}
modifyForRCC(vegKey);
} catch (Exception e) {
e.printStackTrace(System.err);
// throw new RuntimeException(e);
}
}
/**
* Updates the release canopy cover (rcc) for a certain vegetation.
*
* @param key vegetation key to update
*/
void modifyForRCC(String key) {
double amount = -999;
for (int i = 0; i < processes.size(); i++) {
String pname = processes.get(i);
String parts[] = pname.split("\\|");
String proc = parts[0];
switch (proc) {
case "plant":
if (parts.length > 1) {
amount = Double.parseDouble(parts[1]);
if (amount > 0) {
dbs.updateVegsRCC(key, amount);
}
amount = Double.parseDouble(parts[2]);
if (amount > 0) {
dbs.updateVegsRowWidth(key, amount);
}
amount = Double.parseDouble(parts[3]);
if (amount > 0) {
dbs.updateVegsCanopyCoverCoef(key, amount);
}
}
}
}
}
/**
* Get amount of residue removed by either a remove-residue operation or a
* burning operation.
*
* @return get amount of residue removed
*/
double checkRemResidue() {
double amount = -999;
for (int i = 0; i < processes.size(); i++) {
String pname = processes.get(i);
String parts[] = pname.split("\\|");
String proc = parts[0];
switch (proc) {
case "remove-residue":
if (parts.length > 1) {
amount = Double.parseDouble(parts[1]);
} else {
amount = 1.0;
}
return amount;
case "burning":
if (parts.length > 1) {
amount = Double.parseDouble(parts[2]);
} else {
amount = 1.0;
}
return amount;
}
}
return amount;
}
/**
* Get residue added name from operation, null if no residue added in
* operation.
*
* @return residue added name
*/
String checkEmbeddedResidue() {
String name = null;
for (int i = 0; i < processes.size(); i++) {
String pname = processes.get(i);
String parts[] = pname.split("\\|");
String proc = parts[0];
switch (proc) {
case "add-residue":
// return last key added
name = dbs.getLastResidue();
break;
}
}
return name;
}
/**
* Get any errors associated with this operation.
*
* @return string of error messages if any
*/
String getErrors() {
return errors;
}
/**
* Change the year of this operation by +1
*/
void adjustYears() {
int yr = getYear();
setYear(yr + 1);
}
/**
* Read all the detail database parameters for crop, operation and residue
* tied to this operation. May add to error messages.
*
* @return true if database parameters are read.
*/
// Read the op and veg records
public boolean readDBBlobs() {
if (tranOpName != null) {
try {
opBlob = getBlobCRLMOD(tranOpName, "operations");
//if (use_CRLMOD == false) {
//opBlob = getBlob(tranOpName, "operations");
//} else {
// opBlob = getBlobCRLMOD(tranOpName, "operations");
//}
if (opBlob.equals("")) {
opStatus = RecStatus.MISSING;
errors = errors + "Error, no operation data for: " + tranOpName + "\n";
} else {
opStatus = RecStatus.OK;
}
} catch (Exception e) {
opBlob = null;
opStatus = RecStatus.MISSING;
errors = errors + "Error, no operation data for: " + tranOpName + "\n";
}
}
if (tranVegName != null) {
try {
vegBlob = getBlobCRLMOD(tranVegName, "vegetations");
//if (use_CRLMOD == false) {
//vegBlob = getBlob(tranVegName, "vegetations");
//} else {
// vegBlob = getBlobCRLMOD(tranVegName, "vegetations");
//}
if (vegBlob.equals("")) {
vegStatus = RecStatus.MISSING;
errors = errors + "Error, no vegetation data for: " + tranVegName + "\n";
} else {
vegStatus = RecStatus.OK;
}
} catch (Exception e) {
vegBlob = null;
vegStatus = RecStatus.MISSING;
errors = errors + "Error, no vegetation data for: " + tranVegName + "\n";
}
}
// operation either has a vegetation or residue or neither,
if (tranResName != null) {
try {
resBlob = getBlobCRLMOD(tranResName, "residues");
//if (use_CRLMOD == false) {
//resBlob = getBlob(tranResName, "vegetations");
//} else {
// resBlob = getBlobCRLMOD(tranResName, "residues");
//}
if (resBlob.equals("")) {
resStatus = RecStatus.MISSING;
errors = errors + "Error, no vegetation/residue data for: " + tranResName + "\n";
} else {
resStatus = RecStatus.OK;
}
} catch (Exception e) {
resBlob = null;
resStatus = RecStatus.MISSING;
errors = errors + "Error, no vegetation/residue data for: " + tranResName + "\n";
}
}
return true;
}
/**
* Get detail database parameters for either crops, operation or residue.
*
* @param name name of record to retrieve
* @param table whether name is a crop, operation or residue
* @return data blob from that record.
*/
private String getBlobCRLMOD(String name, String table) {
String data = "";
if (table == "operations") {
data = dbs.getOpBlob(name);
} else if (table == "vegetations") {
data = dbs.getVegBlob(name);
} else if (table == "residues") {
data = dbs.getResBlob(name);
}
return data;
}
/**
* Adjust operation date string to the specified year
*
* @param yr year to set in the date string
*/
public void setYear(int yr) {
String mdate[] = date.split("-");
mdate[0] = String.format("%04d", yr);
date = mdate[0] + "-" + mdate[1] + "-" + mdate[2];
}
/**
* Get year portion of operation date string.
*
* @return year part of date string
*/
public int getYear() {
String mdate[] = date.split("-");
return Integer.parseInt(mdate[0]);
}
/**
* Get month portion of operation date string.
*
* @return month part of date string
*/
public int getMonth() {
String mdate[] = date.split("-");
return Integer.parseInt(mdate[1]);
}
/**
* Get day portion of operation date string
*
* @return day part of date string.
*/
public int getDay() {
String mdate[] = date.split("-");
return Integer.parseInt(mdate[2]);
}
public int getJulianDay() {
int jdate;
String mdate[] = date.split("-");
int yr = Integer.parseInt(mdate[0]);
int mon = Integer.parseInt(mdate[1]) - 1;
int day = Integer.parseInt(mdate[2]);
GregorianCalendar gc = new GregorianCalendar();
gc.set(GregorianCalendar.DAY_OF_MONTH, day);
gc.set(GregorianCalendar.MONTH, mon);
gc.set(GregorianCalendar.YEAR, 2001);
jdate = gc.get(GregorianCalendar.DAY_OF_YEAR);
return jdate;
}
/**
* Get date of operation as a string
*
* @return date of operation
*/
public String getDate() {
return date;
}
/**
* Get status for operation to include in comments for output file.
*
* @return string indicating if this operation is ok
*/
private String getOpStatus() {
return (opStatus == RecStatus.MISSING) ? "MISSING" : "OK";
}
/**
* Get status for vegetation to include in comments for output file.
*
* @return string indicating if the vegetation is ok
*/
private String getVegStatus() {
return (vegStatus == RecStatus.MISSING) ? "MISSING" : "OK";
}
/**
* Get description of this operation to include in comments for output file.
*
* @return string representation of the the operation
*/
public String toString() {
String st;
if ((vegName != null) && (vegName != "")) {
st = date + "|" + opName + "|" + tranOpName + "|" + getOpStatus() + "|" + vegName + "|" + tranVegName + "|" + getVegStatus();
} else {
st = date + "|" + opName + "|" + tranOpName + "|" + getOpStatus();
}
for (int i = 0; i < processes.size(); i++) {
if ((processes.get(i) == "kill-crop") && (forceKillCrop == false)) {
st = st + "\n\t" + processes.get(i) + " (Ignored)";
} else {
st = st + "\n\t" + processes.get(i);
}
}
return st;
}
/**
* Get the key associated with the vegetation
*
* @param def default string to return if no vegetation
* @return key to this vegetation in the operation record.
*/
public String getCurCrop(String def) {
if ((vegName.equals("")) || (vegStatus == RecStatus.MISSING)) {
return def;
} else {
return vegKey;
}
}
/**
* Set the vegetation key and harvest yield for this operation.
*
* @param key vegetation key to use
*/
public void setVegIfEmpty(String key) {
if (harVegKey == null) {
harVegKey = key;
targetyield = dbs.getVegTargetYield(harVegKey);
} else if (harVegKey.equals("")) {
harVegKey = key;
targetyield = dbs.getVegTargetYield(harVegKey);
}
}
/**
* Gets vegetation key associated with this operation
*
* @return vegetation key for this operation
*/
public String getVegKey() {
return vegKey;
}
/**
* Check this operation has a harvest and plant processing together. WEPP will
* need to the setup to have the plant operation on the next day because they
* can not occur on the same day.
*
* @return true if operation has both a plant and harvest
*/
public boolean hasHarvestAndPlant() {
boolean hasHarvest = false;
boolean hasPlant = false;
for (int i = 0; i < processes.size(); i++) {
String pname = processes.get(i);
String parts[] = pname.split("\\|");
String proc = parts[0];
switch (proc) {
case "harvest":
hasHarvest = true;
break;
case "plant":
hasPlant = true;
break;
}
}
return (hasHarvest && hasPlant);
}
/**
* Converts a numeric month into a 3 character string.
*
* @return data string
*/
public String getAltDate() {
String[] monstrs = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int mon = getMonth();
int day = getDay();
int yr = getYear();
return String.format("%s %02d, %02d", monstrs[mon - 1], day, yr);
}
public boolean isPerennialMaturePlant() {
boolean rval = false;
// if a perennial has a 1-1-1 planting date assume this is
// handled in the initial conditions.
//if ((getMonth() == 1) && (getDay() == 1) && (getYear() == 1)) {
if (hasProcess("initialplant")) {
if (dbs.isPerennial(vegKey)) {
if (dbs.getSenescenceDay(vegKey) > 0) {
rval = true;
}
}
}
//}
return rval;
}
/**
* This converts an operation into a string that may contain zero or more
* lower level WEPP operations.
*
* @param curCrop Current crop that is growing.
* @return String of lower level operations to output
*/
public String toOpString(String curCrop) {
String stl;
boolean hasHarvest = false;
boolean advDate = false;
int[] nextDate;
String[] dparts = date.split("-");
int year = Integer.parseInt(dparts[0]);
int mon = Integer.parseInt(dparts[1]);
int day = Integer.parseInt(dparts[2]);
int prisec = 2;
float rowwid = -999;
stl = "";
for (int i = 0; i < processes.size(); i++) {
String pname = processes.get(i);
String parts[] = pname.split("\\|");
String proc = parts[0];
String weppkey;
String amount;
if (advDate == true) {
nextDate = incDay(mon, day, year);
// Force all remaining processes to move to the next day
mon = nextDate[0];
day = nextDate[1];
year = nextDate[2];
advDate = false;
}
switch (proc) {
case "tillage":
weppkey = parts[1];
float tdmean = dbs.getTillDepth(weppkey);
rowwid = dbs.getTillRowWidth(weppkey);
stl = stl + String.format("%4d %2d %2d 1 Tillage\t OpCropDef.%s {%f, %d}\n", mon, day, year, weppkey, tdmean, prisec);
break;
case "initialplant":
// nothing to do
break;
case "plant":
if (rowwid < 0) {
rowwid = (float) 0.75;
}
if (dbs.isPerennial(vegKey)) {
rowwid = 0;
if (deletePlantProcess == false) {
int senday = dbs.getSenescenceDay(vegKey);
stl = stl + String.format("%4d %2d %2d 1 Plant-Perennial\tCropDef.%s {%f,%d}\n", mon, day, year, vegKey, rowwid, senday);
}
} else {
float rowwidmod = Float.parseFloat(parts[2]);
if (rowwidmod > 0) {
rowwid = rowwidmod;
}
stl = stl + String.format("%4d %2d %2d 1 Plant-Annual\tCropDef.%s {%f}\n", mon, day, year, vegKey, rowwid);
}
break;
case "kill-crop":
if (forceKillCrop) {
if (dbs.isPerennial(curCrop)) {
stl = stl + String.format("%4d %2d %2d 1 Kill-Perennial\tCropDef.%s {}\n", mon, day, year, curCrop);
} else {
stl = stl + String.format("%4d %2d %2d 1 Herbicide-App\t {}\n", mon, day, year);
}
}
break;
case "kill-annual-crop":
if (forceKillCrop) {
if (dbs.isPerennial(curCrop)) {
stl = stl + String.format("%4d %2d %2d 1 Kill-Perennial\tCropDef.%s {}\n", mon, day, year, curCrop);
} else {
stl = stl + String.format("%4d %2d %2d 1 Herbicide-App\t {}\n", mon, day, year);
}
}
break;
case "add-residue":
// this could be that the operation has a residue specified but
// it was not passed in via the editor so there is no addtion.
if (resKey != null) {
stl = stl + String.format("%4d %2d %2d 1 Residue-Addition\t ResidueDef.%s {}\n", mon, day, year, resKey);
}
break;
case "harvest":
stl = stl + String.format("%4d %2d %2d 1 Harvest-Annual\tCropDef.%s {}\n", mon, day, year, harVegKey);
hasHarvest = true;
break;
/*
case "cut-perennial":
stl = stl + String.format("%4d %2d %2d 1 Cut-Perennial\tCropDef.%s {}\n", mon, day, year, curCrop);
break;
case "cut-perennial-leave":
stl = stl + String.format("%4d %2d %2d 1 Cut-Perennial-Leave\tCropDef.%s {}\n", mon, day, year, curCrop);
break;
case "cut-annual":
amount = parts[1]; // fraction of height removed,
stl = stl + String.format("%4d %2d %2d 1 Cut-Annual\tCropDef.%s {" + amount + "}\n", mon, day, year, curCrop);
break;
case "cut-annual-leave":
amount = parts[1]; // fraction of height removed, leave on field
stl = stl + String.format("%4d %2d %2d 1 Cut-Annual-Leave\tCropDef.%s {" + amount + "}\n", mon, day, year, curCrop);
break;
*/
case "irrigation":
weppkey = parts[1];
// there are two types of irrigation: depletion and fixed stationary
stl = stl + String.format("%4d %2d %2d 1 Start-Irrigation\tIrrDef.%s {}\n", mon, day, year, weppkey);
break;
case "fixed-irrigation":
weppkey = parts[1];
// there are two types of irrigation: depletion and fixed stationary
stl = stl + String.format("%4d %2d %2d 1 Irrigate\tDailyIrrDef.%s {}\n", mon, day, year, weppkey);
break;
case "remove-residue":
if (resKey != null) {
stl = stl + String.format("%4d %2d %2d 1 Residue-Removal\t ResidueDef.%s {}\n", mon, day, year, resKey);
}
break;
case "burning":
String standLost = parts[1];
String flatLost = parts[2];
// burning only works for annuals
if ((dbs.isPerennial(curCrop) == false) || (dbs.isPerennial(curCrop) == true)) {
stl = stl + String.format("%4d %2d %2d 1 Burning {" + standLost + "," + flatLost + "}\n", mon, day, year);
} else {
if (resKey != null) {
stl = stl + String.format("%4d %2d %2d 1 Residue-Removal\t ResidueDef.%s {}\n", mon, day, year, resKey);
}
}
break;
case "silage":
// use with caution - only one per crop scenario
stl = stl + String.format("%4d %2d %2d 1 Silage {}\n", mon, day, year);
hasHarvest = true;
break;
case "flatten-residue":
amount = parts[1];
stl = stl + String.format("%4d %2d %2d 1 Shredding {" + amount + "}\n", mon, day, year);
break;
case "remove-live":
case "remove-live-not-yield":
if ((curCrop.equals("")) || dbs.isPerennial(curCrop)) {
if (parts.length >= 2) {
amount = parts[1]; // % of live biomass removed
stl = stl + String.format("%4d %2d %2d 1 Graze-Perennial {" + amount + "}\n", mon, day, year);
} else {
stl = stl + String.format("%4d %2d %2d 1 Cut-Perennial {}\n", mon, day, year);
}
} else {
if (parts.length >= 2) {
amount = parts[1]; // % of height removed
} else {
amount = "1.0"; // if no parameter remove 100%
}
stl = stl + String.format("%4d %2d %2d 1 Cut-Annual {" + amount + "}\n", mon, day, year);
}
break;
case "remove-live-leave":
case "remove-live-leave-not-yield":
if (dbs.isPerennial(curCrop)) {
if (parts.length >= 2) {
amount = parts[1]; // % of live biomass removed but left on field
} else {
amount = "0";
}
stl = stl + String.format("%4d %2d %2d 1 Cut-Perennial-Leave {" + amount + "}\n", mon, day, year);
} else {
if (parts.length >= 2) {
amount = parts[1]; // % of height removed but left on field
} else {
amount = "1.0";
}
stl = stl + String.format("%4d %2d %2d 1 Cut-Annual-Leave {" + amount + "}\n", mon, day, year);
}
break;
case "irrigation-stop":
break;
case "next-day":
advDate = true;
break;
case "none":
// has no WEPP equivalent
stl = stl + String.format("%4d %2d %2d 1 NO-OP {}\n", mon, day, year);
break;
}
}
if (processes.size() == 0) {
stl = stl + String.format("%4d %2d %2d 1 NO-OP {}\n", mon, day, year);
}
return stl;
}
/**
* From the data add one day. This is because WEPP can't do some combinations
* of processes on the same day.
*
* @param mon current month
* @param day current day
* @param yr current year
* @return operation date advanced one day
*/
private int[] incDay(int mon, int day, int yr) {
int[] pdate = {1, 1, 1};
GregorianCalendar gc = new GregorianCalendar();
gc.set(GregorianCalendar.DAY_OF_MONTH, day);
gc.set(GregorianCalendar.MONTH, mon - 1);
gc.set(GregorianCalendar.YEAR, 2001); // use 2001 as a non-leap year
gc.add(Calendar.DAY_OF_MONTH, 1);
pdate[1] = gc.get(Calendar.DAY_OF_MONTH);
pdate[0] = gc.get(Calendar.MONTH) + 1;
int nyr = gc.get(Calendar.YEAR);
pdate[2] = yr + (nyr - 2001);
return pdate;
}
/**
* Get the vegetation key of plant in this operation.
*
* @return key for the vegetation, null if the operation has no vegetation
*/
public String getPlant() {
return vegName.equals("") ? null : dbs.getVegKey(vegName);
}
/**
* Check if an operation contains a vegetation
*
* @return true if operation contains a vegetation
*/
public boolean hasPlant() {
return vegName.equals("") ? false : true;
}
/**
* Get residue for this operation.
*
* @return residue associated with this operation
*/
public String getResidue() {
return resName;
}
/**
* Get fuel usage in l/ha for this operation
*
* @return fuel usage
*/
public float getFuel() {
return fuel;
}
/**
* Get STIR value for this operation. This value is not computed, it is
* entered in the data record for the operation.
*
* @return STIR for the operation
*/
public float getSTIR() {
return stir;
}
/**
* Create a date string for the operation.
*
* @param year new year
* @param mon new month
* @param day new day
*/
public void changeDate(int year, int mon, int day) {
date = String.format("%04d-%02d-%02d", year, mon, day);
}
/**
* Set flag to indicate if a crop is growing during this operation.
*
* @param val true if crop is growing
* @return value passed in
*/
public boolean setCropGrowing(boolean val) {
cropGrowing = val;
return cropGrowing;
}
/**
* Check if there is a crop growing during this operation.
*
* @return true if crop growing
*/
public boolean getCropGrowing() {
return cropGrowing;
}
/**
* Set if this operation should kill the crop or not.
*
* @param val kill flag
* @return value passed in
*/
public boolean setIncludeKill(boolean val) {
forceKillCrop = val;
return forceKillCrop;
}
/**
* Check if one of the processes has an implied kill-crop.
*
* @return true if growth stopped by this operation
*/
public boolean hasStopGrowthProcess(String vkey) {
boolean rc = false;
for (int i = 0; i < processes.size(); i++) {
String pname = processes.get(i);
String parts[] = pname.split("\\|");
String proc = parts[0];
switch (proc) {
case "harvest":
case "kill-crop":
case "silage":
rc = true;
break;
case "kill-annual-crop":
if (!dbs.isPerennial(vkey)) {
rc = true;
}
break;
}
}
return rc;
}
/**
* Check if this operation could be the start/end of an interval.
*
* @return true if this operation defines an interval date.
*/
public boolean hasIntervalProcess() {
boolean rc = false;
for (int i = 0; i < processes.size(); i++) {
String pname = processes.get(i);
String parts[] = pname.split("\\|");
String proc = parts[0];
switch (proc) {
case "harvest":
case "silage":
rc = true;
break;
}
}
return rc;
}
/**
* Check if this operation has any process related to potential crop
* calibration.
*
* @return true if this operation should be considered for calibration
*/
public boolean hasCalRelatedProcess() {
boolean rc = false;
for (int i = 0; i < processes.size(); i++) {
String pname = processes.get(i);
String parts[] = pname.split("\\|");
String proc = parts[0];
switch (proc) {
case "harvest":
case "remove-live":
case "remove-live-leave":
case "silage":
rc = true;
break;
}
}
return rc;
}
/**
* Check if this operation has a specific process.
*
* @param pro name to check for
* @return true if operation contains the process
*/
public boolean hasProcess(String pro) {
boolean rc = false;
for (int i = 0; i < processes.size(); i++) {
String pname = processes.get(i);
String parts[] = pname.split("\\|");
String proc = parts[0];
if (proc.equals(pro)) {
rc = true;
}
}
return rc;
}
/**
* Check if this operation contains irrigation.
*
* @return irrigation name if found, else empty string
*/
public String getIrrigationKey() {
String key = "";
for (int i = 0; i < processes.size(); i++) {
String pname = processes.get(i);
String parts[] = pname.split("\\|");
String proc = parts[0];
if (proc.equals("irrigation")) {
key = parts[1];
}
}
return key;
}
/**
* Increment the date for this operation.
*
* @return new date as a string
*/
public String incDayString() {
String[] dparts = date.split("-");
int year = Integer.parseInt(dparts[0]);
int mon = Integer.parseInt(dparts[1]);
int day = Integer.parseInt(dparts[2]);
int[] nextDate = incDay(mon, day, year);
mon = nextDate[0];
day = nextDate[1];
year = nextDate[2];
return String.format("%04d-%02d-%02d", year, mon, day);
}
/**
* Check if operation is doing a harvest.
*
* @return vegetation that is being harvested.
*/
public String getHarVegKey() {
return harVegKey;
}
/**
* Check if dates are the same between operations.
*
* @param lm Operation to check
* @return 0= equal dates
*/
@Override
public int compareTo(LMODOperation lm) {
return date.compareTo(lm.date);
}
/**
* Get yield associated with this operation.
*
* @return yield if any
*/
public float getYield() {
return yield;
}
/**
* Get target yield for this operation as dry weight.
*
* @return target yield if any n kg/m^2
*/
public float getTargetYield() {
return targetyield;
}
/**
* Get target yield taking into moisture and converting units to what is in
* the data record for the vegetation.
*
* @return yield in user units
*/
public float getTargetYieldConv() {
float targetYieldConv = (float) 0.0001;
double dryYield = targetyield;
if (dryYield > 0.0001) {
double yldConv = getYieldConvFactor();
double moisture = getMoisture();
double cyld = yldConv * dryYield; // this is dry yield
targetYieldConv = (float) (cyld / (1.0 - (moisture / 100.0))); // what user sees, account for moisture
targetYieldConv = targetYieldConv + (float) 0.0001;
}
return targetYieldConv;
}
/**
* Get the factor that converts from kg/m^2 to the user defined yield units.
*
* @return factor for conversion.
*/
public float getYieldConvFactor() {
return dbs.getVegYieldConvFactor(harVegKey);
}
/**
* Get moisture content of yield for this operation.
*
* @return typical moisture content from crop record.
*/
public float getMoisture() {
return dbs.getVegYieldMoisture(harVegKey);
}
/**
* Get yield units string from crop data record.
*
* @return yield units
*/
public String getYldUnits() {
return dbs.getVegYieldUnits(harVegKey);
}
/**
* Get vegetation name associated with any harvest in this operation.
*
* @return harvest crop name, if any
*/
public String getHarVegName() {
return dbs.getVegName(harVegKey);
}
/**
* Get vegetation name associated with this operation
*
* @return vegetation name, if any
*/
public String getVegName() {
return vegName;
}
}