WEPSManagement.java [src/nodes] Revision: default Date:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package nodes;
import csip.utils.Client;
import static csip.ModelDataService.ERROR;
import static csip.ModelDataService.KEY_METAINFO;
import static csip.ModelDataService.KEY_PARAMETER;
import static csip.ModelDataService.KEY_RESULT;
import static csip.ModelDataService.KEY_STATUS;
import static csip.ModelDataService.KEY_VALUE;
import static csip.ModelDataService.VALUE;
import csip.api.server.ServiceException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import parsers.ParseTypes;
import parsers.ParserException;
import parsers.WEPSParser;
import translators.Translator;
import static utils.Constants.ID;
import static utils.Constants.LIMIT;
import static utils.Constants.NAME;
import static utils.Constants.NATIVE_FORMATS;
import static utils.Constants.RESIDUES;
import utils.TranslatorException;
import utils.Urls;
import utils.Util;
/**
*
* @author Brad
*/
public class WEPSManagement extends Management {
public WEPSManagement(Urls urls) {
super(urls);
}
@Override
public void readJSONData(JSONObject data, Translator.FORMAT type) throws JSONException, TranslatorException {
super.readJSONData(data, type);
rotateEvents();
}
/**
* Prevents a fallow year in weps if the rotation starts toward the end of the year
*/
// public void rotateEvents(){
// LocalDate start = eventData.get(0).getDate();
// LocalDate end = eventData.get(eventData.size() - 1).getDate();
// int current_index = 0; // this will keep the shifted year in order
//
// for(Iterator<Event> iterator = eventData.iterator(); iterator.hasNext();){ // must do it this way so I can remove
// Event event = iterator.next();
// if(event.getDate().withYear(start.getYear()).isBefore(start)
// && event.getDate().getYear() == end.getYear()){
// eventData.remove(event);
// event.setDate(event.getDate().withYear(start.getYear()));
// eventData.add(current_index, event);
// current_index++;
// }
// }
//
// }
public void readManData(File manFile) throws IOException, ServiceException, ParserException {
WEPSParser parser = new WEPSParser(manFile.getAbsolutePath());
ParseTypes type;
Event datum;
while ((type = parser.readNext()) != ParseTypes.END) {
if (type == ParseTypes.START) {
rotationYears = parser.getRotationYears();
}
if (type == ParseTypes.DATE) {
datum = new Event();
datum.setDate(parser.getDate());
datum.readManData(parser);
eventData.add(datum);
}
}
}
/**
*
* @return total fuel usage in gal/ acre
*/
public Double calculateTotalFuelUsage() {
List<Double> fuelUsages = calculateFuelUsage();
Double totalFuel = 0.0;
// trying this suggestion but it is just totalling the fuel values. Looks like map reduce.
totalFuel = fuelUsages.stream().map((f) -> f).reduce(totalFuel, (accumulator, _item) -> accumulator + _item);
return totalFuel;
}
/**
*
* @return fuel usage by interval in gal/acre
*/
public List<Double> calculateFuelUsage() {
List<Double> fuels = new ArrayList();
Double fuelUse;
for (List<WEPSOperation> interval : getCropIntervals()) {
fuelUse = 0.0;
fuelUse = interval.stream().map((op) -> op.calculateFuel()).reduce(fuelUse, (accumulator, _item) -> accumulator + _item);
fuels.add(fuelUse * 0.106907); // L/ha -> gal/acre
}
return fuels;
}
private List<List<WEPSOperation>> getCropIntervals() {
List<List<WEPSOperation>> intervals = new ArrayList();
List<WEPSOperation> ops;
WEPSOperation op;
ops = new ArrayList();
for (Event e : eventData) {
op = ( WEPSOperation ) e.getOperation();
ops.add(op);
if (op.containsAction("P", 31)) {
intervals.add(ops);
ops = new ArrayList();
}
}
if (intervals.isEmpty())
intervals.add(ops); // No kill crop was found so put everything into one interval.
else
intervals.get(0).addAll(ops); // take the last operations and put them in the first interval due to wrap around.
return intervals;
}
/**
* This method take all the assumed crops from a WEPS man file and converts them to residues if
* they are actually residues
*/
public void convertResidues() throws JSONException, Exception {
Crop crop;
JSONObject req;
JSONObject meta;
JSONArray params;
JSONObject jparam;
JSONArray jvalues;
JSONObject jnative_formats;
JSONObject res;
JSONArray results;
JSONObject lmod;
JSONObject value;
JSONArray residues;
JSONObject jresidue = null;
JSONObject responseMeta;
JSONObject jlimit;
Map<String, JSONObject> fileData;
req = new JSONObject();
meta = new JSONObject();
params = new JSONArray();
req.put(KEY_METAINFO, meta);
req.put(KEY_PARAMETER, params);
jnative_formats = new JSONObject();
jnative_formats.put(NAME, NATIVE_FORMATS);
jnative_formats.put(KEY_VALUE, "FALSE");
params.put(jnative_formats);
jlimit = new JSONObject();
jlimit.put(NAME, LIMIT);
jlimit.put(VALUE, "all");
params.put(jlimit);
jparam = new JSONObject();
jvalues = new JSONArray();
jparam.put(NAME, NAME);
params.put(jparam);
jparam.put(VALUE, jvalues);
for (Event datum : eventData) {
crop = datum.getCrop();
if (crop != null) {
jvalues.put(datum.getCrop().getName());
}
}
res = new Client().doPOST(urls.getResidue(), req);
responseMeta = res.getJSONObject(KEY_METAINFO);
if (!responseMeta.getString(KEY_STATUS).equalsIgnoreCase("Failed")) {
results = res.getJSONArray(KEY_RESULT);
lmod = results.getJSONObject(0);
value = lmod.getJSONObject(VALUE);
residues = value.getJSONArray(RESIDUES);
fileData = Util.mapResidueResultsByName(residues, Translator.FORMAT.KEY);
for (Event datum : eventData) {
if (datum.getCrop() != null) {
jresidue = fileData.get(datum.getCrop().getName());
// If it is null assume it is a crop and do nothing
// If it is found then it should be a residue so we need to convert it.
if (jresidue != null) {
datum.addResidue(new WEPSResidue(jresidue.getString(ID), datum.getCrop().getName()));
datum.removeCrop();
}
}
}
} else {
String error = responseMeta.getString(ERROR);
throw new ServiceException("residue service error: " + error);
}
}
}