V1_0.java [src/java/m/ipat] 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 m.ipat;

import csip.ModelDataService;
import csip.ServiceException;
import csip.annotations.Description;
import csip.annotations.Name;
import csip.annotations.Resource;
import database.ipat.IPAT_Db;
import database.nrt.NRT_DB;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.Path;
import static m.ipat.Crops.APPLIATION_DEPTH;
import static m.ipat.IpatInput.IRRIGATION_LAND_UNITS;
import static m.ipat.IpatInput.WELL_LIFT;
import m.ipat.IpatOutput.LandUnits;
import static m.ipat.LandUnit.ROTATION_CROPS;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import utils.EvalResult;

/**
 *
 * @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
 */
@Name("iPAT")
@Description("iPAT")
@Path("m/ipat/1.0")
@Resource(from = database.DBResources.class)

public class V1_0 extends ModelDataService {

    IpatInput ipat;
    IpatOutput ipat_output;

    @Override
    public void preProcess() throws ServiceException, JSONException, SQLException {
        ipat = new IpatInput();
        ipat_output = new IpatOutput((name, val, descr, unit) -> this.putResult(name, val, descr, unit));

        ipat.readValuesFromJSON(getParam());
        ipat.setRowFirst();

        try (NRT_DB nrt_db = new NRT_DB(getClass(), LOG)) {
            ipat.setString(IpatInput.STATE_NUMBER, nrt_db.findStateCode(ipat.getGeometry(IpatInput.LOCATION)));
        }
    }

    @Override
    public void doProcess() throws ServiceException, SQLException {
        try (IPAT_Db ipat_db = new IPAT_Db(this.getClass(), LOG)) {
            getIPATCrops(ipat_db);  //  Also validates that the CRLMOD crop id provided is valid for irrigation calculations.
            computeIrrigationEnergyConsumptionResults(ipat_db);

        }
    }

    @Override
    public void postProcess() throws ServiceException, JSONException {

        JSONArray outArray = new JSONArray();
        ipat.toJSONAll(outArray);
        if (null != ipat_output) {
            ipat_output.putResult();
        }
    }

    protected void getIPATCrops(IPAT_Db ipat_db) throws ServiceException {
        LandUnit landUnits = (LandUnit) ipat.getValue(IRRIGATION_LAND_UNITS);
        
        for (int i = 0; i < landUnits.rowCount(); i++) {
            Crops crops = (Crops) landUnits.getValue(i, ROTATION_CROPS);
            for (int j = 0; j < crops.rowCount(); j++) {
                crops.setInteger(j, Crops.CROP_ID, ipat_db.getCropId(crops.getInteger(j, Crops.CRLMOD_CROP_ID)));
            }
        }

    }

    protected void computeIrrigationEnergyConsumptionResults(IPAT_Db ipat_db) throws ServiceException {
        double totalSystemEfficiency = 0.0;
        double maxTotalSystemEfficiency = 0.0;
        double costFactors = 0.0; // = 1.3715 * ((well_lift + pressure * 2.31) / unit_ppe / unit_hp_hr)
        double waterUse = 0.0;    // = crop_acres * water_applied_gross_feet
        int wellLift = ipat.getInteger(WELL_LIFT);
        double energyCost = ipat.getDouble(IpatInput.ENERGY_COST_RATE);
        int systemPressure = ipat.getInteger(IpatInput.SYSTEM_PRESSURE);
        LandUnit landUnits = (LandUnit) ipat.getValue(IRRIGATION_LAND_UNITS);

        //  AKA "System Efficiency" in original software        
//        double irrigEfficiency = ipat_db.irrigationEfficiency(ipat.getInteger(IpatInput.IRRIGATION_SYSTEM)); //Also validates the id exists...

        PowerPlant powerPlant = ipat_db.getPowerSource(ipat.getInteger(IpatInput.POWER_SOURCE)); //Also validates the id exists...      

        // User specified system mods
//        double flowMeterEfficiency = ipat_db.getFlowMeterEfficiency(ipat.getBoolean(IpatInput.FLOW_METER));
//        double irrigScheduleEfficiency = ipat_db.getIrrigScheduleEfficiency(ipat.getBoolean(IpatInput.IRRIGATION_SCHEDULING));
//        double mtnUpgradeEfficiency = ipat_db.getMtnUpgradeEfficiency(ipat.getBoolean(IpatInput.MAINTENANCE_UPGRADES));
//
//        //  Database supplied maximum system mods
//        double maxFlowMeterEfficiency = ipat_db.getFlowMeterEfficiency(true);
//        double maxIrrigScheduleEfficiency = ipat_db.getIrrigScheduleEfficiency(true);
//        double maxMtnUpgradeEfficiency = ipat_db.getMtnUpgradeEfficiency(true);

        if (EvalResult.testDefaultInteger(wellLift)) {
            wellLift = ipat_db.getWellLift(ipat.getString(IpatInput.STATE_NUMBER));
        }

//        totalSystemEfficiency = irrigEfficiency + flowMeterEfficiency + irrigScheduleEfficiency + mtnUpgradeEfficiency;
//        maxTotalSystemEfficiency = irrigEfficiency + maxFlowMeterEfficiency + maxIrrigScheduleEfficiency + maxMtnUpgradeEfficiency;
        
        //  Assuming, now, that all adjustments are made in the GUI and no longer need to be accounted for here...
        totalSystemEfficiency = 1.0;

        //Per crop we have to re-do all calculations....
        for (int i = 0; i < landUnits.rowCount(); i++) {
            Crops crops = (Crops) landUnits.getValue(i, ROTATION_CROPS);

            double lWaterUse = 0.0;
            double actual_water_applied = 0.0;
            double assumed_water_applied = 0.0;
            double irr_acres = landUnits.getDouble(i, LandUnit.IRRIGATED_ACRES);

            for (int j = 0; j < crops.rowCount(); j++) {
                double water_applied_gross_inches = crops.getInteger(j, APPLIATION_DEPTH);
                double water_applied_gross_feet = water_applied_gross_inches / 12;

                double tWater_applied = water_applied_gross_feet * totalSystemEfficiency;
                actual_water_applied += tWater_applied;
                assumed_water_applied  += water_applied_gross_feet;

                double cWaterUse = irr_acres * water_applied_gross_feet;
                lWaterUse += cWaterUse;  //  Should be this??  (water_applied_gross_feet * (1.0 + (1.0 - totalSystemEfficiency)));

                crops.setDouble(j, Crops.WATER_REQUIREMENT, cWaterUse);
                crops.setDouble(j, Crops.WATER_USE, tWater_applied);
            }

            waterUse += lWaterUse;
            ipat_output.addLandUnit(landUnits.getString(i, LandUnits.LAND_UNIT_ID), lWaterUse, assumed_water_applied * 12.0);
        }
        costFactors = 1.3715 * ((wellLift + systemPressure * 2.31) / powerPlant.eval_gain / powerPlant.hp_hr_per_energy_unit);

        double seasonalIrrCost = energyCost * waterUse * costFactors;  //Per the original software.  [energyCost is called unit_cost in the original software]

        Map<String, Object> row = new HashMap<>();
        row.put(IpatOutput.IRRIG_SYS_WATER_USE, waterUse);
        row.put(IpatOutput.IRRIG_SYS_COST, seasonalIrrCost);

        ipat_output.appendRow(row);

    }

}